[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