Statistics
| Branch: | Revision:

ffmpeg / libavfilter / libmpcodecs / vf_pullup.c @ e4852fb3

History | View | Annotate | Download (9.48 KB)

1
/*
2
 * This file is part of MPlayer.
3
 *
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.
8
 *
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.
13
 *
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.
17
 */
18

    
19
#include <stdio.h>
20
#include <stdlib.h>
21
#include <string.h>
22

    
23
#include "config.h"
24
#include "mp_msg.h"
25
#include "cpudetect.h"
26

    
27
#include "img_format.h"
28
#include "mp_image.h"
29
#include "vf.h"
30

    
31
#include "libvo/fastmemcpy.h"
32

    
33
#include "pullup.h"
34

    
35
#undef MAX
36
#define MAX(a,b) ((a)>(b)?(a):(b))
37

    
38
struct vf_priv_s {
39
    struct pullup_context *ctx;
40
    int init;
41
    int fakecount;
42
    char *qbuf;
43
};
44

    
45
static void init_pullup(struct vf_instance *vf, mp_image_t *mpi)
46
{
47
    struct pullup_context *c = vf->priv->ctx;
48

    
49
    if (mpi->flags & MP_IMGFLAG_PLANAR) {
50
        c->format = PULLUP_FMT_Y;
51
        c->nplanes = 4;
52
        pullup_preinit_context(c);
53
        c->bpp[0] = c->bpp[1] = c->bpp[2] = 8;
54
        c->w[0] = mpi->w;
55
        c->h[0] = mpi->h;
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);
59
        c->h[3] = 2;
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;
64
    }
65

    
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;
72

    
73
    pullup_init_context(c);
74

    
75
    vf->priv->init = 1;
76
    vf->priv->qbuf = malloc(c->w[3]);
77
}
78

    
79

    
80
#if 0
81
static void get_image(struct vf_instance *vf, mp_image_t *mpi)
82
{
83
    struct pullup_context *c = vf->priv->ctx;
84
    struct pullup_buffer *b;
85

86
    if (mpi->type == MP_IMGTYPE_STATIC) return;
87

88
    if (!vf->priv->init) init_pullup(vf, mpi);
89

90
    b = pullup_get_buffer(c, 2);
91
    if (!b) return; /* shouldn't happen... */
92

93
    mpi->priv = b;
94

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];
101

102
    mpi->flags |= MP_IMGFLAG_DIRECT;
103
    mpi->flags &= ~MP_IMGFLAG_DRAW_CALLBACK;
104
}
105
#endif
106

    
107
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
108
{
109
    struct pullup_context *c = vf->priv->ctx;
110
    struct pullup_buffer *b;
111
    struct pullup_frame *f;
112
    mp_image_t *dmpi;
113
    int ret;
114
    int p;
115
    int i;
116

    
117
    if (!vf->priv->init) init_pullup(vf, mpi);
118

    
119
    if (mpi->flags & MP_IMGFLAG_DIRECT) {
120
        b = mpi->priv;
121
        mpi->priv = 0;
122
    } else {
123
        b = pullup_get_buffer(c, 2);
124
        if (!b) {
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);
128
            return 0;
129
        }
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]);
139
        }
140
    }
141
    if (mpi->qscale) {
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]);
144
    }
145

    
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);
152

    
153
    pullup_release_buffer(b, 2);
154

    
155
    f = pullup_get_frame(c);
156

    
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;
160

    
161
    if (f->length < 2) {
162
        pullup_release_frame(f);
163
        f = pullup_get_frame(c);
164
        if (!f) return 0;
165
        if (f->length < 2) {
166
            pullup_release_frame(f);
167
            if (!(mpi->fields & MP_IMGFIELD_REPEAT_FIRST))
168
                return 0;
169
            f = pullup_get_frame(c);
170
            if (!f) return 0;
171
            if (f->length < 2) {
172
                pullup_release_frame(f);
173
                return 0;
174
            }
175
        }
176
    }
177

    
178
#if 0
179
    /* Average qscale tables from both frames. */
180
    if (mpi->qscale) {
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;
184
        }
185
    }
186
#else
187
    /* Take worst of qscale tables from both frames. */
188
    if (mpi->qscale) {
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]]);
191
        }
192
    }
193
#endif
194

    
195
    /* If the frame isn't already exportable... */
196
    while (!f->buffer) {
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);
203
            break;
204
        }
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);
226
        }
227
        pullup_release_frame(f);
228
        if (mpi->qscale) {
229
            dmpi->qscale = vf->priv->qbuf;
230
            dmpi->qstride = mpi->qstride;
231
            dmpi->qscale_type = mpi->qscale_type;
232
        }
233
        return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
234
    }
235
    dmpi = vf_get_image(vf->next, mpi->imgfmt,
236
        MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
237
        mpi->width, mpi->height);
238

    
239
    dmpi->planes[0] = f->buffer->planes[0];
240
    dmpi->planes[1] = f->buffer->planes[1];
241
    dmpi->planes[2] = f->buffer->planes[2];
242

    
243
    dmpi->stride[0] = c->stride[0];
244
    dmpi->stride[1] = c->stride[1];
245
    dmpi->stride[2] = c->stride[2];
246

    
247
    if (mpi->qscale) {
248
        dmpi->qscale = vf->priv->qbuf;
249
        dmpi->qstride = mpi->qstride;
250
        dmpi->qscale_type = mpi->qscale_type;
251
    }
252
    ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
253
    pullup_release_frame(f);
254
    return ret;
255
}
256

    
257
static int query_format(struct vf_instance *vf, unsigned int fmt)
258
{
259
    /* FIXME - support more formats */
260
    switch (fmt) {
261
    case IMGFMT_YV12:
262
    case IMGFMT_IYUV:
263
    case IMGFMT_I420:
264
        return vf_next_query_format(vf, fmt);
265
    }
266
    return 0;
267
}
268

    
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)
272
{
273
    if (height&3) return 0;
274
    return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
275
}
276

    
277
static void uninit(struct vf_instance *vf)
278
{
279
    pullup_free_context(vf->priv->ctx);
280
    free(vf->priv);
281
}
282

    
283
static int vf_open(vf_instance_t *vf, char *args)
284
{
285
    struct vf_priv_s *p;
286
    struct pullup_context *c;
287
    //vf->get_image = get_image;
288
    vf->put_image = put_image;
289
    vf->config = config;
290
    vf->query_format = query_format;
291
    vf->uninit = uninit;
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();
295
    p->fakecount = 1;
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;
300
    c->metric_plane = 0;
301
    if (args) {
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);
303
    }
304
    return 1;
305
}
306

    
307
const vf_info_t vf_info_pullup = {
308
    "pullup (from field sequence to frames)",
309
    "pullup",
310
    "Rich Felker",
311
    "",
312
    vf_open,
313
    NULL
314
};