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

Jonathan Campbell jonathan at castus.tv
Sat Sep 7 22:24:03 CEST 2013


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?

-- Jonathan C.
> On Sat, Sep 07, 2013 at 01:21:16AM -0700, Jonathan Campbell wrote:
>> I'm writing a program to provide "random access" decoding for
>> various file formats including those involving MP3 or AC-3 and I
>> want to bring up something that might help improve the FFMPEG ABI.
>>
>> I found that I can provide sample-level random access for MP3 if,
>> when non-sequential access is needed, I just step back about 8-16
>> MP3 frames (compensating for the bit reservoir and MDCT window) and
>> decode up to the one I need. The problem is AC-3 and it's noise
>> coding. If I try the same trick with AC-3, stepping back 2-3 frames
>> so that the MDCT window can build up, no matter how precisely I do
>> it there are discontinuities between the previous decode and the
>> decode I started again from the same bitstream.
>>
>> I had written a hack for FFMPEG 1.0.1 where by setting a flag, if
>> noise bands are present, the codec seeds the RNG with a checksum of
>> the AC-3 or AAC frame and then proceeds to decode as normal. Then,
>> decoding the same AC-3 frames always results in the same PCM output,
>> and the same trick I used with MP3 then works correctly. It can be
>> set for programs that want this behavior while existing code can
>> leave it unset and maintain existing decode behavior.
>>
>> Open source video editing projects could benefit from that feature
>> when allowing the user to edit from formats and containers involving
>> these codecs.
>>
>> If I rewrite that patch for FFMPEG 1.2.2 and FFMPEG 2.0, would any
>> of you be interested in incorporating it upstream?
> yes
>
> [...]
>
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

-------------- next part --------------
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);
+
     /* 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)
 
 #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);
+	}
+    }
+    c->index = 0;
+}
+
 void av_bmg_get(AVLFG *lfg, double out[2])
 {
     double x1, x2, w;
diff -r -u ffmpeg-1.2.3.old/libavutil/lfg.h ffmpeg-1.2.3/libavutil/lfg.h
--- ffmpeg-1.2.3.old/libavutil/lfg.h	2013-08-10 16:23:28.000000000 -0700
+++ ffmpeg-1.2.3/libavutil/lfg.h	2013-09-07 12:50:54.731128225 -0700
@@ -28,6 +28,7 @@
 } 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