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.
25 #include "cpudetect.h"
27 #include "img_format.h"
31 #include "libvo/fastmemcpy.h"
36 #define MAX(a,b) ((a)>(b)?(a):(b))
39 struct pullup_context
*ctx
;
46 static void init_pullup(struct vf_instance
*vf
, mp_image_t
*mpi
)
48 struct pullup_context
*c
= vf
->priv
->ctx
;
50 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
51 c
->format
= PULLUP_FMT_Y
;
53 pullup_preinit_context(c
);
54 c
->bpp
[0] = c
->bpp
[1] = c
->bpp
[2] = 8;
57 c
->w
[1] = c
->w
[2] = mpi
->chroma_width
;
58 c
->h
[1] = c
->h
[2] = mpi
->chroma_height
;
59 c
->w
[3] = ((mpi
->w
+15)/16) * ((mpi
->h
+15)/16);
61 c
->stride
[0] = mpi
->width
;
62 c
->stride
[1] = c
->stride
[2] = mpi
->chroma_width
;
63 c
->stride
[3] = c
->w
[3];
64 c
->background
[1] = c
->background
[2] = 128;
67 if (gCpuCaps
.hasMMX
) c
->cpu
|= PULLUP_CPU_MMX
;
68 if (gCpuCaps
.hasMMX2
) c
->cpu
|= PULLUP_CPU_MMX2
;
69 if (gCpuCaps
.has3DNow
) c
->cpu
|= PULLUP_CPU_3DNOW
;
70 if (gCpuCaps
.has3DNowExt
) c
->cpu
|= PULLUP_CPU_3DNOWEXT
;
71 if (gCpuCaps
.hasSSE
) c
->cpu
|= PULLUP_CPU_SSE
;
72 if (gCpuCaps
.hasSSE2
) c
->cpu
|= PULLUP_CPU_SSE2
;
74 pullup_init_context(c
);
77 vf
->priv
->qbuf
= malloc(c
->w
[3]);
82 static void get_image(struct vf_instance
*vf
, mp_image_t
*mpi
)
84 struct pullup_context
*c
= vf
->priv
->ctx
;
85 struct pullup_buffer
*b
;
87 if (mpi
->type
== MP_IMGTYPE_STATIC
) return;
89 if (!vf
->priv
->init
) init_pullup(vf
, mpi
);
91 b
= pullup_get_buffer(c
, 2);
92 if (!b
) return; /* shouldn't happen... */
96 mpi
->planes
[0] = b
->planes
[0];
97 mpi
->planes
[1] = b
->planes
[1];
98 mpi
->planes
[2] = b
->planes
[2];
99 mpi
->stride
[0] = c
->stride
[0];
100 mpi
->stride
[1] = c
->stride
[1];
101 mpi
->stride
[2] = c
->stride
[2];
103 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
104 mpi
->flags
&= ~MP_IMGFLAG_DRAW_CALLBACK
;
108 static int put_image(struct vf_instance
*vf
, mp_image_t
*mpi
, double pts
)
110 struct pullup_context
*c
= vf
->priv
->ctx
;
111 struct pullup_buffer
*b
;
112 struct pullup_frame
*f
;
118 if (!vf
->priv
->init
) init_pullup(vf
, mpi
);
120 if (mpi
->flags
& MP_IMGFLAG_DIRECT
) {
124 b
= pullup_get_buffer(c
, 2);
126 mp_msg(MSGT_VFILTER
,MSGL_ERR
,"Could not get buffer from pullup!\n");
127 f
= pullup_get_frame(c
);
128 pullup_release_frame(f
);
131 memcpy_pic(b
->planes
[0], mpi
->planes
[0], mpi
->w
, mpi
->h
,
132 c
->stride
[0], mpi
->stride
[0]);
133 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
134 memcpy_pic(b
->planes
[1], mpi
->planes
[1],
135 mpi
->chroma_width
, mpi
->chroma_height
,
136 c
->stride
[1], mpi
->stride
[1]);
137 memcpy_pic(b
->planes
[2], mpi
->planes
[2],
138 mpi
->chroma_width
, mpi
->chroma_height
,
139 c
->stride
[2], mpi
->stride
[2]);
143 fast_memcpy(b
->planes
[3], mpi
->qscale
, c
->w
[3]);
144 fast_memcpy(b
->planes
[3]+c
->w
[3], mpi
->qscale
, c
->w
[3]);
147 p
= mpi
->fields
& MP_IMGFIELD_TOP_FIRST
? 0 :
148 (mpi
->fields
& MP_IMGFIELD_ORDERED
? 1 : 0);
150 if (pts
== MP_NOPTS_VALUE
) {
151 pullup_submit_field(c
, b
, p
, MP_NOPTS_VALUE
);
152 pullup_submit_field(c
, b
, p
^1, MP_NOPTS_VALUE
);
153 if (mpi
->fields
& MP_IMGFIELD_REPEAT_FIRST
)
154 pullup_submit_field(c
, b
, p
, MP_NOPTS_VALUE
);
157 if (vf
->priv
->lastpts
== MP_NOPTS_VALUE
)
158 delta
= 1001.0/60000.0; // delta = field time distance
160 delta
= (pts
- vf
->priv
->lastpts
) / 2;
161 if (delta
<= 0.0 || delta
>= 0.5) {
162 pullup_submit_field(c
, b
, p
, pts
);
163 pullup_submit_field(c
, b
, p
^1, pts
);
164 if (mpi
->fields
& MP_IMGFIELD_REPEAT_FIRST
)
165 pullup_submit_field(c
, b
, p
, pts
);
167 vf
->priv
->lastpts
= pts
;
168 if (mpi
->fields
& MP_IMGFIELD_REPEAT_FIRST
) {
169 pullup_submit_field(c
, b
, p
, pts
- delta
);
170 pullup_submit_field(c
, b
, p
^1, pts
);
171 pullup_submit_field(c
, b
, p
, pts
+ delta
);
173 pullup_submit_field(c
, b
, p
, pts
- delta
* 0.5);
174 pullup_submit_field(c
, b
, p
^1, pts
+ delta
* 0.5);
179 pullup_release_buffer(b
, 2);
181 f
= pullup_get_frame(c
);
183 /* Fake yes for first few frames (buffer depth) to keep from
184 * breaking A/V sync with G1's bad architecture... */
185 if (!f
) return vf
->priv
->fakecount
? (--vf
->priv
->fakecount
,1) : 0;
188 pullup_release_frame(f
);
189 f
= pullup_get_frame(c
);
192 pullup_release_frame(f
);
193 if (!(mpi
->fields
& MP_IMGFIELD_REPEAT_FIRST
))
195 f
= pullup_get_frame(c
);
198 pullup_release_frame(f
);
205 /* Average qscale tables from both frames. */
207 for (i
=0; i
<c
->w
[3]; i
++) {
208 vf
->priv
->qbuf
[i
] = (f
->ofields
[0]->planes
[3][i
]
209 + f
->ofields
[1]->planes
[3][i
+c
->w
[3]])>>1;
213 /* Take worst of qscale tables from both frames. */
215 for (i
=0; i
<c
->w
[3]; i
++) {
216 vf
->priv
->qbuf
[i
] = MAX(f
->ofields
[0]->planes
[3][i
], f
->ofields
[1]->planes
[3][i
+c
->w
[3]]);
221 /* If the frame isn't already exportable... */
223 dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
,
224 MP_IMGTYPE_TEMP
, MP_IMGFLAG_ACCEPT_STRIDE
,
225 mpi
->width
, mpi
->height
);
226 /* FIXME: Is it ok to discard dmpi if it's not direct? */
227 if (!(dmpi
->flags
& MP_IMGFLAG_DIRECT
)) {
228 pullup_pack_frame(c
, f
);
231 /* Direct render fields into output buffer */
232 my_memcpy_pic(dmpi
->planes
[0], f
->ofields
[0]->planes
[0],
233 mpi
->w
, mpi
->h
/2, dmpi
->stride
[0]*2, c
->stride
[0]*2);
234 my_memcpy_pic(dmpi
->planes
[0] + dmpi
->stride
[0],
235 f
->ofields
[1]->planes
[0] + c
->stride
[0],
236 mpi
->w
, mpi
->h
/2, dmpi
->stride
[0]*2, c
->stride
[0]*2);
237 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
238 my_memcpy_pic(dmpi
->planes
[1], f
->ofields
[0]->planes
[1],
239 mpi
->chroma_width
, mpi
->chroma_height
/2,
240 dmpi
->stride
[1]*2, c
->stride
[1]*2);
241 my_memcpy_pic(dmpi
->planes
[1] + dmpi
->stride
[1],
242 f
->ofields
[1]->planes
[1] + c
->stride
[1],
243 mpi
->chroma_width
, mpi
->chroma_height
/2,
244 dmpi
->stride
[1]*2, c
->stride
[1]*2);
245 my_memcpy_pic(dmpi
->planes
[2], f
->ofields
[0]->planes
[2],
246 mpi
->chroma_width
, mpi
->chroma_height
/2,
247 dmpi
->stride
[2]*2, c
->stride
[2]*2);
248 my_memcpy_pic(dmpi
->planes
[2] + dmpi
->stride
[2],
249 f
->ofields
[1]->planes
[2] + c
->stride
[2],
250 mpi
->chroma_width
, mpi
->chroma_height
/2,
251 dmpi
->stride
[2]*2, c
->stride
[2]*2);
253 pullup_release_frame(f
);
255 dmpi
->qscale
= vf
->priv
->qbuf
;
256 dmpi
->qstride
= mpi
->qstride
;
257 dmpi
->qscale_type
= mpi
->qscale_type
;
259 return vf_next_put_image(vf
, dmpi
, f
->pts
);
261 dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
,
262 MP_IMGTYPE_EXPORT
, MP_IMGFLAG_ACCEPT_STRIDE
,
263 mpi
->width
, mpi
->height
);
265 dmpi
->planes
[0] = f
->buffer
->planes
[0];
266 dmpi
->planes
[1] = f
->buffer
->planes
[1];
267 dmpi
->planes
[2] = f
->buffer
->planes
[2];
269 dmpi
->stride
[0] = c
->stride
[0];
270 dmpi
->stride
[1] = c
->stride
[1];
271 dmpi
->stride
[2] = c
->stride
[2];
274 dmpi
->qscale
= vf
->priv
->qbuf
;
275 dmpi
->qstride
= mpi
->qstride
;
276 dmpi
->qscale_type
= mpi
->qscale_type
;
278 ret
= vf_next_put_image(vf
, dmpi
, f
->pts
);
279 pullup_release_frame(f
);
283 static int query_format(struct vf_instance
*vf
, unsigned int fmt
)
285 /* FIXME - support more formats */
290 return vf_next_query_format(vf
, fmt
);
295 static int config(struct vf_instance
*vf
,
296 int width
, int height
, int d_width
, int d_height
,
297 unsigned int flags
, unsigned int outfmt
)
299 if (height
&3) return 0;
300 return vf_next_config(vf
, width
, height
, d_width
, d_height
, flags
, outfmt
);
303 static void uninit(struct vf_instance
*vf
)
305 pullup_free_context(vf
->priv
->ctx
);
309 static int vf_open(vf_instance_t
*vf
, char *args
)
312 struct pullup_context
*c
;
313 //vf->get_image = get_image;
314 vf
->put_image
= put_image
;
316 vf
->query_format
= query_format
;
318 vf
->default_reqs
= VFCAP_ACCEPT_STRIDE
;
319 vf
->priv
= p
= calloc(1, sizeof(struct vf_priv_s
));
320 p
->ctx
= c
= pullup_alloc_context();
322 c
->verbose
= verbose
>0;
323 c
->junk_left
= c
->junk_right
= 1;
324 c
->junk_top
= c
->junk_bottom
= 4;
325 c
->strict_breaks
= 0;
328 sscanf(args
, "%d:%d:%d:%d:%d:%d", &c
->junk_left
, &c
->junk_right
, &c
->junk_top
, &c
->junk_bottom
, &c
->strict_breaks
, &c
->metric_plane
);
333 const vf_info_t vf_info_pullup
= {
334 "pullup (from field sequence to frames)",