[MPlayer-dev-eng] [PATCH] denoise3d increaed precission

Arpi arpi at thot.banki.hu
Sun Feb 9 15:36:23 CET 2003


Hi,

I've spent some (too much) time optimizing denoise3d.c, and especially
increasing the precission of the calculations, since i can see accumulated
rounding errors on the screen sometimes.
The reason is simple. The main equation it uses is LowPass, after cleanup:

#define LowPass(Prev, Curr, Coef) (Curr + Coef[Prev - Curr])

Curr is the current pixel, (Prev - Curr) is the difference from
left/top/previousframe pixel. SO teh crrection factor (Coeff[]) depends
on the pixel difference, which is often a small number, mostly in -5..+5
range. It means quite high rounding errors (+-0.5 compared to +-5)...

Ok, i've changed it to use 16.16 fixed point and 16 times bigger Coeff[]
table. Patch for testing/optinions/etc:
( do not commit this because it's freezee, and it may be slower or even
buggy at some contexts )

Index: vf_denoise3d.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpcodecs/vf_denoise3d.c,v
retrieving revision 1.4
diff -u -r1.4 vf_denoise3d.c
--- vf_denoise3d.c	9 Feb 2003 12:51:59 -0000	1.4
+++ vf_denoise3d.c	9 Feb 2003 14:30:11 -0000
@@ -41,8 +41,8 @@
 //===========================================================================//
 
 struct vf_priv_s {
-        int Coefs[4][512];
-        unsigned char *Line;
+        int Coefs[4][512*16];
+        unsigned int *Line;
 	mp_image_t *pmpi;
 };
 
@@ -55,7 +55,7 @@
 	unsigned int flags, unsigned int outfmt){
 
 	if(vf->priv->Line) free(vf->priv->Line);
-        vf->priv->Line = malloc(width);
+        vf->priv->Line = malloc(width*sizeof(int));
 	vf->priv->pmpi=NULL;
 //        vf->default_caps &= !VFCAP_ACCEPT_STRIDE;
 
@@ -68,46 +68,57 @@
     free(vf->priv->Line);
 }
 
-#define LowPass(Prev, Curr, Coef) (Curr + Coef[Prev - Curr])
+static inline unsigned int LowPassMul(unsigned int PrevMul, unsigned int CurrMul, int* Coef){
+//    int dMul= (PrevMul&0xFFFFFF)-(CurrMul&0xFFFFFF);
+    int dMul= PrevMul-CurrMul;
+    int d=((dMul+0x10007FF)/(65536/16));
+    return CurrMul + Coef[d];
+}
+
+static inline unsigned char LowPassMulPix(unsigned int PrevMul, unsigned int CurrMul, int* Coef){
+    int x=LowPassMul(PrevMul,CurrMul,Coef);
+    unsigned int r=((x+0x10007FFF)/65536);
+    return r; // & 0xFF;
+}
 
 static void deNoise(unsigned char *Frame,        // mpi->planes[x]
                     unsigned char *FramePrev,    // pmpi->planes[x]
                     unsigned char *FrameDest,    // dmpi->planes[x]
-                    unsigned char *LineAnt,      // vf->priv->Line (width bytes)
+                    unsigned int *LineAnt,      // vf->priv->Line (width bytes)
                     int W, int H, int sStride, int pStride, int dStride,
                     int *Horizontal, int *Vertical, int *Temporal)
 {
     int X, Y;
     int sLineOffs = 0, pLineOffs = 0, dLineOffs = 0;
-    unsigned char PixelAnt;
+    unsigned int PixelAnt;
 
     /* First pixel has no left nor top neightbour. Only previous frame */
-    LineAnt[0] = PixelAnt = Frame[0];
-    FrameDest[0] = LowPass(FramePrev[0], LineAnt[0], Temporal);
+    LineAnt[0] = PixelAnt = Frame[0]<<16;
+    FrameDest[0] = LowPassMulPix(FramePrev[0]<<16, PixelAnt, Temporal);
 
     /* Fist line has no top neightbour. Only left one for each pixel and
      * last frame */
     for (X = 1; X < W; X++)
     {
-        PixelAnt = LowPass(PixelAnt, Frame[X], Horizontal);
+        PixelAnt = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal);
         LineAnt[X] = PixelAnt;
-        FrameDest[X] = LowPass(FramePrev[X], LineAnt[X], Temporal);
+        FrameDest[X] = LowPassMulPix(FramePrev[X]<<16, LineAnt[X], Temporal);
     }
 
     for (Y = 1; Y < H; Y++)
     {
 	sLineOffs += sStride, pLineOffs += pStride, dLineOffs += dStride;
         /* First pixel on each line doesn't have previous pixel */
-        PixelAnt = Frame[sLineOffs];
-        LineAnt[0] = LowPass(LineAnt[0], PixelAnt, Vertical);
-        FrameDest[dLineOffs] = LowPass(FramePrev[pLineOffs], LineAnt[0], Temporal);
+        PixelAnt = Frame[sLineOffs]<<16;
+        LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
+        FrameDest[dLineOffs] = LowPassMulPix(FramePrev[pLineOffs]<<16, LineAnt[0], Temporal);
 
         for (X = 1; X < W; X++)
         {
             /* The rest are normal */
-            PixelAnt = LowPass(PixelAnt, Frame[sLineOffs+X], Horizontal);
-            LineAnt[X] = LowPass(LineAnt[X], PixelAnt, Vertical);
-            FrameDest[dLineOffs+X] = LowPass(FramePrev[pLineOffs+X], LineAnt[X], Temporal);
+            PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal);
+            LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical);
+            FrameDest[dLineOffs+X] = LowPassMulPix(FramePrev[pLineOffs+X]<<16, LineAnt[X], Temporal);
         }
     }
 }
