diff mbox

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

Message ID 57C8DD12.7030104@impactstudiopro.com
State Superseded
Headers show

Commit Message

Jonathan Campbell Sept. 2, 2016, 1:59 a.m. UTC
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@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:

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 },

Comments

Michael Niedermayer Sept. 2, 2016, 2:13 a.m. UTC | #1
On Thu, Sep 01, 2016 at 06:59:46PM -0700, Jonathan Campbell 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@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));

patch looks newline garbled

[...]
Jonathan Campbell Sept. 2, 2016, 2:28 a.m. UTC | #2
On 09/01/2016 07:13 PM, Michael Niedermayer wrote:
> On Thu, Sep 01, 2016 at 06:59:46PM -0700, Jonathan Campbell 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@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));
> patch looks newline garbled
>
> [...]
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Yeah, figured that would happen.

Can you accept patches directly from Github?

https://github.com/joncampbell123/FFmpeg/commit/dbd086586f0ad1591ea2013293bbb6e4dbfd0455.patch

Jonathan Campbell
Jonathan Campbell Sept. 2, 2016, 2:34 a.m. UTC | #3
On 09/01/2016 07:13 PM, Michael Niedermayer wrote:
> On Thu, Sep 01, 2016 at 06:59:46PM -0700, Jonathan Campbell 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@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));
> patch looks newline garbled
>
> [...]
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Figured that would happen.

Can you accept patches directly from Github?

https://github.com/joncampbell123/FFmpeg/commit/dbd086586f0ad1591ea2013293bbb6e4dbfd0455.patch 


Jonathan Campbell
Michael Niedermayer Sept. 2, 2016, 11:50 a.m. UTC | #4
On Thu, Sep 01, 2016 at 06:59:46PM -0700, Jonathan Campbell 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@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)));

av_lfg_init involves md5 which is slow and not apropriate to be
executed per frame, this would double the time to decode a frame

 965641 decicycles in rndint,      64 runs,      0 skips 
2375023 decicycles in FRAME,      64 runs,      0 skips


write/use a faster way to init the LFG please 


[...]
Jonathan Campbell Sept. 2, 2016, 5:18 p.m. UTC | #5
CRC computation isn't fast enough? What should I use then? A sum of byte 
values?

Jonathan Campbell
CASTUS

On 09/02/2016 04:50 AM, Michael Niedermayer wrote:
> On Thu, Sep 01, 2016 at 06:59:46PM -0700, Jonathan Campbell 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@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)));
> av_lfg_init involves md5 which is slow and not apropriate to be
> executed per frame, this would double the time to decode a frame
>
>   965641 decicycles in rndint,      64 runs,      0 skips
> 2375023 decicycles in FRAME,      64 runs,      0 skips
>
>
> write/use a faster way to init the LFG please
>
>
> [...]
>
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Jonathan Campbell Sept. 2, 2016, 5:19 p.m. UTC | #6
On 09/02/2016 04:50 AM, Michael Niedermayer wrote:
> On Thu, Sep 01, 2016 at 06:59:46PM -0700, Jonathan Campbell 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@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)));
> av_lfg_init involves md5 which is slow and not apropriate to be
> executed per frame, this would double the time to decode a frame
>
>   965641 decicycles in rndint,      64 runs,      0 skips
> 2375023 decicycles in FRAME,      64 runs,      0 skips
>
>
> write/use a faster way to init the LFG please
>
>
> [...]
>
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
(sorry..)

CRC computation isn't fast enough? What should I use then? A sum of byte 
values?

Jonathan Campbell
CASTUS
Michael Niedermayer Sept. 2, 2016, 8:01 p.m. UTC | #7
On Fri, Sep 02, 2016 at 10:19:23AM -0700, Jonathan Campbell wrote:
[...]
> CRC computation isn't fast enough? What should I use then? A sum of
> byte values?

av_lfg_init() calls av_md5_sum()
av_md5_sum() is too slow to be called per ac3 frame

[...]
Jonathan Campbell Sept. 2, 2016, 8:13 p.m. UTC | #8
On 09/02/2016 01:01 PM, Michael Niedermayer wrote:
> On Fri, Sep 02, 2016 at 10:19:23AM -0700, Jonathan Campbell wrote:
> [...]
>> CRC computation isn't fast enough? What should I use then? A sum of
>> byte values?
> av_lfg_init() calls av_md5_sum()
> av_md5_sum() is too slow to be called per ac3 frame
>
> [...]
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Then for this to work at better performance, I'm going to have to either 
directly modify the AVLFG struct state (probably not a good idea), or 
add a function to libavutil/lfg.c that allows "fast seeding" without the 
use of MD5 which could probably be something as simple as copy the 
32-bit seed 16 times through c->state[] with or without modification 
during the loop. Sound good?

Jonathan Campbell
CASTUS
Michael Niedermayer Sept. 2, 2016, 8:56 p.m. UTC | #9
On Fri, Sep 02, 2016 at 01:13:33PM -0700, Jonathan Campbell wrote:
> 
> On 09/02/2016 01:01 PM, Michael Niedermayer wrote:
> >On Fri, Sep 02, 2016 at 10:19:23AM -0700, Jonathan Campbell wrote:
> >[...]
> >>CRC computation isn't fast enough? What should I use then? A sum of
> >>byte values?
> >av_lfg_init() calls av_md5_sum()
> >av_md5_sum() is too slow to be called per ac3 frame
> >
> >[...]
> >
> >
> >_______________________________________________
> >ffmpeg-devel mailing list
> >ffmpeg-devel@ffmpeg.org
> >http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> Then for this to work at better performance, I'm going to have to
> either directly modify the AVLFG struct state (probably not a good
> idea), or add a function to libavutil/lfg.c that allows "fast
> seeding" without the use of MD5 which could probably be something as
> simple as copy the 32-bit seed 16 times through c->state[] with or
> without modification during the loop. Sound good?

