avformat/mpeg: demux ivtv captions
[ffmpeg.git] / libavcodec / audiotoolboxenc.c
blob908b56055f6a19aa89635e426008612a00cbd5b2
1 /*
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"
28 #include "config.h"
29 #include "audio_frame_queue.h"
30 #include "avcodec.h"
31 #include "bytestream.h"
32 #include "codec_internal.h"
33 #include "encode.h"
34 #include "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 {
43 AVClass *av_class;
44 int mode;
45 int quality;
47 AudioConverterRef converter;
48 struct FFBufQueue frame_queue;
49 struct FFBufQueue used_frame_queue;
51 unsigned pkt_size;
52 AudioFrameQueue afq;
53 int eof;
54 int frame_size;
56 AVFrame* encoding_frame;
57 } ATDecodeContext;
59 static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile)
61 switch (codec) {
62 case AV_CODEC_ID_AAC:
63 switch (profile) {
64 case AV_PROFILE_AAC_LOW:
65 default:
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;
76 #endif
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;
85 #endif
86 case AV_CODEC_ID_PCM_ALAW:
87 return kAudioFormatALaw;
88 case AV_CODEC_ID_PCM_MULAW:
89 return kAudioFormatULaw;
90 default:
91 av_assert0(!"Invalid codec ID!");
92 return 0;
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;
124 } else {
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;
136 } else {
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;
148 return 0;
151 static int read_descr(GetByteContext *gb, int *tag)
153 int len = 0;
154 int count = 4;
155 *tag = bytestream2_get_byte(gb);
156 while (count--) {
157 int c = bytestream2_get_byte(gb);
158 len = (len << 7) | (c & 0x7f);
159 if (!(c & 0x80))
160 break;
162 return len;
165 static int get_ilbc_mode(AVCodecContext *avctx)
167 if (avctx->block_align == 38)
168 return 20;
169 else if (avctx->block_align == 50)
170 return 30;
171 else if (avctx->bit_rate > 0)
172 return avctx->bit_rate <= 14000 ? 30 : 20;
173 else
174 return 30;
177 static av_cold int get_channel_label(int channel)
179 uint64_t map = 1 << channel;
180 if (map <= AV_CH_LOW_FREQUENCY)
181 return channel + 1;
182 else if (map <= AV_CH_BACK_RIGHT)
183 return channel + 29;
184 else if (map <= AV_CH_BACK_CENTER)
185 return channel - 1;
186 else if (map <= AV_CH_SIDE_RIGHT)
187 return channel - 4;
188 else if (map <= AV_CH_TOP_BACK_RIGHT)
189 return channel + 1;
190 else if (map <= AV_CH_STEREO_RIGHT)
191 return -1;
192 else if (map <= AV_CH_WIDE_RIGHT)
193 return channel + 4;
194 else if (map <= AV_CH_SURROUND_DIRECT_RIGHT)
195 return channel - 23;
196 else if (map == AV_CH_LOW_FREQUENCY_2)
197 return kAudioChannelLabel_LFE2;
198 else
199 return -1;
202 static int remap_layout(AudioChannelLayout *layout, const AVChannelLayout *in_layout)
204 int i;
205 layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
206 layout->mNumberChannelDescriptions = in_layout->nb_channels;
207 for (i = 0; i < in_layout->nb_channels; i++) {
208 int c, label;
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;
215 if (label < 0)
216 return AVERROR(EINVAL);
217 c++;
219 return 0;
222 static int get_aac_tag(const AVChannelLayout *in_layout)
224 static const struct {
225 AVChannelLayout chl;
226 int tag;
227 } map[] = {
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 },
242 int i;
244 for (i = 0; i < FF_ARRAY_ELEMS(map); i++)
245 if (!av_channel_layout_compare(in_layout, &map[i].chl))
246 return map[i].tag;
248 return 0;
251 static av_cold int ffat_init_encoder(AVCodecContext *avctx)
253 ATDecodeContext *at = avctx->priv_data;
254 OSStatus status;
255 int ret;
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);
280 if (!channel_layout)
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);
291 if (status != 0) {
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);
303 return status;
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);
314 if (tag) {
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
334 if (at->mode == -1)
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);
349 q = 127 - q * 9;
350 AudioConverterSetProperty(at->converter, kAudioCodecPropertySoundQualityForVBR,
351 sizeof(q), &q);
352 } else
353 #endif
354 if (avctx->bit_rate > 0) {
355 UInt32 rate = avctx->bit_rate;
356 UInt32 size;
357 status = AudioConverterGetPropertyInfo(at->converter,
358 kAudioConverterApplicableEncodeBitRates,
359 &size, NULL);
360 if (!status && size) {
361 UInt32 new_rate = rate;
362 int count;
363 int i;
364 AudioValueRange *ranges = av_malloc(size);
365 if (!ranges)
366 return AVERROR(ENOMEM);
367 AudioConverterGetProperty(at->converter,
368 kAudioConverterApplicableEncodeBitRates,
369 &size, ranges);
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) {
374 new_rate = rate;
375 break;
376 } else if (rate > range->mMaximum) {
377 new_rate = range->mMaximum;
378 } else {
379 new_rate = range->mMinimum;
380 break;
383 if (new_rate != rate) {
384 av_log(avctx, AV_LOG_WARNING,
385 "Bitrate %u not allowed; changing to %u\n", rate, new_rate);
386 rate = new_rate;
388 av_free(ranges);
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;
402 uint8_t *extradata;
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;
411 } else {
412 extradata = avctx->extradata;
414 status = AudioConverterGetProperty(at->converter,
415 kAudioConverterCompressionMagicCookie,
416 &extradata_size, extradata);
417 if (status != 0) {
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) {
421 GetByteContext gb;
422 int tag, len;
423 bytestream2_init(&gb, extradata, extradata_size);
424 do {
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;
433 break;
435 } else if (tag == MP4ESDescrTag) {
436 int flags;
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);
453 if (ret < 0)
454 return ret;
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;
459 if (max_size)
460 AudioConverterSetProperty(at->converter, kAudioCodecPropertyPacketSizeLimitForVBR,
461 sizeof(max_size), &max_size);
463 #endif
465 ff_af_queue_init(avctx, &at->afq);
467 at->encoding_frame = av_frame_alloc();
468 if (!at->encoding_frame)
469 return AVERROR(ENOMEM);
471 return 0;
474 static OSStatus ffat_encode_callback(AudioConverterRef converter, UInt32 *nb_packets,
475 AudioBufferList *data,
476 AudioStreamPacketDescription **packets,
477 void *inctx)
479 AVCodecContext *avctx = inctx;
480 ATDecodeContext *at = avctx->priv_data;
481 AVFrame *frame;
482 int ret;
484 if (!at->frame_queue.available) {
485 if (at->eof) {
486 *nb_packets = 0;
487 return 0;
488 } else {
489 *nb_packets = 0;
490 return 1;
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);
506 if (ret < 0) {
507 *nb_packets = 0;
508 return ret;
511 ff_bufqueue_add(avctx, &at->used_frame_queue, frame);
513 return 0;
516 static int ffat_encode(AVCodecContext *avctx, AVPacket *avpkt,
517 const AVFrame *frame, int *got_packet_ptr)
519 ATDecodeContext *at = avctx->priv_data;
520 OSStatus ret;
522 AudioBufferList out_buffers = {
523 .mNumberBuffers = 1,
524 .mBuffers = {
526 .mNumberChannels = avctx->ch_layout.nb_channels,
527 .mDataByteSize = at->pkt_size,
531 AudioStreamPacketDescription out_pkt_desc = {0};
533 if (frame) {
534 AVFrame *in_frame;
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");
543 return AVERROR_BUG;
546 if ((ret = ff_af_queue_add(&at->afq, frame)) < 0)
547 return ret;
549 in_frame = av_frame_clone(frame);
550 if (!in_frame)
551 return AVERROR(ENOMEM);
553 ff_bufqueue_add(avctx, &at->frame_queue, in_frame);
554 } else {
555 at->eof = 1;
558 if ((ret = ff_alloc_packet(avctx, avpkt, at->pkt_size)) < 0)
559 return ret;
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 :
576 avctx->frame_size,
577 &avpkt->pts,
578 &avpkt->duration);
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;
585 return 0;
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);
604 return 0;
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"},
625 #endif
626 {"aac_at_quality", "quality vs speed control", offsetof(ATDecodeContext, quality), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 2, AE},
627 { NULL },
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, \
634 .option = options, \
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, \
644 .p.id = ID, \
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[]) { \
655 AV_SAMPLE_FMT_S16, \
656 AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NONE \
657 }, \
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,
675 { 0 },
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)