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
;
45 static void init_pullup(struct vf_instance
*vf
, mp_image_t
*mpi
)
47 struct pullup_context
*c
= vf
->priv
->ctx
;
49 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
50 c
->format
= PULLUP_FMT_Y
;
52 pullup_preinit_context(c
);
53 c
->bpp
[0] = c
->bpp
[1] = c
->bpp
[2] = 8;
56 c
->w
[1] = c
->w
[2] = mpi
->chroma_width
;
57 c
->h
[1] = c
->h
[2] = mpi
->chroma_height
;
58 c
->w
[3] = ((mpi
->w
+15)/16) * ((mpi
->h
+15)/16);
60 c
->stride
[0] = mpi
->width
;
61 c
->stride
[1] = c
->stride
[2] = mpi
->chroma_width
;
62 c
->stride
[3] = c
->w
[3];
63 c
->background
[1] = c
->background
[2] = 128;
66 if (gCpuCaps
.hasMMX
) c
->cpu
|= PULLUP_CPU_MMX
;
67 if (gCpuCaps
.hasMMX2
) c
->cpu
|= PULLUP_CPU_MMX2
;
68 if (gCpuCaps
.has3DNow
) c
->cpu
|= PULLUP_CPU_3DNOW
;
69 if (gCpuCaps
.has3DNowExt
) c
->cpu
|= PULLUP_CPU_3DNOWEXT
;
70 if (gCpuCaps
.hasSSE
) c
->cpu
|= PULLUP_CPU_SSE
;
71 if (gCpuCaps
.hasSSE2
) c
->cpu
|= PULLUP_CPU_SSE2
;
73 pullup_init_context(c
);
76 vf
->priv
->qbuf
= malloc(c
->w
[3]);
81 static void get_image(struct vf_instance
*vf
, mp_image_t
*mpi
)
83 struct pullup_context
*c
= vf
->priv
->ctx
;
84 struct pullup_buffer
*b
;
86 if (mpi
->type
== MP_IMGTYPE_STATIC
) return;
88 if (!vf
->priv
->init
) init_pullup(vf
, mpi
);
90 b
= pullup_get_buffer(c
, 2);
91 if (!b
) return; /* shouldn't happen... */
95 mpi
->planes
[0] = b
->planes
[0];
96 mpi
->planes
[1] = b
->planes
[1];
97 mpi
->planes
[2] = b
->planes
[2];
98 mpi
->stride
[0] = c
->stride
[0];
99 mpi
->stride
[1] = c
->stride
[1];
100 mpi
->stride
[2] = c
->stride
[2];
102 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
103 mpi
->flags
&= ~MP_IMGFLAG_DRAW_CALLBACK
;
107 static int put_image(struct vf_instance
*vf
, mp_image_t
*mpi
, double pts
)
109 struct pullup_context
*c
= vf
->priv
->ctx
;
110 struct pullup_buffer
*b
;
111 struct pullup_frame
*f
;
117 if (!vf
->priv
->init
) init_pullup(vf
, mpi
);
119 if (mpi
->flags
& MP_IMGFLAG_DIRECT
) {
123 b
= pullup_get_buffer(c
, 2);
125 mp_msg(MSGT_VFILTER
,MSGL_ERR
,"Could not get buffer from pullup!\n");
126 f
= pullup_get_frame(c
);
127 pullup_release_frame(f
);
130 memcpy_pic(b
->planes
[0], mpi
->planes
[0], mpi
->w
, mpi
->h
,
131 c
->stride
[0], mpi
->stride
[0]);
132 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
133 memcpy_pic(b
->planes
[1], mpi
->planes
[1],
134 mpi
->chroma_width
, mpi
->chroma_height
,
135 c
->stride
[1], mpi
->stride
[1]);
136 memcpy_pic(b
->planes
[2], mpi
->planes
[2],
137 mpi
->chroma_width
, mpi
->chroma_height
,
138 c
->stride
[2], mpi
->stride
[2]);
142 fast_memcpy(b
->planes
[3], mpi
->qscale
, c
->w
[3]);
143 fast_memcpy(b
->planes
[3]+c
->w
[3], mpi
->qscale
, c
->w
[3]);
146 p
= mpi
->fields
& MP_IMGFIELD_TOP_FIRST
? 0 :
147 (mpi
->fields
& MP_IMGFIELD_ORDERED
? 1 : 0);
148 pullup_submit_field(c
, b
, p
);
149 pullup_submit_field(c
, b
, p
^1);
150 if (mpi
->fields
& MP_IMGFIELD_REPEAT_FIRST
)
151 pullup_submit_field(c
, b
, p
);
153 pullup_release_buffer(b
, 2);
155 f
= pullup_get_frame(c
);
157 /* Fake yes for first few frames (buffer depth) to keep from
158 * breaking A/V sync with G1's bad architecture... */
159 if (!f
) return vf
->priv
->fakecount
? (--vf
->priv
->fakecount
,1) : 0;
162 pullup_release_frame(f
);
163 f
= pullup_get_frame(c
);
166 pullup_release_frame(f
);
167 if (!(mpi
->fields
& MP_IMGFIELD_REPEAT_FIRST
))
169 f
= pullup_get_frame(c
);
172 pullup_release_frame(f
);
179 /* Average qscale tables from both frames. */
181 for (i
=0; i
<c
->w
[3]; i
++) {
182 vf
->priv
->qbuf
[i
] = (f
->ofields
[0]->planes
[3][i
]
183 + f
->ofields
[1]->planes
[3][i
+c
->w
[3]])>>1;
187 /* Take worst of qscale tables from both frames. */
189 for (i
=0; i
<c
->w
[3]; i
++) {
190 vf
->priv
->qbuf
[i
] = MAX(f
->ofields
[0]->planes
[3][i
], f
->ofields
[1]->planes
[3][i
+c
->w
[3]]);
195 /* If the frame isn't already exportable... */
197 dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
,
198 MP_IMGTYPE_TEMP
, MP_IMGFLAG_ACCEPT_STRIDE
,
199 mpi
->width
, mpi
->height
);
200 /* FIXME: Is it ok to discard dmpi if it's not direct? */
201 if (!(dmpi
->flags
& MP_IMGFLAG_DIRECT
)) {
202 pullup_pack_frame(c
, f
);
205 /* Direct render fields into output buffer */
206 my_memcpy_pic(dmpi
->planes
[0], f
->ofields
[0]->planes
[0],
207 mpi
->w
, mpi
->h
/2, dmpi
->stride
[0]*2, c
->stride
[0]*2);
208 my_memcpy_pic(dmpi
->planes
[0] + dmpi
->stride
[0],
209 f
->ofields
[1]->planes
[0] + c
->stride
[0],
210 mpi
->w
, mpi
->h
/2, dmpi
->stride
[0]*2, c
->stride
[0]*2);
211 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
212 my_memcpy_pic(dmpi
->planes
[1], f
->ofields
[0]->planes
[1],
213 mpi
->chroma_width
, mpi
->chroma_height
/2,
214 dmpi
->stride
[1]*2, c
->stride
[1]*2);
215 my_memcpy_pic(dmpi
->planes
[1] + dmpi
->stride
[1],
216 f
->ofields
[1]->planes
[1] + c
->stride
[1],
217 mpi
->chroma_width
, mpi
->chroma_height
/2,
218 dmpi
->stride
[1]*2, c
->stride
[1]*2);
219 my_memcpy_pic(dmpi
->planes
[2], f
->ofields
[0]->planes
[2],
220 mpi
->chroma_width
, mpi
->chroma_height
/2,
221 dmpi
->stride
[2]*2, c
->stride
[2]*2);
222 my_memcpy_pic(dmpi
->planes
[2] + dmpi
->stride
[2],
223 f
->ofields
[1]->planes
[2] + c
->stride
[2],
224 mpi
->chroma_width
, mpi
->chroma_height
/2,
225 dmpi
->stride
[2]*2, c
->stride
[2]*2);
227 pullup_release_frame(f
);
229 dmpi
->qscale
= vf
->priv
->qbuf
;
230 dmpi
->qstride
= mpi
->qstride
;
231 dmpi
->qscale_type
= mpi
->qscale_type
;
233 return vf_next_put_image(vf
, dmpi
, MP_NOPTS_VALUE
);
235 dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
,
236 MP_IMGTYPE_EXPORT
, MP_IMGFLAG_ACCEPT_STRIDE
,
237 mpi
->width
, mpi
->height
);
239 dmpi
->planes
[0] = f
->buffer
->planes
[0];
240 dmpi
->planes
[1] = f
->buffer
->planes
[1];
241 dmpi
->planes
[2] = f
->buffer
->planes
[2];
243 dmpi
->stride
[0] = c
->stride
[0];
244 dmpi
->stride
[1] = c
->stride
[1];
245 dmpi
->stride
[2] = c
->stride
[2];
248 dmpi
->qscale
= vf
->priv
->qbuf
;
249 dmpi
->qstride
= mpi
->qstride
;
250 dmpi
->qscale_type
= mpi
->qscale_type
;
252 ret
= vf_next_put_image(vf
, dmpi
, MP_NOPTS_VALUE
);
253 pullup_release_frame(f
);
257 static int query_format(struct vf_instance
*vf
, unsigned int fmt
)
259 /* FIXME - support more formats */
264 return vf_next_query_format(vf
, fmt
);
269 static int config(struct vf_instance
*vf
,
270 int width
, int height
, int d_width
, int d_height
,
271 unsigned int flags
, unsigned int outfmt
)
273 if (height
&3) return 0;
274 return vf_next_config(vf
, width
, height
, d_width
, d_height
, flags
, outfmt
);
277 static void uninit(struct vf_instance
*vf
)
279 pullup_free_context(vf
->priv
->ctx
);
283 static int vf_open(vf_instance_t
*vf
, char *args
)
286 struct pullup_context
*c
;
287 //vf->get_image = get_image;
288 vf
->put_image
= put_image
;
290 vf
->query_format
= query_format
;
292 vf
->default_reqs
= VFCAP_ACCEPT_STRIDE
;
293 vf
->priv
= p
= calloc(1, sizeof(struct vf_priv_s
));
294 p
->ctx
= c
= pullup_alloc_context();
296 c
->verbose
= verbose
>0;
297 c
->junk_left
= c
->junk_right
= 1;
298 c
->junk_top
= c
->junk_bottom
= 4;
299 c
->strict_breaks
= 0;
302 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
);
307 const vf_info_t vf_info_pullup
= {
308 "pullup (from field sequence to frames)",