2 * Audio Toolbox system codecs
4 * copyright (c) 2016 rcombs
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <AudioToolbox/AudioToolbox.h>
25 #define FF_BUFQUEUE_SIZE 256
26 #include "libavfilter/bufferqueue.h"
29 #include "audio_frame_queue.h"
31 #include "bytestream.h"
32 #include "codec_internal.h"
35 #include "libavformat/isom.h"
36 #include "libavutil/avassert.h"
37 #include "libavutil/channel_layout.h"
38 #include "libavutil/mem.h"
39 #include "libavutil/opt.h"
40 #include "libavutil/log.h"
42 typedef struct ATDecodeContext
{
47 AudioConverterRef converter
;
48 struct FFBufQueue frame_queue
;
49 struct FFBufQueue used_frame_queue
;
56 AVFrame
* encoding_frame
;
59 static UInt32
ffat_get_format_id(enum AVCodecID codec
, int profile
)
64 case AV_PROFILE_AAC_LOW
:
66 return kAudioFormatMPEG4AAC
;
67 case AV_PROFILE_AAC_HE
:
68 return kAudioFormatMPEG4AAC_HE
;
69 case AV_PROFILE_AAC_HE_V2
:
70 return kAudioFormatMPEG4AAC_HE_V2
;
71 case AV_PROFILE_AAC_LD
:
72 return kAudioFormatMPEG4AAC_LD
;
73 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
74 case AV_PROFILE_AAC_ELD
:
75 return kAudioFormatMPEG4AAC_ELD
;
78 case AV_CODEC_ID_ADPCM_IMA_QT
:
79 return kAudioFormatAppleIMA4
;
80 case AV_CODEC_ID_ALAC
:
81 return kAudioFormatAppleLossless
;
82 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
83 case AV_CODEC_ID_ILBC
:
84 return kAudioFormatiLBC
;
86 case AV_CODEC_ID_PCM_ALAW
:
87 return kAudioFormatALaw
;
88 case AV_CODEC_ID_PCM_MULAW
:
89 return kAudioFormatULaw
;
91 av_assert0(!"Invalid codec ID!");
96 static int ffat_update_ctx(AVCodecContext
*avctx
)
98 ATDecodeContext
*at
= avctx
->priv_data
;
99 UInt32 size
= sizeof(unsigned);
100 AudioConverterPrimeInfo prime_info
;
101 AudioStreamBasicDescription out_format
;
103 AudioConverterGetProperty(at
->converter
,
104 kAudioConverterPropertyMaximumOutputPacketSize
,
105 &size
, &at
->pkt_size
);
107 if (at
->pkt_size
<= 0)
108 at
->pkt_size
= 1024 * 50;
110 size
= sizeof(prime_info
);
112 if (!AudioConverterGetProperty(at
->converter
,
113 kAudioConverterPrimeInfo
,
114 &size
, &prime_info
)) {
115 avctx
->initial_padding
= prime_info
.leadingFrames
;
118 size
= sizeof(out_format
);
119 if (!AudioConverterGetProperty(at
->converter
,
120 kAudioConverterCurrentOutputStreamDescription
,
121 &size
, &out_format
)) {
122 if (out_format
.mFramesPerPacket
) {
123 avctx
->frame_size
= out_format
.mFramesPerPacket
;
125 /* The doc on mFramesPerPacket says:
126 * For formats with a variable number of frames per packet, such as
127 * Ogg Vorbis, set this field to 0.
128 * Looks like it means for decoding. There is no known case that
129 * mFramesPerPacket is zero for encoding. Use a default value for safety.
131 avctx
->frame_size
= 1024;
132 av_log(avctx
, AV_LOG_WARNING
, "Missing mFramesPerPacket\n");
134 if (out_format
.mBytesPerPacket
&& avctx
->codec_id
== AV_CODEC_ID_ILBC
)
135 avctx
->block_align
= out_format
.mBytesPerPacket
;
137 av_log(avctx
, AV_LOG_ERROR
, "Get OutputStreamDescription failed\n");
138 return AVERROR_EXTERNAL
;
141 at
->frame_size
= avctx
->frame_size
;
142 if (avctx
->codec_id
== AV_CODEC_ID_PCM_MULAW
||
143 avctx
->codec_id
== AV_CODEC_ID_PCM_ALAW
) {
144 at
->pkt_size
*= 1024;
145 avctx
->frame_size
*= 1024;
151 static int read_descr(GetByteContext
*gb
, int *tag
)
155 *tag
= bytestream2_get_byte(gb
);
157 int c
= bytestream2_get_byte(gb
);
158 len
= (len
<< 7) | (c
& 0x7f);
165 static int get_ilbc_mode(AVCodecContext
*avctx
)
167 if (avctx
->block_align
== 38)
169 else if (avctx
->block_align
== 50)
171 else if (avctx
->bit_rate
> 0)
172 return avctx
->bit_rate
<= 14000 ? 30 : 20;
177 static av_cold
int get_channel_label(int channel
)
179 uint64_t map
= 1 << channel
;
180 if (map
<= AV_CH_LOW_FREQUENCY
)
182 else if (map
<= AV_CH_BACK_RIGHT
)
184 else if (map
<= AV_CH_BACK_CENTER
)
186 else if (map
<= AV_CH_SIDE_RIGHT
)
188 else if (map
<= AV_CH_TOP_BACK_RIGHT
)
190 else if (map
<= AV_CH_STEREO_RIGHT
)
192 else if (map
<= AV_CH_WIDE_RIGHT
)
194 else if (map
<= AV_CH_SURROUND_DIRECT_RIGHT
)
196 else if (map
== AV_CH_LOW_FREQUENCY_2
)
197 return kAudioChannelLabel_LFE2
;
202 static int remap_layout(AudioChannelLayout
*layout
, const AVChannelLayout
*in_layout
)
205 layout
->mChannelLayoutTag
= kAudioChannelLayoutTag_UseChannelDescriptions
;
206 layout
->mNumberChannelDescriptions
= in_layout
->nb_channels
;
207 for (i
= 0; i
< in_layout
->nb_channels
; i
++) {
210 c
= av_channel_layout_channel_from_index(in_layout
, i
);
211 if (c
< 0 || c
>= 64)
212 return AVERROR(EINVAL
);
213 label
= get_channel_label(c
);
214 layout
->mChannelDescriptions
[i
].mChannelLabel
= label
;
216 return AVERROR(EINVAL
);
222 static int get_aac_tag(const AVChannelLayout
*in_layout
)
224 static const struct {
228 { AV_CHANNEL_LAYOUT_MONO
, kAudioChannelLayoutTag_Mono
},
229 { AV_CHANNEL_LAYOUT_STEREO
, kAudioChannelLayoutTag_Stereo
},
230 { AV_CHANNEL_LAYOUT_QUAD
, kAudioChannelLayoutTag_AAC_Quadraphonic
},
231 { AV_CHANNEL_LAYOUT_OCTAGONAL
, kAudioChannelLayoutTag_AAC_Octagonal
},
232 { AV_CHANNEL_LAYOUT_SURROUND
, kAudioChannelLayoutTag_AAC_3_0
},
233 { AV_CHANNEL_LAYOUT_4POINT0
, kAudioChannelLayoutTag_AAC_4_0
},
234 { AV_CHANNEL_LAYOUT_5POINT0
, kAudioChannelLayoutTag_AAC_5_0
},
235 { AV_CHANNEL_LAYOUT_5POINT1
, kAudioChannelLayoutTag_AAC_5_1
},
236 { AV_CHANNEL_LAYOUT_6POINT0
, kAudioChannelLayoutTag_AAC_6_0
},
237 { AV_CHANNEL_LAYOUT_6POINT1
, kAudioChannelLayoutTag_AAC_6_1
},
238 { AV_CHANNEL_LAYOUT_7POINT0
, kAudioChannelLayoutTag_AAC_7_0
},
239 { AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK
, kAudioChannelLayoutTag_AAC_7_1
},
240 { AV_CHANNEL_LAYOUT_7POINT1
, kAudioChannelLayoutTag_MPEG_7_1_C
},
244 for (i
= 0; i
< FF_ARRAY_ELEMS(map
); i
++)
245 if (!av_channel_layout_compare(in_layout
, &map
[i
].chl
))
251 static av_cold
int ffat_init_encoder(AVCodecContext
*avctx
)
253 ATDecodeContext
*at
= avctx
->priv_data
;
257 AudioStreamBasicDescription in_format
= {
258 .mSampleRate
= avctx
->sample_rate
,
259 .mFormatID
= kAudioFormatLinearPCM
,
260 .mFormatFlags
= ((avctx
->sample_fmt
== AV_SAMPLE_FMT_FLT
||
261 avctx
->sample_fmt
== AV_SAMPLE_FMT_DBL
) ? kAudioFormatFlagIsFloat
262 : avctx
->sample_fmt
== AV_SAMPLE_FMT_U8
? 0
263 : kAudioFormatFlagIsSignedInteger
)
264 | kAudioFormatFlagIsPacked
,
265 .mBytesPerPacket
= av_get_bytes_per_sample(avctx
->sample_fmt
) * avctx
->ch_layout
.nb_channels
,
266 .mFramesPerPacket
= 1,
267 .mBytesPerFrame
= av_get_bytes_per_sample(avctx
->sample_fmt
) * avctx
->ch_layout
.nb_channels
,
268 .mChannelsPerFrame
= avctx
->ch_layout
.nb_channels
,
269 .mBitsPerChannel
= av_get_bytes_per_sample(avctx
->sample_fmt
) * 8,
271 AudioStreamBasicDescription out_format
= {
272 .mSampleRate
= avctx
->sample_rate
,
273 .mFormatID
= ffat_get_format_id(avctx
->codec_id
, avctx
->profile
),
274 .mChannelsPerFrame
= in_format
.mChannelsPerFrame
,
276 UInt32 layout_size
= sizeof(AudioChannelLayout
) +
277 sizeof(AudioChannelDescription
) * avctx
->ch_layout
.nb_channels
;
278 AudioChannelLayout
*channel_layout
= av_malloc(layout_size
);
281 return AVERROR(ENOMEM
);
283 if (avctx
->codec_id
== AV_CODEC_ID_ILBC
) {
284 int mode
= get_ilbc_mode(avctx
);
285 out_format
.mFramesPerPacket
= 8000 * mode
/ 1000;
286 out_format
.mBytesPerPacket
= (mode
== 20 ? 38 : 50);
289 status
= AudioConverterNew(&in_format
, &out_format
, &at
->converter
);
292 av_log(avctx
, AV_LOG_ERROR
, "AudioToolbox init error: %i\n", (int)status
);
293 av_free(channel_layout
);
294 return AVERROR_UNKNOWN
;
297 if (avctx
->ch_layout
.order
== AV_CHANNEL_ORDER_UNSPEC
)
298 av_channel_layout_default(&avctx
->ch_layout
, avctx
->ch_layout
.nb_channels
);
300 if ((status
= remap_layout(channel_layout
, &avctx
->ch_layout
)) < 0) {
301 av_log(avctx
, AV_LOG_ERROR
, "Invalid channel layout\n");
302 av_free(channel_layout
);
306 if (AudioConverterSetProperty(at
->converter
, kAudioConverterInputChannelLayout
,
307 layout_size
, channel_layout
)) {
308 av_log(avctx
, AV_LOG_ERROR
, "Unsupported input channel layout\n");
309 av_free(channel_layout
);
310 return AVERROR(EINVAL
);
312 if (avctx
->codec_id
== AV_CODEC_ID_AAC
) {
313 int tag
= get_aac_tag(&avctx
->ch_layout
);
315 channel_layout
->mChannelLayoutTag
= tag
;
316 channel_layout
->mNumberChannelDescriptions
= 0;
319 if (AudioConverterSetProperty(at
->converter
, kAudioConverterOutputChannelLayout
,
320 layout_size
, channel_layout
)) {
321 av_log(avctx
, AV_LOG_ERROR
, "Unsupported output channel layout\n");
322 av_free(channel_layout
);
323 return AVERROR(EINVAL
);
325 av_free(channel_layout
);
327 if (avctx
->bits_per_raw_sample
)
328 AudioConverterSetProperty(at
->converter
,
329 kAudioConverterPropertyBitDepthHint
,
330 sizeof(avctx
->bits_per_raw_sample
),
331 &avctx
->bits_per_raw_sample
);
333 #if !TARGET_OS_IPHONE
335 at
->mode
= (avctx
->flags
& AV_CODEC_FLAG_QSCALE
) ?
336 kAudioCodecBitRateControlMode_Variable
:
337 kAudioCodecBitRateControlMode_Constant
;
339 AudioConverterSetProperty(at
->converter
, kAudioCodecPropertyBitRateControlMode
,
340 sizeof(at
->mode
), &at
->mode
);
342 if (at
->mode
== kAudioCodecBitRateControlMode_Variable
) {
343 int q
= avctx
->global_quality
/ FF_QP2LAMBDA
;
344 if (q
< 0 || q
> 14) {
345 av_log(avctx
, AV_LOG_WARNING
,
346 "VBR quality %d out of range, should be 0-14\n", q
);
347 q
= av_clip(q
, 0, 14);
350 AudioConverterSetProperty(at
->converter
, kAudioCodecPropertySoundQualityForVBR
,
354 if (avctx
->bit_rate
> 0) {
355 UInt32 rate
= avctx
->bit_rate
;
357 status
= AudioConverterGetPropertyInfo(at
->converter
,
358 kAudioConverterApplicableEncodeBitRates
,
360 if (!status
&& size
) {
361 UInt32 new_rate
= rate
;
364 AudioValueRange
*ranges
= av_malloc(size
);
366 return AVERROR(ENOMEM
);
367 AudioConverterGetProperty(at
->converter
,
368 kAudioConverterApplicableEncodeBitRates
,
370 count
= size
/ sizeof(AudioValueRange
);
371 for (i
= 0; i
< count
; i
++) {
372 AudioValueRange
*range
= &ranges
[i
];
373 if (rate
>= range
->mMinimum
&& rate
<= range
->mMaximum
) {
376 } else if (rate
> range
->mMaximum
) {
377 new_rate
= range
->mMaximum
;
379 new_rate
= range
->mMinimum
;
383 if (new_rate
!= rate
) {
384 av_log(avctx
, AV_LOG_WARNING
,
385 "Bitrate %u not allowed; changing to %u\n", rate
, new_rate
);
390 AudioConverterSetProperty(at
->converter
, kAudioConverterEncodeBitRate
,
391 sizeof(rate
), &rate
);
394 at
->quality
= 96 - at
->quality
* 32;
395 AudioConverterSetProperty(at
->converter
, kAudioConverterCodecQuality
,
396 sizeof(at
->quality
), &at
->quality
);
398 if (!AudioConverterGetPropertyInfo(at
->converter
, kAudioConverterCompressionMagicCookie
,
399 &avctx
->extradata_size
, NULL
) &&
400 avctx
->extradata_size
) {
401 int extradata_size
= avctx
->extradata_size
;
403 if (!(avctx
->extradata
= av_mallocz(avctx
->extradata_size
+ AV_INPUT_BUFFER_PADDING_SIZE
)))
404 return AVERROR(ENOMEM
);
405 if (avctx
->codec_id
== AV_CODEC_ID_ALAC
) {
406 avctx
->extradata_size
= 0x24;
407 AV_WB32(avctx
->extradata
, 0x24);
408 AV_WB32(avctx
->extradata
+ 4, MKBETAG('a','l','a','c'));
409 extradata
= avctx
->extradata
+ 12;
410 avctx
->extradata_size
= 0x24;
412 extradata
= avctx
->extradata
;
414 status
= AudioConverterGetProperty(at
->converter
,
415 kAudioConverterCompressionMagicCookie
,
416 &extradata_size
, extradata
);
418 av_log(avctx
, AV_LOG_ERROR
, "AudioToolbox cookie error: %i\n", (int)status
);
419 return AVERROR_UNKNOWN
;
420 } else if (avctx
->codec_id
== AV_CODEC_ID_AAC
) {
423 bytestream2_init(&gb
, extradata
, extradata_size
);
425 len
= read_descr(&gb
, &tag
);
426 if (tag
== MP4DecConfigDescrTag
) {
427 bytestream2_skip(&gb
, 13);
428 len
= read_descr(&gb
, &tag
);
429 if (tag
== MP4DecSpecificDescrTag
) {
430 len
= FFMIN(gb
.buffer_end
- gb
.buffer
, len
);
431 memmove(extradata
, gb
.buffer
, len
);
432 avctx
->extradata_size
= len
;
435 } else if (tag
== MP4ESDescrTag
) {
437 bytestream2_skip(&gb
, 2);
438 flags
= bytestream2_get_byte(&gb
);
439 if (flags
& 0x80) //streamDependenceFlag
440 bytestream2_skip(&gb
, 2);
441 if (flags
& 0x40) //URL_Flag
442 bytestream2_skip(&gb
, bytestream2_get_byte(&gb
));
443 if (flags
& 0x20) //OCRstreamFlag
444 bytestream2_skip(&gb
, 2);
446 } while (bytestream2_get_bytes_left(&gb
));
447 } else if (avctx
->codec_id
!= AV_CODEC_ID_ALAC
) {
448 avctx
->extradata_size
= extradata_size
;
452 ret
= ffat_update_ctx(avctx
);
456 #if !TARGET_OS_IPHONE && defined(__MAC_10_9)
457 if (at
->mode
== kAudioCodecBitRateControlMode_Variable
&& avctx
->rc_max_rate
) {
458 UInt32 max_size
= avctx
->rc_max_rate
* avctx
->frame_size
/ avctx
->sample_rate
;
460 AudioConverterSetProperty(at
->converter
, kAudioCodecPropertyPacketSizeLimitForVBR
,
461 sizeof(max_size
), &max_size
);
465 ff_af_queue_init(avctx
, &at
->afq
);
467 at
->encoding_frame
= av_frame_alloc();
468 if (!at
->encoding_frame
)
469 return AVERROR(ENOMEM
);
474 static OSStatus
ffat_encode_callback(AudioConverterRef converter
, UInt32
*nb_packets
,
475 AudioBufferList
*data
,
476 AudioStreamPacketDescription
**packets
,
479 AVCodecContext
*avctx
= inctx
;
480 ATDecodeContext
*at
= avctx
->priv_data
;
484 if (!at
->frame_queue
.available
) {
494 frame
= ff_bufqueue_get(&at
->frame_queue
);
496 data
->mNumberBuffers
= 1;
497 data
->mBuffers
[0].mNumberChannels
= avctx
->ch_layout
.nb_channels
;
498 data
->mBuffers
[0].mDataByteSize
= frame
->nb_samples
*
499 av_get_bytes_per_sample(avctx
->sample_fmt
) *
500 avctx
->ch_layout
.nb_channels
;
501 data
->mBuffers
[0].mData
= frame
->data
[0];
502 if (*nb_packets
> frame
->nb_samples
)
503 *nb_packets
= frame
->nb_samples
;
505 ret
= av_frame_replace(at
->encoding_frame
, frame
);
511 ff_bufqueue_add(avctx
, &at
->used_frame_queue
, frame
);
516 static int ffat_encode(AVCodecContext
*avctx
, AVPacket
*avpkt
,
517 const AVFrame
*frame
, int *got_packet_ptr
)
519 ATDecodeContext
*at
= avctx
->priv_data
;
522 AudioBufferList out_buffers
= {
526 .mNumberChannels
= avctx
->ch_layout
.nb_channels
,
527 .mDataByteSize
= at
->pkt_size
,
531 AudioStreamPacketDescription out_pkt_desc
= {0};
536 if (ff_bufqueue_is_full(&at
->frame_queue
)) {
538 * The frame queue is significantly larger than needed in practice,
539 * but no clear way to determine the minimum number of samples to
540 * get output from AudioConverterFillComplexBuffer().
542 av_log(avctx
, AV_LOG_ERROR
, "Bug: frame queue is too small.\n");
546 if ((ret
= ff_af_queue_add(&at
->afq
, frame
)) < 0)
549 in_frame
= av_frame_clone(frame
);
551 return AVERROR(ENOMEM
);
553 ff_bufqueue_add(avctx
, &at
->frame_queue
, in_frame
);
558 if ((ret
= ff_alloc_packet(avctx
, avpkt
, at
->pkt_size
)) < 0)
562 out_buffers
.mBuffers
[0].mData
= avpkt
->data
;
564 *got_packet_ptr
= avctx
->frame_size
/ at
->frame_size
;
566 ret
= AudioConverterFillComplexBuffer(at
->converter
, ffat_encode_callback
, avctx
,
567 got_packet_ptr
, &out_buffers
,
568 (avctx
->frame_size
> at
->frame_size
) ? NULL
: &out_pkt_desc
);
570 ff_bufqueue_discard_all(&at
->used_frame_queue
);
572 if ((!ret
|| ret
== 1) && *got_packet_ptr
) {
573 avpkt
->size
= out_buffers
.mBuffers
[0].mDataByteSize
;
574 ff_af_queue_remove(&at
->afq
, out_pkt_desc
.mVariableFramesInPacket
?
575 out_pkt_desc
.mVariableFramesInPacket
:
579 avpkt
->flags
|= AV_PKT_FLAG_KEY
;
580 } else if (ret
&& ret
!= 1) {
581 av_log(avctx
, AV_LOG_ERROR
, "Encode error: %i\n", ret
);
582 return AVERROR_EXTERNAL
;
588 static av_cold
void ffat_encode_flush(AVCodecContext
*avctx
)
590 ATDecodeContext
*at
= avctx
->priv_data
;
591 AudioConverterReset(at
->converter
);
592 ff_bufqueue_discard_all(&at
->frame_queue
);
593 ff_bufqueue_discard_all(&at
->used_frame_queue
);
596 static av_cold
int ffat_close_encoder(AVCodecContext
*avctx
)
598 ATDecodeContext
*at
= avctx
->priv_data
;
599 AudioConverterDispose(at
->converter
);
600 ff_bufqueue_discard_all(&at
->frame_queue
);
601 ff_bufqueue_discard_all(&at
->used_frame_queue
);
602 ff_af_queue_close(&at
->afq
);
603 av_frame_free(&at
->encoding_frame
);
607 static const AVProfile aac_profiles
[] = {
608 { AV_PROFILE_AAC_LOW
, "LC" },
609 { AV_PROFILE_AAC_HE
, "HE-AAC" },
610 { AV_PROFILE_AAC_HE_V2
, "HE-AACv2" },
611 { AV_PROFILE_AAC_LD
, "LD" },
612 { AV_PROFILE_AAC_ELD
, "ELD" },
613 { AV_PROFILE_UNKNOWN
},
616 #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
617 static const AVOption options
[] = {
618 #if !TARGET_OS_IPHONE
619 {"aac_at_mode", "ratecontrol mode", offsetof(ATDecodeContext
, mode
), AV_OPT_TYPE_INT
, {.i64
= -1}, -1, kAudioCodecBitRateControlMode_Variable
, AE
, .unit
= "mode"},
620 {"auto", "VBR if global quality is given; CBR otherwise", 0, AV_OPT_TYPE_CONST
, {.i64
= -1}, INT_MIN
, INT_MAX
, AE
, .unit
= "mode"},
621 {"cbr", "constant bitrate", 0, AV_OPT_TYPE_CONST
, {.i64
= kAudioCodecBitRateControlMode_Constant
}, INT_MIN
, INT_MAX
, AE
, .unit
= "mode"},
622 {"abr", "long-term average bitrate", 0, AV_OPT_TYPE_CONST
, {.i64
= kAudioCodecBitRateControlMode_LongTermAverage
}, INT_MIN
, INT_MAX
, AE
, .unit
= "mode"},
623 {"cvbr", "constrained variable bitrate", 0, AV_OPT_TYPE_CONST
, {.i64
= kAudioCodecBitRateControlMode_VariableConstrained
}, INT_MIN
, INT_MAX
, AE
, .unit
= "mode"},
624 {"vbr" , "variable bitrate", 0, AV_OPT_TYPE_CONST
, {.i64
= kAudioCodecBitRateControlMode_Variable
}, INT_MIN
, INT_MAX
, AE
, .unit
= "mode"},
626 {"aac_at_quality", "quality vs speed control", offsetof(ATDecodeContext
, quality
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, 2, AE
},
630 #define FFAT_ENC_CLASS(NAME) \
631 static const AVClass ffat_##NAME##_enc_class = { \
632 .class_name = "at_" #NAME "_enc", \
633 .item_name = av_default_item_name, \
635 .version = LIBAVUTIL_VERSION_INT, \
638 #define FFAT_ENC(NAME, ID, PROFILES, CAPS, CHANNEL_LAYOUTS, CH_LAYOUTS) \
639 FFAT_ENC_CLASS(NAME) \
640 const FFCodec ff_##NAME##_at_encoder = { \
641 .p.name = #NAME "_at", \
642 CODEC_LONG_NAME(#NAME " (AudioToolbox)"), \
643 .p.type = AVMEDIA_TYPE_AUDIO, \
645 .priv_data_size = sizeof(ATDecodeContext), \
646 .init = ffat_init_encoder, \
647 .close = ffat_close_encoder, \
648 FF_CODEC_ENCODE_CB(ffat_encode), \
649 .flush = ffat_encode_flush, \
650 .p.priv_class = &ffat_##NAME##_enc_class, \
651 .p.capabilities = AV_CODEC_CAP_DELAY | \
652 AV_CODEC_CAP_ENCODER_FLUSH CAPS, \
653 .p.ch_layouts = CH_LAYOUTS, \
654 .p.sample_fmts = (const enum AVSampleFormat[]) { \
656 AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NONE \
658 .p.profiles = PROFILES, \
659 .p.wrapper_name = "at", \
662 static const AVChannelLayout aac_at_ch_layouts
[] = {
663 AV_CHANNEL_LAYOUT_MONO
,
664 AV_CHANNEL_LAYOUT_STEREO
,
665 AV_CHANNEL_LAYOUT_SURROUND
,
666 AV_CHANNEL_LAYOUT_4POINT0
,
667 AV_CHANNEL_LAYOUT_5POINT0
,
668 AV_CHANNEL_LAYOUT_5POINT1
,
669 AV_CHANNEL_LAYOUT_6POINT0
,
670 AV_CHANNEL_LAYOUT_6POINT1
,
671 AV_CHANNEL_LAYOUT_7POINT0
,
672 AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK
,
673 AV_CHANNEL_LAYOUT_QUAD
,
674 AV_CHANNEL_LAYOUT_OCTAGONAL
,
678 FFAT_ENC(aac
, AV_CODEC_ID_AAC
, aac_profiles
, , aac_at_channel_layouts
, aac_at_ch_layouts
)
679 //FFAT_ENC(adpcm_ima_qt, AV_CODEC_ID_ADPCM_IMA_QT, NULL)
680 FFAT_ENC(alac
, AV_CODEC_ID_ALAC
, NULL
, , NULL
, NULL
)
681 FFAT_ENC(ilbc
, AV_CODEC_ID_ILBC
, NULL
, , NULL
, NULL
)
682 FFAT_ENC(pcm_alaw
, AV_CODEC_ID_PCM_ALAW
, NULL
, , NULL
, NULL
)
683 FFAT_ENC(pcm_mulaw
, AV_CODEC_ID_PCM_MULAW
, NULL
, , NULL
, NULL
)