comparison libmpcodecs/vf_phase.c @ 12081:e34700c872ac

vf_phase filter by Ville Saari (114263 at foo dot bar dot org)
author rfelker
date Mon, 29 Mar 2004 04:39:04 +0000
parents
children f60bc2314146
comparison
equal deleted inserted replaced
12080:1abbfe730adc 12081:e34700c872ac
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <limits.h>
5
6 #include "../config.h"
7 #include "../mp_msg.h"
8
9 #include "img_format.h"
10 #include "mp_image.h"
11 #include "vf.h"
12
13 #include "../libvo/fastmemcpy.h"
14
15 enum mode { PROGRESSIVE, TOP_FIRST, BOTTOM_FIRST,
16 TOP_FIRST_ANALYZE, BOTTOM_FIRST_ANALYZE,
17 ANALYZE, FULL_ANALYZE, AUTO, AUTO_ANALYZE };
18
19 #define fixed_mode(p) ((p)<=BOTTOM_FIRST)
20
21 struct vf_priv_s
22 {
23 enum mode mode;
24 int verbose;
25 unsigned char *buf[3];
26 };
27
28 /*
29 * Copy fields from either current or buffered previous frame to the
30 * output and store the current frame unmodified to the buffer.
31 */
32
33 static void do_plane(unsigned char *to, unsigned char *from,
34 int w, int h, int ts, int fs,
35 unsigned char **bufp, enum mode mode)
36 {
37 unsigned char *buf, *end;
38 int top;
39
40 if(!*bufp)
41 {
42 mode=PROGRESSIVE;
43 if(!(*bufp=malloc(h*w))) return;
44 }
45
46 for(end=to+h*ts, buf=*bufp, top=1; to<end; from+=fs, to+=ts, buf+=w, top^=1)
47 {
48 memcpy(to, mode==(top?BOTTOM_FIRST:TOP_FIRST)?buf:from, w);
49 memcpy(buf, from, w);
50 }
51 }
52
53 /*
54 * This macro interpolates the value of both fields at a point halfway
55 * between lines and takes the squared difference. In field resolution
56 * the point is a quarter pixel below a line in one field and a quarter
57 * pixel above a line in other.
58 *
59 * (the result is actually multiplied by 25)
60 */
61
62 #define diff(a, as, b, bs) (t=(*a-b[bs]<<2)+a[as<<1]-b[-bs], t*t)
63
64 /*
65 * Find which field combination has the smallest average squared difference
66 * between the fields.
67 */
68
69 static enum mode analyze_plane(unsigned char *old, unsigned char *new,
70 int w, int h, int os, int ns, enum mode mode,
71 int verbose, int fields)
72 {
73 double bdiff, pdiff, tdiff, scale;
74 int bdif, tdif, pdif;
75 int top, t;
76 unsigned char *end, *rend;
77
78 if(mode==AUTO)
79 mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
80 TOP_FIRST:BOTTOM_FIRST:PROGRESSIVE;
81 else if(mode==AUTO_ANALYZE)
82 mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
83 TOP_FIRST_ANALYZE:BOTTOM_FIRST_ANALYZE:FULL_ANALYZE;
84
85 if(fixed_mode(mode))
86 bdiff=pdiff=tdiff=65536.0;
87 else
88 {
89 bdiff=pdiff=tdiff=0.0;
90
91 for(end=new+(h-2)*ns, new+=ns, old+=os, top=0;
92 new<end; new+=ns-w, old+=os-w, top^=1)
93 {
94 pdif=tdif=bdif=0;
95
96 switch(mode)
97 {
98 case TOP_FIRST_ANALYZE:
99 if(top)
100 for(rend=new+w; new<rend; new++, old++)
101 pdif+=diff(new, ns, new, ns),
102 tdif+=diff(new, ns, old, os);
103 else
104 for(rend=new+w; new<rend; new++, old++)
105 pdif+=diff(new, ns, new, ns),
106 tdif+=diff(old, os, new, ns);
107 break;
108
109 case BOTTOM_FIRST_ANALYZE:
110 if(top)
111 for(rend=new+w; new<rend; new++, old++)
112 pdif+=diff(new, ns, new, ns),
113 bdif+=diff(old, os, new, ns);
114 else
115 for(rend=new+w; new<rend; new++, old++)
116 pdif+=diff(new, ns, new, ns),
117 bdif+=diff(new, ns, old, os);
118 break;
119
120 case ANALYZE:
121 if(top)
122 for(rend=new+w; new<rend; new++, old++)
123 tdif+=diff(new, ns, old, os),
124 bdif+=diff(old, os, new, ns);
125 else
126 for(rend=new+w; new<rend; new++, old++)
127 bdif+=diff(new, ns, old, os),
128 tdif+=diff(old, os, new, ns);
129 break;
130
131 default: /* FULL_ANALYZE */
132 if(top)
133 for(rend=new+w; new<rend; new++, old++)
134 pdif+=diff(new, ns, new, ns),
135 tdif+=diff(new, ns, old, os),
136 bdif+=diff(old, os, new, ns);
137 else
138 for(rend=new+w; new<rend; new++, old++)
139 pdif+=diff(new, ns, new, ns),
140 bdif+=diff(new, ns, old, os),
141 tdif+=diff(old, os, new, ns);
142 }
143
144 pdiff+=(double)pdif;
145 tdiff+=(double)tdif;
146 bdiff+=(double)bdif;
147 }
148
149 scale=1.0/(w*(h-3))/25.0;
150 pdiff*=scale;
151 tdiff*=scale;
152 bdiff*=scale;
153
154 if(mode==TOP_FIRST_ANALYZE)
155 bdiff=65536.0;
156 else if(mode==BOTTOM_FIRST_ANALYZE)
157 tdiff=65536.0;
158 else if(mode==ANALYZE)
159 pdiff=65536.0;
160
161 if(bdiff<pdiff && bdiff<tdiff)
162 mode=BOTTOM_FIRST;
163 else if(tdiff<pdiff && tdiff<bdiff)
164 mode=TOP_FIRST;
165 else
166 mode=PROGRESSIVE;
167 }
168
169 if(verbose)
170 {
171 printf("%c", mode==BOTTOM_FIRST?'b':mode==TOP_FIRST?'t':'p');
172 if(tdiff==65536.0) printf(" N/A "); else printf(" %8.2f", tdiff);
173 if(bdiff==65536.0) printf(" N/A "); else printf(" %8.2f", bdiff);
174 if(pdiff==65536.0) printf(" N/A "); else printf(" %8.2f", pdiff);
175 printf(" \n");
176 }
177
178 return mode;
179 }
180
181 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi)
182 {
183 mp_image_t *dmpi;
184 int w;
185 enum mode mode;
186
187 if(!(dmpi=vf_get_image(vf->next, mpi->imgfmt,
188 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
189 mpi->w, mpi->h)))
190 return 0;
191
192 w=dmpi->w;
193 if(!(dmpi->flags&MP_IMGFLAG_PLANAR))
194 w*=dmpi->bpp/8;
195
196 mode=vf->priv->mode;
197
198 if(!vf->priv->buf[0])
199 mode=PROGRESSIVE;
200 else
201 mode=analyze_plane(vf->priv->buf[0], mpi->planes[0],
202 w, dmpi->h, w, mpi->stride[0], mode,
203 vf->priv->verbose, mpi->fields);
204
205 do_plane(dmpi->planes[0], mpi->planes[0],
206 w, dmpi->h,
207 dmpi->stride[0], mpi->stride[0],
208 &vf->priv->buf[0], mode);
209
210 if(dmpi->flags&MP_IMGFLAG_PLANAR)
211 {
212 do_plane(dmpi->planes[1], mpi->planes[1],
213 dmpi->chroma_width, dmpi->chroma_height,
214 dmpi->stride[1], mpi->stride[1],
215 &vf->priv->buf[1], mode);
216 do_plane(dmpi->planes[2], mpi->planes[2],
217 dmpi->chroma_width, dmpi->chroma_height,
218 dmpi->stride[2], mpi->stride[2],
219 &vf->priv->buf[2], mode);
220 }
221
222 return vf_next_put_image(vf, dmpi);
223 }
224
225 static void uninit(struct vf_instance_s* vf)
226 {
227 free(vf->priv->buf[0]);
228 free(vf->priv->buf[1]);
229 free(vf->priv->buf[2]);
230 free(vf->priv);
231 }
232
233 static int open(vf_instance_t *vf, char* args)
234 {
235 vf->put_image = put_image;
236 vf->uninit = uninit;
237 vf->default_reqs = VFCAP_ACCEPT_STRIDE;
238
239 if(!(vf->priv = calloc(1, sizeof(struct vf_priv_s))))
240 {
241 uninit(vf);
242 return 0;
243 }
244
245 vf->priv->mode=AUTO_ANALYZE;
246 vf->priv->verbose=0;
247
248 while(args && *args)
249 {
250 switch(*args)
251 {
252 case 't': vf->priv->mode=TOP_FIRST; break;
253 case 'a': vf->priv->mode=AUTO; break;
254 case 'b': vf->priv->mode=BOTTOM_FIRST; break;
255 case 'u': vf->priv->mode=ANALYZE; break;
256 case 'T': vf->priv->mode=TOP_FIRST_ANALYZE; break;
257 case 'A': vf->priv->mode=AUTO_ANALYZE; break;
258 case 'B': vf->priv->mode=BOTTOM_FIRST_ANALYZE; break;
259 case 'U': vf->priv->mode=FULL_ANALYZE; break;
260 case 'p': vf->priv->mode=PROGRESSIVE; break;
261 case 'v': vf->priv->verbose=1; break;
262 case ':': break;
263
264 default:
265 uninit(vf);
266 return 0; /* bad args */
267 }
268
269 if(args=strchr(args, ':')) args++;
270 }
271
272 return 1;
273 }
274
275 vf_info_t vf_info_phase =
276 {
277 "phase shift fields",
278 "phase",
279 "Ville Saari",
280 "",
281 open,
282 NULL
283 };