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];
00040 unsigned char *Line;
00041 mp_image_t *pmpi;
00042 };
00043
00044
00045
00046
00047
00048 static int config(struct vf_instance *vf,
00049 int width, int height, int d_width, int d_height,
00050 unsigned int flags, unsigned int outfmt){
00051
00052 free(vf->priv->Line);
00053 vf->priv->Line = malloc(width);
00054 vf->priv->pmpi=NULL;
00055
00056
00057 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
00058 }
00059
00060
00061 static void uninit(struct vf_instance *vf)
00062 {
00063 free(vf->priv->Line);
00064 }
00065
00066 #define LowPass(Prev, Curr, Coef) (Curr + Coef[Prev - Curr])
00067
00068 static void deNoise(unsigned char *Frame,
00069 unsigned char *FramePrev,
00070 unsigned char *FrameDest,
00071 unsigned char *LineAnt,
00072 int W, int H, int sStride, int pStride, int dStride,
00073 int *Horizontal, int *Vertical, int *Temporal)
00074 {
00075 int X, Y;
00076 int sLineOffs = 0, pLineOffs = 0, dLineOffs = 0;
00077 unsigned char PixelAnt;
00078
00079
00080 LineAnt[0] = PixelAnt = Frame[0];
00081 FrameDest[0] = LowPass(FramePrev[0], LineAnt[0], Temporal);
00082
00083
00084
00085 for (X = 1; X < W; X++)
00086 {
00087 PixelAnt = LowPass(PixelAnt, Frame[X], Horizontal);
00088 LineAnt[X] = PixelAnt;
00089 FrameDest[X] = LowPass(FramePrev[X], LineAnt[X], Temporal);
00090 }
00091
00092 for (Y = 1; Y < H; Y++)
00093 {
00094 sLineOffs += sStride, pLineOffs += pStride, dLineOffs += dStride;
00095
00096 PixelAnt = Frame[sLineOffs];
00097 LineAnt[0] = LowPass(LineAnt[0], PixelAnt, Vertical);
00098 FrameDest[dLineOffs] = LowPass(FramePrev[pLineOffs], LineAnt[0], Temporal);
00099
00100 for (X = 1; X < W; X++)
00101 {
00102
00103 PixelAnt = LowPass(PixelAnt, Frame[sLineOffs+X], Horizontal);
00104 LineAnt[X] = LowPass(LineAnt[X], PixelAnt, Vertical);
00105 FrameDest[dLineOffs+X] = LowPass(FramePrev[pLineOffs+X], LineAnt[X], Temporal);
00106 }
00107 }
00108 }
00109
00110
00111
00112 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
00113 int cw= mpi->w >> mpi->chroma_x_shift;
00114 int ch= mpi->h >> mpi->chroma_y_shift;
00115 int W = mpi->w, H = mpi->h;
00116
00117 mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
00118 MP_IMGTYPE_IP, MP_IMGFLAG_ACCEPT_STRIDE |
00119 MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
00120 mpi->w,mpi->h);
00121
00122 if(!dmpi) return 0;
00123 if (!vf->priv->pmpi) vf->priv->pmpi=mpi;
00124
00125 deNoise(mpi->planes[0], vf->priv->pmpi->planes[0], dmpi->planes[0],
00126 vf->priv->Line, W, H,
00127 mpi->stride[0], vf->priv->pmpi->stride[0], dmpi->stride[0],
00128 vf->priv->Coefs[0] + 256,
00129 vf->priv->Coefs[0] + 256,
00130 vf->priv->Coefs[1] + 256);
00131 deNoise(mpi->planes[1], vf->priv->pmpi->planes[1], dmpi->planes[1],
00132 vf->priv->Line, cw, ch,
00133 mpi->stride[1], vf->priv->pmpi->stride[1], dmpi->stride[1],
00134 vf->priv->Coefs[2] + 256,
00135 vf->priv->Coefs[2] + 256,
00136 vf->priv->Coefs[3] + 256);
00137 deNoise(mpi->planes[2], vf->priv->pmpi->planes[2], dmpi->planes[2],
00138 vf->priv->Line, cw, ch,
00139 mpi->stride[2], vf->priv->pmpi->stride[2], dmpi->stride[2],
00140 vf->priv->Coefs[2] + 256,
00141 vf->priv->Coefs[2] + 256,
00142 vf->priv->Coefs[3] + 256);
00143
00144 vf->priv->pmpi=dmpi;
00145 return vf_next_put_image(vf,dmpi, pts);
00146 }
00147
00148
00149
00150 static int query_format(struct vf_instance *vf, unsigned int fmt){
00151 switch(fmt)
00152 {
00153 case IMGFMT_YV12:
00154 case IMGFMT_I420:
00155 case IMGFMT_IYUV:
00156 case IMGFMT_YVU9:
00157 case IMGFMT_444P:
00158 case IMGFMT_422P:
00159 case IMGFMT_411P:
00160 return vf_next_query_format(vf, fmt);
00161 }
00162 return 0;
00163 }
00164
00165
00166 #define ABS(A) ( (A) > 0 ? (A) : -(A) )
00167
00168 static void PrecalcCoefs(int *Ct, double Dist25)
00169 {
00170 int i;
00171 double Gamma, Simil, C;
00172
00173 Gamma = log(0.25) / log(1.0 - Dist25/255.0);
00174
00175 for (i = -256; i <= 255; i++)
00176 {
00177 Simil = 1.0 - ABS(i) / 255.0;
00178
00179 C = pow(Simil, Gamma) * (double)i;
00180 Ct[256+i] = (C<0) ? (C-0.5) : (C+0.5);
00181 }
00182 }
00183
00184
00185 static int vf_open(vf_instance_t *vf, char *args){
00186 double LumSpac, LumTmp, ChromSpac, ChromTmp;
00187 double Param1, Param2, Param3;
00188
00189 vf->config=config;
00190 vf->put_image=put_image;
00191 vf->query_format=query_format;
00192 vf->uninit=uninit;
00193 vf->priv=malloc(sizeof(struct vf_priv_s));
00194 memset(vf->priv, 0, sizeof(struct vf_priv_s));
00195
00196 if (args)
00197 {
00198 switch(sscanf(args, "%lf:%lf:%lf",
00199 &Param1, &Param2, &Param3
00200 ))
00201 {
00202 case 0:
00203 LumSpac = PARAM1_DEFAULT;
00204 LumTmp = PARAM3_DEFAULT;
00205
00206 ChromSpac = PARAM2_DEFAULT;
00207 ChromTmp = LumTmp * ChromSpac / LumSpac;
00208 break;
00209
00210 case 1:
00211 LumSpac = Param1;
00212 LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
00213
00214 ChromSpac = PARAM2_DEFAULT * Param1 / PARAM1_DEFAULT;
00215 ChromTmp = LumTmp * ChromSpac / LumSpac;
00216 break;
00217
00218 case 2:
00219 LumSpac = Param1;
00220 LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
00221
00222 ChromSpac = Param2;
00223 ChromTmp = LumTmp * ChromSpac / LumSpac;
00224 break;
00225
00226 case 3:
00227 LumSpac = Param1;
00228 LumTmp = Param3;
00229
00230 ChromSpac = Param2;
00231 ChromTmp = LumTmp * ChromSpac / LumSpac;
00232 break;
00233
00234 default:
00235 LumSpac = PARAM1_DEFAULT;
00236 LumTmp = PARAM3_DEFAULT;
00237
00238 ChromSpac = PARAM2_DEFAULT;
00239 ChromTmp = LumTmp * ChromSpac / LumSpac;
00240 }
00241 }
00242 else
00243 {
00244 LumSpac = PARAM1_DEFAULT;
00245 LumTmp = PARAM3_DEFAULT;
00246
00247 ChromSpac = PARAM2_DEFAULT;
00248 ChromTmp = LumTmp * ChromSpac / LumSpac;
00249 }
00250
00251 PrecalcCoefs(vf->priv->Coefs[0], LumSpac);
00252 PrecalcCoefs(vf->priv->Coefs[1], LumTmp);
00253 PrecalcCoefs(vf->priv->Coefs[2], ChromSpac);
00254 PrecalcCoefs(vf->priv->Coefs[3], ChromTmp);
00255
00256 return 1;
00257 }
00258
00259 const vf_info_t vf_info_denoise3d = {
00260 "3D Denoiser (variable lowpass filter)",
00261 "denoise3d",
00262 "Daniel Moreno",
00263 "",
00264 vf_open,
00265 NULL
00266 };
00267
00268