[FFmpeg-devel] [PATCH] Deterministic Noise Generation option for audio codecs that involve noise generation (RNG)

Jonathan Campbell jonathan at castus.tv
Sun Sep 8 06:14:20 CEST 2013


Got it.

Here's the same patch developed against the FFMPEG git master branch (as 
of commit ffde17e70fd9585775cd6cc79faebb5dc743d298 on 
git://source.ffmpeg.org/ffmpeg.git)

Same changes apply.

-- Jonathan C.
> On Sat, Sep 07, 2013 at 01:24:03PM -0700, Jonathan Campbell wrote:
>> Here you go.
>>
>> This patch adds:
>>
>> -a function to libavutil's linear feedback generator to initialize a
>> known state from binary data and a frame counter value.
>> - two flags to libavcodec/avcodec.h to enable deterministic noise
>> generation and another flag to be implemented in the future to
>> disable noise band coding entirely.
>> - two lines of code to ac3dec.c to seed the LFG on decode to the
>> AC-3 frame and the AVContext frame number.
>>
>> It is written to patch against FFMPEG 1.2.3. Do you need me to make
>> another patch for FFMPEG 2.0.1 or can you guys handle that?
> patches must be against git master or rather they have to apply to
> git master and work.
> releases only receive backports from master.
>
> more comments below
> [...]
>
>> 671cd059b5d1446f2dbc8905bdd6ddef3f23cf02  ffmpeg-1.2.3-codec-flag2-dng.patch
>> diff -r -u ffmpeg-1.2.3.old/libavcodec/ac3dec.c ffmpeg-1.2.3/libavcodec/ac3dec.c
>> --- ffmpeg-1.2.3.old/libavcodec/ac3dec.c	2013-08-26 17:13:44.000000000 -0700
>> +++ ffmpeg-1.2.3/libavcodec/ac3dec.c	2013-09-07 12:50:45.194293510 -0700
>> @@ -1380,6 +1380,10 @@
>>           return ret;
>>       }
>>   
>> +    /* if Deterministic Noise Generation is enabled, then seed the RNG from the input frame */
>> +    if (avctx->flags2 & CODEC_FLAG2_DNG)
>> +	av_lfg_init_from_binary_data_and_frame_number(&s->dith_state,buf,s->frame_size,avctx->frame_number);
> tabs are not allowed in ffmpeg git (except in Makefiles)
>
>
>> +
>>       /* decode the audio blocks */
>>       channel_map = ff_ac3_dec_channel_map[s->output_mode & ~AC3_OUTPUT_LFEON][s->lfe_on];
>>       for (ch = 0; ch < AC3_MAX_CHANNELS; ch++) {
>> diff -r -u ffmpeg-1.2.3.old/libavcodec/avcodec.h ffmpeg-1.2.3/libavcodec/avcodec.h
>> --- ffmpeg-1.2.3.old/libavcodec/avcodec.h	2013-08-26 17:13:44.000000000 -0700
>> +++ ffmpeg-1.2.3/libavcodec/avcodec.h	2013-09-07 12:53:11.816875961 -0700
>> @@ -718,6 +718,8 @@
>>   #define CODEC_FLAG2_LOCAL_HEADER  0x00000008 ///< Place global headers at every keyframe instead of in extradata.
>>   #define CODEC_FLAG2_DROP_FRAME_TIMECODE 0x00002000 ///< timecode is in drop frame format. DEPRECATED!!!!
>>   #define CODEC_FLAG2_IGNORE_CROP   0x00010000 ///< Discard cropping information from SPS.
>> +#define CODEC_FLAG2_DNG           0x00020000 ///< Enable Deterministic Noise Generation.
>> +#define CODEC_FLAG2_NO_NOISE      0x00040000 ///< Disable noise coding (XXX not yet implemented)
> please dont add any flags, the flag systems is rather unflexible and
> the number of flags limited to 32
>
>
>>   
>>   #if FF_API_MPV_GLOBAL_OPTS
>>   #define CODEC_FLAG_CBP_RD         0x04000000 ///< Use rate distortion optimization for cbp.
>> diff -r -u ffmpeg-1.2.3.old/libavutil/lfg.c ffmpeg-1.2.3/libavutil/lfg.c
>> --- ffmpeg-1.2.3.old/libavutil/lfg.c	2013-08-10 16:23:28.000000000 -0700
>> +++ ffmpeg-1.2.3/libavutil/lfg.c	2013-09-07 12:51:04.334630770 -0700
>> @@ -44,6 +44,26 @@
>>       c->index = 0;
>>   }
>>   
>> +av_cold void av_lfg_init_from_binary_data_and_frame_number(AVLFG *c, unsigned char *data,unsigned int data_length,unsigned int counter)
>> +{
>> +    uint8_t tmp[16] = { 0 };
>> +    int i;
>> +
>> +    av_md5_sum(tmp, data, data_length);
>> +    for (i = 8; i < 64; i += 4) {
>> +        c->state[i    ] = AV_RL32(tmp);
>> +        c->state[i + 1] = AV_RL32(tmp + 4);
>> +        c->state[i + 2] = AV_RL32(tmp + 8);
>> +        c->state[i + 3] = AV_RL32(tmp + 12);
>> +	if (i != 60) {
>> +            tmp[4] = i;
>> +	    if (counter != 0 && (i&1) == 0) AV_WL32(tmp+6,counter); /* XXX: Is there a better way? */
>> +	    av_md5_sum(tmp, tmp, 16);
>> +	}
>> +    }
> md5 is slow, running it over the whole frame is overkill
> libavutil/murmur3.c might be an alternative
>
> [...]
>
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

-------------- next part --------------
diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
index 20b4b61..faf068a 100644
--- a/libavcodec/ac3dec.c
+++ b/libavcodec/ac3dec.c
@@ -1381,6 +1381,10 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
         return ret;
 
+    /* if Deterministic Noise Generation is enabled, then seed the RNG from the input frame */
+    if (avctx->flags2 & CODEC_FLAG2_DNG)
+	av_lfg_init_from_binary_data_and_frame_number(&s->dith_state,buf,s->frame_size,avctx->frame_number);
+
     /* decode the audio blocks */
     channel_map = ff_ac3_dec_channel_map[s->output_mode & ~AC3_OUTPUT_LFEON][s->lfe_on];
     for (ch = 0; ch < AC3_MAX_CHANNELS; ch++) {
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 572c5fd..7e66301 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -716,6 +716,8 @@ typedef struct RcOverride{
 #define CODEC_FLAG2_LOCAL_HEADER  0x00000008 ///< Place global headers at every keyframe instead of in extradata.
 #define CODEC_FLAG2_DROP_FRAME_TIMECODE 0x00002000 ///< timecode is in drop frame format. DEPRECATED!!!!
 #define CODEC_FLAG2_IGNORE_CROP   0x00010000 ///< Discard cropping information from SPS.
+#define CODEC_FLAG2_DNG           0x00020000 ///< Enable Deterministic Noise Generation.
+#define CODEC_FLAG2_NO_NOISE      0x00040000 ///< Disable noise coding (XXX not yet implemented)
 
 #define CODEC_FLAG2_CHUNKS        0x00008000 ///< Input bitstream might be truncated at a packet boundaries instead of only at frame boundaries.
 #define CODEC_FLAG2_SHOW_ALL      0x00400000 ///< Show all frames before the first keyframe
diff --git a/libavutil/lfg.c b/libavutil/lfg.c
index ffa2f1f..8debbb4 100644
--- a/libavutil/lfg.c
+++ b/libavutil/lfg.c
@@ -44,6 +44,26 @@ av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
     c->index = 0;
 }
 
+av_cold void av_lfg_init_from_binary_data_and_frame_number(AVLFG *c, unsigned char *data,unsigned int data_length,unsigned int counter)
+{
+    uint8_t tmp[16] = { 0 };
+    int i;
+
+    av_md5_sum(tmp, data, data_length);
+    for (i = 8; i < 64; i += 4) {
+        c->state[i    ] = AV_RL32(tmp);
+        c->state[i + 1] = AV_RL32(tmp + 4);
+        c->state[i + 2] = AV_RL32(tmp + 8);
+        c->state[i + 3] = AV_RL32(tmp + 12);
+	if (i != 60) {
+            tmp[4] = i;
+	    if (counter != 0 && (i&1) == 0) AV_WL32(tmp+6,counter); /* XXX: Is there a better way? */
+	    av_md5_sum(tmp, tmp, 16);
+	}
+    }
+    c->index = 0;
+}
+
 void av_bmg_get(AVLFG *lfg, double out[2])
 {
     double x1, x2, w;
diff --git a/libavutil/lfg.h b/libavutil/lfg.h
index ec90562..1cc38da 100644
--- a/libavutil/lfg.h
+++ b/libavutil/lfg.h
@@ -28,6 +28,7 @@ typedef struct AVLFG {
 } AVLFG;
 
 void av_lfg_init(AVLFG *c, unsigned int seed);
+void av_lfg_init_from_binary_data_and_frame_number(AVLFG *c, unsigned char *data,unsigned int data_length,unsigned int counter);
 
 /**
  * Get the next random unsigned 32-bit number using an ALFG.


More information about the ffmpeg-devel mailing list