vf_perspective.c
Go to the documentation of this file.
1 /*
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  */
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 
28 #include "config.h"
29 #include "mp_msg.h"
30 
31 #if HAVE_MALLOC_H
32 #include <malloc.h>
33 #endif
34 
35 #include "libavutil/mem.h"
36 
37 #include "img_format.h"
38 #include "mp_image.h"
39 #include "vf.h"
40 
41 #define SUB_PIXEL_BITS 8
42 #define SUB_PIXELS (1<<SUB_PIXEL_BITS)
43 #define COEFF_BITS 11
44 
45 //===========================================================================//
46 
47 struct vf_priv_s {
48  double ref[4][2];
50  int32_t (*pv)[2];
51  int pvStride;
52  int cubic;
53 };
54 
55 
56 /***************************************************************************/
57 
58 static void initPv(struct vf_priv_s *priv, int W, int H){
59  double a,b,c,d,e,f,g,h,D;
60  double (*ref)[2]= priv->ref;
61  int x,y;
62 
63  g= ( (ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0])*(ref[2][1] - ref[3][1])
64  - (ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1])*(ref[2][0] - ref[3][0]))*H;
65  h= ( (ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1])*(ref[1][0] - ref[3][0])
66  - (ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0])*(ref[1][1] - ref[3][1]))*W;
67  D= (ref[1][0] - ref[3][0])*(ref[2][1] - ref[3][1])
68  - (ref[2][0] - ref[3][0])*(ref[1][1] - ref[3][1]);
69 
70  a= D*(ref[1][0] - ref[0][0])*H + g*ref[1][0];
71  b= D*(ref[2][0] - ref[0][0])*W + h*ref[2][0];
72  c= D*ref[0][0]*W*H;
73  d= D*(ref[1][1] - ref[0][1])*H + g*ref[1][1];
74  e= D*(ref[2][1] - ref[0][1])*W + h*ref[2][1];
75  f= D*ref[0][1]*W*H;
76 
77  for(y=0; y<H; y++){
78  for(x=0; x<W; x++){
79  int u, v;
80 
81  u= (int)floor( SUB_PIXELS*(a*x + b*y + c)/(g*x + h*y + D*W*H) + 0.5);
82  v= (int)floor( SUB_PIXELS*(d*x + e*y + f)/(g*x + h*y + D*W*H) + 0.5);
83 
84  priv->pv[x + y*W][0]= u;
85  priv->pv[x + y*W][1]= v;
86  }
87  }
88 }
89 
90 static double getCoeff(double d){
91  double A= -0.60;
92  double coeff;
93 
94  d= fabs(d);
95 
96  // Equation is from VirtualDub
97  if(d<1.0)
98  coeff = (1.0 - (A+3.0)*d*d + (A+2.0)*d*d*d);
99  else if(d<2.0)
100  coeff = (-4.0*A + 8.0*A*d - 5.0*A*d*d + A*d*d*d);
101  else
102  coeff=0.0;
103 
104  return coeff;
105 }
106 
107 static int config(struct vf_instance *vf,
108  int width, int height, int d_width, int d_height,
109  unsigned int flags, unsigned int outfmt){
110  int i, j;
111 
112  vf->priv->pvStride= width;
113  vf->priv->pv= av_malloc(width*height*2*sizeof(int32_t));
114  initPv(vf->priv, width, height);
115 
116  for(i=0; i<SUB_PIXELS; i++){
117  double d= i/(double)SUB_PIXELS;
118  double temp[4];
119  double sum=0;
120 
121  for(j=0; j<4; j++)
122  temp[j]= getCoeff(j - d - 1);
123 
124  for(j=0; j<4; j++)
125  sum+= temp[j];
126 
127  for(j=0; j<4; j++)
128  vf->priv->coeff[i][j]= (int)floor((1<<COEFF_BITS)*temp[j]/sum + 0.5);
129  }
130 
131  return ff_vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
132 }
133 
134 static void uninit(struct vf_instance *vf){
135  if(!vf->priv) return;
136 
137  av_free(vf->priv->pv);
138  vf->priv->pv= NULL;
139 
140  free(vf->priv);
141  vf->priv=NULL;
142 }
143 
144 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){
145  int x, y;
146  struct vf_priv_s priv= *privParam;
147 
148  for(y=0; y<h; y++){
149  for(x=0; x<w; x++){
150  int u, v, subU, subV, sum, sx, sy;
151 
152  sx= x << xShift;
153  sy= y << yShift;
154  u= priv.pv[sx + sy*priv.pvStride][0]>>xShift;
155  v= priv.pv[sx + sy*priv.pvStride][1]>>yShift;
156  subU= u & (SUB_PIXELS-1);
157  subV= v & (SUB_PIXELS-1);
158  u >>= SUB_PIXEL_BITS;
159  v >>= SUB_PIXEL_BITS;
160 
161  if(u>0 && v>0 && u<w-2 && v<h-2){
162  const int index= u + v*srcStride;
163  const int a= priv.coeff[subU][0];
164  const int b= priv.coeff[subU][1];
165  const int c= priv.coeff[subU][2];
166  const int d= priv.coeff[subU][3];
167 
168  sum=
169  priv.coeff[subV][0]*( a*src[index - 1 - srcStride] + b*src[index - 0 - srcStride]
170  + c*src[index + 1 - srcStride] + d*src[index + 2 - srcStride])
171  +priv.coeff[subV][1]*( a*src[index - 1 ] + b*src[index - 0 ]
172  + c*src[index + 1 ] + d*src[index + 2 ])
173  +priv.coeff[subV][2]*( a*src[index - 1 + srcStride] + b*src[index - 0 + srcStride]
174  + c*src[index + 1 + srcStride] + d*src[index + 2 + srcStride])
175  +priv.coeff[subV][3]*( a*src[index - 1+2*srcStride] + b*src[index - 0+2*srcStride]
176  + c*src[index + 1+2*srcStride] + d*src[index + 2+2*srcStride]);
177  }else{
178  int dx, dy;
179  sum=0;
180 
181  for(dy=0; dy<4; dy++){
182  int iy= v + dy - 1;
183  if (iy< 0) iy=0;
184  else if(iy>=h) iy=h-1;
185  for(dx=0; dx<4; dx++){
186  int ix= u + dx - 1;
187  if (ix< 0) ix=0;
188  else if(ix>=w) ix=w-1;
189 
190  sum+= priv.coeff[subU][dx]*priv.coeff[subV][dy]
191  *src[ ix + iy*srcStride];
192  }
193  }
194  }
195  sum= (sum + (1<<(COEFF_BITS*2-1)) ) >> (COEFF_BITS*2);
196  if(sum&~255){
197  if(sum<0) sum=0;
198  else sum=255;
199  }
200  dst[ x + y*dstStride]= sum;
201  }
202  }
203 }
204 
205 static inline void resampleLinear(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride,
206  struct vf_priv_s *privParam, int xShift, int yShift){
207  int x, y;
208  struct vf_priv_s priv= *privParam;
209 
210  for(y=0; y<h; y++){
211  for(x=0; x<w; x++){
212  int u, v, subU, subV, sum, sx, sy, index, subUI, subVI;
213 
214  sx= x << xShift;
215  sy= y << yShift;
216  u= priv.pv[sx + sy*priv.pvStride][0]>>xShift;
217  v= priv.pv[sx + sy*priv.pvStride][1]>>yShift;
218  subU= u & (SUB_PIXELS-1);
219  subV= v & (SUB_PIXELS-1);
220  u >>= SUB_PIXEL_BITS;
221  v >>= SUB_PIXEL_BITS;
222  index= u + v*srcStride;
223  subUI= SUB_PIXELS - subU;
224  subVI= SUB_PIXELS - subV;
225 
226  if((unsigned)u < (unsigned)(w - 1)){
227  if((unsigned)v < (unsigned)(h - 1)){
228  sum= subVI*(subUI*src[index ] + subU*src[index +1])
229  +subV *(subUI*src[index+srcStride] + subU*src[index+srcStride+1]);
230  sum= (sum + (1<<(SUB_PIXEL_BITS*2-1)) ) >> (SUB_PIXEL_BITS*2);
231  }else{
232  if(v<0) v= 0;
233  else v= h-1;
234  index= u + v*srcStride;
235  sum= subUI*src[index] + subU*src[index+1];
236  sum= (sum + (1<<(SUB_PIXEL_BITS-1)) ) >> SUB_PIXEL_BITS;
237  }
238  }else{
239  if((unsigned)v < (unsigned)(h - 1)){
240  if(u<0) u= 0;
241  else u= w-1;
242  index= u + v*srcStride;
243  sum= subVI*src[index] + subV*src[index+srcStride];
244  sum= (sum + (1<<(SUB_PIXEL_BITS-1)) ) >> SUB_PIXEL_BITS;
245  }else{
246  if(u<0) u= 0;
247  else u= w-1;
248  if(v<0) v= 0;
249  else v= h-1;
250  index= u + v*srcStride;
251  sum= src[index];
252  }
253  }
254  if(sum&~255){
255  if(sum<0) sum=0;
256  else sum=255;
257  }
258  dst[ x + y*dstStride]= sum;
259  }
260  }
261 }
262 
263 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
264  int cw= mpi->w >> mpi->chroma_x_shift;
265  int ch= mpi->h >> mpi->chroma_y_shift;
266 
269  mpi->w,mpi->h);
270 
271  assert(mpi->flags&MP_IMGFLAG_PLANAR);
272 
273  if(vf->priv->cubic){
274  resampleCubic(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0],
275  vf->priv, 0, 0);
276  resampleCubic(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1],
277  vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
278  resampleCubic(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2],
279  vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
280  }else{
281  resampleLinear(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0],
282  vf->priv, 0, 0);
283  resampleLinear(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1],
284  vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
285  resampleLinear(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2],
286  vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
287  }
288 
289  return ff_vf_next_put_image(vf,dmpi, pts);
290 }
291 
292 //===========================================================================//
293 
294 static int query_format(struct vf_instance *vf, unsigned int fmt){
295  switch(fmt)
296  {
297  case IMGFMT_YV12:
298  case IMGFMT_I420:
299  case IMGFMT_IYUV:
300  case IMGFMT_YVU9:
301  case IMGFMT_444P:
302  case IMGFMT_422P:
303  case IMGFMT_411P:
304  return ff_vf_next_query_format(vf, fmt);
305  }
306  return 0;
307 }
308 
309 static int vf_open(vf_instance_t *vf, char *args){
310  int e;
311 
312  vf->config=config;
313  vf->put_image=put_image;
314 // vf->get_image=get_image;
316  vf->uninit=uninit;
317  vf->priv=malloc(sizeof(struct vf_priv_s));
318  memset(vf->priv, 0, sizeof(struct vf_priv_s));
319 
320  if(args==NULL) return 0;
321 
322  e=sscanf(args, "%lf:%lf:%lf:%lf:%lf:%lf:%lf:%lf:%d",
323  &vf->priv->ref[0][0], &vf->priv->ref[0][1],
324  &vf->priv->ref[1][0], &vf->priv->ref[1][1],
325  &vf->priv->ref[2][0], &vf->priv->ref[2][1],
326  &vf->priv->ref[3][0], &vf->priv->ref[3][1],
327  &vf->priv->cubic
328  );
329 
330  if(e!=9)
331  return 0;
332 
333  return 1;
334 }
335 
337  "perspective correcture",
338  "perspective",
339  "Michael Niedermayer",
340  "",
341  vf_open,
342  NULL
343 };
344 
345 //===========================================================================//
unsigned int imgfmt
Definition: mp_image.h:130
float v
const char * fmt
Definition: avisynth_c.h:669
memory handling functions
Sinusoidal phase f
mp_image_t * ff_vf_get_image(vf_instance_t *vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h)
Definition: vf_mp.c:380
#define COEFF_BITS
#define IMGFMT_YVU9
Definition: img_format.h:117
#define IMGFMT_YV12
Definition: img_format.h:119
void(* uninit)(struct vf_instance *vf)
Definition: vf.h:74
output residual component w
static 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)
int ff_vf_next_config(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt)
Definition: vf_mp.c:584
set threshold d
int(* put_image)(struct vf_instance *vf, mp_image_t *mpi, double pts)
Definition: vf.h:68
uint8_t
static void resampleLinear(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, struct vf_priv_s *privParam, int xShift, int yShift)
#define H
Definition: swscale-test.c:342
#define b
Definition: input.c:42
Definition: vf.h:31
unsigned char * planes[MP_MAX_PLANES]
Definition: mp_image.h:133
D(D(float, sse)
int stride[MP_MAX_PLANES]
Definition: mp_image.h:134
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
int width
Definition: vf_fil.c:32
#define A(x)
int32_t(* pv)[2]
Discrete Time axis x
int16_t * temp
Definition: vf_fspp.c:99
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
#define MP_IMGTYPE_TEMP
Definition: mp_image.h:104
int(* query_format)(struct vf_instance *vf, unsigned int fmt)
Definition: vf.h:64
static int config(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt)
#define IMGFMT_IYUV
Definition: img_format.h:121
uint8_t * src
Definition: vf_fspp.c:98
FFT buffer for g
Definition: stft_peak.m:17
#define SUB_PIXELS
int32_t
float u
static void uninit(struct vf_instance *vf)
int chroma_y_shift
Definition: mp_image.h:145
struct vf_instance * next
Definition: vf.h:84
NULL
Definition: eval.c:55
#define SUB_PIXEL_BITS
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
int index
Definition: gxfenc.c:89
synthesis window for stochastic i
#define IMGFMT_422P
Definition: img_format.h:131
int w
Definition: mp_image.h:132
int(* config)(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt)
Definition: vf.h:59
static int flags
Definition: cpu.c:23
#define IMGFMT_444P
Definition: img_format.h:130
int32_t coeff[1<< SUB_PIXEL_BITS][4]
#define MP_IMGFLAG_PLANAR
Definition: mp_image.h:76
static double c[64]
static int vf_open(vf_instance_t *vf, char *args)
function y
Definition: D.m:1
int ff_vf_next_put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
Definition: vf_mp.c:539
static void initPv(struct vf_priv_s *priv, int W, int H)
else dst[i][x+y *dst_stride[i]]
Definition: vf_mcdeint.c:160
int chroma_x_shift
Definition: mp_image.h:144
#define MP_IMGFLAG_ACCEPT_STRIDE
Definition: mp_image.h:63
struct vf_priv_s * priv
Definition: vf.h:86
#define IMGFMT_I420
Definition: img_format.h:120
int h
Definition: mp_image.h:132
static double getCoeff(double d)
double ref[4][2]
const vf_info_t ff_vf_info_perspective
int ff_vf_next_query_format(struct vf_instance *vf, unsigned int fmt)
Definition: vf_mp.c:371
Definition: vf.h:56
static int query_format(struct vf_instance *vf, unsigned int fmt)
unsigned int flags
Definition: mp_image.h:126
int height
Definition: vf_fil.c:31
#define IMGFMT_411P
Definition: img_format.h:132
normalize window W
Definition: stft_peak.m:10
MUSIC TECHNOLOGY GROUP UNIVERSITAT POMPEU FABRA Free Non Commercial Binary License Agreement UNIVERSITAT POMPEU OR INDICATING ACCEPTANCE BY SELECTING THE ACCEPT BUTTON ON ANY DOWNLOAD OR INSTALL YOU ACCEPT THE TERMS OF THE LICENSE SUMMARY TABLE Software MELODIA Melody Extraction vamp plug in Licensor Music Technology Group Universitat Pompeu Plaça de la Spain Permitted purposes Non commercial internal research and validation and educational purposes only All commercial uses in a production either internal or are prohibited by this license and require an additional commercial exploitation license TERMS AND CONDITIONS SOFTWARE Software means the software programs identified herein in binary any other machine readable any updates or error corrections provided by and any user programming guides and other documentation provided to you by UPF under this Agreement LICENSE Subject to the terms and conditions of this UPF grants you a royalty free