FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vf_phase.c
Go to the documentation of this file.
1 /*
2  * This file is part of MPlayer.
3  *
4  * MPlayer is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * MPlayer is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <limits.h>
23 
24 #include "config.h"
25 #include "mp_msg.h"
26 
27 #include "img_format.h"
28 #include "mp_image.h"
29 #include "vf.h"
30 
31 #include "libvo/fastmemcpy.h"
32 
36 
37 #define fixed_mode(p) ((p)<=BOTTOM_FIRST)
38 
39 struct vf_priv_s
40  {
41  enum mode mode;
42  int verbose;
43  unsigned char *buf[3];
44  };
45 
46 /*
47  * Copy fields from either current or buffered previous frame to the
48  * output and store the current frame unmodified to the buffer.
49  */
50 
51 static void do_plane(unsigned char *to, unsigned char *from,
52  int w, int h, int ts, int fs,
53  unsigned char **bufp, enum mode mode)
54  {
55  unsigned char *buf, *end;
56  int top;
57 
58  if(!*bufp)
59  {
60  mode=PROGRESSIVE;
61  if(!(*bufp=malloc(h*w))) return;
62  }
63 
64  for(end=to+h*ts, buf=*bufp, top=1; to<end; from+=fs, to+=ts, buf+=w, top^=1)
65  {
66  fast_memcpy(to, mode==(top?BOTTOM_FIRST:TOP_FIRST)?buf:from, w);
67  fast_memcpy(buf, from, w);
68  }
69  }
70 
71 /*
72  * This macro interpolates the value of both fields at a point halfway
73  * between lines and takes the squared difference. In field resolution
74  * the point is a quarter pixel below a line in one field and a quarter
75  * pixel above a line in other.
76  *
77  * (the result is actually multiplied by 25)
78  */
79 
80 #define diff(a, as, b, bs) (t=((*a-b[bs])<<2)+a[as<<1]-b[-bs], t*t)
81 
82 /*
83  * Find which field combination has the smallest average squared difference
84  * between the fields.
85  */
86 
87 static enum mode analyze_plane(unsigned char *old, unsigned char *new,
88  int w, int h, int os, int ns, enum mode mode,
89  int verbose, int fields)
90  {
91  double bdiff, pdiff, tdiff, scale;
92  int bdif, tdif, pdif;
93  int top, t;
94  unsigned char *end, *rend;
95 
96  if(mode==AUTO)
97  mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
99  else if(mode==AUTO_ANALYZE)
100  mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
102 
103  if(fixed_mode(mode))
104  bdiff=pdiff=tdiff=65536.0;
105  else
106  {
107  bdiff=pdiff=tdiff=0.0;
108 
109  for(end=new+(h-2)*ns, new+=ns, old+=os, top=0;
110  new<end; new+=ns-w, old+=os-w, top^=1)
111  {
112  pdif=tdif=bdif=0;
113 
114  switch(mode)
115  {
116  case TOP_FIRST_ANALYZE:
117  if(top)
118  for(rend=new+w; new<rend; new++, old++)
119  pdif+=diff(new, ns, new, ns),
120  tdif+=diff(new, ns, old, os);
121  else
122  for(rend=new+w; new<rend; new++, old++)
123  pdif+=diff(new, ns, new, ns),
124  tdif+=diff(old, os, new, ns);
125  break;
126 
128  if(top)
129  for(rend=new+w; new<rend; new++, old++)
130  pdif+=diff(new, ns, new, ns),
131  bdif+=diff(old, os, new, ns);
132  else
133  for(rend=new+w; new<rend; new++, old++)
134  pdif+=diff(new, ns, new, ns),
135  bdif+=diff(new, ns, old, os);
136  break;
137 
138  case ANALYZE:
139  if(top)
140  for(rend=new+w; new<rend; new++, old++)
141  tdif+=diff(new, ns, old, os),
142  bdif+=diff(old, os, new, ns);
143  else
144  for(rend=new+w; new<rend; new++, old++)
145  bdif+=diff(new, ns, old, os),
146  tdif+=diff(old, os, new, ns);
147  break;
148 
149  default: /* FULL_ANALYZE */
150  if(top)
151  for(rend=new+w; new<rend; new++, old++)
152  pdif+=diff(new, ns, new, ns),
153  tdif+=diff(new, ns, old, os),
154  bdif+=diff(old, os, new, ns);
155  else
156  for(rend=new+w; new<rend; new++, old++)
157  pdif+=diff(new, ns, new, ns),
158  bdif+=diff(new, ns, old, os),
159  tdif+=diff(old, os, new, ns);
160  }
161 
162  pdiff+=(double)pdif;
163  tdiff+=(double)tdif;
164  bdiff+=(double)bdif;
165  }
166 
167  scale=1.0/(w*(h-3))/25.0;
168  pdiff*=scale;
169  tdiff*=scale;
170  bdiff*=scale;
171 
172  if(mode==TOP_FIRST_ANALYZE)
173  bdiff=65536.0;
174  else if(mode==BOTTOM_FIRST_ANALYZE)
175  tdiff=65536.0;
176  else if(mode==ANALYZE)
177  pdiff=65536.0;
178 
179  if(bdiff<pdiff && bdiff<tdiff)
180  mode=BOTTOM_FIRST;
181  else if(tdiff<pdiff && tdiff<bdiff)
182  mode=TOP_FIRST;
183  else
184  mode=PROGRESSIVE;
185  }
186 
188  {
189  ff_mp_msg(MSGT_VFILTER, MSGL_INFO, "%c", mode==BOTTOM_FIRST?'b':mode==TOP_FIRST?'t':'p');
190  if(tdiff==65536.0) ff_mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else ff_mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", tdiff);
191  if(bdiff==65536.0) ff_mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else ff_mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", bdiff);
192  if(pdiff==65536.0) ff_mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else ff_mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", pdiff);
194  }
195 
196  return mode;
197  }
198 
199 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
200  {
201  mp_image_t *dmpi;
202  int w;
203  enum mode mode;
204 
205  if(!(dmpi=ff_vf_get_image(vf->next, mpi->imgfmt,
207  mpi->w, mpi->h)))
208  return 0;
209 
210  w=dmpi->w;
211  if(!(dmpi->flags&MP_IMGFLAG_PLANAR))
212  w*=dmpi->bpp/8;
213 
214  mode=vf->priv->mode;
215 
216  if(!vf->priv->buf[0])
217  mode=PROGRESSIVE;
218  else
219  mode=analyze_plane(vf->priv->buf[0], mpi->planes[0],
220  w, dmpi->h, w, mpi->stride[0], mode,
221  vf->priv->verbose, mpi->fields);
222 
223  do_plane(dmpi->planes[0], mpi->planes[0],
224  w, dmpi->h,
225  dmpi->stride[0], mpi->stride[0],
226  &vf->priv->buf[0], mode);
227 
228  if(dmpi->flags&MP_IMGFLAG_PLANAR)
229  {
230  do_plane(dmpi->planes[1], mpi->planes[1],
231  dmpi->chroma_width, dmpi->chroma_height,
232  dmpi->stride[1], mpi->stride[1],
233  &vf->priv->buf[1], mode);
234  do_plane(dmpi->planes[2], mpi->planes[2],
235  dmpi->chroma_width, dmpi->chroma_height,
236  dmpi->stride[2], mpi->stride[2],
237  &vf->priv->buf[2], mode);
238  }
239 
240  return ff_vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
241  }
242 
243 static void uninit(struct vf_instance *vf)
244  {
245  if (!vf->priv)
246  return;
247  free(vf->priv->buf[0]);
248  free(vf->priv->buf[1]);
249  free(vf->priv->buf[2]);
250  free(vf->priv);
251  }
252 
253 static int vf_open(vf_instance_t *vf, char *args)
254  {
255  vf->put_image = put_image;
256  vf->uninit = uninit;
258 
259  if(!(vf->priv = calloc(1, sizeof(struct vf_priv_s))))
260  {
261  uninit(vf);
262  return 0;
263  }
264 
265  vf->priv->mode=AUTO_ANALYZE;
266  vf->priv->verbose=0;
267 
268  while(args && *args)
269  {
270  switch(*args)
271  {
272  case 't': vf->priv->mode=TOP_FIRST; break;
273  case 'a': vf->priv->mode=AUTO; break;
274  case 'b': vf->priv->mode=BOTTOM_FIRST; break;
275  case 'u': vf->priv->mode=ANALYZE; break;
276  case 'T': vf->priv->mode=TOP_FIRST_ANALYZE; break;
277  case 'A': vf->priv->mode=AUTO_ANALYZE; break;
278  case 'B': vf->priv->mode=BOTTOM_FIRST_ANALYZE; break;
279  case 'U': vf->priv->mode=FULL_ANALYZE; break;
280  case 'p': vf->priv->mode=PROGRESSIVE; break;
281  case 'v': vf->priv->verbose=1; break;
282  case ':': break;
283 
284  default:
285  uninit(vf);
286  return 0; /* bad args */
287  }
288 
289  if( (args=strchr(args, ':')) ) args++;
290  }
291 
292  return 1;
293  }
294 
296  {
297  "phase shift fields",
298  "phase",
299  "Ville Saari",
300  "",
301  vf_open,
302  NULL
303  };