Mercurial > mplayer.hg
annotate libmpcodecs/vf_ow.c @ 29221:84ed872376f3
Add #define for HAVE_DVDCSS_DVDCSS_H (needed by internal libdvdread) to config.h
instead of passing -D on the compiler command line.
This is more convenient and already done with most preprocessor definitions
needed by external libraries.
Previously the definition was passed on the command line because libdvdread was
missing the necessary config.h #include, which was now added.
author | diego |
---|---|
date | Tue, 05 May 2009 17:30:50 +0000 |
parents | 290420c32921 |
children | 0f1b5b68af32 |
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 "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 | |
206 static int config(struct vf_instance_s* vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt){ | |
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 | |
219 static void get_image(struct vf_instance_s* vf, mp_image_t *mpi){ | |
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 | |
236 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){ | |
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 | |
257 static void uninit(struct vf_instance_s* vf){ | |
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 //===========================================================================// | |
273 static int query_format(struct vf_instance_s* vf, unsigned int fmt){ | |
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 | |
292 static int open(vf_instance_t *vf, char* args){ | |
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 "", | |
320 open, | |
321 NULL | |
322 }; |