2 Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "../config.h"
26 #include "../mp_msg.h"
32 #include "img_format.h"
35 #include "../libvo/fastmemcpy.h"
37 #define PARAM1_DEFAULT 4.0
38 #define PARAM2_DEFAULT 3.0
39 #define PARAM3_DEFAULT 6.0
41 //===========================================================================//
46 unsigned short *Frame
[3];
50 /***************************************************************************/
52 static void uninit(struct vf_instance_s
* vf
){
53 if(vf
->priv
->Line
){free(vf
->priv
->Line
);vf
->priv
->Line
=NULL
;}
54 if(vf
->priv
->Frame
[0]){free(vf
->priv
->Frame
[0]);vf
->priv
->Frame
[0]=NULL
;}
55 if(vf
->priv
->Frame
[1]){free(vf
->priv
->Frame
[1]);vf
->priv
->Frame
[1]=NULL
;}
56 if(vf
->priv
->Frame
[2]){free(vf
->priv
->Frame
[2]);vf
->priv
->Frame
[2]=NULL
;}
59 static int config(struct vf_instance_s
* vf
,
60 int width
, int height
, int d_width
, int d_height
,
61 unsigned int flags
, unsigned int outfmt
){
64 vf
->priv
->Line
= malloc(width
*sizeof(int));
66 return vf_next_config(vf
,width
,height
,d_width
,d_height
,flags
,outfmt
);
69 static inline unsigned int LowPassMul(unsigned int PrevMul
, unsigned int CurrMul
, int* Coef
){
70 // int dMul= (PrevMul&0xFFFFFF)-(CurrMul&0xFFFFFF);
71 int dMul
= PrevMul
-CurrMul
;
72 int d
=((dMul
+0x10007FF)/(65536/16));
73 return CurrMul
+ Coef
[d
];
76 static void deNoise(unsigned char *Frame
, // mpi->planes[x]
77 unsigned char *FrameDest
, // dmpi->planes[x]
78 unsigned int *LineAnt
, // vf->priv->Line (width bytes)
79 unsigned short **FrameAntPtr
,
80 int W
, int H
, int sStride
, int dStride
,
81 int *Horizontal
, int *Vertical
, int *Temporal
)
84 int sLineOffs
= 0, dLineOffs
= 0;
85 unsigned int PixelAnt
;
87 unsigned short* FrameAnt
=(*FrameAntPtr
);
90 (*FrameAntPtr
)=FrameAnt
=malloc(W
*H
*sizeof(unsigned short));
91 for (Y
= 0; Y
< H
; Y
++){
92 unsigned short* dst
=&FrameAnt
[Y
*W
];
93 unsigned char* src
=Frame
+Y
*sStride
;
94 for (X
= 0; X
< W
; X
++) dst
[X
]=src
[X
]<<8;
98 /* First pixel has no left nor top neightbour. Only previous frame */
99 LineAnt
[0] = PixelAnt
= Frame
[0]<<16;
100 PixelDst
= LowPassMul(FrameAnt
[0]<<8, PixelAnt
, Temporal
);
101 FrameAnt
[0] = ((PixelDst
+0x1000007F)/256);
102 FrameDest
[0]= ((PixelDst
+0x10007FFF)/65536);
104 /* Fist line has no top neightbour. Only left one for each pixel and
106 for (X
= 1; X
< W
; X
++){
107 LineAnt
[X
] = PixelAnt
= LowPassMul(PixelAnt
, Frame
[X
]<<16, Horizontal
);
108 PixelDst
= LowPassMul(FrameAnt
[X
]<<8, PixelAnt
, Temporal
);
109 FrameAnt
[X
] = ((PixelDst
+0x1000007F)/256);
110 FrameDest
[X
]= ((PixelDst
+0x10007FFF)/65536);
113 for (Y
= 1; Y
< H
; Y
++){
114 unsigned int PixelAnt
;
115 unsigned short* LinePrev
=&FrameAnt
[Y
*W
];
116 sLineOffs
+= sStride
, dLineOffs
+= dStride
;
117 /* First pixel on each line doesn't have previous pixel */
118 PixelAnt
= Frame
[sLineOffs
]<<16;
119 LineAnt
[0] = LowPassMul(LineAnt
[0], PixelAnt
, Vertical
);
120 PixelDst
= LowPassMul(LinePrev
[0]<<8, LineAnt
[0], Temporal
);
121 LinePrev
[0] = ((PixelDst
+0x1000007F)/256);
122 FrameDest
[dLineOffs
]= ((PixelDst
+0x10007FFF)/65536);
124 for (X
= 1; X
< W
; X
++){
126 /* The rest are normal */
127 PixelAnt
= LowPassMul(PixelAnt
, Frame
[sLineOffs
+X
]<<16, Horizontal
);
128 LineAnt
[X
] = LowPassMul(LineAnt
[X
], PixelAnt
, Vertical
);
129 PixelDst
= LowPassMul(LinePrev
[X
]<<8, LineAnt
[X
], Temporal
);
130 LinePrev
[X
] = ((PixelDst
+0x1000007F)/256);
131 FrameDest
[dLineOffs
+X
]= ((PixelDst
+0x10007FFF)/65536);
137 static int put_image(struct vf_instance_s
* vf
, mp_image_t
*mpi
){
138 int cw
= mpi
->w
>> mpi
->chroma_x_shift
;
139 int ch
= mpi
->h
>> mpi
->chroma_y_shift
;
140 int W
= mpi
->w
, H
= mpi
->h
;
142 mp_image_t
*dmpi
=vf_get_image(vf
->next
,mpi
->imgfmt
,
143 MP_IMGTYPE_TEMP
, MP_IMGFLAG_ACCEPT_STRIDE
,
148 deNoise(mpi
->planes
[0], dmpi
->planes
[0],
149 vf
->priv
->Line
, &vf
->priv
->Frame
[0], W
, H
,
150 mpi
->stride
[0], dmpi
->stride
[0],
154 deNoise(mpi
->planes
[1], dmpi
->planes
[1],
155 vf
->priv
->Line
, &vf
->priv
->Frame
[1], cw
, ch
,
156 mpi
->stride
[1], dmpi
->stride
[1],
160 deNoise(mpi
->planes
[2], dmpi
->planes
[2],
161 vf
->priv
->Line
, &vf
->priv
->Frame
[2], cw
, ch
,
162 mpi
->stride
[2], dmpi
->stride
[2],
167 return vf_next_put_image(vf
,dmpi
);
170 //===========================================================================//
172 static int query_format(struct vf_instance_s
* vf
, unsigned int fmt
){
182 return vf_next_query_format(vf
, fmt
);
188 #define ABS(A) ( (A) > 0 ? (A) : -(A) )
190 static void PrecalcCoefs(int *Ct
, double Dist25
)
193 double Gamma
, Simil
, C
;
195 Gamma
= log(0.25) / log(1.0 - Dist25
/255.0 - 0.00001);
197 for (i
= -256*16; i
< 256*16; i
++)
199 Simil
= 1.0 - ABS(i
) / (16*255.0);
200 C
= pow(Simil
, Gamma
) * 65536.0 * (double)i
/ 16.0;
201 Ct
[16*256+i
] = (C
<0) ? (C
-0.5) : (C
+0.5);
206 static int open(vf_instance_t
*vf
, char* args
){
207 double LumSpac
, LumTmp
, ChromSpac
, ChromTmp
;
208 double Param1
, Param2
, Param3
, Param4
;
211 vf
->put_image
=put_image
;
212 vf
->query_format
=query_format
;
214 vf
->priv
=malloc(sizeof(struct vf_priv_s
));
215 memset(vf
->priv
, 0, sizeof(struct vf_priv_s
));
219 switch(sscanf(args
, "%lf:%lf:%lf:%lf",
220 &Param1
, &Param2
, &Param3
, &Param4
224 LumSpac
= PARAM1_DEFAULT
;
225 LumTmp
= PARAM3_DEFAULT
;
227 ChromSpac
= PARAM2_DEFAULT
;
228 ChromTmp
= LumTmp
* ChromSpac
/ LumSpac
;
233 LumTmp
= PARAM3_DEFAULT
* Param1
/ PARAM1_DEFAULT
;
235 ChromSpac
= PARAM2_DEFAULT
* Param1
/ PARAM1_DEFAULT
;
236 ChromTmp
= LumTmp
* ChromSpac
/ LumSpac
;
241 LumTmp
= PARAM3_DEFAULT
* Param1
/ PARAM1_DEFAULT
;
244 ChromTmp
= LumTmp
* ChromSpac
/ LumSpac
;
252 ChromTmp
= LumTmp
* ChromSpac
/ LumSpac
;
264 LumSpac
= PARAM1_DEFAULT
;
265 LumTmp
= PARAM3_DEFAULT
;
267 ChromSpac
= PARAM2_DEFAULT
;
268 ChromTmp
= LumTmp
* ChromSpac
/ LumSpac
;
273 LumSpac
= PARAM1_DEFAULT
;
274 LumTmp
= PARAM3_DEFAULT
;
276 ChromSpac
= PARAM2_DEFAULT
;
277 ChromTmp
= LumTmp
* ChromSpac
/ LumSpac
;
280 PrecalcCoefs(vf
->priv
->Coefs
[0], LumSpac
);
281 PrecalcCoefs(vf
->priv
->Coefs
[1], LumTmp
);
282 PrecalcCoefs(vf
->priv
->Coefs
[2], ChromSpac
);
283 PrecalcCoefs(vf
->priv
->Coefs
[3], ChromTmp
);
288 vf_info_t vf_info_hqdn3d
= {
289 "High Quality 3D Denoiser",
291 "Daniel Moreno & A'rpi",
297 //===========================================================================//