23 #include <AudioToolbox/AudioToolbox.h>
25 #define FF_BUFQUEUE_SIZE 256
66 return kAudioFormatMPEG4AAC;
68 return kAudioFormatMPEG4AAC_HE;
70 return kAudioFormatMPEG4AAC_HE_V2;
72 return kAudioFormatMPEG4AAC_LD;
73 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
75 return kAudioFormatMPEG4AAC_ELD;
79 return kAudioFormatAppleIMA4;
81 return kAudioFormatAppleLossless;
82 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
84 return kAudioFormatiLBC;
87 return kAudioFormatALaw;
89 return kAudioFormatULaw;
99 UInt32
size =
sizeof(unsigned);
100 AudioConverterPrimeInfo prime_info;
101 AudioStreamBasicDescription out_format;
104 kAudioConverterPropertyMaximumOutputPacketSize,
110 size =
sizeof(prime_info);
112 if (!AudioConverterGetProperty(at->
converter,
113 kAudioConverterPrimeInfo,
114 &
size, &prime_info)) {
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;
155 *
tag = bytestream2_get_byte(gb);
157 int c = bytestream2_get_byte(gb);
172 return avctx->
bit_rate <= 14000 ? 30 : 20;
197 return kAudioChannelLabel_LFE2;
205 layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
211 if (c < 0 || c >= 64)
214 layout->mChannelDescriptions[
i].mChannelLabel = label;
224 static const struct {
257 AudioStreamBasicDescription in_format = {
259 .mFormatID = kAudioFormatLinearPCM,
263 : kAudioFormatFlagIsSignedInteger)
264 | kAudioFormatFlagIsPacked,
266 .mFramesPerPacket = 1,
271 AudioStreamBasicDescription out_format = {
274 .mChannelsPerFrame = in_format.mChannelsPerFrame,
276 UInt32 layout_size =
sizeof(AudioChannelLayout) +
278 AudioChannelLayout *channel_layout =
av_malloc(layout_size);
285 out_format.mFramesPerPacket = 8000 *
mode / 1000;
286 out_format.mBytesPerPacket = (
mode == 20 ? 38 : 50);
306 if (AudioConverterSetProperty(at->
converter, kAudioConverterInputChannelLayout,
307 layout_size, channel_layout)) {
315 channel_layout->mChannelLayoutTag =
tag;
316 channel_layout->mNumberChannelDescriptions = 0;
319 if (AudioConverterSetProperty(at->
converter, kAudioConverterOutputChannelLayout,
320 layout_size, channel_layout)) {
329 kAudioConverterPropertyBitDepthHint,
333 #if !TARGET_OS_IPHONE
336 kAudioCodecBitRateControlMode_Variable :
337 kAudioCodecBitRateControlMode_Constant;
339 AudioConverterSetProperty(at->
converter, kAudioCodecPropertyBitRateControlMode,
342 if (at->
mode == kAudioCodecBitRateControlMode_Variable) {
344 if (q < 0 || q > 14) {
346 "VBR quality %d out of range, should be 0-14\n", q);
350 AudioConverterSetProperty(at->
converter, kAudioCodecPropertySoundQualityForVBR,
358 kAudioConverterApplicableEncodeBitRates,
361 UInt32 new_rate = rate;
368 kAudioConverterApplicableEncodeBitRates,
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) {
376 }
else if (rate >
range->mMaximum) {
377 new_rate =
range->mMaximum;
379 new_rate =
range->mMinimum;
383 if (new_rate != rate) {
385 "Bitrate %u not allowed; changing to %u\n", rate, new_rate);
390 AudioConverterSetProperty(at->
converter, kAudioConverterEncodeBitRate,
391 sizeof(rate), &rate);
395 AudioConverterSetProperty(at->
converter, kAudioConverterCodecQuality,
398 if (!AudioConverterGetPropertyInfo(at->
converter, kAudioConverterCompressionMagicCookie,
415 kAudioConverterCompressionMagicCookie,
416 &extradata_size, extradata);
438 flags = bytestream2_get_byte(&gb);
456 #if !TARGET_OS_IPHONE && defined(__MAC_10_9)
457 if (at->
mode == kAudioCodecBitRateControlMode_Variable && avctx->
rc_max_rate) {
460 AudioConverterSetProperty(at->
converter, kAudioCodecPropertyPacketSizeLimitForVBR,
461 sizeof(max_size), &max_size);
475 AudioBufferList *
data,
476 AudioStreamPacketDescription **packets,
496 data->mNumberBuffers = 1;
498 data->mBuffers[0].mDataByteSize =
frame->nb_samples *
501 data->mBuffers[0].mData =
frame->data[0];
502 if (*nb_packets >
frame->nb_samples)
503 *nb_packets =
frame->nb_samples;
522 AudioBufferList out_buffers = {
531 AudioStreamPacketDescription out_pkt_desc = {0};
562 out_buffers.mBuffers[0].mData = avpkt->
data;
567 got_packet_ptr, &out_buffers,
572 if ((!
ret ||
ret == 1) && *got_packet_ptr) {
573 avpkt->
size = out_buffers.mBuffers[0].mDataByteSize;
575 out_pkt_desc.mVariableFramesInPacket :
581 }
else if (
ret &&
ret != 1) {
617 #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
619 #if !TARGET_OS_IPHONE
620 {
"aac_at_mode",
"ratecontrol mode", offsetof(
ATDecodeContext,
mode),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, kAudioCodecBitRateControlMode_Variable,
AE, .unit =
"mode"},
621 {
"auto",
"VBR if global quality is given; CBR otherwise", 0,
AV_OPT_TYPE_CONST, {.i64 = -1}, INT_MIN, INT_MAX,
AE, .unit =
"mode"},
622 {
"cbr",
"constant bitrate", 0,
AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_Constant}, INT_MIN, INT_MAX,
AE, .unit =
"mode"},
623 {
"abr",
"long-term average bitrate", 0,
AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_LongTermAverage}, INT_MIN, INT_MAX,
AE, .unit =
"mode"},
624 {
"cvbr",
"constrained variable bitrate", 0,
AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_VariableConstrained}, INT_MIN, INT_MAX,
AE, .unit =
"mode"},
625 {
"vbr" ,
"variable bitrate", 0,
AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_Variable}, INT_MIN, INT_MAX,
AE, .unit =
"mode"},
631 #define FFAT_ENC_CLASS(NAME) \
632 static const AVClass ffat_##NAME##_enc_class = { \
633 .class_name = "at_" #NAME "_enc", \
634 .item_name = av_default_item_name, \
636 .version = LIBAVUTIL_VERSION_INT, \
639 #define FFAT_ENC(NAME, ID, PROFILES, CAPS, CHANNEL_LAYOUTS, CH_LAYOUTS) \
640 FFAT_ENC_CLASS(NAME) \
641 const FFCodec ff_##NAME##_at_encoder = { \
642 .p.name = #NAME "_at", \
643 CODEC_LONG_NAME(#NAME " (AudioToolbox)"), \
644 .p.type = AVMEDIA_TYPE_AUDIO, \
646 .priv_data_size = sizeof(ATDecodeContext), \
647 .init = ffat_init_encoder, \
648 .close = ffat_close_encoder, \
649 FF_CODEC_ENCODE_CB(ffat_encode), \
650 .flush = ffat_encode_flush, \
651 .p.priv_class = &ffat_##NAME##_enc_class, \
652 .p.capabilities = AV_CODEC_CAP_DELAY | \
653 AV_CODEC_CAP_ENCODER_FLUSH CAPS, \
654 .p.profiles = PROFILES, \
655 .p.wrapper_name = "at", \
656 CODEC_CH_LAYOUTS_ARRAY(CH_LAYOUTS), \
657 CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), \