@@ -129,21 +140,21 @@
         deNoise(mpi->planes[0], vf->priv->pmpi->planes[0], dmpi->planes[0],
 		vf->priv->Line, W, H,
                 mpi->stride[0], vf->priv->pmpi->stride[0], dmpi->stride[0],
-                vf->priv->Coefs[0] + 256,
-                vf->priv->Coefs[0] + 256,
-                vf->priv->Coefs[1] + 256);
+                vf->priv->Coefs[0],
+                vf->priv->Coefs[0],
+                vf->priv->Coefs[1]);
         deNoise(mpi->planes[1], vf->priv->pmpi->planes[1], dmpi->planes[1],
 		vf->priv->Line, cw, ch,
                 mpi->stride[1], vf->priv->pmpi->stride[1], dmpi->stride[1],
-                vf->priv->Coefs[2] + 256,
-                vf->priv->Coefs[2] + 256,
-                vf->priv->Coefs[3] + 256);
+                vf->priv->Coefs[2],
+                vf->priv->Coefs[2],
+                vf->priv->Coefs[3]);
         deNoise(mpi->planes[2], vf->priv->pmpi->planes[2], dmpi->planes[2],
 		vf->priv->Line, cw, ch,
                 mpi->stride[2], vf->priv->pmpi->stride[2], dmpi->stride[2],
-                vf->priv->Coefs[2] + 256,
-                vf->priv->Coefs[2] + 256,
-                vf->priv->Coefs[3] + 256);
+                vf->priv->Coefs[2],
+                vf->priv->Coefs[2],
+                vf->priv->Coefs[3]);
 
 	vf->priv->pmpi=dmpi; // save reference image
 	return vf_next_put_image(vf,dmpi);
@@ -176,12 +187,11 @@
 
     Gamma = log(0.25) / log(1.0 - Dist25/255.0);
 
-    for (i = -256; i <= 255; i++)
+    for (i = -256*16; i < 256*16; i++)
     {
-        Simil = 1.0 - ABS(i) / 255.0;
-//        Ct[256+i] = lround(pow(Simil, Gamma) * (double)i);
-        C = pow(Simil, Gamma) * (double)i;
-        Ct[256+i] = (C<0) ? (C-0.5) : (C+0.5);
+        Simil = 1.0 - ABS(i) / (16*255.0);
+        C = pow(Simil, Gamma) * 65536.0 * (double)i / 16.0;
+        Ct[16*256+i] = (C<0) ? (C-0.5) : (C+0.5);
     }
 }
 


A'rpi / Astral & ESP-team

--
Developer of MPlayer, the Movie Player for Linux - http://www.MPlayerHQ.hu
    "However, many people beg for its inclusion in Debian. Why?" - Gabucino
  "Because having new software in Debian is good." - Josselin Mouette
"Because having good software in Debian is new." - Gabucino


More information about the MPlayer-dev-eng mailing list