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