noise reduction of dct coefficients
authorMichael Niedermayer <michaelni@gmx.at>
Sun, 2 Nov 2003 23:19:47 +0000 (23:19 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Sun, 2 Nov 2003 23:19:47 +0000 (23:19 +0000)
Originally committed as revision 2468 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/avcodec.h
libavcodec/i386/mpegvideo_mmx.c
libavcodec/i386/mpegvideo_mmx_template.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo.h

index e3b4753..b169748 100644 (file)
@@ -16,7 +16,7 @@ extern "C" {
 
 #define FFMPEG_VERSION_INT     0x000408
 #define FFMPEG_VERSION         "0.4.8"
-#define LIBAVCODEC_BUILD       4689
+#define LIBAVCODEC_BUILD       4690
 
 #define LIBAVCODEC_VERSION_INT FFMPEG_VERSION_INT
 #define LIBAVCODEC_VERSION     FFMPEG_VERSION
@@ -1358,6 +1358,13 @@ typedef struct AVCodecContext {
      * - decoding: set by user.
      */
     struct AVPaletteControl *palctrl;
+
+    /**
+     * noise reduction strength
+     * - encoding: set by user.
+     * - decoding: unused
+     */
+    int noise_reduction;
     
 } AVCodecContext;
 
index d217e10..9302c7b 100644 (file)
@@ -495,6 +495,7 @@ static void draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, int w)
 
 #define HAVE_MMX2
 #undef RENAME
+#undef RENAMEl
 #define RENAME(a) a ## _MMX2
 #define RENAMEl(a) a ## _mmx2
 #include "mpegvideo_mmx_template.c"
index 2728a8d..f357e14 100644 (file)
@@ -45,6 +45,9 @@ static int RENAME(dct_quantize)(MpegEncContext *s,
     //s->fdct (block);
     RENAMEl(ff_fdct) (block); //cant be anything else ...
 
+    if(s->dct_error_sum)
+        ff_denoise_dct(s, block);
+
     if (s->mb_intra) {
         int dummy;
         if (n < 4)
index c131e72..e459368 100644 (file)
@@ -458,6 +458,11 @@ int MPV_common_init(MpegEncContext *s)
         CHECKED_ALLOCZ(s->q_inter_matrix16, 64*32*2 * sizeof(uint16_t))
         CHECKED_ALLOCZ(s->input_picture, MAX_PICTURE_COUNT * sizeof(Picture*))
         CHECKED_ALLOCZ(s->reordered_input_picture, MAX_PICTURE_COUNT * sizeof(Picture*))
+        
+        if(s->avctx->noise_reduction){
+            CHECKED_ALLOCZ(s->dct_error_sum, 2 * 64 * sizeof(int))
+            CHECKED_ALLOCZ(s->dct_offset, 2 * 64 * sizeof(uint16_t))
+        }
     }
     CHECKED_ALLOCZ(s->blocks, 64*6*2 * sizeof(DCTELEM))
         
@@ -588,6 +593,8 @@ void MPV_common_end(MpegEncContext *s)
     av_freep(&s->blocks);
     av_freep(&s->input_picture);
     av_freep(&s->reordered_input_picture);
+    av_freep(&s->dct_error_sum);
+    av_freep(&s->dct_offset);
 
     if(s->picture){
         for(i=0; i<MAX_PICTURE_COUNT; i++){
@@ -1034,6 +1041,23 @@ int ff_find_unused_picture(MpegEncContext *s, int shared){
     return -1;
 }
 
+static void update_noise_reduction(MpegEncContext *s){
+    int intra, i;
+
+    for(intra=0; intra<2; intra++){
+        if(s->dct_count[intra] > (1<<16)){
+            for(i=0; i<64; i++){
+                s->dct_error_sum[intra][i] >>=1;
+            }
+            s->dct_count[intra] >>= 1;
+        }
+        
+        for(i=0; i<64; i++){
+            s->dct_offset[intra][i]= (s->avctx->noise_reduction * s->dct_count[intra] + s->dct_error_sum[intra][i]/2) / (s->dct_error_sum[intra][i]+1);
+        }
+    }
+}
+
 /**
  * generic function for encode/decode called after coding/decoding the header and before a frame is coded/decoded
  */
@@ -1136,6 +1160,12 @@ alloc:
     else 
         s->dct_unquantize = s->dct_unquantize_mpeg1;
 
+    if(s->dct_error_sum){
+        assert(s->avctx->noise_reduction && s->encoding);
+
+        update_noise_reduction(s);
+    }
+        
 #ifdef HAVE_XVMC
     if(s->avctx->xvmc_acceleration)
         return XVMC_field_start(s, avctx);
@@ -4042,6 +4072,28 @@ static void encode_picture(MpegEncContext *s, int picture_number)
     }
 }
 
+void ff_denoise_dct(MpegEncContext *s, DCTELEM *block){
+    const int intra= s->mb_intra;
+    int i;
+
+    for(i=0; i<64; i++){
+        int level= block[i];
+
+        if(level){
+            if(level>0){
+                s->dct_error_sum[intra][i] += level;
+                level -= s->dct_offset[intra][i];
+                if(level<0) level=0;
+            }else{
+                s->dct_error_sum[intra][i] -= level;
+                level += s->dct_offset[intra][i];
+                if(level>0) level=0;
+            }
+            block[i]= level;
+        }
+    }
+}
+
 static int dct_quantize_trellis_c(MpegEncContext *s, 
                         DCTELEM *block, int n,
                         int qscale, int *overflow){
@@ -4070,7 +4122,10 @@ static int dct_quantize_trellis_c(MpegEncContext *s,
     const int patch_table= s->out_format == FMT_MPEG1 && !s->mb_intra;
         
     s->dsp.fdct (block);
-
+    
+    if(s->dct_error_sum)
+        ff_denoise_dct(s, block);
+    
     qmul= qscale*16;
     qadd= ((qscale-1)|1)*8;
 
@@ -4362,6 +4417,9 @@ static int dct_quantize_c(MpegEncContext *s,
 
     s->dsp.fdct (block);
 
+    if(s->dct_error_sum)
+        ff_denoise_dct(s, block);
+
     if (s->mb_intra) {
         if (!s->h263_aic) {
             if (n < 4)
index 644eeea..53254e5 100644 (file)
@@ -468,6 +468,11 @@ typedef struct MpegEncContext {
     ScanTable intra_h_scantable;
     ScanTable intra_v_scantable;
     ScanTable inter_scantable; ///< if inter == intra then intra should be used to reduce tha cache usage
+    
+    /* noise reduction */
+    int (*dct_error_sum)[64];
+    int dct_count[2];
+    uint16_t (*dct_offset)[64];
 
     void *opaque;              ///< private data for the user
 
@@ -719,6 +724,7 @@ void ff_mpeg_flush(AVCodecContext *avctx);
 void ff_print_debug_info(MpegEncContext *s, Picture *pict);
 void ff_write_quant_matrix(PutBitContext *pb, int16_t *matrix);
 int ff_find_unused_picture(MpegEncContext *s, int shared);
+void ff_denoise_dct(MpegEncContext *s, DCTELEM *block);
 
 void ff_er_frame_start(MpegEncContext *s);
 void ff_er_frame_end(MpegEncContext *s);