[FFmpeg-devel] [aacdec] Parse and drop gain control data, so that SSR packets decode.
Alex Converse
alex.converse at gmail.com
Wed Feb 21 02:18:03 EET 2018
On Tue, Feb 20, 2018 at 3:37 PM, Dale Curtis <dalecurtis at chromium.org> wrote:
> From 97380752ef12337d9b9a01801a9a84df3b4b9c0a Mon Sep 17 00:00:00 2001
> From: Dale Curtis <dalecurtis at chromium.org>
> Date: Thu, 15 Feb 2018 16:22:55 -0800
> Subject: [PATCH] [aacdec] Parse and drop gain control data, so that SSR
> packets decode.
>
> This will result in poor quality audio for SSR streams, but they
> will at least demux and decode without error; partially fixing
> ticket #1693.
>
> This just pulls in the decode_gain_control() function from the
> ffmpeg summer-of-code repo (original author Robert Swain) at
> svn://svn.mplayerhq.hu/soc/aac/aac.c and adds AOT_AAC_SSR to
> decode_audio_specific_config_gb().
>
> Signed-off-by: Dale Curtis <dalecurtis at chromium.org>
> Co-authored-by: Robert Swain <robert.swain at gmail.com>
> ---
> libavcodec/aacdec_template.c | 49 +++++++++++++++++++++++++++++++++---
> 1 file changed, 46 insertions(+), 3 deletions(-)
>
> diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
> index c2d9802023..c3ec3eefe8 100644
> --- a/libavcodec/aacdec_template.c
> +++ b/libavcodec/aacdec_template.c
> @@ -997,6 +997,7 @@ static int decode_audio_specific_config_gb(AACContext *ac,
> switch (m4ac->object_type) {
> case AOT_AAC_MAIN:
> case AOT_AAC_LC:
> + case AOT_AAC_SSR:
> case AOT_AAC_LTP:
> case AOT_ER_AAC_LC:
> case AOT_ER_AAC_LD:
> @@ -1967,6 +1968,44 @@ static void apply_prediction(AACContext *ac, SingleChannelElement *sce)
> reset_all_predictors(sce->predictor_state);
> }
>
> +static int decode_gain_control(SingleChannelElement * sce, GetBitContext * gb)
> +{
> + // wd_num, wd_test, aloc_size
> + static const int gain_mode[4][3] = {
I would make this uint8_t
> + {1, 0, 5}, // ONLY_LONG_SEQUENCE = 0,
> + {2, 1, 2}, // LONG_START_SEQUENCE,
> + {8, 0, 2}, // EIGHT_SHORT_SEQUENCE,
> + {2, 1, 5}, // LONG_STOP_SEQUENCE
> + };
> +
> + // per-element gain control for SSR
> + struct {
> + int max_band;
> + int adjust_num[4][8];
> + int alev[4][8][8];
> + int aloc[4][8][8];
> + } ssr;
I would drop this stack struck and replace the leaf get_bits() with
skip bits. It makes the code that much harder to exploit and there is
no point in storing data we don't plan on decoding
> +
> + const int mode = sce->ics.window_sequence[0];
> + int bd, wd, ad;
> +
> + // FIXME: Store the gain control data on |sce| and do something with it.
> + ssr.max_band = get_bits(gb, 2);
> + for (bd = 0; bd < ssr.max_band; bd++) {
> + for (wd = 0; wd < gain_mode[mode][0]; wd++) {
> + ssr.adjust_num[bd][wd] = get_bits(gb, 3);
> + for (ad = 0; ad < ssr.adjust_num[bd][wd]; ad++) {
> + ssr.alev[bd][wd][ad] = get_bits(gb, 4);
> + if (wd == 0 && gain_mode[mode][1])
> + ssr.aloc[bd][wd][ad] = get_bits(gb, 4);
> + else
> + ssr.aloc[bd][wd][ad] = get_bits(gb, gain_mode[mode][2]);
> + }
> + }
> + }
> + return 0;
> +}
> +
> /**
> * Decode an individual_channel_stream payload; reference: table 4.44.
> *
> @@ -2034,9 +2073,13 @@ static int decode_ics(AACContext *ac, SingleChannelElement *sce,
> goto fail;
> }
> if (!eld_syntax && get_bits1(gb)) {
> - avpriv_request_sample(ac->avctx, "SSR");
> - ret = AVERROR_PATCHWELCOME;
> - goto fail;
> + // FIXME: Do something with the gain control data...
> + ret = decode_gain_control(sce, gb);
> + if (ret < 0) {
> + ret = AVERROR_PATCHWELCOME;
> + avpriv_request_sample(ac->avctx, "SSR");
> + goto fail;
> + }
This block seems funny. decode_gain_control() always returns zero.
Maybe make this warn once per stream when present like some of the
other AAC warn
cases.
> }
> // I see no textual basis in the spec for this occurring after SSR gain
> // control, but this is what both reference and real implmentations do
> --
> 2.16.1.291.g4437f3f132-goog
>
More information about the ffmpeg-devel
mailing list