[FFmpeg-devel] CNG (consistent noise generation) patch for AC-3 decoder
Jonathan Campbell
jonathan at impactstudiopro.com
Sun Sep 4 01:45:17 EEST 2016
On 09/03/2016 07:07 AM, James Almer wrote:
> On 9/3/2016 7:50 AM, Jonathan Campbell wrote:
>> +int av_lfg_init_from_data(AVLFG *c, const uint8_t *data, unsigned int length) {
>> + unsigned int beg, end, segm;
>> + const AVCRC *avcrc;
>> + uint32_t crc = 1;
>> +
>> + c->index = 0;
>
> The AVLFG struct should IMO remain untouched if init is guaranteed to fail,
> as it would be the case with an out or range length value, so move this after
> that check.
>
>> + avcrc = av_crc_get_table(AV_CRC_32_IEEE); /* This can't fail. It's a well-defined table in crc.c */
>
> You could also move this one below.
>
>> +
>> + /* avoid integer overflow in the loop below. */
>> + if (length > (UINT_MAX / 128U)) return AVERROR(EINVAL);
>> +
>> + /* across 64 segments 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 segment 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);
>
> The thing about speed made me wonder, wouldn't using adler32 be faster?
> If so, this feature could maybe even be enabled by default with it.
>
>> + c->state[segm] = (unsigned int)crc;
>> + beg = end;
>> + }
>> +
>> + return 0;
>> +}
>> diff --git a/libavutil/lfg.h b/libavutil/lfg.h
>> index ec90562..72eb673 100644
>> --- a/libavutil/lfg.h
>> +++ b/libavutil/lfg.h
>> @@ -22,6 +22,8 @@
>> #ifndef AVUTIL_LFG_H
>> #define AVUTIL_LFG_H
>>
>> +#include <stdint.h> /* uint8_t type */
>> +
>> typedef struct AVLFG {
>> unsigned int state[64];
>> int index;
>> @@ -29,6 +31,13 @@ typedef struct AVLFG {
>>
>> void av_lfg_init(AVLFG *c, unsigned int seed);
>>
>> +/*
>
> This is meant for doxygen, so /** like in every other function.
>
>> + * Seed the state of the ALFG using binary data.
>> + *
>> + * Return value: 0 on success, negative value (AVERROR) on failure.
>> + */
>> +int av_lfg_init_from_data(AVLFG *c, const uint8_t *data, unsigned int length);
>> +
>> /**
>> * Get the next random unsigned 32-bit number using an ALFG.
>> *
>
> No more comments for me.
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
Here you go.
Jonathan Campbell
-------------- next part --------------
From 5de30d309fb48b26acd8d95f14ef4d4064450ddc Mon Sep 17 00:00:00 2001
From: Jonathan Campbell <jonathan at castus.tv>
Date: Sat, 3 Sep 2016 03:20:41 -0700
Subject: [PATCH 1/4] libavutil version bump, av_lfg_init_from_data() incoming
---
libavutil/version.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libavutil/version.h b/libavutil/version.h
index 7d32c7b..60b58eb 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 55
-#define LIBAVUTIL_VERSION_MINOR 29
+#define LIBAVUTIL_VERSION_MINOR 30
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
--
2.2.2
-------------- next part --------------
From 3cc9a0e4a8bae127ca9254f31cd8b7f00d107395 Mon Sep 17 00:00:00 2001
From: Jonathan Campbell <jonathan at castus.tv>
Date: Sat, 3 Sep 2016 03:29:29 -0700
Subject: [PATCH 2/4] libavutil av_lfg_init_from_data() function
seeds an AVLFG from binary data.
---
libavutil/lfg.c | 27 +++++++++++++++++++++++++++
libavutil/lfg.h | 9 +++++++++
2 files changed, 36 insertions(+)
diff --git a/libavutil/lfg.c b/libavutil/lfg.c
index 08a4f67..0ef456a 100644
--- a/libavutil/lfg.c
+++ b/libavutil/lfg.c
@@ -23,7 +23,9 @@
#include <limits.h>
#include <math.h>
#include "lfg.h"
+#include "crc.h"
#include "md5.h"
+#include "error.h"
#include "intreadwrite.h"
#include "attributes.h"
@@ -58,3 +60,28 @@ void av_bmg_get(AVLFG *lfg, double out[2])
out[0] = x1 * w;
out[1] = x2 * w;
}
+
+int av_lfg_init_from_data(AVLFG *c, const uint8_t *data, unsigned int length) {
+ unsigned int beg, end, segm;
+ const AVCRC *avcrc;
+ uint32_t crc = 1;
+
+ c->index = 0;
+ avcrc = av_crc_get_table(AV_CRC_32_IEEE); /* This can't fail. It's a well-defined table in crc.c */
+
+ /* avoid integer overflow in the loop below. */
+ if (length > (UINT_MAX / 128U)) return AVERROR(EINVAL);
+
+ /* across 64 segments 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 segment 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;
+ }
+
+ return 0;
+}
diff --git a/libavutil/lfg.h b/libavutil/lfg.h
index ec90562..72eb673 100644
--- a/libavutil/lfg.h
+++ b/libavutil/lfg.h
@@ -22,6 +22,8 @@
#ifndef AVUTIL_LFG_H
#define AVUTIL_LFG_H
+#include <stdint.h> /* uint8_t type */
+
typedef struct AVLFG {
unsigned int state[64];
int index;
@@ -29,6 +31,13 @@ typedef struct AVLFG {
void av_lfg_init(AVLFG *c, unsigned int seed);
+/*
+ * Seed the state of the ALFG using binary data.
+ *
+ * Return value: 0 on success, negative value (AVERROR) on failure.
+ */
+int av_lfg_init_from_data(AVLFG *c, const uint8_t *data, unsigned int length);
+
/**
* Get the next random unsigned 32-bit number using an ALFG.
*
--
2.2.2
-------------- next part --------------
From eb8b354c5edf9c876f3e4a209ec617500776fcf2 Mon Sep 17 00:00:00 2001
From: Jonathan Campbell <jonathan at castus.tv>
Date: Sat, 3 Sep 2016 03:34:01 -0700
Subject: [PATCH 3/4] ac3dec consistent noise generation option.
use av_lfg_init_from_data() to seed AC-3 dithering from the AC-3 frame
data to make it consistent given the same AC-3 frame, if option is set.
---
libavcodec/ac3dec.c | 7 +++++++
libavcodec/ac3dec.h | 4 ++++
libavcodec/ac3dec_fixed.c | 1 +
libavcodec/ac3dec_float.c | 1 +
4 files changed, 13 insertions(+)
diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
index fac189b..18a674b 100644
--- a/libavcodec/ac3dec.c
+++ b/libavcodec/ac3dec.c
@@ -1419,6 +1419,13 @@ 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)
+ av_lfg_init_from_data(&s->dith_state, s->input_buffer, FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE));
+
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 },
--
2.2.2
-------------- next part --------------
From 0ea7866d26746ce50ce7fe98fea3b82d1052b5a8 Mon Sep 17 00:00:00 2001
From: Jonathan Campbell <jonathan at castus.tv>
Date: Sat, 3 Sep 2016 15:35:48 -0700
Subject: [PATCH 4/4] don't modify AVLFG state until committed to carrying out
the init.
---
libavutil/lfg.c | 6 +++---
libavutil/lfg.h | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/libavutil/lfg.c b/libavutil/lfg.c
index 0ef456a..46b04d2 100644
--- a/libavutil/lfg.c
+++ b/libavutil/lfg.c
@@ -66,12 +66,12 @@ int av_lfg_init_from_data(AVLFG *c, const uint8_t *data, unsigned int length) {
const AVCRC *avcrc;
uint32_t crc = 1;
- c->index = 0;
- avcrc = av_crc_get_table(AV_CRC_32_IEEE); /* This can't fail. It's a well-defined table in crc.c */
-
/* avoid integer overflow in the loop below. */
if (length > (UINT_MAX / 128U)) return AVERROR(EINVAL);
+ c->index = 0;
+ avcrc = av_crc_get_table(AV_CRC_32_IEEE); /* This can't fail. It's a well-defined table in crc.c */
+
/* across 64 segments 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 segment is 0 bytes. */
diff --git a/libavutil/lfg.h b/libavutil/lfg.h
index 72eb673..1eaa7ba 100644
--- a/libavutil/lfg.h
+++ b/libavutil/lfg.h
@@ -22,7 +22,7 @@
#ifndef AVUTIL_LFG_H
#define AVUTIL_LFG_H
-#include <stdint.h> /* uint8_t type */
+#include <stdint.h>
typedef struct AVLFG {
unsigned int state[64];
--
2.2.2
More information about the ffmpeg-devel
mailing list