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 void init_pullup(struct vf_instance_s
* vf
, mp_image_t
*mpi
)
29 struct pullup_context
*c
= vf
->priv
->ctx
;
31 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
32 c
->format
= PULLUP_FMT_Y
;
34 pullup_preinit_context(c
);
35 c
->bpp
[0] = c
->bpp
[1] = c
->bpp
[2] = 8;
38 c
->w
[1] = c
->w
[2] = mpi
->chroma_width
;
39 c
->h
[1] = c
->h
[2] = mpi
->chroma_height
;
40 c
->w
[3] = ((mpi
->w
+15)/16) * ((mpi
->h
+15)/16);
42 c
->stride
[0] = mpi
->width
;
43 c
->stride
[1] = c
->stride
[2] = mpi
->chroma_width
;
44 c
->stride
[3] = c
->w
[3];
45 c
->background
[1] = c
->background
[2] = 128;
48 if (gCpuCaps
.hasMMX
) c
->cpu
|= PULLUP_CPU_MMX
;
49 if (gCpuCaps
.hasMMX2
) c
->cpu
|= PULLUP_CPU_MMX2
;
50 if (gCpuCaps
.has3DNow
) c
->cpu
|= PULLUP_CPU_3DNOW
;
51 if (gCpuCaps
.has3DNowExt
) c
->cpu
|= PULLUP_CPU_3DNOWEXT
;
52 if (gCpuCaps
.hasSSE
) c
->cpu
|= PULLUP_CPU_SSE
;
53 if (gCpuCaps
.hasSSE2
) c
->cpu
|= PULLUP_CPU_SSE2
;
55 pullup_init_context(c
);
58 vf
->priv
->qbuf
= malloc(c
->w
[3]);
63 static void get_image(struct vf_instance_s
* vf
, mp_image_t
*mpi
)
65 struct pullup_context
*c
= vf
->priv
->ctx
;
66 struct pullup_buffer
*b
;
68 if (mpi
->type
== MP_IMGTYPE_STATIC
) return;
70 if (!vf
->priv
->init
) init_pullup(vf
, mpi
);
72 b
= pullup_get_buffer(c
, 2);
73 if (!b
) return; /* shouldn't happen... */
77 mpi
->planes
[0] = b
->planes
[0];
78 mpi
->planes
[1] = b
->planes
[1];
79 mpi
->planes
[2] = b
->planes
[2];
80 mpi
->stride
[0] = c
->stride
[0];
81 mpi
->stride
[1] = c
->stride
[1];
82 mpi
->stride
[2] = c
->stride
[2];
84 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
85 mpi
->flags
&= ~MP_IMGFLAG_DRAW_CALLBACK
;
89 static int put_image(struct vf_instance_s
* vf
, mp_image_t
*mpi
, double pts
)
91 struct pullup_context
*c
= vf
->priv
->ctx
;
92 struct pullup_buffer
*b
;
93 struct pullup_frame
*f
;
99 if (!vf
->priv
->init
) init_pullup(vf
, mpi
);
101 if (mpi
->flags
& MP_IMGFLAG_DIRECT
) {
105 b
= pullup_get_buffer(c
, 2);
107 mp_msg(MSGT_VFILTER
,MSGL_ERR
,"Could not get buffer from pullup!\n");
108 f
= pullup_get_frame(c
);
109 pullup_release_frame(f
);
112 memcpy_pic(b
->planes
[0], mpi
->planes
[0], mpi
->w
, mpi
->h
,
113 c
->stride
[0], mpi
->stride
[0]);
114 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
115 memcpy_pic(b
->planes
[1], mpi
->planes
[1],
116 mpi
->chroma_width
, mpi
->chroma_height
,
117 c
->stride
[1], mpi
->stride
[1]);
118 memcpy_pic(b
->planes
[2], mpi
->planes
[2],
119 mpi
->chroma_width
, mpi
->chroma_height
,
120 c
->stride
[2], mpi
->stride
[2]);
124 fast_memcpy(b
->planes
[3], mpi
->qscale
, c
->w
[3]);
125 fast_memcpy(b
->planes
[3]+c
->w
[3], mpi
->qscale
, c
->w
[3]);
128 p
= mpi
->fields
& MP_IMGFIELD_TOP_FIRST
? 0 :
129 (mpi
->fields
& MP_IMGFIELD_ORDERED
? 1 : 0);
130 pullup_submit_field(c
, b
, p
);
131 pullup_submit_field(c
, b
, p
^1);
132 if (mpi
->fields
& MP_IMGFIELD_REPEAT_FIRST
)
133 pullup_submit_field(c
, b
, p
);
135 pullup_release_buffer(b
, 2);
137 f
= pullup_get_frame(c
);
139 /* Fake yes for first few frames (buffer depth) to keep from
140 * breaking A/V sync with G1's bad architecture... */
141 if (!f
) return vf
->priv
->fakecount
? (--vf
->priv
->fakecount
,1) : 0;
144 pullup_release_frame(f
);
145 f
= pullup_get_frame(c
);
148 pullup_release_frame(f
);
149 if (!(mpi
->fields
& MP_IMGFIELD_REPEAT_FIRST
))
151 f
= pullup_get_frame(c
);
154 pullup_release_frame(f
);
161 /* Average qscale tables from both frames. */
163 for (i
=0; i
<c
->w
[3]; i
++) {
164 vf
->priv
->qbuf
[i
] = (f
->ofields
[0]->planes
[3][i
]
165 + f
->ofields
[1]->planes
[3][i
+c
->w
[3]])>>1;
169 /* Take worst of qscale tables from both frames. */
171 for (i
=0; i
<c
->w
[3]; i
++) {
172 vf
->priv
->qbuf
[i
] = MAX(f
->ofields
[0]->planes
[3][i
], f
->ofields
[1]->planes
[3][i
+c
->w
[3]]);
177 /* If the frame isn't already exportable... */
179 dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
,
180 MP_IMGTYPE_TEMP
, MP_IMGFLAG_ACCEPT_STRIDE
,
181 mpi
->width
, mpi
->height
);
182 /* FIXME: Is it ok to discard dmpi if it's not direct? */
183 if (!(dmpi
->flags
& MP_IMGFLAG_DIRECT
)) {
184 pullup_pack_frame(c
, f
);
187 /* Direct render fields into output buffer */
188 my_memcpy_pic(dmpi
->planes
[0], f
->ofields
[0]->planes
[0],
189 mpi
->w
, mpi
->h
/2, dmpi
->stride
[0]*2, c
->stride
[0]*2);
190 my_memcpy_pic(dmpi
->planes
[0] + dmpi
->stride
[0],
191 f
->ofields
[1]->planes
[0] + c
->stride
[0],
192 mpi
->w
, mpi
->h
/2, dmpi
->stride
[0]*2, c
->stride
[0]*2);
193 if (mpi
->flags
& MP_IMGFLAG_PLANAR
) {
194 my_memcpy_pic(dmpi
->planes
[1], f
->ofields
[0]->planes
[1],
195 mpi
->chroma_width
, mpi
->chroma_height
/2,
196 dmpi
->stride
[1]*2, c
->stride
[1]*2);
197 my_memcpy_pic(dmpi
->planes
[1] + dmpi
->stride
[1],
198 f
->ofields
[1]->planes
[1] + c
->stride
[1],
199 mpi
->chroma_width
, mpi
->chroma_height
/2,
200 dmpi
->stride
[1]*2, c
->stride
[1]*2);
201 my_memcpy_pic(dmpi
->planes
[2], f
->ofields
[0]->planes
[2],
202 mpi
->chroma_width
, mpi
->chroma_height
/2,
203 dmpi
->stride
[2]*2, c
->stride
[2]*2);
204 my_memcpy_pic(dmpi
->planes
[2] + dmpi
->stride
[2],
205 f
->ofields
[1]->planes
[2] + c
->stride
[2],
206 mpi
->chroma_width
, mpi
->chroma_height
/2,
207 dmpi
->stride
[2]*2, c
->stride
[2]*2);
209 pullup_release_frame(f
);
211 dmpi
->qscale
= vf
->priv
->qbuf
;
212 dmpi
->qstride
= mpi
->qstride
;
213 dmpi
->qscale_type
= mpi
->qscale_type
;
215 return vf_next_put_image(vf
, dmpi
, MP_NOPTS_VALUE
);
217 dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
,
218 MP_IMGTYPE_EXPORT
, MP_IMGFLAG_ACCEPT_STRIDE
,
219 mpi
->width
, mpi
->height
);
221 dmpi
->planes
[0] = f
->buffer
->planes
[0];
222 dmpi
->planes
[1] = f
->buffer
->planes
[1];
223 dmpi
->planes
[2] = f
->buffer
->planes
[2];
225 dmpi
->stride
[0] = c
->stride
[0];
226 dmpi
->stride
[1] = c
->stride
[1];
227 dmpi
->stride
[2] = c
->stride
[2];
230 dmpi
->qscale
= vf
->priv
->qbuf
;
231 dmpi
->qstride
= mpi
->qstride
;
232 dmpi
->qscale_type
= mpi
->qscale_type
;
234 ret
= vf_next_put_image(vf
, dmpi
, MP_NOPTS_VALUE
);
235 pullup_release_frame(f
);
239 static int query_format(struct vf_instance_s
* vf
, unsigned int fmt
)
241 /* FIXME - support more formats */
246 return vf_next_query_format(vf
, fmt
);
251 static int config(struct vf_instance_s
* vf
,
252 int width
, int height
, int d_width
, int d_height
,
253 unsigned int flags
, unsigned int outfmt
)
255 if (height
&3) return 0;
256 return vf_next_config(vf
, width
, height
, d_width
, d_height
, flags
, outfmt
);
259 static void uninit(struct vf_instance_s
* vf
)
261 pullup_free_context(vf
->priv
->ctx
);
265 static int open(vf_instance_t
*vf
, char* args
)
268 struct pullup_context
*c
;
269 //vf->get_image = get_image;
270 vf
->put_image
= put_image
;
272 vf
->query_format
= query_format
;
274 vf
->default_reqs
= VFCAP_ACCEPT_STRIDE
;
275 vf
->priv
= p
= calloc(1, sizeof(struct vf_priv_s
));
276 p
->ctx
= c
= pullup_alloc_context();
278 c
->verbose
= verbose
>0;
279 c
->junk_left
= c
->junk_right
= 1;
280 c
->junk_top
= c
->junk_bottom
= 4;
281 c
->strict_breaks
= 0;
284 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
);
289 const vf_info_t vf_info_pullup
= {
290 "pullup (from field sequence to frames)",