[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