blob: 9245aa9dc41b9a15953749975347492b5933641e [file] [log] [blame]
Rodger Combs65cff812016-02-24 03:01:241/*
2 * Audio Toolbox system codecs
3 *
rcombseabf5e62021-01-20 07:02:564 * copyright (c) 2016 rcombs
Rodger Combs65cff812016-02-24 03:01:245 *
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
Rick Kern143685a2016-06-02 06:25:2125#define FF_BUFQUEUE_SIZE 256
26#include "libavfilter/bufferqueue.h"
27
Rodger Combs65cff812016-02-24 03:01:2428#include "config.h"
29#include "audio_frame_queue.h"
30#include "avcodec.h"
31#include "bytestream.h"
Andreas Rheinhardt56e9e022021-05-11 13:17:1332#include "encode.h"
Rodger Combs65cff812016-02-24 03:01:2433#include "internal.h"
34#include "libavformat/isom.h"
35#include "libavutil/avassert.h"
Andreas Rheinhardt1be3d8a2021-06-11 23:10:5836#include "libavutil/channel_layout.h"
Rodger Combs65cff812016-02-24 03:01:2437#include "libavutil/opt.h"
38#include "libavutil/log.h"
39
40typedef struct ATDecodeContext {
41 AVClass *av_class;
42 int mode;
43 int quality;
44
45 AudioConverterRef converter;
Rick Kern143685a2016-06-02 06:25:2146 struct FFBufQueue frame_queue;
47 struct FFBufQueue used_frame_queue;
Rodger Combs65cff812016-02-24 03:01:2448
49 unsigned pkt_size;
50 AudioFrameQueue afq;
51 int eof;
52 int frame_size;
Jiejun Zhang677701c2018-01-03 04:54:2053
54 AVFrame* encoding_frame;
Rodger Combs65cff812016-02-24 03:01:2455} ATDecodeContext;
56
57static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile)
58{
59 switch (codec) {
60 case AV_CODEC_ID_AAC:
61 switch (profile) {
62 case FF_PROFILE_AAC_LOW:
63 default:
64 return kAudioFormatMPEG4AAC;
65 case FF_PROFILE_AAC_HE:
66 return kAudioFormatMPEG4AAC_HE;
67 case FF_PROFILE_AAC_HE_V2:
68 return kAudioFormatMPEG4AAC_HE_V2;
69 case FF_PROFILE_AAC_LD:
70 return kAudioFormatMPEG4AAC_LD;
71 case FF_PROFILE_AAC_ELD:
72 return kAudioFormatMPEG4AAC_ELD;
73 }
74 case AV_CODEC_ID_ADPCM_IMA_QT:
75 return kAudioFormatAppleIMA4;
76 case AV_CODEC_ID_ALAC:
77 return kAudioFormatAppleLossless;
78 case AV_CODEC_ID_ILBC:
79 return kAudioFormatiLBC;
80 case AV_CODEC_ID_PCM_ALAW:
81 return kAudioFormatALaw;
82 case AV_CODEC_ID_PCM_MULAW:
83 return kAudioFormatULaw;
84 default:
85 av_assert0(!"Invalid codec ID!");
86 return 0;
87 }
88}
89
90static void ffat_update_ctx(AVCodecContext *avctx)
91{
92 ATDecodeContext *at = avctx->priv_data;
93 UInt32 size = sizeof(unsigned);
94 AudioConverterPrimeInfo prime_info;
95 AudioStreamBasicDescription out_format;
96
97 AudioConverterGetProperty(at->converter,
98 kAudioConverterPropertyMaximumOutputPacketSize,
99 &size, &at->pkt_size);
100
101 if (at->pkt_size <= 0)
102 at->pkt_size = 1024 * 50;
103
104 size = sizeof(prime_info);
105
106 if (!AudioConverterGetProperty(at->converter,
107 kAudioConverterPrimeInfo,
108 &size, &prime_info)) {
109 avctx->initial_padding = prime_info.leadingFrames;
110 }
111
112 size = sizeof(out_format);
113 if (!AudioConverterGetProperty(at->converter,
114 kAudioConverterCurrentOutputStreamDescription,
115 &size, &out_format)) {
116 if (out_format.mFramesPerPacket)
117 avctx->frame_size = out_format.mFramesPerPacket;
118 if (out_format.mBytesPerPacket && avctx->codec_id == AV_CODEC_ID_ILBC)
119 avctx->block_align = out_format.mBytesPerPacket;
120 }
121
122 at->frame_size = avctx->frame_size;
123 if (avctx->codec_id == AV_CODEC_ID_PCM_MULAW ||
124 avctx->codec_id == AV_CODEC_ID_PCM_ALAW) {
125 at->pkt_size *= 1024;
126 avctx->frame_size *= 1024;
127 }
128}
129
130static int read_descr(GetByteContext *gb, int *tag)
131{
132 int len = 0;
133 int count = 4;
134 *tag = bytestream2_get_byte(gb);
135 while (count--) {
136 int c = bytestream2_get_byte(gb);
137 len = (len << 7) | (c & 0x7f);
138 if (!(c & 0x80))
139 break;
140 }
141 return len;
142}
143
144static int get_ilbc_mode(AVCodecContext *avctx)
145{
146 if (avctx->block_align == 38)
147 return 20;
148 else if (avctx->block_align == 50)
149 return 30;
150 else if (avctx->bit_rate > 0)
151 return avctx->bit_rate <= 14000 ? 30 : 20;
152 else
153 return 30;
154}
155
Rodger Combsc820e602016-03-23 21:46:39156static av_cold int get_channel_label(int channel)
157{
158 uint64_t map = 1 << channel;
159 if (map <= AV_CH_LOW_FREQUENCY)
160 return channel + 1;
161 else if (map <= AV_CH_BACK_RIGHT)
162 return channel + 29;
163 else if (map <= AV_CH_BACK_CENTER)
164 return channel - 1;
165 else if (map <= AV_CH_SIDE_RIGHT)
166 return channel - 4;
167 else if (map <= AV_CH_TOP_BACK_RIGHT)
168 return channel + 1;
169 else if (map <= AV_CH_STEREO_RIGHT)
170 return -1;
171 else if (map <= AV_CH_WIDE_RIGHT)
172 return channel + 4;
173 else if (map <= AV_CH_SURROUND_DIRECT_RIGHT)
174 return channel - 23;
175 else if (map == AV_CH_LOW_FREQUENCY_2)
176 return kAudioChannelLabel_LFE2;
177 else
178 return -1;
179}
180
181static int remap_layout(AudioChannelLayout *layout, uint64_t in_layout, int count)
182{
183 int i;
184 int c = 0;
185 layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
186 layout->mNumberChannelDescriptions = count;
187 for (i = 0; i < count; i++) {
188 int label;
189 while (!(in_layout & (1 << c)) && c < 64)
190 c++;
191 if (c == 64)
192 return AVERROR(EINVAL); // This should never happen
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(uint64_t in_layout)
203{
204 switch (in_layout) {
205 case AV_CH_LAYOUT_MONO:
206 return kAudioChannelLayoutTag_Mono;
207 case AV_CH_LAYOUT_STEREO:
208 return kAudioChannelLayoutTag_Stereo;
209 case AV_CH_LAYOUT_QUAD:
210 return kAudioChannelLayoutTag_AAC_Quadraphonic;
211 case AV_CH_LAYOUT_OCTAGONAL:
212 return kAudioChannelLayoutTag_AAC_Octagonal;
213 case AV_CH_LAYOUT_SURROUND:
214 return kAudioChannelLayoutTag_AAC_3_0;
215 case AV_CH_LAYOUT_4POINT0:
216 return kAudioChannelLayoutTag_AAC_4_0;
217 case AV_CH_LAYOUT_5POINT0:
218 return kAudioChannelLayoutTag_AAC_5_0;
219 case AV_CH_LAYOUT_5POINT1:
220 return kAudioChannelLayoutTag_AAC_5_1;
221 case AV_CH_LAYOUT_6POINT0:
222 return kAudioChannelLayoutTag_AAC_6_0;
223 case AV_CH_LAYOUT_6POINT1:
224 return kAudioChannelLayoutTag_AAC_6_1;
225 case AV_CH_LAYOUT_7POINT0:
226 return kAudioChannelLayoutTag_AAC_7_0;
227 case AV_CH_LAYOUT_7POINT1_WIDE_BACK:
228 return kAudioChannelLayoutTag_AAC_7_1;
229 case AV_CH_LAYOUT_7POINT1:
230 return kAudioChannelLayoutTag_MPEG_7_1_C;
231 default:
232 return 0;
233 }
234}
235
Rodger Combs65cff812016-02-24 03:01:24236static av_cold int ffat_init_encoder(AVCodecContext *avctx)
237{
238 ATDecodeContext *at = avctx->priv_data;
239 OSStatus status;
240
241 AudioStreamBasicDescription in_format = {
242 .mSampleRate = avctx->sample_rate,
243 .mFormatID = kAudioFormatLinearPCM,
244 .mFormatFlags = ((avctx->sample_fmt == AV_SAMPLE_FMT_FLT ||
245 avctx->sample_fmt == AV_SAMPLE_FMT_DBL) ? kAudioFormatFlagIsFloat
246 : avctx->sample_fmt == AV_SAMPLE_FMT_U8 ? 0
247 : kAudioFormatFlagIsSignedInteger)
248 | kAudioFormatFlagIsPacked,
249 .mBytesPerPacket = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->channels,
250 .mFramesPerPacket = 1,
251 .mBytesPerFrame = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->channels,
252 .mChannelsPerFrame = avctx->channels,
253 .mBitsPerChannel = av_get_bytes_per_sample(avctx->sample_fmt) * 8,
254 };
255 AudioStreamBasicDescription out_format = {
256 .mSampleRate = avctx->sample_rate,
257 .mFormatID = ffat_get_format_id(avctx->codec_id, avctx->profile),
258 .mChannelsPerFrame = in_format.mChannelsPerFrame,
259 };
Rodger Combsc820e602016-03-23 21:46:39260 UInt32 layout_size = sizeof(AudioChannelLayout) +
261 sizeof(AudioChannelDescription) * avctx->channels;
262 AudioChannelLayout *channel_layout = av_malloc(layout_size);
263
264 if (!channel_layout)
265 return AVERROR(ENOMEM);
Rodger Combs65cff812016-02-24 03:01:24266
267 if (avctx->codec_id == AV_CODEC_ID_ILBC) {
268 int mode = get_ilbc_mode(avctx);
269 out_format.mFramesPerPacket = 8000 * mode / 1000;
270 out_format.mBytesPerPacket = (mode == 20 ? 38 : 50);
271 }
272
273 status = AudioConverterNew(&in_format, &out_format, &at->converter);
274
275 if (status != 0) {
276 av_log(avctx, AV_LOG_ERROR, "AudioToolbox init error: %i\n", (int)status);
Rodger Combsc820e602016-03-23 21:46:39277 av_free(channel_layout);
Rodger Combs65cff812016-02-24 03:01:24278 return AVERROR_UNKNOWN;
279 }
280
Rodger Combsc820e602016-03-23 21:46:39281 if (!avctx->channel_layout)
282 avctx->channel_layout = av_get_default_channel_layout(avctx->channels);
Rodger Combs65cff812016-02-24 03:01:24283
Rodger Combsc820e602016-03-23 21:46:39284 if ((status = remap_layout(channel_layout, avctx->channel_layout, avctx->channels)) < 0) {
285 av_log(avctx, AV_LOG_ERROR, "Invalid channel layout\n");
286 av_free(channel_layout);
287 return status;
288 }
Rodger Combs65cff812016-02-24 03:01:24289
Rodger Combsc820e602016-03-23 21:46:39290 if (AudioConverterSetProperty(at->converter, kAudioConverterInputChannelLayout,
291 layout_size, channel_layout)) {
292 av_log(avctx, AV_LOG_ERROR, "Unsupported input channel layout\n");
293 av_free(channel_layout);
294 return AVERROR(EINVAL);
295 }
296 if (avctx->codec_id == AV_CODEC_ID_AAC) {
297 int tag = get_aac_tag(avctx->channel_layout);
298 if (tag) {
299 channel_layout->mChannelLayoutTag = tag;
300 channel_layout->mNumberChannelDescriptions = 0;
301 }
302 }
303 if (AudioConverterSetProperty(at->converter, kAudioConverterOutputChannelLayout,
304 layout_size, channel_layout)) {
305 av_log(avctx, AV_LOG_ERROR, "Unsupported output channel layout\n");
306 av_free(channel_layout);
307 return AVERROR(EINVAL);
308 }
309 av_free(channel_layout);
310
311 if (avctx->bits_per_raw_sample)
Rodger Combs65cff812016-02-24 03:01:24312 AudioConverterSetProperty(at->converter,
313 kAudioConverterPropertyBitDepthHint,
Rodger Combsc820e602016-03-23 21:46:39314 sizeof(avctx->bits_per_raw_sample),
315 &avctx->bits_per_raw_sample);
Rodger Combs65cff812016-02-24 03:01:24316
Rodger Combs06673272016-03-24 15:17:42317#if !TARGET_OS_IPHONE
Rodger Combs65cff812016-02-24 03:01:24318 if (at->mode == -1)
319 at->mode = (avctx->flags & AV_CODEC_FLAG_QSCALE) ?
320 kAudioCodecBitRateControlMode_Variable :
321 kAudioCodecBitRateControlMode_Constant;
322
323 AudioConverterSetProperty(at->converter, kAudioCodecPropertyBitRateControlMode,
Rodger Combsc820e602016-03-23 21:46:39324 sizeof(at->mode), &at->mode);
Rodger Combs65cff812016-02-24 03:01:24325
326 if (at->mode == kAudioCodecBitRateControlMode_Variable) {
327 int q = avctx->global_quality / FF_QP2LAMBDA;
328 if (q < 0 || q > 14) {
329 av_log(avctx, AV_LOG_WARNING,
330 "VBR quality %d out of range, should be 0-14\n", q);
331 q = av_clip(q, 0, 14);
332 }
333 q = 127 - q * 9;
334 AudioConverterSetProperty(at->converter, kAudioCodecPropertySoundQualityForVBR,
Rodger Combsc820e602016-03-23 21:46:39335 sizeof(q), &q);
Rodger Combs06673272016-03-24 15:17:42336 } else
337#endif
338 if (avctx->bit_rate > 0) {
Rodger Combs65cff812016-02-24 03:01:24339 UInt32 rate = avctx->bit_rate;
Rodger Combsc820e602016-03-23 21:46:39340 UInt32 size;
341 status = AudioConverterGetPropertyInfo(at->converter,
342 kAudioConverterApplicableEncodeBitRates,
343 &size, NULL);
344 if (!status && size) {
345 UInt32 new_rate = rate;
346 int count;
347 int i;
348 AudioValueRange *ranges = av_malloc(size);
349 if (!ranges)
350 return AVERROR(ENOMEM);
351 AudioConverterGetProperty(at->converter,
352 kAudioConverterApplicableEncodeBitRates,
353 &size, ranges);
354 count = size / sizeof(AudioValueRange);
355 for (i = 0; i < count; i++) {
356 AudioValueRange *range = &ranges[i];
357 if (rate >= range->mMinimum && rate <= range->mMaximum) {
358 new_rate = rate;
359 break;
360 } else if (rate > range->mMaximum) {
361 new_rate = range->mMaximum;
362 } else {
363 new_rate = range->mMinimum;
364 break;
365 }
366 }
367 if (new_rate != rate) {
368 av_log(avctx, AV_LOG_WARNING,
369 "Bitrate %u not allowed; changing to %u\n", rate, new_rate);
370 rate = new_rate;
371 }
372 av_free(ranges);
373 }
Rodger Combs65cff812016-02-24 03:01:24374 AudioConverterSetProperty(at->converter, kAudioConverterEncodeBitRate,
Rodger Combsc820e602016-03-23 21:46:39375 sizeof(rate), &rate);
Rodger Combs65cff812016-02-24 03:01:24376 }
377
378 at->quality = 96 - at->quality * 32;
379 AudioConverterSetProperty(at->converter, kAudioConverterCodecQuality,
Rodger Combsc820e602016-03-23 21:46:39380 sizeof(at->quality), &at->quality);
Rodger Combs65cff812016-02-24 03:01:24381
382 if (!AudioConverterGetPropertyInfo(at->converter, kAudioConverterCompressionMagicCookie,
383 &avctx->extradata_size, NULL) &&
384 avctx->extradata_size) {
385 int extradata_size = avctx->extradata_size;
386 uint8_t *extradata;
387 if (!(avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE)))
388 return AVERROR(ENOMEM);
389 if (avctx->codec_id == AV_CODEC_ID_ALAC) {
390 avctx->extradata_size = 0x24;
391 AV_WB32(avctx->extradata, 0x24);
392 AV_WB32(avctx->extradata + 4, MKBETAG('a','l','a','c'));
393 extradata = avctx->extradata + 12;
394 avctx->extradata_size = 0x24;
395 } else {
396 extradata = avctx->extradata;
397 }
398 status = AudioConverterGetProperty(at->converter,
399 kAudioConverterCompressionMagicCookie,
400 &extradata_size, extradata);
401 if (status != 0) {
402 av_log(avctx, AV_LOG_ERROR, "AudioToolbox cookie error: %i\n", (int)status);
403 return AVERROR_UNKNOWN;
404 } else if (avctx->codec_id == AV_CODEC_ID_AAC) {
405 GetByteContext gb;
406 int tag, len;
407 bytestream2_init(&gb, extradata, extradata_size);
408 do {
409 len = read_descr(&gb, &tag);
410 if (tag == MP4DecConfigDescrTag) {
411 bytestream2_skip(&gb, 13);
412 len = read_descr(&gb, &tag);
413 if (tag == MP4DecSpecificDescrTag) {
414 len = FFMIN(gb.buffer_end - gb.buffer, len);
415 memmove(extradata, gb.buffer, len);
416 avctx->extradata_size = len;
417 break;
418 }
419 } else if (tag == MP4ESDescrTag) {
420 int flags;
421 bytestream2_skip(&gb, 2);
422 flags = bytestream2_get_byte(&gb);
423 if (flags & 0x80) //streamDependenceFlag
424 bytestream2_skip(&gb, 2);
425 if (flags & 0x40) //URL_Flag
426 bytestream2_skip(&gb, bytestream2_get_byte(&gb));
427 if (flags & 0x20) //OCRstreamFlag
428 bytestream2_skip(&gb, 2);
429 }
430 } while (bytestream2_get_bytes_left(&gb));
431 } else if (avctx->codec_id != AV_CODEC_ID_ALAC) {
432 avctx->extradata_size = extradata_size;
433 }
434 }
435
436 ffat_update_ctx(avctx);
437
Rodger Combs36770d82016-03-27 17:17:25438#if !TARGET_OS_IPHONE && defined(__MAC_10_9)
Rodger Combs65cff812016-02-24 03:01:24439 if (at->mode == kAudioCodecBitRateControlMode_Variable && avctx->rc_max_rate) {
Rodger Combsc820e602016-03-23 21:46:39440 UInt32 max_size = avctx->rc_max_rate * avctx->frame_size / avctx->sample_rate;
Rodger Combs65cff812016-02-24 03:01:24441 if (max_size)
Rodger Combsc820e602016-03-23 21:46:39442 AudioConverterSetProperty(at->converter, kAudioCodecPropertyPacketSizeLimitForVBR,
443 sizeof(max_size), &max_size);
Rodger Combs65cff812016-02-24 03:01:24444 }
Dan Dennedy28688d72016-03-25 04:13:18445#endif
Rodger Combs65cff812016-02-24 03:01:24446
447 ff_af_queue_init(avctx, &at->afq);
448
Jiejun Zhang677701c2018-01-03 04:54:20449 at->encoding_frame = av_frame_alloc();
450 if (!at->encoding_frame)
451 return AVERROR(ENOMEM);
452
Rodger Combs65cff812016-02-24 03:01:24453 return 0;
454}
455
456static OSStatus ffat_encode_callback(AudioConverterRef converter, UInt32 *nb_packets,
457 AudioBufferList *data,
458 AudioStreamPacketDescription **packets,
459 void *inctx)
460{
461 AVCodecContext *avctx = inctx;
462 ATDecodeContext *at = avctx->priv_data;
Rick Kern143685a2016-06-02 06:25:21463 AVFrame *frame;
Jiejun Zhang677701c2018-01-03 04:54:20464 int ret;
Rodger Combs65cff812016-02-24 03:01:24465
Rick Kern143685a2016-06-02 06:25:21466 if (!at->frame_queue.available) {
467 if (at->eof) {
468 *nb_packets = 0;
469 return 0;
470 } else {
471 *nb_packets = 0;
472 return 1;
473 }
Rodger Combs65cff812016-02-24 03:01:24474 }
475
Rick Kern143685a2016-06-02 06:25:21476 frame = ff_bufqueue_get(&at->frame_queue);
Rodger Combs65cff812016-02-24 03:01:24477
478 data->mNumberBuffers = 1;
Rodger Combs7524b672016-03-23 21:29:50479 data->mBuffers[0].mNumberChannels = avctx->channels;
Rick Kern143685a2016-06-02 06:25:21480 data->mBuffers[0].mDataByteSize = frame->nb_samples *
Rodger Combs65cff812016-02-24 03:01:24481 av_get_bytes_per_sample(avctx->sample_fmt) *
482 avctx->channels;
Rick Kern143685a2016-06-02 06:25:21483 data->mBuffers[0].mData = frame->data[0];
484 if (*nb_packets > frame->nb_samples)
485 *nb_packets = frame->nb_samples;
486
Jiejun Zhang677701c2018-01-03 04:54:20487 av_frame_unref(at->encoding_frame);
488 ret = av_frame_ref(at->encoding_frame, frame);
489 if (ret < 0) {
490 *nb_packets = 0;
491 return ret;
492 }
493
Rick Kern143685a2016-06-02 06:25:21494 ff_bufqueue_add(avctx, &at->used_frame_queue, frame);
Rodger Combs65cff812016-02-24 03:01:24495
496 return 0;
497}
498
499static int ffat_encode(AVCodecContext *avctx, AVPacket *avpkt,
500 const AVFrame *frame, int *got_packet_ptr)
501{
502 ATDecodeContext *at = avctx->priv_data;
503 OSStatus ret;
504
505 AudioBufferList out_buffers = {
506 .mNumberBuffers = 1,
507 .mBuffers = {
508 {
509 .mNumberChannels = avctx->channels,
510 .mDataByteSize = at->pkt_size,
511 }
512 }
513 };
514 AudioStreamPacketDescription out_pkt_desc = {0};
515
Rodger Combs65cff812016-02-24 03:01:24516 if (frame) {
Rick Kern143685a2016-06-02 06:25:21517 AVFrame *in_frame;
518
519 if (ff_bufqueue_is_full(&at->frame_queue)) {
520 /*
521 * The frame queue is significantly larger than needed in practice,
522 * but no clear way to determine the minimum number of samples to
523 * get output from AudioConverterFillComplexBuffer().
524 */
525 av_log(avctx, AV_LOG_ERROR, "Bug: frame queue is too small.\n");
526 return AVERROR_BUG;
527 }
528
Rodger Combs65cff812016-02-24 03:01:24529 if ((ret = ff_af_queue_add(&at->afq, frame)) < 0)
530 return ret;
Rick Kern143685a2016-06-02 06:25:21531
532 in_frame = av_frame_clone(frame);
533 if (!in_frame)
534 return AVERROR(ENOMEM);
535
536 ff_bufqueue_add(avctx, &at->frame_queue, in_frame);
Rodger Combs65cff812016-02-24 03:01:24537 } else {
538 at->eof = 1;
539 }
540
Andreas Rheinhardt56e9e022021-05-11 13:17:13541 if ((ret = ff_alloc_packet(avctx, avpkt, at->pkt_size)) < 0)
Rick Kern143685a2016-06-02 06:25:21542 return ret;
543
544
Rodger Combs65cff812016-02-24 03:01:24545 out_buffers.mBuffers[0].mData = avpkt->data;
546
547 *got_packet_ptr = avctx->frame_size / at->frame_size;
548
549 ret = AudioConverterFillComplexBuffer(at->converter, ffat_encode_callback, avctx,
550 got_packet_ptr, &out_buffers,
551 (avctx->frame_size > at->frame_size) ? NULL : &out_pkt_desc);
Rick Kern143685a2016-06-02 06:25:21552
553 ff_bufqueue_discard_all(&at->used_frame_queue);
554
Rodger Combs65cff812016-02-24 03:01:24555 if ((!ret || ret == 1) && *got_packet_ptr) {
556 avpkt->size = out_buffers.mBuffers[0].mDataByteSize;
557 ff_af_queue_remove(&at->afq, out_pkt_desc.mVariableFramesInPacket ?
558 out_pkt_desc.mVariableFramesInPacket :
559 avctx->frame_size,
560 &avpkt->pts,
561 &avpkt->duration);
562 } else if (ret && ret != 1) {
563 av_log(avctx, AV_LOG_WARNING, "Encode error: %i\n", ret);
564 }
565
566 return 0;
567}
568
569static av_cold void ffat_encode_flush(AVCodecContext *avctx)
570{
571 ATDecodeContext *at = avctx->priv_data;
572 AudioConverterReset(at->converter);
Rick Kern143685a2016-06-02 06:25:21573 ff_bufqueue_discard_all(&at->frame_queue);
574 ff_bufqueue_discard_all(&at->used_frame_queue);
Rodger Combs65cff812016-02-24 03:01:24575}
576
577static av_cold int ffat_close_encoder(AVCodecContext *avctx)
578{
579 ATDecodeContext *at = avctx->priv_data;
580 AudioConverterDispose(at->converter);
Rick Kern143685a2016-06-02 06:25:21581 ff_bufqueue_discard_all(&at->frame_queue);
582 ff_bufqueue_discard_all(&at->used_frame_queue);
Rodger Combs65cff812016-02-24 03:01:24583 ff_af_queue_close(&at->afq);
Jiejun Zhang677701c2018-01-03 04:54:20584 av_frame_free(&at->encoding_frame);
Rodger Combs65cff812016-02-24 03:01:24585 return 0;
586}
587
588static const AVProfile aac_profiles[] = {
589 { FF_PROFILE_AAC_LOW, "LC" },
590 { FF_PROFILE_AAC_HE, "HE-AAC" },
591 { FF_PROFILE_AAC_HE_V2, "HE-AACv2" },
592 { FF_PROFILE_AAC_LD, "LD" },
593 { FF_PROFILE_AAC_ELD, "ELD" },
594 { FF_PROFILE_UNKNOWN },
595};
596
597#define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
598static const AVOption options[] = {
Rodger Combs06673272016-03-24 15:17:42599#if !TARGET_OS_IPHONE
Rodger Combs65cff812016-02-24 03:01:24600 {"aac_at_mode", "ratecontrol mode", offsetof(ATDecodeContext, mode), AV_OPT_TYPE_INT, {.i64 = -1}, -1, kAudioCodecBitRateControlMode_Variable, AE, "mode"},
601 {"auto", "VBR if global quality is given; CBR otherwise", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, INT_MIN, INT_MAX, AE, "mode"},
602 {"cbr", "constant bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_Constant}, INT_MIN, INT_MAX, AE, "mode"},
603 {"abr", "long-term average bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_LongTermAverage}, INT_MIN, INT_MAX, AE, "mode"},
604 {"cvbr", "constrained variable bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_VariableConstrained}, INT_MIN, INT_MAX, AE, "mode"},
605 {"vbr" , "variable bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_Variable}, INT_MIN, INT_MAX, AE, "mode"},
Rodger Combs06673272016-03-24 15:17:42606#endif
Rodger Combs65cff812016-02-24 03:01:24607 {"aac_at_quality", "quality vs speed control", offsetof(ATDecodeContext, quality), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 2, AE},
608 { NULL },
609};
610
611#define FFAT_ENC_CLASS(NAME) \
612 static const AVClass ffat_##NAME##_enc_class = { \
613 .class_name = "at_" #NAME "_enc", \
614 .item_name = av_default_item_name, \
615 .option = options, \
616 .version = LIBAVUTIL_VERSION_INT, \
617 };
618
619#define FFAT_ENC(NAME, ID, PROFILES, ...) \
620 FFAT_ENC_CLASS(NAME) \
Andreas Rheinhardta247ac62021-02-25 09:50:26621 const AVCodec ff_##NAME##_at_encoder = { \
Rodger Combs65cff812016-02-24 03:01:24622 .name = #NAME "_at", \
623 .long_name = NULL_IF_CONFIG_SMALL(#NAME " (AudioToolbox)"), \
624 .type = AVMEDIA_TYPE_AUDIO, \
625 .id = ID, \
626 .priv_data_size = sizeof(ATDecodeContext), \
627 .init = ffat_init_encoder, \
628 .close = ffat_close_encoder, \
629 .encode2 = ffat_encode, \
630 .flush = ffat_encode_flush, \
631 .priv_class = &ffat_##NAME##_enc_class, \
Andreas Rheinhardtc6852492021-05-15 11:02:25632 .capabilities = AV_CODEC_CAP_DELAY | \
Philip Langdale22b25b32020-04-10 20:32:11633 AV_CODEC_CAP_ENCODER_FLUSH __VA_ARGS__, \
Rodger Combs65cff812016-02-24 03:01:24634 .sample_fmts = (const enum AVSampleFormat[]) { \
635 AV_SAMPLE_FMT_S16, \
636 AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NONE \
637 }, \
638 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \
639 .profiles = PROFILES, \
wm4b945fed2017-12-11 15:18:44640 .wrapper_name = "at", \
Rodger Combs65cff812016-02-24 03:01:24641 };
642
Rodger Combsc820e602016-03-23 21:46:39643static const uint64_t aac_at_channel_layouts[] = {
644 AV_CH_LAYOUT_MONO,
645 AV_CH_LAYOUT_STEREO,
646 AV_CH_LAYOUT_SURROUND,
647 AV_CH_LAYOUT_4POINT0,
648 AV_CH_LAYOUT_5POINT0,
649 AV_CH_LAYOUT_5POINT1,
650 AV_CH_LAYOUT_6POINT0,
651 AV_CH_LAYOUT_6POINT1,
652 AV_CH_LAYOUT_7POINT0,
653 AV_CH_LAYOUT_7POINT1_WIDE_BACK,
654 AV_CH_LAYOUT_QUAD,
655 AV_CH_LAYOUT_OCTAGONAL,
656 0,
657};
658
659FFAT_ENC(aac, AV_CODEC_ID_AAC, aac_profiles, , .channel_layouts = aac_at_channel_layouts)
Rodger Combs65cff812016-02-24 03:01:24660//FFAT_ENC(adpcm_ima_qt, AV_CODEC_ID_ADPCM_IMA_QT, NULL)
James Almer13b1bbf2020-05-21 15:20:11661FFAT_ENC(alac, AV_CODEC_ID_ALAC, NULL, | AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
Rodger Combs65cff812016-02-24 03:01:24662FFAT_ENC(ilbc, AV_CODEC_ID_ILBC, NULL)
663FFAT_ENC(pcm_alaw, AV_CODEC_ID_PCM_ALAW, NULL)
664FFAT_ENC(pcm_mulaw, AV_CODEC_ID_PCM_MULAW, NULL)