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.
27 #include "img_format.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)
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
;
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
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
;
94 unsigned char *end
, *rend
;
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
;
104 bdiff
=pdiff
=tdiff
=65536.0;
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)
116 case TOP_FIRST_ANALYZE
:
118 for(rend
=new+w
; new<rend
; new++, old
++)
119 pdif
+=diff(new, ns
, new, ns
),
120 tdif
+=diff(new, ns
, old
, os
);
122 for(rend
=new+w
; new<rend
; new++, old
++)
123 pdif
+=diff(new, ns
, new, ns
),
124 tdif
+=diff(old
, os
, new, ns
);
127 case BOTTOM_FIRST_ANALYZE
:
129 for(rend
=new+w
; new<rend
; new++, old
++)
130 pdif
+=diff(new, ns
, new, ns
),
131 bdif
+=diff(old
, os
, new, ns
);
133 for(rend
=new+w
; new<rend
; new++, old
++)
134 pdif
+=diff(new, ns
, new, ns
),
135 bdif
+=diff(new, ns
, old
, os
);
140 for(rend
=new+w
; new<rend
; new++, old
++)
141 tdif
+=diff(new, ns
, old
, os
),
142 bdif
+=diff(old
, os
, new, ns
);
144 for(rend
=new+w
; new<rend
; new++, old
++)
145 bdif
+=diff(new, ns
, old
, os
),
146 tdif
+=diff(old
, os
, new, ns
);
149 default: /* FULL_ANALYZE */
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
);
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
);
167 scale
=1.0/(w
*(h
-3))/25.0;
172 if(mode
==TOP_FIRST_ANALYZE
)
174 else if(mode
==BOTTOM_FIRST_ANALYZE
)
176 else if(mode
==ANALYZE
)
179 if(bdiff
<pdiff
&& bdiff
<tdiff
)
181 else if(tdiff
<pdiff
&& tdiff
<bdiff
)
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");
199 static int put_image(struct vf_instance
*vf
, mp_image_t
*mpi
, double pts
)
205 if(!(dmpi
=vf_get_image(vf
->next
, mpi
->imgfmt
,
206 MP_IMGTYPE_TEMP
, MP_IMGFLAG_ACCEPT_STRIDE
,
211 if(!(dmpi
->flags
&MP_IMGFLAG_PLANAR
))
216 if(!vf
->priv
->buf
[0])
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],
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
, MP_NOPTS_VALUE
);
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]);
251 static int vf_open(vf_instance_t
*vf
, char *args
)
253 vf
->put_image
= put_image
;
255 vf
->default_reqs
= VFCAP_ACCEPT_STRIDE
;
257 if(!(vf
->priv
= calloc(1, sizeof(struct vf_priv_s
))))
263 vf
->priv
->mode
=AUTO_ANALYZE
;
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;
284 return 0; /* bad args */
287 if( (args
=strchr(args
, ':')) ) args
++;
293 const vf_info_t vf_info_phase
=
295 "phase shift fields",