Mercurial > mplayer.hg
annotate libmpcodecs/vf_perspective.c @ 32282:606e4157cd4c
Split alloc and init of context so that parameters can be set in the context
instead of requireing being passed through function parameters. This also
makes sws work with AVOptions.
author | michael |
---|---|
date | Sun, 26 Sep 2010 19:33:57 +0000 |
parents | a972c1a4a012 |
children | 8fa2f43cb760 |
rev | line source |
---|---|
8112 | 1 /* |
26727 | 2 * Copyright (C) 2002 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 */ | |
8112 | 20 |
21 #include <stdio.h> | |
22 #include <stdlib.h> | |
23 #include <string.h> | |
24 #include <inttypes.h> | |
25 #include <assert.h> | |
26 #include <math.h> | |
27 | |
17012 | 28 #include "config.h" |
29 #include "mp_msg.h" | |
8112 | 30 |
28594
df67d03dde3b
Convert HAVE_MALLOC_H into a 0/1 definition, fixes the warning:
diego
parents:
26727
diff
changeset
|
31 #if HAVE_MALLOC_H |
8112 | 32 #include <malloc.h> |
33 #endif | |
34 | |
35 #include "img_format.h" | |
36 #include "mp_image.h" | |
37 #include "vf.h" | |
38 | |
39 #define SUB_PIXEL_BITS 8 | |
40 #define SUB_PIXELS (1<<SUB_PIXEL_BITS) | |
41 #define COEFF_BITS 11 | |
42 | |
43 //===========================================================================// | |
44 | |
45 struct vf_priv_s { | |
46 double ref[4][2]; | |
47 int32_t coeff[1<<SUB_PIXEL_BITS][4]; | |
48 int32_t (*pv)[2]; | |
49 int pvStride; | |
50 int cubic; | |
51 }; | |
52 | |
53 | |
54 /***************************************************************************/ | |
55 | |
56 static void initPv(struct vf_priv_s *priv, int W, int H){ | |
57 double a,b,c,d,e,f,g,h,D; | |
58 double (*ref)[2]= priv->ref; | |
59 int x,y; | |
60 | |
61 g= ( (ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0])*(ref[2][1] - ref[3][1]) | |
62 - (ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1])*(ref[2][0] - ref[3][0]))*H; | |
63 h= ( (ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1])*(ref[1][0] - ref[3][0]) | |
64 - (ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0])*(ref[1][1] - ref[3][1]))*W; | |
65 D= (ref[1][0] - ref[3][0])*(ref[2][1] - ref[3][1]) | |
66 - (ref[2][0] - ref[3][0])*(ref[1][1] - ref[3][1]); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
67 |
8112 | 68 a= D*(ref[1][0] - ref[0][0])*H + g*ref[1][0]; |
69 b= D*(ref[2][0] - ref[0][0])*W + h*ref[2][0]; | |
70 c= D*ref[0][0]*W*H; | |
71 d= D*(ref[1][1] - ref[0][1])*H + g*ref[1][1]; | |
72 e= D*(ref[2][1] - ref[0][1])*W + h*ref[2][1]; | |
73 f= D*ref[0][1]*W*H; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
74 |
8112 | 75 for(y=0; y<H; y++){ |
76 for(x=0; x<W; x++){ | |
77 int u, v; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
78 |
8112 | 79 u= (int)floor( SUB_PIXELS*(a*x + b*y + c)/(g*x + h*y + D*W*H) + 0.5); |
80 v= (int)floor( SUB_PIXELS*(d*x + e*y + f)/(g*x + h*y + D*W*H) + 0.5); | |
81 | |
82 priv->pv[x + y*W][0]= u; | |
83 priv->pv[x + y*W][1]= v; | |
84 } | |
85 } | |
86 } | |
87 | |
88 static double getCoeff(double d){ | |
89 double A= -0.60; | |
90 double coeff; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
91 |
8112 | 92 d= fabs(d); |
93 | |
94 // Equation is from VirtualDub | |
95 if(d<1.0) | |
96 coeff = (1.0 - (A+3.0)*d*d + (A+2.0)*d*d*d); | |
97 else if(d<2.0) | |
98 coeff = (-4.0*A + 8.0*A*d - 5.0*A*d*d + A*d*d*d); | |
99 else | |
100 coeff=0.0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
101 |
8112 | 102 return coeff; |
103 } | |
104 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
105 static int config(struct vf_instance *vf, |
8112 | 106 int width, int height, int d_width, int d_height, |
107 unsigned int flags, unsigned int outfmt){ | |
108 int i, j; | |
109 | |
110 vf->priv->pvStride= width; | |
111 vf->priv->pv= (void*)memalign(8, width*height*2*sizeof(int32_t)); | |
112 initPv(vf->priv, width, height); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
113 |
8112 | 114 for(i=0; i<SUB_PIXELS; i++){ |
115 double d= i/(double)SUB_PIXELS; | |
116 double temp[4]; | |
117 double sum=0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
118 |
8112 | 119 for(j=0; j<4; j++) |
120 temp[j]= getCoeff(j - d - 1); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
121 |
8112 | 122 for(j=0; j<4; j++) |
123 sum+= temp[j]; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
124 |
8112 | 125 for(j=0; j<4; j++) |
126 vf->priv->coeff[i][j]= (int)floor((1<<COEFF_BITS)*temp[j]/sum + 0.5); | |
127 } | |
128 | |
129 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
130 } | |
131 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
132 static void uninit(struct vf_instance *vf){ |
8112 | 133 if(!vf->priv) return; |
134 | |
135 if(vf->priv->pv) free(vf->priv->pv); | |
136 vf->priv->pv= NULL; | |
137 | |
138 free(vf->priv); | |
139 vf->priv=NULL; | |
140 } | |
141 | |
142 static inline void resampleCubic(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, struct vf_priv_s *privParam, int xShift, int yShift){ | |
143 int x, y; | |
144 struct vf_priv_s priv= *privParam; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
145 |
8112 | 146 for(y=0; y<h; y++){ |
147 for(x=0; x<w; x++){ | |
148 int u, v, subU, subV, sum, sx, sy; | |
149 | |
150 sx= x << xShift; | |
151 sy= y << yShift; | |
152 u= priv.pv[sx + sy*priv.pvStride][0]>>xShift; | |
153 v= priv.pv[sx + sy*priv.pvStride][1]>>yShift; | |
154 subU= u & (SUB_PIXELS-1); | |
155 subV= v & (SUB_PIXELS-1); | |
156 u >>= SUB_PIXEL_BITS; | |
157 v >>= SUB_PIXEL_BITS; | |
158 | |
159 if(u>0 && v>0 && u<w-2 && v<h-2){ | |
160 const int index= u + v*srcStride; | |
161 const int a= priv.coeff[subU][0]; | |
162 const int b= priv.coeff[subU][1]; | |
163 const int c= priv.coeff[subU][2]; | |
164 const int d= priv.coeff[subU][3]; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
165 |
8112 | 166 sum= |
167 priv.coeff[subV][0]*( a*src[index - 1 - srcStride] + b*src[index - 0 - srcStride] | |
168 + c*src[index + 1 - srcStride] + d*src[index + 2 - srcStride]) | |
169 +priv.coeff[subV][1]*( a*src[index - 1 ] + b*src[index - 0 ] | |
170 + c*src[index + 1 ] + d*src[index + 2 ]) | |
171 +priv.coeff[subV][2]*( a*src[index - 1 + srcStride] + b*src[index - 0 + srcStride] | |
172 + c*src[index + 1 + srcStride] + d*src[index + 2 + srcStride]) | |
173 +priv.coeff[subV][3]*( a*src[index - 1+2*srcStride] + b*src[index - 0+2*srcStride] | |
174 + c*src[index + 1+2*srcStride] + d*src[index + 2+2*srcStride]); | |
175 }else{ | |
176 int dx, dy; | |
177 sum=0; | |
178 | |
179 for(dy=0; dy<4; dy++){ | |
180 int iy= v + dy - 1; | |
181 if (iy< 0) iy=0; | |
182 else if(iy>=h) iy=h-1; | |
183 for(dx=0; dx<4; dx++){ | |
184 int ix= u + dx - 1; | |
185 if (ix< 0) ix=0; | |
186 else if(ix>=w) ix=w-1; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
187 |
8112 | 188 sum+= priv.coeff[subU][dx]*priv.coeff[subV][dy] |
189 *src[ ix + iy*srcStride]; | |
190 } | |
191 } | |
192 } | |
193 sum= (sum + (1<<(COEFF_BITS*2-1)) ) >> (COEFF_BITS*2); | |
194 if(sum&~255){ | |
195 if(sum<0) sum=0; | |
196 else sum=255; | |
197 } | |
198 dst[ x + y*dstStride]= sum; | |
199 } | |
200 } | |
201 } | |
202 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
203 static inline void resampleLinear(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, |
8112 | 204 struct vf_priv_s *privParam, int xShift, int yShift){ |
205 int x, y; | |
206 struct vf_priv_s priv= *privParam; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
207 |
8112 | 208 for(y=0; y<h; y++){ |
209 for(x=0; x<w; x++){ | |
210 int u, v, subU, subV, sum, sx, sy, index, subUI, subVI; | |
211 | |
212 sx= x << xShift; | |
213 sy= y << yShift; | |
214 u= priv.pv[sx + sy*priv.pvStride][0]>>xShift; | |
215 v= priv.pv[sx + sy*priv.pvStride][1]>>yShift; | |
216 subU= u & (SUB_PIXELS-1); | |
217 subV= v & (SUB_PIXELS-1); | |
218 u >>= SUB_PIXEL_BITS; | |
219 v >>= SUB_PIXEL_BITS; | |
220 index= u + v*srcStride; | |
221 subUI= SUB_PIXELS - subU; | |
222 subVI= SUB_PIXELS - subV; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
223 |
8112 | 224 if((unsigned)u < (unsigned)(w - 1)){ |
225 if((unsigned)v < (unsigned)(h - 1)){ | |
226 sum= subVI*(subUI*src[index ] + subU*src[index +1]) | |
227 +subV *(subUI*src[index+srcStride] + subU*src[index+srcStride+1]); | |
228 sum= (sum + (1<<(SUB_PIXEL_BITS*2-1)) ) >> (SUB_PIXEL_BITS*2); | |
229 }else{ | |
230 if(v<0) v= 0; | |
231 else v= h-1; | |
232 index= u + v*srcStride; | |
233 sum= subUI*src[index] + subU*src[index+1]; | |
234 sum= (sum + (1<<(SUB_PIXEL_BITS-1)) ) >> SUB_PIXEL_BITS; | |
235 } | |
236 }else{ | |
237 if((unsigned)v < (unsigned)(h - 1)){ | |
238 if(u<0) u= 0; | |
239 else u= w-1; | |
240 index= u + v*srcStride; | |
241 sum= subVI*src[index] + subV*src[index+srcStride]; | |
242 sum= (sum + (1<<(SUB_PIXEL_BITS-1)) ) >> SUB_PIXEL_BITS; | |
243 }else{ | |
244 if(u<0) u= 0; | |
245 else u= w-1; | |
246 if(v<0) v= 0; | |
247 else v= h-1; | |
248 index= u + v*srcStride; | |
249 sum= src[index]; | |
250 } | |
251 } | |
252 if(sum&~255){ | |
253 if(sum<0) sum=0; | |
254 else sum=255; | |
255 } | |
256 dst[ x + y*dstStride]= sum; | |
257 } | |
258 } | |
259 } | |
260 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
261 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ |
8112 | 262 int cw= mpi->w >> mpi->chroma_x_shift; |
263 int ch= mpi->h >> mpi->chroma_y_shift; | |
264 | |
265 mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt, | |
266 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, | |
267 mpi->w,mpi->h); | |
268 | |
269 assert(mpi->flags&MP_IMGFLAG_PLANAR); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
270 |
8112 | 271 if(vf->priv->cubic){ |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
272 resampleCubic(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], |
8112 | 273 vf->priv, 0, 0); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
274 resampleCubic(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1], |
8112 | 275 vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
276 resampleCubic(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2], |
8112 | 277 vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift); |
278 }else{ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
279 resampleLinear(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], |
8112 | 280 vf->priv, 0, 0); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
281 resampleLinear(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1], |
8112 | 282 vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
283 resampleLinear(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2], |
8112 | 284 vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift); |
285 } | |
286 | |
17906
20aca9baf5d8
passing pts through the filter layer (lets see if pts or cola comes out at the end)
michael
parents:
17367
diff
changeset
|
287 return vf_next_put_image(vf,dmpi, pts); |
8112 | 288 } |
289 | |
290 //===========================================================================// | |
291 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
292 static int query_format(struct vf_instance *vf, unsigned int fmt){ |
8112 | 293 switch(fmt) |
294 { | |
295 case IMGFMT_YV12: | |
296 case IMGFMT_I420: | |
297 case IMGFMT_IYUV: | |
298 case IMGFMT_YVU9: | |
299 case IMGFMT_444P: | |
300 case IMGFMT_422P: | |
301 case IMGFMT_411P: | |
302 return vf_next_query_format(vf, fmt); | |
303 } | |
304 return 0; | |
305 } | |
306 | |
30638
a7b908875c14
Rename open() vf initialization function to vf_open().
diego
parents:
29263
diff
changeset
|
307 static int vf_open(vf_instance_t *vf, char *args){ |
8112 | 308 int e; |
309 | |
310 vf->config=config; | |
311 vf->put_image=put_image; | |
312 // vf->get_image=get_image; | |
313 vf->query_format=query_format; | |
314 vf->uninit=uninit; | |
315 vf->priv=malloc(sizeof(struct vf_priv_s)); | |
316 memset(vf->priv, 0, sizeof(struct vf_priv_s)); | |
317 | |
318 if(args==NULL) return 0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28594
diff
changeset
|
319 |
8112 | 320 e=sscanf(args, "%lf:%lf:%lf:%lf:%lf:%lf:%lf:%lf:%d", |
321 &vf->priv->ref[0][0], &vf->priv->ref[0][1], | |
322 &vf->priv->ref[1][0], &vf->priv->ref[1][1], | |
323 &vf->priv->ref[2][0], &vf->priv->ref[2][1], | |
324 &vf->priv->ref[3][0], &vf->priv->ref[3][1], | |
325 &vf->priv->cubic | |
326 ); | |
327 | |
328 if(e!=9) | |
329 return 0; | |
330 | |
331 return 1; | |
332 } | |
333 | |
25221 | 334 const vf_info_t vf_info_perspective = { |
8112 | 335 "perspective correcture", |
336 "perspective", | |
337 "Michael Niedermayer", | |
338 "", | |
30638
a7b908875c14
Rename open() vf initialization function to vf_open().
diego
parents:
29263
diff
changeset
|
339 vf_open, |
9593
e9a2af584986
Add the new -vf option wich is the same as vop in reverse order.
albeu
parents:
8112
diff
changeset
|
340 NULL |
8112 | 341 }; |
342 | |
343 //===========================================================================// |