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
41typedef 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
58static 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
91static 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
131static 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
145static 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
157static 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
182static 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
202static 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
231static 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
451static 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
494static 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
565static 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
573static 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
584static 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
594static 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
641static 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
658static 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
675FFAT_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)
677FFAT_ENC(alac,         AV_CODEC_ID_ALAC,         NULL, | AV_CODEC_CAP_VARIABLE_FRAME_SIZE, NULL, NULL)
678FFAT_ENC(ilbc,         AV_CODEC_ID_ILBC,         NULL, , NULL, NULL)
679FFAT_ENC(pcm_alaw,     AV_CODEC_ID_PCM_ALAW,     NULL, , NULL, NULL)
680FFAT_ENC(pcm_mulaw,    AV_CODEC_ID_PCM_MULAW,    NULL, , NULL, NULL)
681