[FFmpeg-devel] [PATCH 2/6] lavc/audiotoolboxenc: fix a number of config issues
crossle song
crosslesong at gmail.com
Fri Apr 1 05:25:54 CEST 2016
Merge please
On Mon, Mar 28, 2016 at 1:20 AM, Rodger Combs <rodger.combs at gmail.com>
wrote:
> - size variables were used in a confusing way
> - incorrect size var use led to channel layouts not being set properly
> - channel layouts were incorrectly mapped for >2-channel AAC
> - bitrates not accepted by the encoder were discarded instead of being
> clamped
> - some minor style/indentation fixes
> ---
> libavcodec/audiotoolboxenc.c | 198
> ++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 176 insertions(+), 22 deletions(-)
>
> diff --git a/libavcodec/audiotoolboxenc.c b/libavcodec/audiotoolboxenc.c
> index 4797b2a..22352da 100644
> --- a/libavcodec/audiotoolboxenc.c
> +++ b/libavcodec/audiotoolboxenc.c
> @@ -146,6 +146,86 @@ static int get_ilbc_mode(AVCodecContext *avctx)
> return 30;
> }
>
> +static av_cold int get_channel_label(int channel)
> +{
> + uint64_t map = 1 << channel;
> + if (map <= AV_CH_LOW_FREQUENCY)
> + return channel + 1;
> + else if (map <= AV_CH_BACK_RIGHT)
> + return channel + 29;
> + else if (map <= AV_CH_BACK_CENTER)
> + return channel - 1;
> + else if (map <= AV_CH_SIDE_RIGHT)
> + return channel - 4;
> + else if (map <= AV_CH_TOP_BACK_RIGHT)
> + return channel + 1;
> + else if (map <= AV_CH_STEREO_RIGHT)
> + return -1;
> + else if (map <= AV_CH_WIDE_RIGHT)
> + return channel + 4;
> + else if (map <= AV_CH_SURROUND_DIRECT_RIGHT)
> + return channel - 23;
> + else if (map == AV_CH_LOW_FREQUENCY_2)
> + return kAudioChannelLabel_LFE2;
> + else
> + return -1;
> +}
> +
> +static int remap_layout(AudioChannelLayout *layout, uint64_t in_layout,
> int count)
> +{
> + int i;
> + int c = 0;
> + layout->mChannelLayoutTag =
> kAudioChannelLayoutTag_UseChannelDescriptions;
> + layout->mNumberChannelDescriptions = count;
> + for (i = 0; i < count; i++) {
> + int label;
> + while (!(in_layout & (1 << c)) && c < 64)
> + c++;
> + if (c == 64)
> + return AVERROR(EINVAL); // This should never happen
> + label = get_channel_label(c);
> + layout->mChannelDescriptions[i].mChannelLabel = label;
> + if (label < 0)
> + return AVERROR(EINVAL);
> + c++;
> + }
> + return 0;
> +}
> +
> +static int get_aac_tag(uint64_t in_layout)
> +{
> + switch (in_layout) {
> + case AV_CH_LAYOUT_MONO:
> + return kAudioChannelLayoutTag_Mono;
> + case AV_CH_LAYOUT_STEREO:
> + return kAudioChannelLayoutTag_Stereo;
> + case AV_CH_LAYOUT_QUAD:
> + return kAudioChannelLayoutTag_AAC_Quadraphonic;
> + case AV_CH_LAYOUT_OCTAGONAL:
> + return kAudioChannelLayoutTag_AAC_Octagonal;
> + case AV_CH_LAYOUT_SURROUND:
> + return kAudioChannelLayoutTag_AAC_3_0;
> + case AV_CH_LAYOUT_4POINT0:
> + return kAudioChannelLayoutTag_AAC_4_0;
> + case AV_CH_LAYOUT_5POINT0:
> + return kAudioChannelLayoutTag_AAC_5_0;
> + case AV_CH_LAYOUT_5POINT1:
> + return kAudioChannelLayoutTag_AAC_5_1;
> + case AV_CH_LAYOUT_6POINT0:
> + return kAudioChannelLayoutTag_AAC_6_0;
> + case AV_CH_LAYOUT_6POINT1:
> + return kAudioChannelLayoutTag_AAC_6_1;
> + case AV_CH_LAYOUT_7POINT0:
> + return kAudioChannelLayoutTag_AAC_7_0;
> + case AV_CH_LAYOUT_7POINT1_WIDE_BACK:
> + return kAudioChannelLayoutTag_AAC_7_1;
> + case AV_CH_LAYOUT_7POINT1:
> + return kAudioChannelLayoutTag_MPEG_7_1_C;
> + default:
> + return 0;
> + }
> +}
> +
> static av_cold int ffat_init_encoder(AVCodecContext *avctx)
> {
> ATDecodeContext *at = avctx->priv_data;
> @@ -170,11 +250,12 @@ static av_cold int ffat_init_encoder(AVCodecContext
> *avctx)
> .mFormatID = ffat_get_format_id(avctx->codec_id, avctx->profile),
> .mChannelsPerFrame = in_format.mChannelsPerFrame,
> };
> - AudioChannelLayout channel_layout = {
> - .mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelBitmap,
> - .mChannelBitmap = avctx->channel_layout,
> - };
> - UInt32 size = sizeof(channel_layout);
> + UInt32 layout_size = sizeof(AudioChannelLayout) +
> + sizeof(AudioChannelDescription) *
> avctx->channels;
> + AudioChannelLayout *channel_layout = av_malloc(layout_size);
> +
> + if (!channel_layout)
> + return AVERROR(ENOMEM);
>
> if (avctx->codec_id == AV_CODEC_ID_ILBC) {
> int mode = get_ilbc_mode(avctx);
> @@ -186,22 +267,45 @@ static av_cold int ffat_init_encoder(AVCodecContext
> *avctx)
>
> if (status != 0) {
> av_log(avctx, AV_LOG_ERROR, "AudioToolbox init error: %i\n",
> (int)status);
> + av_free(channel_layout);
> return AVERROR_UNKNOWN;
> }
>
> - size = sizeof(UInt32);
> + if (!avctx->channel_layout)
> + avctx->channel_layout =
> av_get_default_channel_layout(avctx->channels);
> +
> + if ((status = remap_layout(channel_layout, avctx->channel_layout,
> avctx->channels)) < 0) {
> + av_log(avctx, AV_LOG_ERROR, "Invalid channel layout\n");
> + av_free(channel_layout);
> + return status;
> + }
>
> - AudioConverterSetProperty(at->converter,
> kAudioConverterInputChannelLayout,
> - size, &channel_layout);
> - AudioConverterSetProperty(at->converter,
> kAudioConverterOutputChannelLayout,
> - size, &channel_layout);
> + if (AudioConverterSetProperty(at->converter,
> kAudioConverterInputChannelLayout,
> + layout_size, channel_layout)) {
> + av_log(avctx, AV_LOG_ERROR, "Unsupported input channel layout\n");
> + av_free(channel_layout);
> + return AVERROR(EINVAL);
> + }
> + if (avctx->codec_id == AV_CODEC_ID_AAC) {
> + int tag = get_aac_tag(avctx->channel_layout);
> + if (tag) {
> + channel_layout->mChannelLayoutTag = tag;
> + channel_layout->mNumberChannelDescriptions = 0;
> + }
> + }
> + if (AudioConverterSetProperty(at->converter,
> kAudioConverterOutputChannelLayout,
> + layout_size, channel_layout)) {
> + av_log(avctx, AV_LOG_ERROR, "Unsupported output channel
> layout\n");
> + av_free(channel_layout);
> + return AVERROR(EINVAL);
> + }
> + av_free(channel_layout);
>
> - if (avctx->bits_per_raw_sample) {
> - size = sizeof(avctx->bits_per_raw_sample);
> + if (avctx->bits_per_raw_sample)
> AudioConverterSetProperty(at->converter,
> kAudioConverterPropertyBitDepthHint,
> - size, &avctx->bits_per_raw_sample);
> - }
> + sizeof(avctx->bits_per_raw_sample),
> + &avctx->bits_per_raw_sample);
>
> if (at->mode == -1)
> at->mode = (avctx->flags & AV_CODEC_FLAG_QSCALE) ?
> @@ -209,7 +313,7 @@ static av_cold int ffat_init_encoder(AVCodecContext
> *avctx)
> kAudioCodecBitRateControlMode_Constant;
>
> AudioConverterSetProperty(at->converter,
> kAudioCodecPropertyBitRateControlMode,
> - size, &at->mode);
> + sizeof(at->mode), &at->mode);
>
> if (at->mode == kAudioCodecBitRateControlMode_Variable) {
> int q = avctx->global_quality / FF_QP2LAMBDA;
> @@ -220,16 +324,50 @@ static av_cold int ffat_init_encoder(AVCodecContext
> *avctx)
> }
> q = 127 - q * 9;
> AudioConverterSetProperty(at->converter,
> kAudioCodecPropertySoundQualityForVBR,
> - size, &q);
> + sizeof(q), &q);
> } else if (avctx->bit_rate > 0) {
> UInt32 rate = avctx->bit_rate;
> + UInt32 size;
> + status = AudioConverterGetPropertyInfo(at->converter,
> +
> kAudioConverterApplicableEncodeBitRates,
> + &size, NULL);
> + if (!status && size) {
> + UInt32 new_rate = rate;
> + int count;
> + int i;
> + AudioValueRange *ranges = av_malloc(size);
> + if (!ranges)
> + return AVERROR(ENOMEM);
> + AudioConverterGetProperty(at->converter,
> +
> kAudioConverterApplicableEncodeBitRates,
> + &size, ranges);
> + count = size / sizeof(AudioValueRange);
> + for (i = 0; i < count; i++) {
> + AudioValueRange *range = &ranges[i];
> + if (rate >= range->mMinimum && rate <= range->mMaximum) {
> + new_rate = rate;
> + break;
> + } else if (rate > range->mMaximum) {
> + new_rate = range->mMaximum;
> + } else {
> + new_rate = range->mMinimum;
> + break;
> + }
> + }
> + if (new_rate != rate) {
> + av_log(avctx, AV_LOG_WARNING,
> + "Bitrate %u not allowed; changing to %u\n", rate,
> new_rate);
> + rate = new_rate;
> + }
> + av_free(ranges);
> + }
> AudioConverterSetProperty(at->converter,
> kAudioConverterEncodeBitRate,
> - size, &rate);
> + sizeof(rate), &rate);
> }
>
> at->quality = 96 - at->quality * 32;
> AudioConverterSetProperty(at->converter, kAudioConverterCodecQuality,
> - size, &at->quality);
> + sizeof(at->quality), &at->quality);
>
> if (!AudioConverterGetPropertyInfo(at->converter,
> kAudioConverterCompressionMagicCookie,
> &avctx->extradata_size, NULL) &&
> @@ -289,10 +427,10 @@ static av_cold int ffat_init_encoder(AVCodecContext
> *avctx)
>
> #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
> if (at->mode == kAudioCodecBitRateControlMode_Variable &&
> avctx->rc_max_rate) {
> - int max_size = avctx->rc_max_rate * avctx->frame_size /
> avctx->sample_rate;
> + UInt32 max_size = avctx->rc_max_rate * avctx->frame_size /
> avctx->sample_rate;
> if (max_size)
> - AudioConverterSetProperty(at->converter,
> kAudioCodecPropertyPacketSizeLimitForVBR,
> - size, &max_size);
> + AudioConverterSetProperty(at->converter,
> kAudioCodecPropertyPacketSizeLimitForVBR,
> + sizeof(max_size), &max_size);
> }
> #endif
>
> @@ -455,7 +593,23 @@ static const AVOption options[] = {
> .profiles = PROFILES, \
> };
>
> -FFAT_ENC(aac, AV_CODEC_ID_AAC, aac_profiles)
> +static const uint64_t aac_at_channel_layouts[] = {
> + AV_CH_LAYOUT_MONO,
> + AV_CH_LAYOUT_STEREO,
> + AV_CH_LAYOUT_SURROUND,
> + AV_CH_LAYOUT_4POINT0,
> + AV_CH_LAYOUT_5POINT0,
> + AV_CH_LAYOUT_5POINT1,
> + AV_CH_LAYOUT_6POINT0,
> + AV_CH_LAYOUT_6POINT1,
> + AV_CH_LAYOUT_7POINT0,
> + AV_CH_LAYOUT_7POINT1_WIDE_BACK,
> + AV_CH_LAYOUT_QUAD,
> + AV_CH_LAYOUT_OCTAGONAL,
> + 0,
> +};
> +
> +FFAT_ENC(aac, AV_CODEC_ID_AAC, aac_profiles, ,
> .channel_layouts = aac_at_channel_layouts)
> //FFAT_ENC(adpcm_ima_qt, AV_CODEC_ID_ADPCM_IMA_QT, NULL)
> FFAT_ENC(alac, AV_CODEC_ID_ALAC, NULL, |
> AV_CODEC_CAP_VARIABLE_FRAME_SIZE | AV_CODEC_CAP_LOSSLESS)
> FFAT_ENC(ilbc, AV_CODEC_ID_ILBC, NULL)
> --
> 2.7.3
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
More information about the ffmpeg-devel
mailing list