diff --git a/libmpcodecs/vf_hqdn3d.c b/libmpcodecs/vf_hqdn3d.c index ce59d0f66e..4a3168f132 100644 --- a/libmpcodecs/vf_hqdn3d.c +++ b/libmpcodecs/vf_hqdn3d.c @@ -73,6 +73,68 @@ static inline unsigned int LowPassMul(unsigned int PrevMul, unsigned int CurrMul return CurrMul + Coef[d]; } +static void deNoiseTemporal( + unsigned char *Frame, // mpi->planes[x] + unsigned char *FrameDest, // dmpi->planes[x] + unsigned short *FrameAnt, + int W, int H, int sStride, int dStride, + int *Temporal) +{ + int X, Y; + int PixelDst; + + for (Y = 0; Y < H; Y++){ + for (X = 0; X < W; X++){ + PixelDst = LowPassMul(FrameAnt[X]<<8, Frame[X]<<16, Temporal); + FrameAnt[X] = ((PixelDst+0x1000007F)/256); + FrameDest[X]= ((PixelDst+0x10007FFF)/65536); + } + Frame += sStride; + FrameDest += dStride; + FrameAnt += W; + } +} + +static void deNoiseSpacial( + unsigned char *Frame, // mpi->planes[x] + unsigned char *FrameDest, // dmpi->planes[x] + unsigned int *LineAnt, // vf->priv->Line (width bytes) + int W, int H, int sStride, int dStride, + int *Horizontal, int *Vertical) +{ + int X, Y; + int sLineOffs = 0, dLineOffs = 0; + unsigned int PixelAnt; + int PixelDst; + + /* First pixel has no left nor top neightbour. */ + PixelDst = LineAnt[0] = PixelAnt = Frame[0]<<16; + FrameDest[0]= ((PixelDst+0x10007FFF)/65536); + + /* Fist line has no top neightbour, only left. */ + for (X = 1; X < W; X++){ + PixelDst = LineAnt[X] = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal); + FrameDest[X]= ((PixelDst+0x10007FFF)/65536); + } + + for (Y = 1; Y < H; Y++){ + unsigned int PixelAnt; + sLineOffs += sStride, dLineOffs += dStride; + /* First pixel on each line doesn't have previous pixel */ + PixelAnt = Frame[sLineOffs]<<16; + PixelDst = LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical); + FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)/65536); + + for (X = 1; X < W; X++){ + int PixelDst; + /* The rest are normal */ + PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal); + PixelDst = LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical); + FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)/65536); + } + } +} + static void deNoise(unsigned char *Frame, // mpi->planes[x] unsigned char *FrameDest, // dmpi->planes[x] unsigned int *LineAnt, // vf->priv->Line (width bytes) @@ -95,6 +157,17 @@ static void deNoise(unsigned char *Frame, // mpi->planes[x] } } + if(!Horizontal[0] && !Vertical[0]){ + deNoiseTemporal(Frame, FrameDest, FrameAnt, + W, H, sStride, dStride, Temporal); + return; + } + if(!Temporal[0]){ + deNoiseSpacial(Frame, FrameDest, LineAnt, + W, H, sStride, dStride, Horizontal, Vertical); + return; + } + /* First pixel has no left nor top neightbour. Only previous frame */ LineAnt[0] = PixelAnt = Frame[0]<<16; PixelDst = LowPassMul(FrameAnt[0]<<8, PixelAnt, Temporal); @@ -194,12 +267,14 @@ static void PrecalcCoefs(int *Ct, double Dist25) Gamma = log(0.25) / log(1.0 - Dist25/255.0 - 0.00001); - for (i = -256*16; i < 256*16; i++) + for (i = -255*16; i <= 255*16; i++) { 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); } + + Ct[0] = (Dist25 != 0); }