mp_msg: print messages to stdout, statusline to stderr
[mplayer.git] / libmpcodecs / vf_phase.c
blobb9ea66c50675b35748997136c2753710b77a5b90
1 /*
2 * This file is part of MPlayer.
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.
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.
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.
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <limits.h>
24 #include "config.h"
25 #include "mp_msg.h"
27 #include "img_format.h"
28 #include "mp_image.h"
29 #include "vf.h"
31 #include "libvo/fastmemcpy.h"
33 enum mode { PROGRESSIVE, TOP_FIRST, BOTTOM_FIRST,
34 TOP_FIRST_ANALYZE, BOTTOM_FIRST_ANALYZE,
35 ANALYZE, FULL_ANALYZE, AUTO, AUTO_ANALYZE };
37 #define fixed_mode(p) ((p)<=BOTTOM_FIRST)
39 struct vf_priv_s
41 enum mode mode;
42 int verbose;
43 unsigned char *buf[3];
47 * Copy fields from either current or buffered previous frame to the
48 * output and store the current frame unmodified to the buffer.
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)
55 unsigned char *buf, *end;
56 int top;
58 if(!*bufp)
60 mode=PROGRESSIVE;
61 if(!(*bufp=malloc(h*w))) return;
64 for(end=to+h*ts, buf=*bufp, top=1; to<end; from+=fs, to+=ts, buf+=w, top^=1)
66 fast_memcpy(to, mode==(top?BOTTOM_FIRST:TOP_FIRST)?buf:from, w);
67 fast_memcpy(buf, from, w);
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.
77 * (the result is actually multiplied by 25)
80 #define diff(a, as, b, bs) (t=((*a-b[bs])<<2)+a[as<<1]-b[-bs], t*t)
83 * Find which field combination has the smallest average squared difference
84 * between the fields.
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)
91 double bdiff, pdiff, tdiff, scale;
92 int bdif, tdif, pdif;
93 int top, t;
94 unsigned char *end, *rend;
96 if(mode==AUTO)
97 mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
98 TOP_FIRST:BOTTOM_FIRST:PROGRESSIVE;
99 else if(mode==AUTO_ANALYZE)
100 mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
101 TOP_FIRST_ANALYZE:BOTTOM_FIRST_ANALYZE:FULL_ANALYZE;
103 if(fixed_mode(mode))
104 bdiff=pdiff=tdiff=65536.0;
105 else
107 bdiff=pdiff=tdiff=0.0;
109 for(end=new+(h-2)*ns, new+=ns, old+=os, top=0;
110 new<end; new+=ns-w, old+=os-w, top^=1)
112 pdif=tdif=bdif=0;
114 switch(mode)
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;
127 case BOTTOM_FIRST_ANALYZE:
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;
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;
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);
162 pdiff+=(double)pdif;
163 tdiff+=(double)tdif;
164 bdiff+=(double)bdif;
167 scale=1.0/(w*(h-3))/25.0;
168 pdiff*=scale;
169 tdiff*=scale;
170 bdiff*=scale;
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;
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;
187 if( mp_msg_test(MSGT_VFILTER,MSGL_V) )
189 mp_msg(MSGT_VFILTER, MSGL_INFO, "%c", mode==BOTTOM_FIRST?'b':mode==TOP_FIRST?'t':'p');
190 if(tdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", tdiff);
191 if(bdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", bdiff);
192 if(pdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", pdiff);
193 mp_msg(MSGT_VFILTER, MSGL_INFO," \n");
196 return mode;
199 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
201 mp_image_t *dmpi;
202 int w;
203 enum mode mode;
205 if(!(dmpi=vf_get_image(vf->next, mpi->imgfmt,
206 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
207 mpi->w, mpi->h)))
208 return 0;
210 w=dmpi->w;
211 if(!(dmpi->flags&MP_IMGFLAG_PLANAR))
212 w*=dmpi->bpp/8;
214 mode=vf->priv->mode;
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);
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);
228 if(dmpi->flags&MP_IMGFLAG_PLANAR)
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);
240 return vf_next_put_image(vf, dmpi, pts);
243 static void uninit(struct vf_instance *vf)
245 free(vf->priv->buf[0]);
246 free(vf->priv->buf[1]);
247 free(vf->priv->buf[2]);
248 free(vf->priv);
251 static int vf_open(vf_instance_t *vf, char *args)
253 vf->put_image = put_image;
254 vf->uninit = uninit;
255 vf->default_reqs = VFCAP_ACCEPT_STRIDE;
257 if(!(vf->priv = calloc(1, sizeof(struct vf_priv_s))))
259 uninit(vf);
260 return 0;
263 vf->priv->mode=AUTO_ANALYZE;
264 vf->priv->verbose=0;
266 while(args && *args)
268 switch(*args)
270 case 't': vf->priv->mode=TOP_FIRST; break;
271 case 'a': vf->priv->mode=AUTO; break;
272 case 'b': vf->priv->mode=BOTTOM_FIRST; break;
273 case 'u': vf->priv->mode=ANALYZE; break;
274 case 'T': vf->priv->mode=TOP_FIRST_ANALYZE; break;
275 case 'A': vf->priv->mode=AUTO_ANALYZE; break;
276 case 'B': vf->priv->mode=BOTTOM_FIRST_ANALYZE; break;
277 case 'U': vf->priv->mode=FULL_ANALYZE; break;
278 case 'p': vf->priv->mode=PROGRESSIVE; break;
279 case 'v': vf->priv->verbose=1; break;
280 case ':': break;
282 default:
283 uninit(vf);
284 return 0; /* bad args */
287 if( (args=strchr(args, ':')) ) args++;
290 return 1;
293 const vf_info_t vf_info_phase =
295 "phase shift fields",
296 "phase",
297 "Ville Saari",
299 vf_open,
300 NULL