[FFmpeg-devel] CNG (consistent noise generation) patch for AC-3 decoder

Jonathan Campbell jonathan at impactstudiopro.com
Sun Sep 4 01:23:32 EEST 2016


On 09/03/2016 01:32 PM, Rostislav Pehlivanov wrote:
> On 2 September 2016 at 02:59, Jonathan Campbell <
> jonathan at impactstudiopro.com> wrote:
> 
>> I finished the consistent noise generation patch for AC-3 decoding.
>>
>> Set AVOption "cons_noisegen" to 1 (true) to enable it.
>>
>> Git repository:
>> https://github.com/joncampbell123/FFmpeg.git
>>
>> commit dbd086586f0ad1591ea2013293bbb6e4dbfd0455
>> Author: Jonathan Campbell <jonathan at castus.tv>
>> Date:   Thu Sep 1 18:46:16 2016 -0700
>>
>>     AC-3 consistent noise generation: avopt -cons_noisegen <number>
>>
>>     When -cons_noisegen 1, the linear feedback generator used for AC-3
>>     dithering is seeded with the contents of the AC-3 frame. Seeding from
>>     the AC-3 frame ensures the dithering noise comes out exactly the same
>>     when given the same AC-3 frame data, which can then be used by
>>     non-linear editing software to reliably decode discontinuous segments
>> of
>>     an AC-3 bitstream without gaps or discontinuities.
>>
>> Jonathan Campbell
>>
>> Patch follows, hope Thunderbird doesn't garble it:
>>
>> diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
>> index fac189b..28048d7 100644
>> --- a/libavcodec/ac3dec.c
>> +++ b/libavcodec/ac3dec.c
>> @@ -1419,6 +1419,19 @@ static int ac3_decode_frame(AVCodecContext *
>> avctx, void *data,
>>                              (const uint16_t *) buf, cnt);
>>      } else
>>          memcpy(s->input_buffer, buf, FFMIN(buf_size,
>> AC3_FRAME_BUFFER_SIZE));
>> +
>> +    /* if consistent noise generation is enabled, seed the linear
>> feedback generator
>> +     * with the contents of the AC-3 frame so that the noise is identical
>> across
>> +     * decodes given the same AC-3 frame data, for use with non-linear
>> edititing software. */
>> +    if (s->consistent_noise_generation) {
>> +        const AVCRC *avcrc = av_crc_get_table(AV_CRC_32_IEEE);
>> +
>> +        if (avcrc != NULL)
>> +            av_lfg_init(&s->dith_state, av_crc(avcrc, 0, s->input_buffer,
>> FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE)));
>> +        else
>> +            av_log(avctx, AV_LOG_ERROR, "CNG unable to seed from frame");
>> +    }
>> +
>>      buf = s->input_buffer;
>>      /* initialize the GetBitContext with the start of valid AC-3 Frame */
>>      if ((ret = init_get_bits8(&s->gbc, buf, buf_size)) < 0)
>> diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h
>> index c2b867e..98184e9 100644
>> --- a/libavcodec/ac3dec.h
>> +++ b/libavcodec/ac3dec.h
>> @@ -177,6 +177,10 @@ typedef struct AC3DecodeContext {
>>      int end_freq[AC3_MAX_CHANNELS];         ///< end frequency bin
>>               (endmant)
>>  ///@}
>>
>> +///@name Consistent noise generation
>> +    int consistent_noise_generation;        ///< seed noise generation
>> with AC-3 frame on decode
>> +///@}
>> +
>>  ///@name Rematrixing
>>      int num_rematrixing_bands;              ///< number of rematrixing
>> bands            (nrematbnd)
>>      int rematrixing_flags[4];               ///< rematrixing flags
>>               (rematflg)
>> diff --git a/libavcodec/ac3dec_fixed.c b/libavcodec/ac3dec_fixed.c
>> index 6416da4..1f79ade 100644
>> --- a/libavcodec/ac3dec_fixed.c
>> +++ b/libavcodec/ac3dec_fixed.c
>> @@ -168,6 +168,7 @@ static void ac3_downmix_c_fixed16(int16_t **samples,
>> int16_t (*matrix)[2],
>>  #include "ac3dec.c"
>>
>>  static const AVOption options[] = {
>> +    { "cons_noisegen", "enable consistent noise generation",
>> OFFSET(consistent_noise_generation), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1,
>> PAR },
>>      { "drc_scale", "percentage of dynamic range compression to apply",
>> OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR },
>>      { "heavy_compr", "enable heavy dynamic range compression",
>> OFFSET(heavy_compression), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, PAR },
>>      { NULL},
>> diff --git a/libavcodec/ac3dec_float.c b/libavcodec/ac3dec_float.c
>> index 0a5319a..b85a4ce 100644
>> --- a/libavcodec/ac3dec_float.c
>> +++ b/libavcodec/ac3dec_float.c
>> @@ -32,6 +32,7 @@
>>  #include "ac3dec.c"
>>
>>  static const AVOption options[] = {
>> +    { "cons_noisegen", "enable consistent noise generation",
>> OFFSET(consistent_noise_generation), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1,
>> PAR },
>>      { "drc_scale", "percentage of dynamic range compression to apply",
>> OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR },
>>      { "heavy_compr", "enable heavy dynamic range compression",
>> OFFSET(heavy_compression), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, PAR },
>>      { "target_level", "target level in -dBFS (0 not applied)",
>> OFFSET(target_level), AV_OPT_TYPE_INT, {.i64 = 0 }, -31, 0, PAR },
>>
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel at ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
> 
> Any random noise, hardcoded constant or not sill sounds like white noise.
Yes.

> What is the point of this patch?
To make the random noise consistent with the AC-3 frame data given to the decoder, so that decoding the same data gives the exact same audio samples. It doesn't matter to normal file playback but it does matter to non-linear editing software that would want the decoded audio to be consistent for editing purposes no matter where or how much it decodes.

Without CNG, the dithering would change the audio slightly every time the same audio is decoded and that can cause audible discontinuities between cuts on the NLE's timeline even if the audio across the cuts is continuous from one to the other. The discontinuities are most noticeable if the AC-3 audio is slowed down or encoded at a lower sample rate like 16KHz.
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
Jonathan Campbell


More information about the ffmpeg-devel mailing list