Mercurial > mplayer.hg
annotate libmpcodecs/vf_ow.c @ 27319:09cf111f68b8
Revert to previous dependency checking behavior.
Take included header files into account when generating dependency files.
This has problems when header files are removed or renamed, but does not
silently miscompile files.
author | diego |
---|---|
date | Sat, 26 Jul 2008 18:36:48 +0000 |
parents | 82601a38e2a7 |
children | df67d03dde3b |
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 */ | |
29 | |
30 #include <stdio.h> | |
31 #include <string.h> | |
32 #include <inttypes.h> | |
33 #include <math.h> | |
34 | |
35 #include "config.h" | |
36 | |
37 #include "mp_msg.h" | |
38 | |
39 #ifdef HAVE_MALLOC_H | |
40 #include <malloc.h> | |
41 #endif | |
42 | |
43 #include "img_format.h" | |
44 #include "mp_image.h" | |
45 #include "vf.h" | |
46 | |
47 //===========================================================================// | |
48 static const uint8_t __attribute__((aligned(8))) dither[8][8]={ | |
49 { 0, 48, 12, 60, 3, 51, 15, 63, }, | |
50 { 32, 16, 44, 28, 35, 19, 47, 31, }, | |
51 { 8, 56, 4, 52, 11, 59, 7, 55, }, | |
52 { 40, 24, 36, 20, 43, 27, 39, 23, }, | |
53 { 2, 50, 14, 62, 1, 49, 13, 61, }, | |
54 { 34, 18, 46, 30, 33, 17, 45, 29, }, | |
55 { 10, 58, 6, 54, 9, 57, 5, 53, }, | |
56 { 42, 26, 38, 22, 41, 25, 37, 21, }, | |
57 }; | |
58 //FIXME the above is duplicated in many filters | |
59 | |
60 struct vf_priv_s { | |
61 float strength[2]; | |
62 float delta; | |
63 int mode; | |
64 int depth; | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
65 float *plane[16][4]; |
24677 | 66 int stride; |
67 }; | |
68 | |
69 #define S 1.41421356237 //sqrt(2) | |
70 | |
71 static const double coeff[2][5]={ | |
72 { | |
73 0.6029490182363579 *S, | |
74 0.2668641184428723 *S, | |
75 -0.07822326652898785 *S, | |
76 -0.01686411844287495 *S, | |
77 0.02674875741080976 *S | |
78 },{ | |
79 1.115087052456994 /S, | |
80 -0.5912717631142470 /S, | |
81 -0.05754352622849957 /S, | |
82 0.09127176311424948 /S | |
83 } | |
84 }; | |
85 | |
86 static const double icoeff[2][5]={ | |
87 { | |
88 1.115087052456994 /S, | |
89 0.5912717631142470 /S, | |
90 -0.05754352622849957 /S, | |
91 -0.09127176311424948 /S | |
92 },{ | |
93 0.6029490182363579 *S, | |
94 -0.2668641184428723 *S, | |
95 -0.07822326652898785 *S, | |
96 0.01686411844287495 *S, | |
97 0.02674875741080976 *S | |
98 } | |
99 }; | |
100 #undef S | |
101 | |
102 static inline int mirror(int x, int w){ | |
103 while((unsigned)x > (unsigned)w){ | |
104 x=-x; | |
105 if(x<0) x+= 2*w; | |
106 } | |
107 return x; | |
108 } | |
109 | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
110 static inline void decompose(float *dstL, float *dstH, float *src, int stride, int w){ |
24677 | 111 int x, i; |
112 for(x=0; x<w; x++){ | |
113 double sumL= src[x*stride] * coeff[0][0]; | |
114 double sumH= src[x*stride] * coeff[1][0]; | |
115 for(i=1; i<=4; i++){ | |
116 double s= (src[mirror(x-i, w-1)*stride] + src[mirror(x+i, w-1)*stride]); | |
117 | |
118 sumL+= coeff[0][i]*s; | |
119 sumH+= coeff[1][i]*s; | |
120 } | |
121 dstL[x*stride]= sumL; | |
122 dstH[x*stride]= sumH; | |
123 } | |
124 } | |
125 | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
126 static inline void compose(float *dst, float *srcL, float *srcH, int stride, int w){ |
24677 | 127 int x, i; |
128 for(x=0; x<w; x++){ | |
129 double sumL= srcL[x*stride] * icoeff[0][0]; | |
130 double sumH= srcH[x*stride] * icoeff[1][0]; | |
131 for(i=1; i<=4; i++){ | |
132 int x0= mirror(x-i, w-1)*stride; | |
133 int x1= mirror(x+i, w-1)*stride; | |
134 | |
135 sumL+= icoeff[0][i]*(srcL[x0] + srcL[x1]); | |
136 sumH+= icoeff[1][i]*(srcH[x0] + srcH[x1]); | |
137 } | |
138 dst[x*stride]= (sumL + sumH)*0.5; | |
139 } | |
140 } | |
141 | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
142 static inline void decompose2D(float *dstL, float *dstH, float *src, 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 decompose(dstL + ystride*y + xstride*x, dstH + ystride*y + xstride*x, src + 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 inline void compose2D(float *dst, float *srcL, float *srcH, int xstride, int ystride, int step, int w, int h){ |
24677 | 150 int y, x; |
151 for(y=0; y<h; y++) | |
152 for(x=0; x<step; x++) | |
153 compose(dst + ystride*y + xstride*x, srcL + ystride*y + xstride*x, srcH + ystride*y + xstride*x, step*xstride, (w-x+step-1)/step); | |
154 } | |
155 | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
156 static void decompose2D2(float *dst[4], float *src, float *temp[2], int stride, int step, int w, int h){ |
24677 | 157 decompose2D(temp[0], temp[1], src , 1, stride, step , w, h); |
158 decompose2D( dst[0], dst[1], temp[0], stride, 1, step , h, w); | |
159 decompose2D( dst[2], dst[3], temp[1], stride, 1, step , h, w); | |
160 } | |
161 | |
24680
4d56303b85ab
change double arrays to float (this should be accurate enough)
michael
parents:
24679
diff
changeset
|
162 static void compose2D2(float *dst, float *src[4], float *temp[2], int stride, int step, int w, int h){ |
24677 | 163 compose2D(temp[0], src[0], src[1], stride, 1, step , h, w); |
164 compose2D(temp[1], src[2], src[3], stride, 1, step , h, w); | |
165 compose2D(dst , temp[0], temp[1], 1, stride, step , w, h); | |
166 } | |
167 | |
168 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){ | |
169 int x,y, i, j; | |
24808 | 170 // double sum=0; |
24677 | 171 double s= p->strength[!is_luma]; |
24679 | 172 int depth= p->depth; |
173 | |
174 while(1<<depth > width || 1<<depth > height) | |
175 depth--; | |
24677 | 176 |
177 for(y=0; y<height; y++) | |
178 for(x=0; x<width; x++) | |
179 p->plane[0][0][x + y*p->stride]= src[x + y*src_stride]; | |
180 | |
24679 | 181 for(i=0; i<depth; i++){ |
24677 | 182 decompose2D2(p->plane[i+1], p->plane[i][0], p->plane[0]+1,p->stride, 1<<i, width, height); |
183 } | |
24679 | 184 for(i=0; i<depth; i++){ |
24677 | 185 for(j=1; j<4; j++){ |
186 for(y=0; y<height; y++){ | |
187 for(x=0; x<width; x++){ | |
188 double v= p->plane[i+1][j][x + y*p->stride]; | |
189 if (v> s) v-=s; | |
190 else if(v<-s) v+=s; | |
191 else v =0; | |
192 p->plane[i+1][j][x + y*p->stride]= v; | |
193 } | |
194 } | |
195 } | |
196 } | |
24679 | 197 for(i=depth-1; i>=0; i--){ |
24677 | 198 compose2D2(p->plane[i][0], p->plane[i+1], p->plane[0]+1, p->stride, 1<<i, width, height); |
199 } | |
200 | |
201 for(y=0; y<height; y++) | |
202 for(x=0; x<width; x++){ | |
203 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 :) | |
204 // double e= i - src[x + y*src_stride]; | |
205 // sum += e*e; | |
206 if((unsigned)i > 255U) i= ~(i>>31); | |
207 dst[x + y*dst_stride]= i; | |
208 } | |
209 | |
210 // printf("%f\n", sum/height/width); | |
211 } | |
212 | |
213 static int config(struct vf_instance_s* vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt){ | |
214 int h= (height+15)&(~15); | |
215 int i,j; | |
216 | |
217 vf->priv->stride= (width+15)&(~15); | |
218 for(j=0; j<4; j++){ | |
219 for(i=0; i<=vf->priv->depth; i++) | |
220 vf->priv->plane[i][j]= malloc(vf->priv->stride*h*sizeof(vf->priv->plane[0][0][0])); | |
221 } | |
222 | |
223 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
224 } | |
225 | |
226 static void get_image(struct vf_instance_s* vf, mp_image_t *mpi){ | |
227 if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change | |
228 // ok, we can do pp in-place (or pp disabled): | |
229 vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, | |
230 mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height); | |
231 mpi->planes[0]=vf->dmpi->planes[0]; | |
232 mpi->stride[0]=vf->dmpi->stride[0]; | |
233 mpi->width=vf->dmpi->width; | |
234 if(mpi->flags&MP_IMGFLAG_PLANAR){ | |
235 mpi->planes[1]=vf->dmpi->planes[1]; | |
236 mpi->planes[2]=vf->dmpi->planes[2]; | |
237 mpi->stride[1]=vf->dmpi->stride[1]; | |
238 mpi->stride[2]=vf->dmpi->stride[2]; | |
239 } | |
240 mpi->flags|=MP_IMGFLAG_DIRECT; | |
241 } | |
242 | |
243 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){ | |
244 mp_image_t *dmpi; | |
245 | |
246 if(!(mpi->flags&MP_IMGFLAG_DIRECT)){ | |
247 // no DR, so get a new image! hope we'll get DR buffer: | |
248 dmpi=vf_get_image(vf->next,mpi->imgfmt, | |
249 MP_IMGTYPE_TEMP, | |
250 MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE, | |
251 mpi->width,mpi->height); | |
252 vf_clone_mpi_attributes(dmpi, mpi); | |
253 }else{ | |
254 dmpi=vf->dmpi; | |
255 } | |
256 | |
257 filter(vf->priv, dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, 1); | |
258 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); | |
259 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); | |
260 | |
261 return vf_next_put_image(vf,dmpi, pts); | |
262 } | |
263 | |
264 static void uninit(struct vf_instance_s* vf){ | |
265 int i,j; | |
266 if(!vf->priv) return; | |
267 | |
268 for(j=0; j<4; j++){ | |
269 for(i=0; i<16; i++){ | |
270 free(vf->priv->plane[i][j]); | |
271 vf->priv->plane[i][j]= NULL; | |
272 } | |
273 } | |
274 | |
275 free(vf->priv); | |
276 vf->priv=NULL; | |
277 } | |
278 | |
279 //===========================================================================// | |
280 static int query_format(struct vf_instance_s* vf, unsigned int fmt){ | |
281 switch(fmt){ | |
282 case IMGFMT_YVU9: | |
283 case IMGFMT_IF09: | |
284 case IMGFMT_YV12: | |
285 case IMGFMT_I420: | |
286 case IMGFMT_IYUV: | |
287 case IMGFMT_CLPL: | |
288 case IMGFMT_Y800: | |
289 case IMGFMT_Y8: | |
290 case IMGFMT_444P: | |
291 case IMGFMT_422P: | |
292 case IMGFMT_411P: | |
293 return vf_next_query_format(vf,fmt); | |
294 } | |
295 return 0; | |
296 } | |
297 | |
298 | |
299 static int open(vf_instance_t *vf, char* args){ | |
300 vf->config=config; | |
301 vf->put_image=put_image; | |
302 vf->get_image=get_image; | |
303 vf->query_format=query_format; | |
304 vf->uninit=uninit; | |
305 vf->priv=malloc(sizeof(struct vf_priv_s)); | |
306 memset(vf->priv, 0, sizeof(struct vf_priv_s)); | |
307 | |
308 vf->priv->depth= 8; | |
309 vf->priv->strength[0]= 1.0; | |
310 vf->priv->strength[1]= 1.0; | |
311 vf->priv->delta= 1.0; | |
312 | |
313 if (args) sscanf(args, "%d:%f:%f:%d:%f", &vf->priv->depth, | |
314 &vf->priv->strength[0], | |
315 &vf->priv->strength[1], | |
316 &vf->priv->mode, | |
317 &vf->priv->delta); | |
318 | |
319 return 1; | |
320 } | |
321 | |
25221 | 322 const vf_info_t vf_info_ow = { |
24677 | 323 "overcomplete wavelet denoiser", |
324 "ow", | |
325 "Michael Niedermayer", | |
326 "", | |
327 open, | |
328 NULL | |
329 }; |