1 /*
2 * Audio Toolbox system codecs
3 *
4 * copyright (c) 2016 rcombs
5 *
6 * This file is part of FFmpeg.
7 *
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.
12 *
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.
17 *
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
21 */
22
23 #include <AudioToolbox/AudioToolbox.h>
24
25 #define FF_BUFQUEUE_SIZE 256
26 #include "libavfilter/bufferqueue.h"
27
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/opt.h"
39 #include "libavutil/log.h"
40
41 typedef struct ATDecodeContext {
42 AVClass *av_class;
43 int mode;
44 int quality;
45
46 AudioConverterRef converter;
47 struct FFBufQueue frame_queue;
48 struct FFBufQueue used_frame_queue;
49
50 unsigned pkt_size;
51 AudioFrameQueue afq;
52 int eof;
53 int frame_size;
54
55 AVFrame* encoding_frame;
56 } ATDecodeContext;
57
ffat_get_format_id(enum AVCodecID codec,int profile)58 static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile)
59 {
60 switch (codec) {
61 case AV_CODEC_ID_AAC:
62 switch (profile) {
63 case FF_PROFILE_AAC_LOW:
64 default:
65 return kAudioFormatMPEG4AAC;
66 case FF_PROFILE_AAC_HE:
67 return kAudioFormatMPEG4AAC_HE;
68 case FF_PROFILE_AAC_HE_V2:
69 return kAudioFormatMPEG4AAC_HE_V2;
70 case FF_PROFILE_AAC_LD:
71 return kAudioFormatMPEG4AAC_LD;
72 case FF_PROFILE_AAC_ELD:
73 return kAudioFormatMPEG4AAC_ELD;
74 }
75 case AV_CODEC_ID_ADPCM_IMA_QT:
76 return kAudioFormatAppleIMA4;
77 case AV_CODEC_ID_ALAC:
78 return kAudioFormatAppleLossless;
79 case AV_CODEC_ID_ILBC:
80 return kAudioFormatiLBC;
81 case AV_CODEC_ID_PCM_ALAW:
82 return kAudioFormatALaw;
83 case AV_CODEC_ID_PCM_MULAW:
84 return kAudioFormatULaw;
85 default:
86 av_assert0(!"Invalid codec ID!");
87 return 0;
88 }
89 }
90
ffat_update_ctx(AVCodecContext * avctx)91 static void ffat_update_ctx(AVCodecContext *avctx)
92 {
93 ATDecodeContext *at = avctx->priv_data;
94 UInt32 size = sizeof(unsigned);
95 AudioConverterPrimeInfo prime_info;
96 AudioStreamBasicDescription out_format;
97
98 AudioConverterGetProperty(at->converter,
99 kAudioConverterPropertyMaximumOutputPacketSize,
100 &size, &at->pkt_size);
101
102 if (at->pkt_size <= 0)
103 at->pkt_size = 1024 * 50;
104
105 size = sizeof(prime_info);
106
107 if (!AudioConverterGetProperty(at->converter,
108 kAudioConverterPrimeInfo,
109 &size, &prime_info)) {
110 avctx->initial_padding = prime_info.leadingFrames;
111 }
112
113 size = sizeof(out_format);
114 if (!AudioConverterGetProperty(at->converter,
115 kAudioConverterCurrentOutputStreamDescription,
116 &size, &out_format)) {
117 if (out_format.mFramesPerPacket)
118 avctx->frame_size = out_format.mFramesPerPacket;
119 if (out_format.mBytesPerPacket && avctx->codec_id == AV_CODEC_ID_ILBC)
120 avctx->block_align = out_format.mBytesPerPacket;
121 }
122
123 at->frame_size = avctx->frame_size;
124 if (avctx->codec_id == AV_CODEC_ID_PCM_MULAW ||
125 avctx->codec_id == AV_CODEC_ID_PCM_ALAW) {
126 at->pkt_size *= 1024;
127 avctx->frame_size *= 1024;
128 }
129 }
130
read_descr(GetByteContext * gb,int * tag)131 static int read_descr(GetByteContext *gb, int *tag)
132 {
133 int len = 0;
134 int count = 4;
135 *tag = bytestream2_get_byte(gb);
136 while (count--) {
137 int c = bytestream2_get_byte(gb);
138 len = (len << 7) | (c & 0x7f);
139 if (!(c & 0x80))
140 break;
141 }
142 return len;
143 }
144
get_ilbc_mode(AVCodecContext * avctx)145 static int get_ilbc_mode(AVCodecContext *avctx)
146 {
147 if (avctx->block_align == 38)
148 return 20;
149 else if (avctx->block_align == 50)
150 return 30;
151 else if (avctx->bit_rate > 0)
152 return avctx->bit_rate <= 14000 ? 30 : 20;
153 else
154 return 30;
155 }
156
get_channel_label(int channel)157 static av_cold int get_channel_label(int channel)
158 {
159 uint64_t map = 1 << channel;
160 if (map <= AV_CH_LOW_FREQUENCY)
161 return channel + 1;
162 else if (map <= AV_CH_BACK_RIGHT)
163 return channel + 29;
164 else if (map <= AV_CH_BACK_CENTER)
165 return channel - 1;
166 else if (map <= AV_CH_SIDE_RIGHT)
167 return channel - 4;
168 else if (map <= AV_CH_TOP_BACK_RIGHT)
169 return channel + 1;
170 else if (map <= AV_CH_STEREO_RIGHT)
171 return -1;
172 else if (map <= AV_CH_WIDE_RIGHT)
173 return channel + 4;
174 else if (map <= AV_CH_SURROUND_DIRECT_RIGHT)
175 return channel - 23;
176 else if (map == AV_CH_LOW_FREQUENCY_2)
177 return kAudioChannelLabel_LFE2;
178 else
179 return -1;
180 }
181
remap_layout(AudioChannelLayout * layout,const AVChannelLayout * in_layout)182 static int remap_layout(AudioChannelLayout *layout, const AVChannelLayout *in_layout)
183 {
184 int i;
185 layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
186 layout->mNumberChannelDescriptions = in_layout->nb_channels;
187 for (i = 0; i < in_layout->nb_channels; i++) {
188 int c, label;
189
190 c = av_channel_layout_channel_from_index(in_layout, i);
191 if (c < 0 || c >= 64)
192 return AVERROR(EINVAL);
193 label = get_channel_label(c);
194 layout->mChannelDescriptions[i].mChannelLabel = label;
195 if (label < 0)
196 return AVERROR(EINVAL);
197 c++;
198 }
199 return 0;
200 }
201
get_aac_tag(const AVChannelLayout * in_layout)202 static int get_aac_tag(const AVChannelLayout *in_layout)
203 {
204 static const struct {
205 AVChannelLayout chl;
206 int tag;
207 } map[] = {
208 { AV_CHANNEL_LAYOUT_MONO, kAudioChannelLayoutTag_Mono },
209 { AV_CHANNEL_LAYOUT_STEREO, kAudioChannelLayoutTag_Stereo },
210 { AV_CHANNEL_LAYOUT_QUAD, kAudioChannelLayoutTag_AAC_Quadraphonic },
211 { AV_CHANNEL_LAYOUT_OCTAGONAL, kAudioChannelLayoutTag_AAC_Octagonal },
212 { AV_CHANNEL_LAYOUT_SURROUND, kAudioChannelLayoutTag_AAC_3_0 },
213 { AV_CHANNEL_LAYOUT_4POINT0, kAudioChannelLayoutTag_AAC_4_0 },
214 { AV_CHANNEL_LAYOUT_5POINT0, kAudioChannelLayoutTag_AAC_5_0 },
215 { AV_CHANNEL_LAYOUT_5POINT1, kAudioChannelLayoutTag_AAC_5_1 },
216 { AV_CHANNEL_LAYOUT_6POINT0, kAudioChannelLayoutTag_AAC_6_0 },
217 { AV_CHANNEL_LAYOUT_6POINT1, kAudioChannelLayoutTag_AAC_6_1 },
218 { AV_CHANNEL_LAYOUT_7POINT0, kAudioChannelLayoutTag_AAC_7_0 },
219 { AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK, kAudioChannelLayoutTag_AAC_7_1 },
220 { AV_CHANNEL_LAYOUT_7POINT1, kAudioChannelLayoutTag_MPEG_7_1_C },
221 };
222 int i;
223
224 for (i = 0; i < FF_ARRAY_ELEMS(map); i++)
225 if (!av_channel_layout_compare(in_layout, &map[i].chl))
226 return map[i].tag;
227
228 return 0;
229 }
230
ffat_init_encoder(AVCodecContext * avctx)231 static av_cold int ffat_init_encoder(AVCodecContext *avctx)
232 {
233 ATDecodeContext *at = avctx->priv_data;
234 OSStatus status;
235
236 AudioStreamBasicDescription in_format = {
237 .mSampleRate = avctx->sample_rate,
238 .mFormatID = kAudioFormatLinearPCM,
239 .mFormatFlags = ((avctx->sample_fmt == AV_SAMPLE_FMT_FLT ||
240 avctx->sample_fmt == AV_SAMPLE_FMT_DBL) ? kAudioFormatFlagIsFloat
241 : avctx->sample_fmt == AV_SAMPLE_FMT_U8 ? 0
242 : kAudioFormatFlagIsSignedInteger)
243 | kAudioFormatFlagIsPacked,
244 .mBytesPerPacket = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->ch_layout.nb_channels,
245 .mFramesPerPacket = 1,
246 .mBytesPerFrame = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->ch_layout.nb_channels,
247 .mChannelsPerFrame = avctx->ch_layout.nb_channels,
248 .mBitsPerChannel = av_get_bytes_per_sample(avctx->sample_fmt) * 8,
249 };
250 AudioStreamBasicDescription out_format = {
251 .mSampleRate = avctx->sample_rate,
252 .mFormatID = ffat_get_format_id(avctx->codec_id, avctx->profile),
253 .mChannelsPerFrame = in_format.mChannelsPerFrame,
254 };
255 UInt32 layout_size = sizeof(AudioChannelLayout) +
256 sizeof(AudioChannelDescription) * avctx->ch_layout.nb_channels;
257 AudioChannelLayout *channel_layout = av_malloc(layout_size);
258
259 if (!channel_layout)
260 return AVERROR(ENOMEM);
261
262 if (avctx->codec_id == AV_CODEC_ID_ILBC) {
263 int mode = get_ilbc_mode(avctx);
264 out_format.mFramesPerPacket = 8000 * mode / 1000;
265 out_format.mBytesPerPacket = (mode == 20 ? 38 : 50);
266 }
267
268 status = AudioConverterNew(&in_format, &out_format, &at->converter);
269
270 if (status != 0) {
271 av_log(avctx, AV_LOG_ERROR, "AudioToolbox init error: %i\n", (int)status);
272 av_free(channel_layout);
273 return AVERROR_UNKNOWN;
274 }
275
276 if (avctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
277 av_channel_layout_default(&avctx->ch_layout, avctx->ch_layout.nb_channels);
278
279 if ((status = remap_layout(channel_layout, &avctx->ch_layout)) < 0) {
280 av_log(avctx, AV_LOG_ERROR, "Invalid channel layout\n");
281 av_free(channel_layout);
282 return status;
283 }
284
285 if (AudioConverterSetProperty(at->converter, kAudioConverterInputChannelLayout,
286 layout_size, channel_layout)) {
287 av_log(avctx, AV_LOG_ERROR, "Unsupported input channel layout\n");
288 av_free(channel_layout);
289 return AVERROR(EINVAL);
290 }
291 if (avctx->codec_id == AV_CODEC_ID_AAC) {
292 int tag = get_aac_tag(&avctx->ch_layout);
293 if (tag) {
294 channel_layout->mChannelLayoutTag = tag;
295 channel_layout->mNumberChannelDescriptions = 0;
296 }
297 }
298 if (AudioConverterSetProperty(at->converter, kAudioConverterOutputChannelLayout,
299 layout_size, channel_layout)) {
300 av_log(avctx, AV_LOG_ERROR, "Unsupported output channel layout\n");
301 av_free(channel_layout);
302 return AVERROR(EINVAL);
303 }
304 av_free(channel_layout);
305
306 if (avctx->bits_per_raw_sample)
307 AudioConverterSetProperty(at->converter,
308 kAudioConverterPropertyBitDepthHint,
309 sizeof(avctx->bits_per_raw_sample),
310 &avctx->bits_per_raw_sample);
311
312 #if !TARGET_OS_IPHONE
313 if (at->mode == -1)
314 at->mode = (avctx->flags & AV_CODEC_FLAG_QSCALE) ?
315 kAudioCodecBitRateControlMode_Variable :
316 kAudioCodecBitRateControlMode_Constant;
317
318 AudioConverterSetProperty(at->converter, kAudioCodecPropertyBitRateControlMode,
319 sizeof(at->mode), &at->mode);
320
321 if (at->mode == kAudioCodecBitRateControlMode_Variable) {
322 int q = avctx->global_quality / FF_QP2LAMBDA;
323 if (q < 0 || q > 14) {
324 av_log(avctx, AV_LOG_WARNING,
325 "VBR quality %d out of range, should be 0-14\n", q);
326 q = av_clip(q, 0, 14);
327 }
328 q = 127 - q * 9;
329 AudioConverterSetProperty(at->converter, kAudioCodecPropertySoundQualityForVBR,
330 sizeof(q), &q);
331 } else
332 #endif
333 if (avctx->bit_rate > 0) {
334 UInt32 rate = avctx->bit_rate;
335 UInt32 size;
336 status = AudioConverterGetPropertyInfo(at->converter,
337 kAudioConverterApplicableEncodeBitRates,
338 &size, NULL);
339 if (!status && size) {
340 UInt32 new_rate = rate;
341 int count;
342 int i;
343 AudioValueRange *ranges = av_malloc(size);
344 if (!ranges)
345 return AVERROR(ENOMEM);
346 AudioConverterGetProperty(at->converter,
347 kAudioConverterApplicableEncodeBitRates,
348 &size, ranges);
349 count = size / sizeof(AudioValueRange);
350 for (i = 0; i < count; i++) {
351 AudioValueRange *range = &ranges[i];
352 if (rate >= range->mMinimum && rate <= range->mMaximum) {
353 new_rate = rate;
354 break;
355 } else if (rate > range->mMaximum) {
356 new_rate = range->mMaximum;
357 } else {
358 new_rate = range->mMinimum;
359 break;
360 }
361 }
362 if (new_rate != rate) {
363 av_log(avctx, AV_LOG_WARNING,
364 "Bitrate %u not allowed; changing to %u\n", rate, new_rate);
365 rate = new_rate;
366 }
367 av_free(ranges);
368 }
369 AudioConverterSetProperty(at->converter, kAudioConverterEncodeBitRate,
370 sizeof(rate), &rate);
371 }
372
373 at->quality = 96 - at->quality * 32;
374 AudioConverterSetProperty(at->converter, kAudioConverterCodecQuality,
375 sizeof(at->quality), &at->quality);
376
377 if (!AudioConverterGetPropertyInfo(at->converter, kAudioConverterCompressionMagicCookie,
378 &avctx->extradata_size, NULL) &&
379 avctx->extradata_size) {
380 int extradata_size = avctx->extradata_size;
381 uint8_t *extradata;
382 if (!(avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE)))
383 return AVERROR(ENOMEM);
384 if (avctx->codec_id == AV_CODEC_ID_ALAC) {
385 avctx->extradata_size = 0x24;
386 AV_WB32(avctx->extradata, 0x24);
387 AV_WB32(avctx->extradata + 4, MKBETAG('a','l','a','c'));
388 extradata = avctx->extradata + 12;
389 avctx->extradata_size = 0x24;
390 } else {
391 extradata = avctx->extradata;
392 }
393 status = AudioConverterGetProperty(at->converter,
394 kAudioConverterCompressionMagicCookie,
395 &extradata_size, extradata);
396 if (status != 0) {
397 av_log(avctx, AV_LOG_ERROR, "AudioToolbox cookie error: %i\n", (int)status);
398 return AVERROR_UNKNOWN;
399 } else if (avctx->codec_id == AV_CODEC_ID_AAC) {
400 GetByteContext gb;
401 int tag, len;
402 bytestream2_init(&gb, extradata, extradata_size);
403 do {
404 len = read_descr(&gb, &tag);
405 if (tag == MP4DecConfigDescrTag) {
406 bytestream2_skip(&gb, 13);
407 len = read_descr(&gb, &tag);
408 if (tag == MP4DecSpecificDescrTag) {
409 len = FFMIN(gb.buffer_end - gb.buffer, len);
410 memmove(extradata, gb.buffer, len);
411 avctx->extradata_size = len;
412 break;
413 }
414 } else if (tag == MP4ESDescrTag) {
415 int flags;
416 bytestream2_skip(&gb, 2);
417 flags = bytestream2_get_byte(&gb);
418 if (flags & 0x80) //streamDependenceFlag
419 bytestream2_skip(&gb, 2);
420 if (flags & 0x40) //URL_Flag
421 bytestream2_skip(&gb, bytestream2_get_byte(&gb));
422 if (flags & 0x20) //OCRstreamFlag
423 bytestream2_skip(&gb, 2);
424 }
425 } while (bytestream2_get_bytes_left(&gb));
426 } else if (avctx->codec_id != AV_CODEC_ID_ALAC) {
427 avctx->extradata_size = extradata_size;
428 }
429 }
430
431 ffat_update_ctx(avctx);
432
433 #if !TARGET_OS_IPHONE && defined(__MAC_10_9)
434 if (at->mode == kAudioCodecBitRateControlMode_Variable && avctx->rc_max_rate) {
435 UInt32 max_size = avctx->rc_max_rate * avctx->frame_size / avctx->sample_rate;
436 if (max_size)
437 AudioConverterSetProperty(at->converter, kAudioCodecPropertyPacketSizeLimitForVBR,
438 sizeof(max_size), &max_size);
439 }
440 #endif
441
442 ff_af_queue_init(avctx, &at->afq);
443
444 at->encoding_frame = av_frame_alloc();
445 if (!at->encoding_frame)
446 return AVERROR(ENOMEM);
447
448 return 0;
449 }
450
ffat_encode_callback(AudioConverterRef converter,UInt32 * nb_packets,AudioBufferList * data,AudioStreamPacketDescription ** packets,void * inctx)451 static OSStatus ffat_encode_callback(AudioConverterRef converter, UInt32 *nb_packets,
452 AudioBufferList *data,
453 AudioStreamPacketDescription **packets,
454 void *inctx)
455 {
456 AVCodecContext *avctx = inctx;
457 ATDecodeContext *at = avctx->priv_data;
458 AVFrame *frame;
459 int ret;
460
461 if (!at->frame_queue.available) {
462 if (at->eof) {
463 *nb_packets = 0;
464 return 0;
465 } else {
466 *nb_packets = 0;
467 return 1;
468 }
469 }
470
471 frame = ff_bufqueue_get(&at->frame_queue);
472
473 data->mNumberBuffers = 1;
474 data->mBuffers[0].mNumberChannels = avctx->ch_layout.nb_channels;
475 data->mBuffers[0].mDataByteSize = frame->nb_samples *
476 av_get_bytes_per_sample(avctx->sample_fmt) *
477 avctx->ch_layout.nb_channels;
478 data->mBuffers[0].mData = frame->data[0];
479 if (*nb_packets > frame->nb_samples)
480 *nb_packets = frame->nb_samples;
481
482 av_frame_unref(at->encoding_frame);
483 ret = av_frame_ref(at->encoding_frame, frame);
484 if (ret < 0) {
485 *nb_packets = 0;
486 return ret;
487 }
488
489 ff_bufqueue_add(avctx, &at->used_frame_queue, frame);
490
491 return 0;
492 }
493
ffat_encode(AVCodecContext * avctx,AVPacket * avpkt,const AVFrame * frame,int * got_packet_ptr)494 static int ffat_encode(AVCodecContext *avctx, AVPacket *avpkt,
495 const AVFrame *frame, int *got_packet_ptr)
496 {
497 ATDecodeContext *at = avctx->priv_data;
498 OSStatus ret;
499
500 AudioBufferList out_buffers = {
501 .mNumberBuffers = 1,
502 .mBuffers = {
503 {
504 .mNumberChannels = avctx->ch_layout.nb_channels,
505 .mDataByteSize = at->pkt_size,
506 }
507 }
508 };
509 AudioStreamPacketDescription out_pkt_desc = {0};
510
511 if (frame) {
512 AVFrame *in_frame;
513
514 if (ff_bufqueue_is_full(&at->frame_queue)) {
515 /*
516 * The frame queue is significantly larger than needed in practice,
517 * but no clear way to determine the minimum number of samples to
518 * get output from AudioConverterFillComplexBuffer().
519 */
520 av_log(avctx, AV_LOG_ERROR, "Bug: frame queue is too small.\n");
521 return AVERROR_BUG;
522 }
523
524 if ((ret = ff_af_queue_add(&at->afq, frame)) < 0)
525 return ret;
526
527 in_frame = av_frame_clone(frame);
528 if (!in_frame)
529 return AVERROR(ENOMEM);
530
531 ff_bufqueue_add(avctx, &at->frame_queue, in_frame);
532 } else {
533 at->eof = 1;
534 }
535
536 if ((ret = ff_alloc_packet(avctx, avpkt, at->pkt_size)) < 0)
537 return ret;
538
539
540 out_buffers.mBuffers[0].mData = avpkt->data;
541
542 *got_packet_ptr = avctx->frame_size / at->frame_size;
543
544 ret = AudioConverterFillComplexBuffer(at->converter, ffat_encode_callback, avctx,
545 got_packet_ptr, &out_buffers,
546 (avctx->frame_size > at->frame_size) ? NULL : &out_pkt_desc);
547
548 ff_bufqueue_discard_all(&at->used_frame_queue);
549
550 if ((!ret || ret == 1) && *got_packet_ptr) {
551 avpkt->size = out_buffers.mBuffers[0].mDataByteSize;
552 ff_af_queue_remove(&at->afq, out_pkt_desc.mVariableFramesInPacket ?
553 out_pkt_desc.mVariableFramesInPacket :
554 avctx->frame_size,
555 &avpkt->pts,
556 &avpkt->duration);
557 } else if (ret && ret != 1) {
558 av_log(avctx, AV_LOG_ERROR, "Encode error: %i\n", ret);
559 return AVERROR_EXTERNAL;
560 }
561
562 return 0;
563 }
564
ffat_encode_flush(AVCodecContext * avctx)565 static av_cold void ffat_encode_flush(AVCodecContext *avctx)
566 {
567 ATDecodeContext *at = avctx->priv_data;
568 AudioConverterReset(at->converter);
569 ff_bufqueue_discard_all(&at->frame_queue);
570 ff_bufqueue_discard_all(&at->used_frame_queue);
571 }
572
ffat_close_encoder(AVCodecContext * avctx)573 static av_cold int ffat_close_encoder(AVCodecContext *avctx)
574 {
575 ATDecodeContext *at = avctx->priv_data;
576 AudioConverterDispose(at->converter);
577 ff_bufqueue_discard_all(&at->frame_queue);
578 ff_bufqueue_discard_all(&at->used_frame_queue);
579 ff_af_queue_close(&at->afq);
580 av_frame_free(&at->encoding_frame);
581 return 0;
582 }
583
584 static const AVProfile aac_profiles[] = {
585 { FF_PROFILE_AAC_LOW, "LC" },
586 { FF_PROFILE_AAC_HE, "HE-AAC" },
587 { FF_PROFILE_AAC_HE_V2, "HE-AACv2" },
588 { FF_PROFILE_AAC_LD, "LD" },
589 { FF_PROFILE_AAC_ELD, "ELD" },
590 { FF_PROFILE_UNKNOWN },
591 };
592
593 #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
594 static const AVOption options[] = {
595 #if !TARGET_OS_IPHONE
596 {"aac_at_mode", "ratecontrol mode", offsetof(ATDecodeContext, mode), AV_OPT_TYPE_INT, {.i64 = -1}, -1, kAudioCodecBitRateControlMode_Variable, AE, "mode"},
597 {"auto", "VBR if global quality is given; CBR otherwise", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, INT_MIN, INT_MAX, AE, "mode"},
598 {"cbr", "constant bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_Constant}, INT_MIN, INT_MAX, AE, "mode"},
599 {"abr", "long-term average bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_LongTermAverage}, INT_MIN, INT_MAX, AE, "mode"},
600 {"cvbr", "constrained variable bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_VariableConstrained}, INT_MIN, INT_MAX, AE, "mode"},
601 {"vbr" , "variable bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_Variable}, INT_MIN, INT_MAX, AE, "mode"},
602 #endif
603 {"aac_at_quality", "quality vs speed control", offsetof(ATDecodeContext, quality), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 2, AE},
604 { NULL },
605 };
606
607 #define FFAT_ENC_CLASS(NAME) \
608 static const AVClass ffat_##NAME##_enc_class = { \
609 .class_name = "at_" #NAME "_enc", \
610 .item_name = av_default_item_name, \
611 .option = options, \
612 .version = LIBAVUTIL_VERSION_INT, \
613 };
614
615 #define FFAT_ENC(NAME, ID, PROFILES, CAPS, CHANNEL_LAYOUTS, CH_LAYOUTS) \
616 FFAT_ENC_CLASS(NAME) \
617 const FFCodec ff_##NAME##_at_encoder = { \
618 .p.name = #NAME "_at", \
619 .p.long_name = NULL_IF_CONFIG_SMALL(#NAME " (AudioToolbox)"), \
620 .p.type = AVMEDIA_TYPE_AUDIO, \
621 .p.id = ID, \
622 .priv_data_size = sizeof(ATDecodeContext), \
623 .init = ffat_init_encoder, \
624 .close = ffat_close_encoder, \
625 FF_CODEC_ENCODE_CB(ffat_encode), \
626 .flush = ffat_encode_flush, \
627 .p.priv_class = &ffat_##NAME##_enc_class, \
628 .p.capabilities = AV_CODEC_CAP_DELAY | \
629 AV_CODEC_CAP_ENCODER_FLUSH CAPS, \
630 .p.channel_layouts = CHANNEL_LAYOUTS, \
631 .p.ch_layouts = CH_LAYOUTS, \
632 .p.sample_fmts = (const enum AVSampleFormat[]) { \
633 AV_SAMPLE_FMT_S16, \
634 AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NONE \
635 }, \
636 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \
637 .p.profiles = PROFILES, \
638 .p.wrapper_name = "at", \
639 };
640
641 static const AVChannelLayout aac_at_ch_layouts[] = {
642 AV_CHANNEL_LAYOUT_MONO,
643 AV_CHANNEL_LAYOUT_STEREO,
644 AV_CHANNEL_LAYOUT_SURROUND,
645 AV_CHANNEL_LAYOUT_4POINT0,
646 AV_CHANNEL_LAYOUT_5POINT0,
647 AV_CHANNEL_LAYOUT_5POINT1,
648 AV_CHANNEL_LAYOUT_6POINT0,
649 AV_CHANNEL_LAYOUT_6POINT1,
650 AV_CHANNEL_LAYOUT_7POINT0,
651 AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK,
652 AV_CHANNEL_LAYOUT_QUAD,
653 AV_CHANNEL_LAYOUT_OCTAGONAL,
654 { 0 },
655 };
656
657 #if FF_API_OLD_CHANNEL_LAYOUT
658 static const uint64_t aac_at_channel_layouts[] = {
659 AV_CH_LAYOUT_MONO,
660 AV_CH_LAYOUT_STEREO,
661 AV_CH_LAYOUT_SURROUND,
662 AV_CH_LAYOUT_4POINT0,
663 AV_CH_LAYOUT_5POINT0,
664 AV_CH_LAYOUT_5POINT1,
665 AV_CH_LAYOUT_6POINT0,
666 AV_CH_LAYOUT_6POINT1,
667 AV_CH_LAYOUT_7POINT0,
668 AV_CH_LAYOUT_7POINT1_WIDE_BACK,
669 AV_CH_LAYOUT_QUAD,
670 AV_CH_LAYOUT_OCTAGONAL,
671 0,
672 };
673 #endif
674
675 FFAT_ENC(aac, AV_CODEC_ID_AAC, aac_profiles, , aac_at_channel_layouts, aac_at_ch_layouts)
676 //FFAT_ENC(adpcm_ima_qt, AV_CODEC_ID_ADPCM_IMA_QT, NULL)
677 FFAT_ENC(alac, AV_CODEC_ID_ALAC, NULL, | AV_CODEC_CAP_VARIABLE_FRAME_SIZE, NULL, NULL)
678 FFAT_ENC(ilbc, AV_CODEC_ID_ILBC, NULL, , NULL, NULL)
679 FFAT_ENC(pcm_alaw, AV_CODEC_ID_PCM_ALAW, NULL, , NULL, NULL)
680 FFAT_ENC(pcm_mulaw, AV_CODEC_ID_PCM_MULAW, NULL, , NULL, NULL)
681