9 #include "img_format.h"
13 #include "libvo/fastmemcpy.h"
18 #define MAX(a,b) ((a)>(b)?(a):(b))
21 struct pullup_context
*ctx
;
27 static inline void *my_memcpy_pic(void * dst
, void * src
, int bytesPerLine
, int height
, int dstStride
, int srcStride
)
32 for(i
=0; i
<height
; i
++)
34 memcpy(dst
, src
, bytesPerLine
);
42 static inline void *il_memcpy_pic(void *dst
, void *src0
, void *src1
, int w
, int h
, int ds
, int ss
)
61 static void init_pullup(struct vf_instance_s
* vf
, mp_image_t
*mpi
)
63 struct pullup_context
*c
= vf
->priv
->ctx
;
65 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
66 c
->format
= PULLUP_FMT_Y
;
68 pullup_preinit_context(c
);
69 c
->bpp
[0] = c
->bpp
[1] = c
->bpp
[2] = 8;
72 c
->w
[1] = c
->w
[2] = mpi
->chroma_width
;
73 c
->h
[1] = c
->h
[2] = mpi
->chroma_height
;
74 c
->w
[3] = ((mpi
->w
+15)/16) * ((mpi
->h
+15)/16);
76 c
->stride
[0] = mpi
->width
;
77 c
->stride
[1] = c
->stride
[2] = mpi
->chroma_width
;
78 c
->stride
[3] = c
->w
[3];
79 c
->background
[1] = c
->background
[2] = 128;
82 if (gCpuCaps
.hasMMX
) c
->cpu
|= PULLUP_CPU_MMX
;
83 if (gCpuCaps
.hasMMX2
) c
->cpu
|= PULLUP_CPU_MMX2
;
84 if (gCpuCaps
.has3DNow
) c
->cpu
|= PULLUP_CPU_3DNOW
;
85 if (gCpuCaps
.has3DNowExt
) c
->cpu
|= PULLUP_CPU_3DNOWEXT
;
86 if (gCpuCaps
.hasSSE
) c
->cpu
|= PULLUP_CPU_SSE
;
87 if (gCpuCaps
.hasSSE2
) c
->cpu
|= PULLUP_CPU_SSE2
;
89 pullup_init_context(c
);
92 vf
->priv
->qbuf
= malloc(c
->w
[3]);
96 static void get_image(struct vf_instance_s
* vf
, mp_image_t
*mpi
)
98 struct pullup_context
*c
= vf
->priv
->ctx
;
99 struct pullup_buffer
*b
;
101 if (mpi
->type
== MP_IMGTYPE_STATIC
) return;
103 if (!vf
->priv
->init
) init_pullup(vf
, mpi
);
105 b
= pullup_get_buffer(c
, 2);
106 if (!b
) return; /* shouldn't happen... */
110 mpi
->planes
[0] = b
->planes
[0];
111 mpi
->planes
[1] = b
->planes
[1];
112 mpi
->planes
[2] = b
->planes
[2];
113 mpi
->stride
[0] = c
->stride
[0];
114 mpi
->stride
[1] = c
->stride
[1];
115 mpi
->stride
[2] = c
->stride
[2];
117 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
118 mpi
->flags
&= ~MP_IMGFLAG_DRAW_CALLBACK
;
121 static int put_image(struct vf_instance_s
* vf
, mp_image_t
*mpi
, double pts
)
123 struct pullup_context
*c
= vf
->priv
->ctx
;
124 struct pullup_buffer
*b
;
125 struct pullup_frame
*f
;
131 if (!vf
->priv
->init
) init_pullup(vf
, mpi
);
133 if (mpi
->flags
& MP_IMGFLAG_DIRECT
) {
137 b
= pullup_get_buffer(c
, 2);
139 mp_msg(MSGT_VFILTER
,MSGL_ERR
,"Could not get buffer from pullup!\n");
140 f
= pullup_get_frame(c
);
141 pullup_release_frame(f
);
144 memcpy_pic(b
->planes
[0], mpi
->planes
[0], mpi
->w
, mpi
->h
,
145 c
->stride
[0], mpi
->stride
[0]);
146 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
147 memcpy_pic(b
->planes
[1], mpi
->planes
[1],
148 mpi
->chroma_width
, mpi
->chroma_height
,
149 c
->stride
[1], mpi
->stride
[1]);
150 memcpy_pic(b
->planes
[2], mpi
->planes
[2],
151 mpi
->chroma_width
, mpi
->chroma_height
,
152 c
->stride
[2], mpi
->stride
[2]);
156 memcpy(b
->planes
[3], mpi
->qscale
, c
->w
[3]);
157 memcpy(b
->planes
[3]+c
->w
[3], mpi
->qscale
, c
->w
[3]);
160 p
= mpi
->fields
& MP_IMGFIELD_TOP_FIRST
? 0 :
161 (mpi
->fields
& MP_IMGFIELD_ORDERED
? 1 : 0);
162 pullup_submit_field(c
, b
, p
);
163 pullup_submit_field(c
, b
, p
^1);
164 if (mpi
->fields
& MP_IMGFIELD_REPEAT_FIRST
)
165 pullup_submit_field(c
, b
, p
);
167 pullup_release_buffer(b
, 2);
169 f
= pullup_get_frame(c
);
171 /* Fake yes for first few frames (buffer depth) to keep from
172 * breaking A/V sync with G1's bad architecture... */
173 if (!f
) return vf
->priv
->fakecount
? (--vf
->priv
->fakecount
,1) : 0;
176 pullup_release_frame(f
);
177 f
= pullup_get_frame(c
);
180 pullup_release_frame(f
);
181 if (!(mpi
->fields
& MP_IMGFIELD_REPEAT_FIRST
))
183 f
= pullup_get_frame(c
);
186 pullup_release_frame(f
);
193 /* Average qscale tables from both frames. */
195 for (i
=0; i
<c
->w
[3]; i
++) {
196 vf
->priv
->qbuf
[i
] = (f
->ofields
[0]->planes
[3][i
]
197 + f
->ofields
[1]->planes
[3][i
+c
->w
[3]])>>1;
201 /* Take worst of qscale tables from both frames. */
203 for (i
=0; i
<c
->w
[3]; i
++) {
204 vf
->priv
->qbuf
[i
] = MAX(f
->ofields
[0]->planes
[3][i
], f
->ofields
[1]->planes
[3][i
+c
->w
[3]]);
209 /* If the frame isn't already exportable... */
211 dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
,
212 MP_IMGTYPE_TEMP
, MP_IMGFLAG_ACCEPT_STRIDE
,
213 mpi
->width
, mpi
->height
);
214 /* FIXME: Is it ok to discard dmpi if it's not direct? */
215 if (!(dmpi
->flags
& MP_IMGFLAG_DIRECT
)) {
216 pullup_pack_frame(c
, f
);
219 /* Direct render fields into output buffer */
221 /* Write-order copy seems to have worse cache performance
222 * than read-order, but both should be checked on
223 * various cpus to see which is actually better...*/
224 il_memcpy_pic(dmpi
->planes
[0], f
->ofields
[0]->planes
[0],
225 f
->ofields
[1]->planes
[0] + c
->stride
[0],
226 mpi
->w
, mpi
->h
, dmpi
->stride
[0], c
->stride
[0]);
227 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
228 il_memcpy_pic(dmpi
->planes
[1], f
->ofields
[0]->planes
[1],
229 f
->ofields
[1]->planes
[1] + c
->stride
[1],
230 mpi
->chroma_width
, mpi
->chroma_height
,
231 dmpi
->stride
[1], c
->stride
[1]);
232 il_memcpy_pic(dmpi
->planes
[2], f
->ofields
[0]->planes
[2],
233 f
->ofields
[1]->planes
[2] + c
->stride
[2],
234 mpi
->chroma_width
, mpi
->chroma_height
,
235 dmpi
->stride
[2], c
->stride
[2]);
238 my_memcpy_pic(dmpi
->planes
[0], f
->ofields
[0]->planes
[0],
239 mpi
->w
, mpi
->h
/2, dmpi
->stride
[0]*2, c
->stride
[0]*2);
240 my_memcpy_pic(dmpi
->planes
[0] + dmpi
->stride
[0],
241 f
->ofields
[1]->planes
[0] + c
->stride
[0],
242 mpi
->w
, mpi
->h
/2, dmpi
->stride
[0]*2, c
->stride
[0]*2);
243 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
244 my_memcpy_pic(dmpi
->planes
[1], f
->ofields
[0]->planes
[1],
245 mpi
->chroma_width
, mpi
->chroma_height
/2,
246 dmpi
->stride
[1]*2, c
->stride
[1]*2);
247 my_memcpy_pic(dmpi
->planes
[1] + dmpi
->stride
[1],
248 f
->ofields
[1]->planes
[1] + c
->stride
[1],
249 mpi
->chroma_width
, mpi
->chroma_height
/2,
250 dmpi
->stride
[1]*2, c
->stride
[1]*2);
251 my_memcpy_pic(dmpi
->planes
[2], f
->ofields
[0]->planes
[2],
252 mpi
->chroma_width
, mpi
->chroma_height
/2,
253 dmpi
->stride
[2]*2, c
->stride
[2]*2);
254 my_memcpy_pic(dmpi
->planes
[2] + dmpi
->stride
[2],
255 f
->ofields
[1]->planes
[2] + c
->stride
[2],
256 mpi
->chroma_width
, mpi
->chroma_height
/2,
257 dmpi
->stride
[2]*2, c
->stride
[2]*2);
260 pullup_release_frame(f
);
262 dmpi
->qscale
= vf
->priv
->qbuf
;
263 dmpi
->qstride
= mpi
->qstride
;
264 dmpi
->qscale_type
= mpi
->qscale_type
;
266 return vf_next_put_image(vf
, dmpi
, MP_NOPTS_VALUE
);
268 dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
,
269 MP_IMGTYPE_EXPORT
, MP_IMGFLAG_ACCEPT_STRIDE
,
270 mpi
->width
, mpi
->height
);
272 dmpi
->planes
[0] = f
->buffer
->planes
[0];
273 dmpi
->planes
[1] = f
->buffer
->planes
[1];
274 dmpi
->planes
[2] = f
->buffer
->planes
[2];
276 dmpi
->stride
[0] = c
->stride
[0];
277 dmpi
->stride
[1] = c
->stride
[1];
278 dmpi
->stride
[2] = c
->stride
[2];
281 dmpi
->qscale
= vf
->priv
->qbuf
;
282 dmpi
->qstride
= mpi
->qstride
;
283 dmpi
->qscale_type
= mpi
->qscale_type
;
285 ret
= vf_next_put_image(vf
, dmpi
, MP_NOPTS_VALUE
);
286 pullup_release_frame(f
);
290 static int query_format(struct vf_instance_s
* vf
, unsigned int fmt
)
292 /* FIXME - support more formats */
297 return vf_next_query_format(vf
, fmt
);
302 static int config(struct vf_instance_s
* vf
,
303 int width
, int height
, int d_width
, int d_height
,
304 unsigned int flags
, unsigned int outfmt
)
306 if (height
&3) return 0;
307 return vf_next_config(vf
, width
, height
, d_width
, d_height
, flags
, outfmt
);
310 static void uninit(struct vf_instance_s
* vf
)
312 pullup_free_context(vf
->priv
->ctx
);
316 static int open(vf_instance_t
*vf
, char* args
)
319 struct pullup_context
*c
;
320 //vf->get_image = get_image;
321 vf
->put_image
= put_image
;
323 vf
->query_format
= query_format
;
325 vf
->default_reqs
= VFCAP_ACCEPT_STRIDE
;
326 vf
->priv
= p
= calloc(1, sizeof(struct vf_priv_s
));
327 p
->ctx
= c
= pullup_alloc_context();
329 c
->verbose
= verbose
>0;
330 c
->junk_left
= c
->junk_right
= 1;
331 c
->junk_top
= c
->junk_bottom
= 4;
332 c
->strict_breaks
= 0;
335 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
);
340 vf_info_t vf_info_pullup
= {
341 "pullup (from field sequence to frames)",