23 #include <AudioToolbox/AudioToolbox.h>
25 #define FF_BUFQUEUE_SIZE 256
65 return kAudioFormatMPEG4AAC;
67 return kAudioFormatMPEG4AAC_HE;
69 return kAudioFormatMPEG4AAC_HE_V2;
71 return kAudioFormatMPEG4AAC_LD;
72 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
74 return kAudioFormatMPEG4AAC_ELD;
78 return kAudioFormatAppleIMA4;
80 return kAudioFormatAppleLossless;
81 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
83 return kAudioFormatiLBC;
86 return kAudioFormatALaw;
88 return kAudioFormatULaw;
98 UInt32
size =
sizeof(unsigned);
99 AudioConverterPrimeInfo prime_info;
100 AudioStreamBasicDescription out_format;
103 kAudioConverterPropertyMaximumOutputPacketSize,
109 size =
sizeof(prime_info);
111 if (!AudioConverterGetProperty(at->
converter,
112 kAudioConverterPrimeInfo,
113 &
size, &prime_info)) {
117 size =
sizeof(out_format);
118 if (!AudioConverterGetProperty(at->
converter,
119 kAudioConverterCurrentOutputStreamDescription,
120 &
size, &out_format)) {
121 if (out_format.mFramesPerPacket) {
122 avctx->
frame_size = out_format.mFramesPerPacket;
154 *
tag = bytestream2_get_byte(gb);
156 int c = bytestream2_get_byte(gb);
171 return avctx->
bit_rate <= 14000 ? 30 : 20;
196 return kAudioChannelLabel_LFE2;
204 layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
210 if (c < 0 || c >= 64)
213 layout->mChannelDescriptions[
i].mChannelLabel = label;
223 static const struct {
256 AudioStreamBasicDescription in_format = {
258 .mFormatID = kAudioFormatLinearPCM,
262 : kAudioFormatFlagIsSignedInteger)
263 | kAudioFormatFlagIsPacked,
265 .mFramesPerPacket = 1,
270 AudioStreamBasicDescription out_format = {
273 .mChannelsPerFrame = in_format.mChannelsPerFrame,
275 UInt32 layout_size =
sizeof(AudioChannelLayout) +
277 AudioChannelLayout *channel_layout =
av_malloc(layout_size);
284 out_format.mFramesPerPacket = 8000 *
mode / 1000;
285 out_format.mBytesPerPacket = (
mode == 20 ? 38 : 50);
305 if (AudioConverterSetProperty(at->
converter, kAudioConverterInputChannelLayout,
306 layout_size, channel_layout)) {
314 channel_layout->mChannelLayoutTag =
tag;
315 channel_layout->mNumberChannelDescriptions = 0;
318 if (AudioConverterSetProperty(at->
converter, kAudioConverterOutputChannelLayout,
319 layout_size, channel_layout)) {
328 kAudioConverterPropertyBitDepthHint,
332 #if !TARGET_OS_IPHONE
335 kAudioCodecBitRateControlMode_Variable :
336 kAudioCodecBitRateControlMode_Constant;
338 AudioConverterSetProperty(at->
converter, kAudioCodecPropertyBitRateControlMode,
341 if (at->
mode == kAudioCodecBitRateControlMode_Variable) {
343 if (q < 0 || q > 14) {
345 "VBR quality %d out of range, should be 0-14\n", q);
349 AudioConverterSetProperty(at->
converter, kAudioCodecPropertySoundQualityForVBR,
357 kAudioConverterApplicableEncodeBitRates,
360 UInt32 new_rate = rate;
367 kAudioConverterApplicableEncodeBitRates,
369 count =
size /
sizeof(AudioValueRange);
370 for (
i = 0;
i < count;
i++) {
371 AudioValueRange *
range = &ranges[
i];
372 if (rate >=
range->mMinimum && rate <= range->mMaximum) {
375 }
else if (rate >
range->mMaximum) {
376 new_rate =
range->mMaximum;
378 new_rate =
range->mMinimum;
382 if (new_rate != rate) {
384 "Bitrate %u not allowed; changing to %u\n", rate, new_rate);
389 AudioConverterSetProperty(at->
converter, kAudioConverterEncodeBitRate,
390 sizeof(rate), &rate);
394 AudioConverterSetProperty(at->
converter, kAudioConverterCodecQuality,
397 if (!AudioConverterGetPropertyInfo(at->
converter, kAudioConverterCompressionMagicCookie,
414 kAudioConverterCompressionMagicCookie,
415 &extradata_size, extradata);
437 flags = bytestream2_get_byte(&gb);
455 #if !TARGET_OS_IPHONE && defined(__MAC_10_9)
456 if (at->
mode == kAudioCodecBitRateControlMode_Variable && avctx->
rc_max_rate) {
459 AudioConverterSetProperty(at->
converter, kAudioCodecPropertyPacketSizeLimitForVBR,
460 sizeof(max_size), &max_size);
474 AudioBufferList *
data,
475 AudioStreamPacketDescription **packets,
495 data->mNumberBuffers = 1;
521 AudioBufferList out_buffers = {
530 AudioStreamPacketDescription out_pkt_desc = {0};
561 out_buffers.mBuffers[0].mData = avpkt->
data;
566 got_packet_ptr, &out_buffers,
571 if ((!
ret ||
ret == 1) && *got_packet_ptr) {
572 avpkt->
size = out_buffers.mBuffers[0].mDataByteSize;
574 out_pkt_desc.mVariableFramesInPacket :
578 }
else if (
ret &&
ret != 1) {
614 #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
616 #if !TARGET_OS_IPHONE
617 {
"aac_at_mode",
"ratecontrol mode", offsetof(
ATDecodeContext,
mode),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, kAudioCodecBitRateControlMode_Variable,
AE, .unit =
"mode"},
618 {
"auto",
"VBR if global quality is given; CBR otherwise", 0,
AV_OPT_TYPE_CONST, {.i64 = -1}, INT_MIN, INT_MAX,
AE, .unit =
"mode"},
619 {
"cbr",
"constant bitrate", 0,
AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_Constant}, INT_MIN, INT_MAX,
AE, .unit =
"mode"},
620 {
"abr",
"long-term average bitrate", 0,
AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_LongTermAverage}, INT_MIN, INT_MAX,
AE, .unit =
"mode"},
621 {
"cvbr",
"constrained variable bitrate", 0,
AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_VariableConstrained}, INT_MIN, INT_MAX,
AE, .unit =
"mode"},
622 {
"vbr" ,
"variable bitrate", 0,
AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_Variable}, INT_MIN, INT_MAX,
AE, .unit =
"mode"},
628 #define FFAT_ENC_CLASS(NAME) \
629 static const AVClass ffat_##NAME##_enc_class = { \
630 .class_name = "at_" #NAME "_enc", \
631 .item_name = av_default_item_name, \
633 .version = LIBAVUTIL_VERSION_INT, \
636 #define FFAT_ENC(NAME, ID, PROFILES, CAPS, CHANNEL_LAYOUTS, CH_LAYOUTS) \
637 FFAT_ENC_CLASS(NAME) \
638 const FFCodec ff_##NAME##_at_encoder = { \
639 .p.name = #NAME "_at", \
640 CODEC_LONG_NAME(#NAME " (AudioToolbox)"), \
641 .p.type = AVMEDIA_TYPE_AUDIO, \
643 .priv_data_size = sizeof(ATDecodeContext), \
644 .init = ffat_init_encoder, \
645 .close = ffat_close_encoder, \
646 FF_CODEC_ENCODE_CB(ffat_encode), \
647 .flush = ffat_encode_flush, \
648 .p.priv_class = &ffat_##NAME##_enc_class, \
649 .p.capabilities = AV_CODEC_CAP_DELAY | \
650 AV_CODEC_CAP_ENCODER_FLUSH CAPS, \
651 .p.ch_layouts = CH_LAYOUTS, \
652 .p.sample_fmts = (const enum AVSampleFormat[]) { \
654 AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NONE \
656 .p.profiles = PROFILES, \
657 .p.wrapper_name = "at", \