Mercurial > mplayer.hg
annotate libmpcodecs/vf_ow.c @ 33273:8c4a81b0bd5f
Update Doxyfile from doxygen 1.3.7 to 1.5.6.
The latter is the version available in Debian oldstable and should thus be a
suitable baseline that can be expected to be available on all systems.
The update makes new Doxygen features available in the configuration file
and avoids several deprecation warnings when using newer doxygen versions.
author | diego |
---|---|
date | Wed, 04 May 2011 14:27:35 +0000 |
parents | a972c1a4a012 |
children |
rev | line source |
---|---|
24677 | 1 /* |
26727 | 2 * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at> |
3 * | |
4 * This file is part of MPlayer. | |
5 * | |
6 * MPlayer is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * MPlayer is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License along | |
17 * with MPlayer; if not, write to the Free Software Foundation, Inc., | |
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
19 */ | |
24677 | 20 |
21 /** | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
22 * @todo try to change to int |
24677 | 23 * @todo try lifting based implementation |
24 * @todo optimize optimize optimize | |
25 * @todo hard tresholding | |
26 * @todo use QP to decide filter strength | |
27 * @todo wavelet normalization / least squares optimal signal vs. noise thresholds | |
28 */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29087
diff
changeset
|
29 |
24677 | 30 #include <stdio.h> |
31 #include <string.h> | |
32 #include <inttypes.h> | |
33 #include <math.h> | |
34 | |
35 #include "mp_msg.h" | |
36 #include "img_format.h" | |
37 #include "mp_image.h" | |
38 #include "vf.h" | |
39 | |
40 //===========================================================================// | |
41 static const uint8_t __attribute__((aligned(8))) dither[8][8]={ | |
42 { 0, 48, 12, 60, 3, 51, 15, 63, }, | |
43 { 32, 16, 44, 28, 35, 19, 47, 31, }, | |
44 { 8, 56, 4, 52, 11, 59, 7, 55, }, | |
45 { 40, 24, 36, 20, 43, 27, 39, 23, }, | |
46 { 2, 50, 14, 62, 1, 49, 13, 61, }, | |
47 { 34, 18, 46, 30, 33, 17, 45, 29, }, | |
48 { 10, 58, 6, 54, 9, 57, 5, 53, }, | |
49 { 42, 26, 38, 22, 41, 25, 37, 21, }, | |
50 }; | |
51 //FIXME the above is duplicated in many filters | |
52 | |
53 struct vf_priv_s { | |
54 float strength[2]; | |
55 float delta; | |
56 int mode; | |
57 int depth; | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
58 float *plane[16][4]; |
24677 | 59 int stride; |
60 }; | |
61 | |
62 #define S 1.41421356237 //sqrt(2) | |
63 | |
64 static const double coeff[2][5]={ | |
65 { | |
66 0.6029490182363579 *S, | |
67 0.2668641184428723 *S, | |
68 -0.07822326652898785 *S, | |
69 -0.01686411844287495 *S, | |
70 0.02674875741080976 *S | |
71 },{ | |
72 1.115087052456994 /S, | |
73 -0.5912717631142470 /S, | |
74 -0.05754352622849957 /S, | |
75 0.09127176311424948 /S | |
76 } | |
77 }; | |
78 | |
79 static const double icoeff[2][5]={ | |
80 { | |
81 1.115087052456994 /S, | |
82 0.5912717631142470 /S, | |
83 -0.05754352622849957 /S, | |
84 -0.09127176311424948 /S | |
85 },{ | |
86 0.6029490182363579 *S, | |
87 -0.2668641184428723 *S, | |
88 -0.07822326652898785 *S, | |
89 0.01686411844287495 *S, | |
90 0.02674875741080976 *S | |
91 } | |
92 }; | |
93 #undef S | |
94 | |
95 static inline int mirror(int x, int w){ | |
96 while((unsigned)x > (unsigned)w){ | |
97 x=-x; | |
98 if(x<0) x+= 2*w; | |
99 } | |
100 return x; | |
101 } | |
102 | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
103 static inline void decompose(float *dstL, float *dstH, float *src, int stride, int w){ |
24677 | 104 int x, i; |
105 for(x=0; x<w; x++){ | |
106 double sumL= src[x*stride] * coeff[0][0]; | |
107 double sumH= src[x*stride] * coeff[1][0]; | |
108 for(i=1; i<=4; i++){ | |
109 double s= (src[mirror(x-i, w-1)*stride] + src[mirror(x+i, w-1)*stride]); | |
110 | |
111 sumL+= coeff[0][i]*s; | |
112 sumH+= coeff[1][i]*s; | |
113 } | |
114 dstL[x*stride]= sumL; | |
115 dstH[x*stride]= sumH; | |
116 } | |
117 } | |
118 | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
119 static inline void compose(float *dst, float *srcL, float *srcH, int stride, int w){ |
24677 | 120 int x, i; |
121 for(x=0; x<w; x++){ | |
122 double sumL= srcL[x*stride] * icoeff[0][0]; | |
123 double sumH= srcH[x*stride] * icoeff[1][0]; | |
124 for(i=1; i<=4; i++){ | |
125 int x0= mirror(x-i, w-1)*stride; | |
126 int x1= mirror(x+i, w-1)*stride; | |
127 | |
128 sumL+= icoeff[0][i]*(srcL[x0] + srcL[x1]); | |
129 sumH+= icoeff[1][i]*(srcH[x0] + srcH[x1]); | |
130 } | |
131 dst[x*stride]= (sumL + sumH)*0.5; | |
132 } | |
133 } | |
134 | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
135 static inline void decompose2D(float *dstL, float *dstH, float *src, int xstride, int ystride, int step, int w, int h){ |
24677 | 136 int y, x; |
137 for(y=0; y<h; y++) | |
138 for(x=0; x<step; x++) | |
139 decompose(dstL + ystride*y + xstride*x, dstH + ystride*y + xstride*x, src + ystride*y + xstride*x, step*xstride, (w-x+step-1)/step); | |
140 } | |
141 | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
142 static inline void compose2D(float *dst, float *srcL, float *srcH, int xstride, int ystride, int step, int w, int h){ |
24677 | 143 int y, x; |
144 for(y=0; y<h; y++) | |
145 for(x=0; x<step; x++) | |
146 compose(dst + ystride*y + xstride*x, srcL + ystride*y + xstride*x, srcH + ystride*y + xstride*x, step*xstride, (w-x+step-1)/step); | |
147 } | |
148 | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
149 static void decompose2D2(float *dst[4], float *src, float *temp[2], int stride, int step, int w, int h){ |
24677 | 150 decompose2D(temp[0], temp[1], src , 1, stride, step , w, h); |
151 decompose2D( dst[0], dst[1], temp[0], stride, 1, step , h, w); | |
152 decompose2D( dst[2], dst[3], temp[1], stride, 1, step , h, w); | |
153 } | |
154 | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
155 static void compose2D2(float *dst, float *src[4], float *temp[2], int stride, int step, int w, int h){ |
24677 | 156 compose2D(temp[0], src[0], src[1], stride, 1, step , h, w); |
157 compose2D(temp[1], src[2], src[3], stride, 1, step , h, w); | |
158 compose2D(dst , temp[0], temp[1], 1, stride, step , w, h); | |
159 } | |
160 | |
161 static void filter(struct vf_priv_s *p, uint8_t *dst, uint8_t *src, int dst_stride, int src_stride, int width, int height, int is_luma){ | |
162 int x,y, i, j; | |
24808 | 163 // double sum=0; |
24677 | 164 double s= p->strength[!is_luma]; |
24679 | 165 int depth= p->depth; |
166 | |
167 while(1<<depth > width || 1<<depth > height) | |
168 depth--; | |
24677 | 169 |
170 for(y=0; y<height; y++) | |
171 for(x=0; x<width; x++) | |
172 p->plane[0][0][x + y*p->stride]= src[x + y*src_stride]; | |
173 | |
24679 | 174 for(i=0; i<depth; i++){ |
24677 | 175 decompose2D2(p->plane[i+1], p->plane[i][0], p->plane[0]+1,p->stride, 1<<i, width, height); |
176 } | |
24679 | 177 for(i=0; i<depth; i++){ |
24677 | 178 for(j=1; j<4; j++){ |
179 for(y=0; y<height; y++){ | |
180 for(x=0; x<width; x++){ | |
181 double v= p->plane[i+1][j][x + y*p->stride]; | |
182 if (v> s) v-=s; | |
183 else if(v<-s) v+=s; | |
184 else v =0; | |
185 p->plane[i+1][j][x + y*p->stride]= v; | |
186 } | |
187 } | |
188 } | |
189 } | |
24679 | 190 for(i=depth-1; i>=0; i--){ |
24677 | 191 compose2D2(p->plane[i][0], p->plane[i+1], p->plane[0]+1, p->stride, 1<<i, width, height); |
192 } | |
193 | |
194 for(y=0; y<height; y++) | |
195 for(x=0; x<width; x++){ | |
196 i= p->plane[0][0][x + y*p->stride] + dither[x&7][y&7]*(1.0/64) + 1.0/128; //yes the rounding is insane but optimal :) | |
197 // double e= i - src[x + y*src_stride]; | |
198 // sum += e*e; | |
199 if((unsigned)i > 255U) i= ~(i>>31); | |
200 dst[x + y*dst_stride]= i; | |
201 } | |
202 | |
203 // printf("%f\n", sum/height/width); | |
204 } | |
205 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
206 static int config(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt){ |
24677 | 207 int h= (height+15)&(~15); |
208 int i,j; | |
209 | |
210 vf->priv->stride= (width+15)&(~15); | |
211 for(j=0; j<4; j++){ | |
212 for(i=0; i<=vf->priv->depth; i++) | |
213 vf->priv->plane[i][j]= malloc(vf->priv->stride*h*sizeof(vf->priv->plane[0][0][0])); | |
214 } | |
215 | |
216 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
217 } | |
218 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
219 static void get_image(struct vf_instance *vf, mp_image_t *mpi){ |
24677 | 220 if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change |
221 // ok, we can do pp in-place (or pp disabled): | |
222 vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, | |
223 mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height); | |
224 mpi->planes[0]=vf->dmpi->planes[0]; | |
225 mpi->stride[0]=vf->dmpi->stride[0]; | |
226 mpi->width=vf->dmpi->width; | |
227 if(mpi->flags&MP_IMGFLAG_PLANAR){ | |
228 mpi->planes[1]=vf->dmpi->planes[1]; | |
229 mpi->planes[2]=vf->dmpi->planes[2]; | |
230 mpi->stride[1]=vf->dmpi->stride[1]; | |
231 mpi->stride[2]=vf->dmpi->stride[2]; | |
232 } | |
233 mpi->flags|=MP_IMGFLAG_DIRECT; | |
234 } | |
235 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
236 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ |
24677 | 237 mp_image_t *dmpi; |
238 | |
239 if(!(mpi->flags&MP_IMGFLAG_DIRECT)){ | |
240 // no DR, so get a new image! hope we'll get DR buffer: | |
241 dmpi=vf_get_image(vf->next,mpi->imgfmt, | |
242 MP_IMGTYPE_TEMP, | |
243 MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE, | |
244 mpi->width,mpi->height); | |
245 vf_clone_mpi_attributes(dmpi, mpi); | |
246 }else{ | |
247 dmpi=vf->dmpi; | |
248 } | |
249 | |
250 filter(vf->priv, dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, 1); | |
251 filter(vf->priv, dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, 0); | |
252 filter(vf->priv, dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, 0); | |
253 | |
254 return vf_next_put_image(vf,dmpi, pts); | |
255 } | |
256 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
257 static void uninit(struct vf_instance *vf){ |
24677 | 258 int i,j; |
259 if(!vf->priv) return; | |
260 | |
261 for(j=0; j<4; j++){ | |
262 for(i=0; i<16; i++){ | |
263 free(vf->priv->plane[i][j]); | |
264 vf->priv->plane[i][j]= NULL; | |
265 } | |
266 } | |
267 | |
268 free(vf->priv); | |
269 vf->priv=NULL; | |
270 } | |
271 | |
272 //===========================================================================// | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
273 static int query_format(struct vf_instance *vf, unsigned int fmt){ |
24677 | 274 switch(fmt){ |
275 case IMGFMT_YVU9: | |
276 case IMGFMT_IF09: | |
277 case IMGFMT_YV12: | |
278 case IMGFMT_I420: | |
279 case IMGFMT_IYUV: | |
280 case IMGFMT_CLPL: | |
281 case IMGFMT_Y800: | |
282 case IMGFMT_Y8: | |
283 case IMGFMT_444P: | |
284 case IMGFMT_422P: | |
285 case IMGFMT_411P: | |
286 return vf_next_query_format(vf,fmt); | |
287 } | |
288 return 0; | |
289 } | |
290 | |
291 | |
30638
a7b908875c14
Rename open() vf initialization function to vf_open().
diego
parents:
29263
diff
changeset
|
292 static int vf_open(vf_instance_t *vf, char *args){ |
24677 | 293 vf->config=config; |
294 vf->put_image=put_image; | |
295 vf->get_image=get_image; | |
296 vf->query_format=query_format; | |
297 vf->uninit=uninit; | |
298 vf->priv=malloc(sizeof(struct vf_priv_s)); | |
299 memset(vf->priv, 0, sizeof(struct vf_priv_s)); | |
300 | |
301 vf->priv->depth= 8; | |
302 vf->priv->strength[0]= 1.0; | |
303 vf->priv->strength[1]= 1.0; | |
304 vf->priv->delta= 1.0; | |
305 | |
306 if (args) sscanf(args, "%d:%f:%f:%d:%f", &vf->priv->depth, | |
307 &vf->priv->strength[0], | |
308 &vf->priv->strength[1], | |
309 &vf->priv->mode, | |
310 &vf->priv->delta); | |
311 | |
312 return 1; | |
313 } | |
314 | |
25221 | 315 const vf_info_t vf_info_ow = { |
24677 | 316 "overcomplete wavelet denoiser", |
317 "ow", | |
318 "Michael Niedermayer", | |
319 "", | |
30638
a7b908875c14
Rename open() vf initialization function to vf_open().
diego
parents:
29263
diff
changeset
|
320 vf_open, |
24677 | 321 NULL |
322 }; |