00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <inttypes.h>
00025 #include <math.h>
00026
00027 #include "mp_msg.h"
00028 #include "img_format.h"
00029 #include "mp_image.h"
00030 #include "vf.h"
00031
00032 #define PARAM1_DEFAULT 4.0
00033 #define PARAM2_DEFAULT 3.0
00034 #define PARAM3_DEFAULT 6.0
00035
00036
00037
00038 struct vf_priv_s {
00039 int Coefs[4][512*16];
00040 unsigned int *Line;
00041 unsigned short *Frame[3];
00042 };
00043
00044
00045
00046
00047 static void uninit(struct vf_instance *vf)
00048 {
00049 free(vf->priv->Line);
00050 free(vf->priv->Frame[0]);
00051 free(vf->priv->Frame[1]);
00052 free(vf->priv->Frame[2]);
00053
00054 vf->priv->Line = NULL;
00055 vf->priv->Frame[0] = NULL;
00056 vf->priv->Frame[1] = NULL;
00057 vf->priv->Frame[2] = NULL;
00058 }
00059
00060 static int config(struct vf_instance *vf,
00061 int width, int height, int d_width, int d_height,
00062 unsigned int flags, unsigned int outfmt){
00063
00064 uninit(vf);
00065 vf->priv->Line = malloc(width*sizeof(int));
00066
00067 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
00068 }
00069
00070 static inline unsigned int LowPassMul(unsigned int PrevMul, unsigned int CurrMul, int* Coef){
00071
00072 int dMul= PrevMul-CurrMul;
00073 unsigned int d=((dMul+0x10007FF)>>12);
00074 return CurrMul + Coef[d];
00075 }
00076
00077 static void deNoiseTemporal(
00078 unsigned char *Frame,
00079 unsigned char *FrameDest,
00080 unsigned short *FrameAnt,
00081 int W, int H, int sStride, int dStride,
00082 int *Temporal)
00083 {
00084 long X, Y;
00085 unsigned int PixelDst;
00086
00087 for (Y = 0; Y < H; Y++){
00088 for (X = 0; X < W; X++){
00089 PixelDst = LowPassMul(FrameAnt[X]<<8, Frame[X]<<16, Temporal);
00090 FrameAnt[X] = ((PixelDst+0x1000007F)>>8);
00091 FrameDest[X]= ((PixelDst+0x10007FFF)>>16);
00092 }
00093 Frame += sStride;
00094 FrameDest += dStride;
00095 FrameAnt += W;
00096 }
00097 }
00098
00099 static void deNoiseSpacial(
00100 unsigned char *Frame,
00101 unsigned char *FrameDest,
00102 unsigned int *LineAnt,
00103 int W, int H, int sStride, int dStride,
00104 int *Horizontal, int *Vertical)
00105 {
00106 long X, Y;
00107 long sLineOffs = 0, dLineOffs = 0;
00108 unsigned int PixelAnt;
00109 unsigned int PixelDst;
00110
00111
00112 PixelDst = LineAnt[0] = PixelAnt = Frame[0]<<16;
00113 FrameDest[0]= ((PixelDst+0x10007FFF)>>16);
00114
00115
00116 for (X = 1; X < W; X++){
00117 PixelDst = LineAnt[X] = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal);
00118 FrameDest[X]= ((PixelDst+0x10007FFF)>>16);
00119 }
00120
00121 for (Y = 1; Y < H; Y++){
00122 unsigned int PixelAnt;
00123 sLineOffs += sStride, dLineOffs += dStride;
00124
00125 PixelAnt = Frame[sLineOffs]<<16;
00126 PixelDst = LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
00127 FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)>>16);
00128
00129 for (X = 1; X < W; X++){
00130 unsigned int PixelDst;
00131
00132 PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal);
00133 PixelDst = LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical);
00134 FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)>>16);
00135 }
00136 }
00137 }
00138
00139 static void deNoise(unsigned char *Frame,
00140 unsigned char *FrameDest,
00141 unsigned int *LineAnt,
00142 unsigned short **FrameAntPtr,
00143 int W, int H, int sStride, int dStride,
00144 int *Horizontal, int *Vertical, int *Temporal)
00145 {
00146 long X, Y;
00147 long sLineOffs = 0, dLineOffs = 0;
00148 unsigned int PixelAnt;
00149 unsigned int PixelDst;
00150 unsigned short* FrameAnt=(*FrameAntPtr);
00151
00152 if(!FrameAnt){
00153 (*FrameAntPtr)=FrameAnt=malloc(W*H*sizeof(unsigned short));
00154 for (Y = 0; Y < H; Y++){
00155 unsigned short* dst=&FrameAnt[Y*W];
00156 unsigned char* src=Frame+Y*sStride;
00157 for (X = 0; X < W; X++) dst[X]=src[X]<<8;
00158 }
00159 }
00160
00161 if(!Horizontal[0] && !Vertical[0]){
00162 deNoiseTemporal(Frame, FrameDest, FrameAnt,
00163 W, H, sStride, dStride, Temporal);
00164 return;
00165 }
00166 if(!Temporal[0]){
00167 deNoiseSpacial(Frame, FrameDest, LineAnt,
00168 W, H, sStride, dStride, Horizontal, Vertical);
00169 return;
00170 }
00171
00172
00173 LineAnt[0] = PixelAnt = Frame[0]<<16;
00174 PixelDst = LowPassMul(FrameAnt[0]<<8, PixelAnt, Temporal);
00175 FrameAnt[0] = ((PixelDst+0x1000007F)>>8);
00176 FrameDest[0]= ((PixelDst+0x10007FFF)>>16);
00177
00178
00179
00180 for (X = 1; X < W; X++){
00181 LineAnt[X] = PixelAnt = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal);
00182 PixelDst = LowPassMul(FrameAnt[X]<<8, PixelAnt, Temporal);
00183 FrameAnt[X] = ((PixelDst+0x1000007F)>>8);
00184 FrameDest[X]= ((PixelDst+0x10007FFF)>>16);
00185 }
00186
00187 for (Y = 1; Y < H; Y++){
00188 unsigned int PixelAnt;
00189 unsigned short* LinePrev=&FrameAnt[Y*W];
00190 sLineOffs += sStride, dLineOffs += dStride;
00191
00192 PixelAnt = Frame[sLineOffs]<<16;
00193 LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
00194 PixelDst = LowPassMul(LinePrev[0]<<8, LineAnt[0], Temporal);
00195 LinePrev[0] = ((PixelDst+0x1000007F)>>8);
00196 FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)>>16);
00197
00198 for (X = 1; X < W; X++){
00199 unsigned int PixelDst;
00200
00201 PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal);
00202 LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical);
00203 PixelDst = LowPassMul(LinePrev[X]<<8, LineAnt[X], Temporal);
00204 LinePrev[X] = ((PixelDst+0x1000007F)>>8);
00205 FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)>>16);
00206 }
00207 }
00208 }
00209
00210
00211 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
00212 int cw= mpi->w >> mpi->chroma_x_shift;
00213 int ch= mpi->h >> mpi->chroma_y_shift;
00214 int W = mpi->w, H = mpi->h;
00215
00216 mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
00217 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
00218 mpi->w,mpi->h);
00219
00220 if(!dmpi) return 0;
00221
00222 deNoise(mpi->planes[0], dmpi->planes[0],
00223 vf->priv->Line, &vf->priv->Frame[0], W, H,
00224 mpi->stride[0], dmpi->stride[0],
00225 vf->priv->Coefs[0],
00226 vf->priv->Coefs[0],
00227 vf->priv->Coefs[1]);
00228 deNoise(mpi->planes[1], dmpi->planes[1],
00229 vf->priv->Line, &vf->priv->Frame[1], cw, ch,
00230 mpi->stride[1], dmpi->stride[1],
00231 vf->priv->Coefs[2],
00232 vf->priv->Coefs[2],
00233 vf->priv->Coefs[3]);
00234 deNoise(mpi->planes[2], dmpi->planes[2],
00235 vf->priv->Line, &vf->priv->Frame[2], cw, ch,
00236 mpi->stride[2], dmpi->stride[2],
00237 vf->priv->Coefs[2],
00238 vf->priv->Coefs[2],
00239 vf->priv->Coefs[3]);
00240
00241 return vf_next_put_image(vf,dmpi, pts);
00242 }
00243
00244
00245
00246 static int query_format(struct vf_instance *vf, unsigned int fmt){
00247 switch(fmt)
00248 {
00249 case IMGFMT_YV12:
00250 case IMGFMT_I420:
00251 case IMGFMT_IYUV:
00252 case IMGFMT_YVU9:
00253 case IMGFMT_444P:
00254 case IMGFMT_422P:
00255 case IMGFMT_411P:
00256 return vf_next_query_format(vf, fmt);
00257 }
00258 return 0;
00259 }
00260
00261
00262 #define ABS(A) ( (A) > 0 ? (A) : -(A) )
00263
00264 static void PrecalcCoefs(int *Ct, double Dist25)
00265 {
00266 int i;
00267 double Gamma, Simil, C;
00268
00269 Gamma = log(0.25) / log(1.0 - Dist25/255.0 - 0.00001);
00270
00271 for (i = -255*16; i <= 255*16; i++)
00272 {
00273 Simil = 1.0 - ABS(i) / (16*255.0);
00274 C = pow(Simil, Gamma) * 65536.0 * (double)i / 16.0;
00275 Ct[16*256+i] = (C<0) ? (C-0.5) : (C+0.5);
00276 }
00277
00278 Ct[0] = (Dist25 != 0);
00279 }
00280
00281
00282 static int vf_open(vf_instance_t *vf, char *args){
00283 double LumSpac, LumTmp, ChromSpac, ChromTmp;
00284 double Param1, Param2, Param3, Param4;
00285
00286 vf->config=config;
00287 vf->put_image=put_image;
00288 vf->query_format=query_format;
00289 vf->uninit=uninit;
00290 vf->priv=malloc(sizeof(struct vf_priv_s));
00291 memset(vf->priv, 0, sizeof(struct vf_priv_s));
00292
00293 if (args)
00294 {
00295 switch(sscanf(args, "%lf:%lf:%lf:%lf",
00296 &Param1, &Param2, &Param3, &Param4
00297 ))
00298 {
00299 case 0:
00300 LumSpac = PARAM1_DEFAULT;
00301 LumTmp = PARAM3_DEFAULT;
00302
00303 ChromSpac = PARAM2_DEFAULT;
00304 ChromTmp = LumTmp * ChromSpac / LumSpac;
00305 break;
00306
00307 case 1:
00308 LumSpac = Param1;
00309 LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
00310
00311 ChromSpac = PARAM2_DEFAULT * Param1 / PARAM1_DEFAULT;
00312 ChromTmp = LumTmp * ChromSpac / LumSpac;
00313 break;
00314
00315 case 2:
00316 LumSpac = Param1;
00317 LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
00318
00319 ChromSpac = Param2;
00320 ChromTmp = LumTmp * ChromSpac / LumSpac;
00321 break;
00322
00323 case 3:
00324 LumSpac = Param1;
00325 LumTmp = Param3;
00326
00327 ChromSpac = Param2;
00328 ChromTmp = LumTmp * ChromSpac / LumSpac;
00329 break;
00330
00331 case 4:
00332 LumSpac = Param1;
00333 LumTmp = Param3;
00334
00335 ChromSpac = Param2;
00336 ChromTmp = Param4;
00337 break;
00338
00339 default:
00340 LumSpac = PARAM1_DEFAULT;
00341 LumTmp = PARAM3_DEFAULT;
00342
00343 ChromSpac = PARAM2_DEFAULT;
00344 ChromTmp = LumTmp * ChromSpac / LumSpac;
00345 }
00346 }
00347 else
00348 {
00349 LumSpac = PARAM1_DEFAULT;
00350 LumTmp = PARAM3_DEFAULT;
00351
00352 ChromSpac = PARAM2_DEFAULT;
00353 ChromTmp = LumTmp * ChromSpac / LumSpac;
00354 }
00355
00356 PrecalcCoefs(vf->priv->Coefs[0], LumSpac);
00357 PrecalcCoefs(vf->priv->Coefs[1], LumTmp);
00358 PrecalcCoefs(vf->priv->Coefs[2], ChromSpac);
00359 PrecalcCoefs(vf->priv->Coefs[3], ChromTmp);
00360
00361 return 1;
00362 }
00363
00364 const vf_info_t vf_info_hqdn3d = {
00365 "High Quality 3D Denoiser",
00366 "hqdn3d",
00367 "Daniel Moreno & A'rpi",
00368 "",
00369 vf_open,
00370 NULL
00371 };
00372
00373