7 #include "../cpudetect.h"
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
)
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
);
186 /* Average qscale tables from both frames. */
188 for (i
=0; i
<c
->w
[3]; i
++) {
189 vf
->priv
->qbuf
[i
] = (f
->ofields
[0]->planes
[3][i
]
190 + f
->ofields
[1]->planes
[3][i
+c
->w
[3]])>>1;
194 /* Take worst of qscale tables from both frames. */
196 for (i
=0; i
<c
->w
[3]; i
++) {
197 vf
->priv
->qbuf
[i
] = MAX(f
->ofields
[0]->planes
[3][i
], f
->ofields
[1]->planes
[3][i
+c
->w
[3]]);
202 /* If the frame isn't already exportable... */
204 dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
,
205 MP_IMGTYPE_TEMP
, MP_IMGFLAG_ACCEPT_STRIDE
,
206 mpi
->width
, mpi
->height
);
207 /* FIXME: Is it ok to discard dmpi if it's not direct? */
208 if (!(dmpi
->flags
& MP_IMGFLAG_DIRECT
)) {
209 pullup_pack_frame(c
, f
);
212 /* Direct render fields into output buffer */
214 /* Write-order copy seems to have worse cache performance
215 * than read-order, but both should be checked on
216 * various cpus to see which is actually better...*/
217 il_memcpy_pic(dmpi
->planes
[0], f
->ofields
[0]->planes
[0],
218 f
->ofields
[1]->planes
[0] + c
->stride
[0],
219 mpi
->w
, mpi
->h
, dmpi
->stride
[0], c
->stride
[0]);
220 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
221 il_memcpy_pic(dmpi
->planes
[1], f
->ofields
[0]->planes
[1],
222 f
->ofields
[1]->planes
[1] + c
->stride
[1],
223 mpi
->chroma_width
, mpi
->chroma_height
,
224 dmpi
->stride
[1], c
->stride
[1]);
225 il_memcpy_pic(dmpi
->planes
[2], f
->ofields
[0]->planes
[2],
226 f
->ofields
[1]->planes
[2] + c
->stride
[2],
227 mpi
->chroma_width
, mpi
->chroma_height
,
228 dmpi
->stride
[2], c
->stride
[2]);
231 my_memcpy_pic(dmpi
->planes
[0], f
->ofields
[0]->planes
[0],
232 mpi
->w
, mpi
->h
/2, dmpi
->stride
[0]*2, c
->stride
[0]*2);
233 my_memcpy_pic(dmpi
->planes
[0] + dmpi
->stride
[0],
234 f
->ofields
[1]->planes
[0] + c
->stride
[0],
235 mpi
->w
, mpi
->h
/2, dmpi
->stride
[0]*2, c
->stride
[0]*2);
236 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
237 my_memcpy_pic(dmpi
->planes
[1], f
->ofields
[0]->planes
[1],
238 mpi
->chroma_width
, mpi
->chroma_height
/2,
239 dmpi
->stride
[1]*2, c
->stride
[1]*2);
240 my_memcpy_pic(dmpi
->planes
[1] + dmpi
->stride
[1],
241 f
->ofields
[1]->planes
[1] + c
->stride
[1],
242 mpi
->chroma_width
, mpi
->chroma_height
/2,
243 dmpi
->stride
[1]*2, c
->stride
[1]*2);
244 my_memcpy_pic(dmpi
->planes
[2], f
->ofields
[0]->planes
[2],
245 mpi
->chroma_width
, mpi
->chroma_height
/2,
246 dmpi
->stride
[2]*2, c
->stride
[2]*2);
247 my_memcpy_pic(dmpi
->planes
[2] + dmpi
->stride
[2],
248 f
->ofields
[1]->planes
[2] + c
->stride
[2],
249 mpi
->chroma_width
, mpi
->chroma_height
/2,
250 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
);
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
);
279 pullup_release_frame(f
);
283 static int query_format(struct vf_instance_s
* vf
, unsigned int fmt
)
285 /* FIXME - support more formats */
290 return vf_next_query_format(vf
, fmt
);
295 static int config(struct vf_instance_s
* 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_s
* vf
)
305 pullup_free_context(vf
->priv
->ctx
);
309 static int 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
;
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 vf_info_t vf_info_pullup
= {
334 "pullup (from field sequence to frames)",