yes, something like this
probably spliting the input into 16 parts get 16 CRCs and use them
instead of replication is probably better


[...]
Jonathan Campbell Sept. 2, 2016, 11:05 p.m. UTC | #10
On 09/02/2016 01:56 PM, Michael Niedermayer wrote:
> On Fri, Sep 02, 2016 at 01:13:33PM -0700, Jonathan Campbell wrote:
>> On 09/02/2016 01:01 PM, Michael Niedermayer wrote:
>>> On Fri, Sep 02, 2016 at 10:19:23AM -0700, Jonathan Campbell wrote:
>>> [...]
>>>> CRC computation isn't fast enough? What should I use then? A sum of
>>>> byte values?
>>> av_lfg_init() calls av_md5_sum()
>>> av_md5_sum() is too slow to be called per ac3 frame
>>>
>>> [...]
>>>
>>>
>>> _______________________________________________
>>> ffmpeg-devel mailing list
>>> ffmpeg-devel@ffmpeg.org
>>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> Then for this to work at better performance, I'm going to have to
>> either directly modify the AVLFG struct state (probably not a good
>> idea), or add a function to libavutil/lfg.c that allows "fast
>> seeding" without the use of MD5 which could probably be something as
>> simple as copy the 32-bit seed 16 times through c->state[] with or
>> without modification during the loop. Sound good?
> yes, something like this
> probably spliting the input into 16 parts get 16 CRCs and use them
> instead of replication is probably better
>
>
> [...]
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
How's this:

void av_lfg_init_from_data(AVLFG *c, const unsigned char *data, unsigned 
int length) {
     unsigned int beg, end, segm;
     const AVCRC *avcrc;
     uint32_t crc = 0;

     avcrc = av_crc_get_table(AV_CRC_32_IEEE);
     if (avcrc == NULL) return;

     /* try to avoid integer overflow during the segmented crc loop below.
      * the code below would break if "end" went backwards before "beg". */
     if (length > (UINT_MAX / 128U)) return;

     /* across 64 pieces of the incoming data,
      * do a running crc of each segment and store the crc as the state 
for that slot.
      * this works even if the length of the piece is 0 bytes. */
     beg = 0;
     for (segm = 0;segm < 64;segm++) {
         end = (((segm + 1) * length) / 64);
         crc = av_crc(avcrc, crc, data + beg, end - beg);
         c->state[segm] = (unsigned int)crc;
         beg = end;
     }
}

I also realize that c->state[] is an array of 64 unsigned ints, not 64 
bytes.
A running CRC over the data is used to fill in all 64 slots of the LFG. 
This code should work correctly even if any one of the 64 "slots" is 
computed from 0 bytes of the source (when length < 64).

Jonathan Campbell
Michael Niedermayer Sept. 2, 2016, 11:37 p.m. UTC | #11
On Fri, Sep 02, 2016 at 04:05:44PM -0700, Jonathan Campbell wrote:
> 
> On 09/02/2016 01:56 PM, Michael Niedermayer wrote:
> >On Fri, Sep 02, 2016 at 01:13:33PM -0700, Jonathan Campbell wrote:
> >>On 09/02/2016 01:01 PM, Michael Niedermayer wrote:
> >>>On Fri, Sep 02, 2016 at 10:19:23AM -0700, Jonathan Campbell wrote:
> >>>[...]
> >>>>CRC computation isn't fast enough? What should I use then? A sum of
> >>>>byte values?
> >>>av_lfg_init() calls av_md5_sum()
> >>>av_md5_sum() is too slow to be called per ac3 frame
> >>>
> >>>[...]
> >>>
> >>>
> >>>_______________________________________________
> >>>ffmpeg-devel mailing list
> >>>ffmpeg-devel@ffmpeg.org
> >>>http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >>Then for this to work at better performance, I'm going to have to
> >>either directly modify the AVLFG struct state (probably not a good
> >>idea), or add a function to libavutil/lfg.c that allows "fast
> >>seeding" without the use of MD5 which could probably be something as
> >>simple as copy the 32-bit seed 16 times through c->state[] with or
> >>without modification during the loop. Sound good?
> >yes, something like this
> >probably spliting the input into 16 parts get 16 CRCs and use them
> >instead of replication is probably better
> >
> >
> >[...]
> >
> >
> >_______________________________________________
> >ffmpeg-devel mailing list
> >ffmpeg-devel@ffmpeg.org
> >http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> How's this:
> 
> void av_lfg_init_from_data(AVLFG *c, const unsigned char *data,
> unsigned int length) {
>     unsigned int beg, end, segm;
>     const AVCRC *avcrc;

>     uint32_t crc = 0;

1 might be better

should be ok otherwise didnt review it deeply though

[...]
Rostislav Pehlivanov Sept. 3, 2016, 8:32 p.m. UTC | #12
On 2 September 2016 at 02:59, Jonathan Campbell <
jonathan@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@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@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>

Any random noise, hardcoded constant or not sill sounds like white noise.
What is the point of this patch?
Jonathan Campbell Sept. 3, 2016, 10:23 p.m. UTC | #13
On 09/03/2016 01:32 PM, Rostislav Pehlivanov wrote:
> On 2 September 2016 at 02:59, Jonathan Campbell <
> jonathan@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@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@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@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
Jonathan Campbell
diff mbox

Patch

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",