Statistics
| Branch: | Revision:

ffmpeg / libavfilter / vf_mp.c @ master

History | View | Annotate | Download (30.7 KB)

1 3aa43978 Michael Niedermayer
/*
2
 * Copyright (c) 2011 Michael Niedermayer
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 *
20
 * Parts of this file have been stolen from mplayer
21
 */
22
23
/**
24
 * @file
25
 */
26
27
#include "avfilter.h"
28
#include "libavutil/avassert.h"
29
#include "libavutil/pixdesc.h"
30
#include "libavutil/intreadwrite.h"
31 7ffe76e5 Reinhard Tartler
#include "libavutil/imgutils.h"
32 3aa43978 Michael Niedermayer
33
#include "libmpcodecs/vf.h"
34
#include "libmpcodecs/img_format.h"
35
#include "libmpcodecs/cpudetect.h"
36
#include "libmpcodecs/vd_ffmpeg.h"
37
#include "libmpcodecs/vf_scale.h"
38
#include "libmpcodecs/libvo/fastmemcpy.h"
39
40
#include "libswscale/swscale.h"
41
42
43
//FIXME maybe link the orig in
44
static const struct {
45
    int fmt;
46
    enum PixelFormat pix_fmt;
47
} conversion_map[] = {
48
    {IMGFMT_ARGB, PIX_FMT_ARGB},
49
    {IMGFMT_BGRA, PIX_FMT_BGRA},
50
    {IMGFMT_BGR24, PIX_FMT_BGR24},
51
    {IMGFMT_BGR16BE, PIX_FMT_RGB565BE},
52
    {IMGFMT_BGR16LE, PIX_FMT_RGB565LE},
53
    {IMGFMT_BGR15BE, PIX_FMT_RGB555BE},
54
    {IMGFMT_BGR15LE, PIX_FMT_RGB555LE},
55
    {IMGFMT_BGR12BE, PIX_FMT_RGB444BE},
56
    {IMGFMT_BGR12LE, PIX_FMT_RGB444LE},
57
    {IMGFMT_BGR8,  PIX_FMT_RGB8},
58
    {IMGFMT_BGR4,  PIX_FMT_RGB4},
59
    {IMGFMT_BGR1,  PIX_FMT_MONOBLACK},
60
    {IMGFMT_RGB1,  PIX_FMT_MONOBLACK},
61
    {IMGFMT_RG4B,  PIX_FMT_BGR4_BYTE},
62
    {IMGFMT_BG4B,  PIX_FMT_RGB4_BYTE},
63
    {IMGFMT_RGB48LE, PIX_FMT_RGB48LE},
64
    {IMGFMT_RGB48BE, PIX_FMT_RGB48BE},
65
    {IMGFMT_ABGR, PIX_FMT_ABGR},
66
    {IMGFMT_RGBA, PIX_FMT_RGBA},
67
    {IMGFMT_RGB24, PIX_FMT_RGB24},
68
    {IMGFMT_RGB16BE, PIX_FMT_BGR565BE},
69
    {IMGFMT_RGB16LE, PIX_FMT_BGR565LE},
70
    {IMGFMT_RGB15BE, PIX_FMT_BGR555BE},
71
    {IMGFMT_RGB15LE, PIX_FMT_BGR555LE},
72
    {IMGFMT_RGB12BE, PIX_FMT_BGR444BE},
73
    {IMGFMT_RGB12LE, PIX_FMT_BGR444LE},
74
    {IMGFMT_RGB8,  PIX_FMT_BGR8},
75
    {IMGFMT_RGB4,  PIX_FMT_BGR4},
76
    {IMGFMT_BGR8,  PIX_FMT_PAL8},
77
    {IMGFMT_YUY2,  PIX_FMT_YUYV422},
78
    {IMGFMT_UYVY,  PIX_FMT_UYVY422},
79
    {IMGFMT_NV12,  PIX_FMT_NV12},
80
    {IMGFMT_NV21,  PIX_FMT_NV21},
81
    {IMGFMT_Y800,  PIX_FMT_GRAY8},
82
    {IMGFMT_Y8,    PIX_FMT_GRAY8},
83
    {IMGFMT_YVU9,  PIX_FMT_YUV410P},
84
    {IMGFMT_IF09,  PIX_FMT_YUV410P},
85
    {IMGFMT_YV12,  PIX_FMT_YUV420P},
86
    {IMGFMT_I420,  PIX_FMT_YUV420P},
87
    {IMGFMT_IYUV,  PIX_FMT_YUV420P},
88
    {IMGFMT_411P,  PIX_FMT_YUV411P},
89
    {IMGFMT_422P,  PIX_FMT_YUV422P},
90
    {IMGFMT_444P,  PIX_FMT_YUV444P},
91
    {IMGFMT_440P,  PIX_FMT_YUV440P},
92
93
    {IMGFMT_420A,  PIX_FMT_YUVA420P},
94
95
    {IMGFMT_420P16_LE,  PIX_FMT_YUV420P16LE},
96
    {IMGFMT_420P16_BE,  PIX_FMT_YUV420P16BE},
97
    {IMGFMT_422P16_LE,  PIX_FMT_YUV422P16LE},
98
    {IMGFMT_422P16_BE,  PIX_FMT_YUV422P16BE},
99
    {IMGFMT_444P16_LE,  PIX_FMT_YUV444P16LE},
100
    {IMGFMT_444P16_BE,  PIX_FMT_YUV444P16BE},
101
102
    // YUVJ are YUV formats that use the full Y range and not just
103
    // 16 - 235 (see colorspaces.txt).
104
    // Currently they are all treated the same way.
105
    {IMGFMT_YV12,  PIX_FMT_YUVJ420P},
106
    {IMGFMT_422P,  PIX_FMT_YUVJ422P},
107
    {IMGFMT_444P,  PIX_FMT_YUVJ444P},
108
    {IMGFMT_440P,  PIX_FMT_YUVJ440P},
109
110
    {IMGFMT_XVMC_MOCO_MPEG2, PIX_FMT_XVMC_MPEG2_MC},
111
    {IMGFMT_XVMC_IDCT_MPEG2, PIX_FMT_XVMC_MPEG2_IDCT},
112
    {IMGFMT_VDPAU_MPEG1,     PIX_FMT_VDPAU_MPEG1},
113
    {IMGFMT_VDPAU_MPEG2,     PIX_FMT_VDPAU_MPEG2},
114
    {IMGFMT_VDPAU_H264,      PIX_FMT_VDPAU_H264},
115
    {IMGFMT_VDPAU_WMV3,      PIX_FMT_VDPAU_WMV3},
116
    {IMGFMT_VDPAU_VC1,       PIX_FMT_VDPAU_VC1},
117
    {IMGFMT_VDPAU_MPEG4,     PIX_FMT_VDPAU_MPEG4},
118
    {0, PIX_FMT_NONE}
119
};
120
121
//copied from vf.c
122
extern const vf_info_t vf_info_vo;
123
extern const vf_info_t vf_info_rectangle;
124
extern const vf_info_t vf_info_bmovl;
125
extern const vf_info_t vf_info_crop;
126
extern const vf_info_t vf_info_expand;
127
extern const vf_info_t vf_info_pp;
128
extern const vf_info_t vf_info_scale;
129
extern const vf_info_t vf_info_format;
130
extern const vf_info_t vf_info_noformat;
131
extern const vf_info_t vf_info_flip;
132
extern const vf_info_t vf_info_rotate;
133
extern const vf_info_t vf_info_mirror;
134
extern const vf_info_t vf_info_palette;
135
extern const vf_info_t vf_info_lavc;
136
extern const vf_info_t vf_info_zrmjpeg;
137
extern const vf_info_t vf_info_dvbscale;
138
extern const vf_info_t vf_info_cropdetect;
139
extern const vf_info_t vf_info_test;
140
extern const vf_info_t vf_info_noise;
141
extern const vf_info_t vf_info_yvu9;
142
extern const vf_info_t vf_info_lavcdeint;
143
extern const vf_info_t vf_info_eq;
144
extern const vf_info_t vf_info_eq2;
145
extern const vf_info_t vf_info_gradfun;
146
extern const vf_info_t vf_info_halfpack;
147
extern const vf_info_t vf_info_dint;
148
extern const vf_info_t vf_info_1bpp;
149
extern const vf_info_t vf_info_2xsai;
150
extern const vf_info_t vf_info_unsharp;
151
extern const vf_info_t vf_info_swapuv;
152
extern const vf_info_t vf_info_il;
153
extern const vf_info_t vf_info_fil;
154
extern const vf_info_t vf_info_boxblur;
155
extern const vf_info_t vf_info_sab;
156
extern const vf_info_t vf_info_smartblur;
157
extern const vf_info_t vf_info_perspective;
158
extern const vf_info_t vf_info_down3dright;
159
extern const vf_info_t vf_info_field;
160
extern const vf_info_t vf_info_denoise3d;
161
extern const vf_info_t vf_info_hqdn3d;
162
extern const vf_info_t vf_info_detc;
163
extern const vf_info_t vf_info_telecine;
164
extern const vf_info_t vf_info_tinterlace;
165
extern const vf_info_t vf_info_tfields;
166
extern const vf_info_t vf_info_ivtc;
167
extern const vf_info_t vf_info_ilpack;
168
extern const vf_info_t vf_info_dsize;
169
extern const vf_info_t vf_info_decimate;
170
extern const vf_info_t vf_info_softpulldown;
171
extern const vf_info_t vf_info_pullup;
172
extern const vf_info_t vf_info_filmdint;
173
extern const vf_info_t vf_info_framestep;
174
extern const vf_info_t vf_info_tile;
175
extern const vf_info_t vf_info_delogo;
176
extern const vf_info_t vf_info_remove_logo;
177
extern const vf_info_t vf_info_hue;
178
extern const vf_info_t vf_info_spp;
179
extern const vf_info_t vf_info_uspp;
180
extern const vf_info_t vf_info_fspp;
181
extern const vf_info_t vf_info_pp7;
182
extern const vf_info_t vf_info_yuvcsp;
183
extern const vf_info_t vf_info_kerndeint;
184
extern const vf_info_t vf_info_rgbtest;
185
extern const vf_info_t vf_info_qp;
186
extern const vf_info_t vf_info_phase;
187
extern const vf_info_t vf_info_divtc;
188
extern const vf_info_t vf_info_harddup;
189
extern const vf_info_t vf_info_softskip;
190
extern const vf_info_t vf_info_screenshot;
191
extern const vf_info_t vf_info_ass;
192
extern const vf_info_t vf_info_mcdeint;
193
extern const vf_info_t vf_info_yadif;
194
extern const vf_info_t vf_info_blackframe;
195
extern const vf_info_t vf_info_geq;
196
extern const vf_info_t vf_info_ow;
197
extern const vf_info_t vf_info_fixpts;
198
extern const vf_info_t vf_info_stereo3d;
199
200
201
static const vf_info_t* const filters[]={
202
    &vf_info_2xsai,
203
    &vf_info_blackframe,
204
    &vf_info_boxblur,
205
    &vf_info_cropdetect,
206
    &vf_info_decimate,
207
    &vf_info_delogo,
208
    &vf_info_denoise3d,
209
    &vf_info_detc,
210
    &vf_info_dint,
211
    &vf_info_divtc,
212
    &vf_info_down3dright,
213
    &vf_info_dsize,
214
    &vf_info_eq2,
215
    &vf_info_eq,
216
    &vf_info_field,
217
    &vf_info_fil,
218
//    &vf_info_filmdint, cmmx.h vd.h ‘opt_screen_size_x’
219
    &vf_info_fixpts,
220
    &vf_info_framestep,
221
    &vf_info_fspp,
222
    &vf_info_geq,
223
    &vf_info_gradfun,
224
    &vf_info_harddup,
225
    &vf_info_hqdn3d,
226
    &vf_info_hue,
227
    &vf_info_il,
228
    &vf_info_ilpack,
229
    &vf_info_ivtc,
230
    &vf_info_kerndeint,
231
    &vf_info_mcdeint,
232
    &vf_info_mirror,
233
    &vf_info_noise,
234
    &vf_info_ow,
235
    &vf_info_palette,
236
    &vf_info_perspective,
237
    &vf_info_phase,
238
    &vf_info_pp7,
239
    &vf_info_pullup,
240
    &vf_info_qp,
241
    &vf_info_rectangle,
242
    &vf_info_remove_logo,
243
    &vf_info_rgbtest,
244
    &vf_info_rotate,
245
    &vf_info_sab,
246
    &vf_info_screenshot,
247
    &vf_info_smartblur,
248
    &vf_info_softpulldown,
249
    &vf_info_softskip,
250
    &vf_info_spp,
251
    &vf_info_swapuv,
252
    &vf_info_telecine,
253
    &vf_info_test,
254
    &vf_info_tile,
255
    &vf_info_tinterlace,
256
    &vf_info_unsharp,
257
    &vf_info_uspp,
258
    &vf_info_yuvcsp,
259
    &vf_info_yvu9,
260
261
    NULL
262
};
263
264
/*
265
Unsupported filters
266
1bpp
267
ass
268
bmovl
269
crop
270
dvbscale
271
flip
272
expand
273
format
274
halfpack
275
lavc
276
lavcdeint
277
noformat
278
pp
279
scale
280
stereo3d
281
tfields
282
vo
283
yadif
284
zrmjpeg
285
*/
286
287
CpuCaps gCpuCaps; //FIXME initialize this so optims work
288
289
290
//exact copy from vf_scale.c
291
int get_sws_cpuflags(void){
292
    return
293
          (gCpuCaps.hasMMX   ? SWS_CPU_CAPS_MMX   : 0)
294
        | (gCpuCaps.hasMMX2  ? SWS_CPU_CAPS_MMX2  : 0)
295
        | (gCpuCaps.has3DNow ? SWS_CPU_CAPS_3DNOW : 0)
296
        | (gCpuCaps.hasAltiVec ? SWS_CPU_CAPS_ALTIVEC : 0);
297
}
298
299
static void sws_getFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, SwsFilter **dstFilterParam)
300
{
301
        static int firstTime=1;
302
        *flags=0;
303
304
#if ARCH_X86
305
        if(gCpuCaps.hasMMX)
306
                __asm__ volatile("emms\n\t"::: "memory"); //FIXME this should not be required but it IS (even for non-MMX versions)
307
#endif
308
        if(firstTime)
309
        {
310
                firstTime=0;
311
                *flags= SWS_PRINT_INFO;
312
        }
313
        else if( mp_msg_test(MSGT_VFILTER,MSGL_DBG2) ) *flags= SWS_PRINT_INFO;
314
315
        switch(SWS_BILINEAR)
316
        {
317
                case 0: *flags|= SWS_FAST_BILINEAR; break;
318
                case 1: *flags|= SWS_BILINEAR; break;
319
                case 2: *flags|= SWS_BICUBIC; break;
320
                case 3: *flags|= SWS_X; break;
321
                case 4: *flags|= SWS_POINT; break;
322
                case 5: *flags|= SWS_AREA; break;
323
                case 6: *flags|= SWS_BICUBLIN; break;
324
                case 7: *flags|= SWS_GAUSS; break;
325
                case 8: *flags|= SWS_SINC; break;
326
                case 9: *flags|= SWS_LANCZOS; break;
327
                case 10:*flags|= SWS_SPLINE; break;
328
                default:*flags|= SWS_BILINEAR; break;
329
        }
330
331
        *srcFilterParam= NULL;
332
        *dstFilterParam= NULL;
333
}
334
335
//exact copy from vf_scale.c
336
// will use sws_flags & src_filter (from cmd line)
337
struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat)
338
{
339
        int flags, i;
340
        SwsFilter *dstFilterParam, *srcFilterParam;
341
        enum PixelFormat dfmt, sfmt;
342
343
        for(i=0; conversion_map[i].fmt && dstFormat != conversion_map[i].fmt; i++);
344
        dfmt= conversion_map[i].pix_fmt;
345
        for(i=0; conversion_map[i].fmt && srcFormat != conversion_map[i].fmt; i++);
346
        sfmt= conversion_map[i].pix_fmt;
347
348
        if (srcFormat == IMGFMT_RGB8 || srcFormat == IMGFMT_BGR8) sfmt = PIX_FMT_PAL8;
349
        sws_getFlagsAndFilterFromCmdLine(&flags, &srcFilterParam, &dstFilterParam);
350
351
        return sws_getContext(srcW, srcH, sfmt, dstW, dstH, dfmt, flags | get_sws_cpuflags(), srcFilterParam, dstFilterParam, NULL);
352
}
353
354
typedef struct {
355
    vf_instance_t vf;
356
    vf_instance_t next_vf;
357
    AVFilterContext *avfctx;
358
    int frame_returned;
359
} MPContext;
360
361
void mp_msg(int mod, int lev, const char *format, ... ){
362
    va_list va;
363
    va_start(va, format);
364
    //FIXME convert lev/mod
365
    av_vlog(NULL, AV_LOG_DEBUG, format, va);
366
    va_end(va);
367
}
368
369
int mp_msg_test(int mod, int lev){
370
    return 123;
371
}
372
373
void init_avcodec(void)
374
{
375
    //we maybe should init but its kinda 1. unneeded 2. a bit inpolite from here
376
}
377
378
//Exact copy of vf.c
379
void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src){
380
    dst->pict_type= src->pict_type;
381
    dst->fields = src->fields;
382
    dst->qscale_type= src->qscale_type;
383
    if(dst->width == src->width && dst->height == src->height){
384
        dst->qstride= src->qstride;
385
        dst->qscale= src->qscale;
386
    }
387
}
388
389
//Exact copy of vf.c
390
void vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){
391
    if (vf->next->draw_slice) {
392
        vf->next->draw_slice(vf->next,src,stride,w,h,x,y);
393
        return;
394
    }
395
    if (!vf->dmpi) {
396
        mp_msg(MSGT_VFILTER,MSGL_ERR,"draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
397
        return;
398
    }
399
    if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) {
400
        memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+vf->dmpi->bpp/8*x,
401
            src[0], vf->dmpi->bpp/8*w, h, vf->dmpi->stride[0], stride[0]);
402
        return;
403
    }
404
    memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+x, src[0],
405
        w, h, vf->dmpi->stride[0], stride[0]);
406
    memcpy_pic(vf->dmpi->planes[1]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[1]+(x>>vf->dmpi->chroma_x_shift),
407
        src[1], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]);
408
    memcpy_pic(vf->dmpi->planes[2]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[2]+(x>>vf->dmpi->chroma_x_shift),
409
        src[2], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]);
410
}
411
412
//Exact copy of vf.c
413
void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h){
414
    int y;
415
    if(mpi->flags&MP_IMGFLAG_PLANAR){
416
        y0&=~1;h+=h&1;
417
        if(x0==0 && w==mpi->width){
418
            // full width clear:
419
            memset(mpi->planes[0]+mpi->stride[0]*y0,0,mpi->stride[0]*h);
420
            memset(mpi->planes[1]+mpi->stride[1]*(y0>>mpi->chroma_y_shift),128,mpi->stride[1]*(h>>mpi->chroma_y_shift));
421
            memset(mpi->planes[2]+mpi->stride[2]*(y0>>mpi->chroma_y_shift),128,mpi->stride[2]*(h>>mpi->chroma_y_shift));
422
        } else
423
        for(y=y0;y<y0+h;y+=2){
424
            memset(mpi->planes[0]+x0+mpi->stride[0]*y,0,w);
425
            memset(mpi->planes[0]+x0+mpi->stride[0]*(y+1),0,w);
426
            memset(mpi->planes[1]+(x0>>mpi->chroma_x_shift)+mpi->stride[1]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
427
            memset(mpi->planes[2]+(x0>>mpi->chroma_x_shift)+mpi->stride[2]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
428
        }
429
        return;
430
    }
431
    // packed:
432
    for(y=y0;y<y0+h;y++){
433
        unsigned char* dst=mpi->planes[0]+mpi->stride[0]*y+(mpi->bpp>>3)*x0;
434
        if(mpi->flags&MP_IMGFLAG_YUV){
435
            unsigned int* p=(unsigned int*) dst;
436
            int size=(mpi->bpp>>3)*w/4;
437
            int i;
438
#if HAVE_BIGENDIAN
439
#define CLEAR_PACKEDYUV_PATTERN 0x00800080
440
#define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x80008000
441
#else
442
#define CLEAR_PACKEDYUV_PATTERN 0x80008000
443
#define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x00800080
444
#endif
445
            if(mpi->flags&MP_IMGFLAG_SWAPPED){
446
                for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
447
                for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
448
            } else {
449
                for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN;
450
                for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN;
451
            }
452
        } else
453
            memset(dst,0,(mpi->bpp>>3)*w);
454
    }
455
}
456
457
int vf_next_query_format(struct vf_instance *vf, unsigned int fmt){
458
    return 1;
459
}
460
461
//used by delogo
462
unsigned int vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred){
463
    return preferred;
464
}
465
466
mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h){
467
    MPContext *m= ((uint8_t*)vf) - offsetof(MPContext, next_vf);
468
  mp_image_t* mpi=NULL;
469
  int w2;
470
  int number = mp_imgtype >> 16;
471
472
  av_assert0(vf->next == NULL); // all existing filters call this just on next
473
474
  //vf_dint needs these as it calls vf_get_image() before configuring the output
475
  if(vf->w==0 && w>0) vf->w=w;
476
  if(vf->h==0 && h>0) vf->h=h;
477
478
  av_assert0(w == -1 || w >= vf->w);
479
  av_assert0(h == -1 || h >= vf->h);
480
  av_assert0(vf->w > 0);
481
  av_assert0(vf->h > 0);
482
483
  av_log(m->avfctx, AV_LOG_DEBUG, "get_image: %d:%d, vf: %d:%d\n", w,h,vf->w,vf->h);
484
485
  if (w == -1) w = vf->w;
486
  if (h == -1) h = vf->h;
487
488
  w2=(mp_imgflag&MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE)?((w+15)&(~15)):w;
489
490
  // Note: we should call libvo first to check if it supports direct rendering
491
  // and if not, then fallback to software buffers:
492
  switch(mp_imgtype & 0xff){
493
  case MP_IMGTYPE_EXPORT:
494
    if(!vf->imgctx.export_images[0]) vf->imgctx.export_images[0]=new_mp_image(w2,h);
495
    mpi=vf->imgctx.export_images[0];
496
    break;
497
  case MP_IMGTYPE_STATIC:
498
    if(!vf->imgctx.static_images[0]) vf->imgctx.static_images[0]=new_mp_image(w2,h);
499
    mpi=vf->imgctx.static_images[0];
500
    break;
501
  case MP_IMGTYPE_TEMP:
502
    if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
503
    mpi=vf->imgctx.temp_images[0];
504
    break;
505
  case MP_IMGTYPE_IPB:
506
    if(!(mp_imgflag&MP_IMGFLAG_READABLE)){ // B frame:
507
      if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
508
      mpi=vf->imgctx.temp_images[0];
509
      break;
510
    }
511
  case MP_IMGTYPE_IP:
512
    if(!vf->imgctx.static_images[vf->imgctx.static_idx]) vf->imgctx.static_images[vf->imgctx.static_idx]=new_mp_image(w2,h);
513
    mpi=vf->imgctx.static_images[vf->imgctx.static_idx];
514
    vf->imgctx.static_idx^=1;
515
    break;
516
  case MP_IMGTYPE_NUMBERED:
517
    if (number == -1) {
518
      int i;
519
      for (i = 0; i < NUM_NUMBERED_MPI; i++)
520
        if (!vf->imgctx.numbered_images[i] || !vf->imgctx.numbered_images[i]->usage_count)
521
          break;
522
      number = i;
523
    }
524
    if (number < 0 || number >= NUM_NUMBERED_MPI) return NULL;
525
    if (!vf->imgctx.numbered_images[number]) vf->imgctx.numbered_images[number] = new_mp_image(w2,h);
526
    mpi = vf->imgctx.numbered_images[number];
527
    mpi->number = number;
528
    break;
529
  }
530
  if(mpi){
531
    mpi->type=mp_imgtype;
532
    mpi->w=vf->w; mpi->h=vf->h;
533
    // keep buffer allocation status & color flags only:
534
//    mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE|MP_IMGFLAG_DIRECT);
535
    mpi->flags&=MP_IMGFLAG_ALLOCATED|MP_IMGFLAG_TYPE_DISPLAYED|MP_IMGFLAGMASK_COLORS;
536
    // accept restrictions, draw_slice and palette flags only:
537
    mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK|MP_IMGFLAG_RGB_PALETTE);
538
    if(!vf->draw_slice) mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK;
539
    if(mpi->width!=w2 || mpi->height!=h){
540
//      printf("vf.c: MPI parameters changed!  %dx%d -> %dx%d   \n", mpi->width,mpi->height,w2,h);
541
        if(mpi->flags&MP_IMGFLAG_ALLOCATED){
542
            if(mpi->width<w2 || mpi->height<h){
543
                // need to re-allocate buffer memory:
544
                av_free(mpi->planes[0]);
545
                mpi->flags&=~MP_IMGFLAG_ALLOCATED;
546
                mp_msg(MSGT_VFILTER,MSGL_V,"vf.c: have to REALLOCATE buffer memory :(\n");
547
            }
548
//      } else {
549
        } {
550
            mpi->width=w2; mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
551
            mpi->height=h; mpi->chroma_height=(h + (1<<mpi->chroma_y_shift) - 1)>>mpi->chroma_y_shift;
552
        }
553
    }
554
    if(!mpi->bpp) mp_image_setfmt(mpi,outfmt);
555
    if(!(mpi->flags&MP_IMGFLAG_ALLOCATED) && mpi->type>MP_IMGTYPE_EXPORT){
556
557
        av_assert0(!vf->get_image);
558
        // check libvo first!
559
        if(vf->get_image) vf->get_image(vf,mpi);
560
561
        if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
562
          // non-direct and not yet allocated image. allocate it!
563
          if (!mpi->bpp) { // no way we can allocate this
564
              mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
565
                     "vf_get_image: Tried to allocate a format that can not be allocated!\n");
566
              return NULL;
567
          }
568
569
          // check if codec prefer aligned stride:
570
          if(mp_imgflag&MP_IMGFLAG_PREFER_ALIGNED_STRIDE){
571
              int align=(mpi->flags&MP_IMGFLAG_PLANAR &&
572
                         mpi->flags&MP_IMGFLAG_YUV) ?
573
                         (8<<mpi->chroma_x_shift)-1 : 15; // -- maybe FIXME
574
              w2=((w+align)&(~align));
575
              if(mpi->width!=w2){
576
#if 0
577
                  // we have to change width... check if we CAN co it:
578
                  int flags=vf->query_format(vf,outfmt); // should not fail
579
                  if(!(flags&3)) mp_msg(MSGT_DECVIDEO,MSGL_WARN,"??? vf_get_image{vf->query_format(outfmt)} failed!\n");
580
//                printf("query -> 0x%X    \n",flags);
581
                  if(flags&VFCAP_ACCEPT_STRIDE){
582
#endif
583
                      mpi->width=w2;
584
                      mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
585
//                  }
586
              }
587
          }
588
589
          mp_image_alloc_planes(mpi);
590
//        printf("clearing img!\n");
591
          vf_mpi_clear(mpi,0,0,mpi->width,mpi->height);
592
        }
593
    }
594
    av_assert0(!vf->start_slice);
595
    if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)
596
        if(vf->start_slice) vf->start_slice(vf,mpi);
597
    if(!(mpi->flags&MP_IMGFLAG_TYPE_DISPLAYED)){
598
            mp_msg(MSGT_DECVIDEO,MSGL_V,"*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
599
                  "NULL"/*vf->info->name*/,
600
                  (mpi->type==MP_IMGTYPE_EXPORT)?"Exporting":
601
                  ((mpi->flags&MP_IMGFLAG_DIRECT)?"Direct Rendering":"Allocating"),
602
                  (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)?" (slices)":"",
603
                  mpi->width,mpi->height,mpi->bpp,
604
                  (mpi->flags&MP_IMGFLAG_YUV)?"YUV":((mpi->flags&MP_IMGFLAG_SWAPPED)?"BGR":"RGB"),
605
                  (mpi->flags&MP_IMGFLAG_PLANAR)?"planar":"packed",
606
                  mpi->bpp*mpi->width*mpi->height/8);
607
            mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"(imgfmt: %x, planes: %p,%p,%p strides: %d,%d,%d, chroma: %dx%d, shift: h:%d,v:%d)\n",
608
                mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
609
                mpi->stride[0], mpi->stride[1], mpi->stride[2],
610
                mpi->chroma_width, mpi->chroma_height, mpi->chroma_x_shift, mpi->chroma_y_shift);
611
            mpi->flags|=MP_IMGFLAG_TYPE_DISPLAYED;
612
    }
613
614
  mpi->qscale = NULL;
615
  }
616
  mpi->usage_count++;
617
//    printf("\rVF_MPI: %p %p %p %d %d %d    \n",
618
//      mpi->planes[0],mpi->planes[1],mpi->planes[2],
619
//      mpi->stride[0],mpi->stride[1],mpi->stride[2]);
620
  return mpi;
621
}
622
623
624
int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){
625
    MPContext *m= (void*)vf;
626
    AVFilterLink *outlink     = m->avfctx->outputs[0];
627
    AVFilterBuffer    *pic    = av_mallocz(sizeof(AVFilterBuffer));
628
    AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef));
629
    int i;
630
631
    av_assert0(vf->next);
632
633
    av_log(m->avfctx, AV_LOG_DEBUG, "vf_next_put_image\n");
634
635
    if (!pic || !picref)
636
        goto fail;
637
638
    picref->buf = pic;
639
    picref->buf->please_use_av_free= av_free;
640
    if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps))))
641
        goto fail;
642
643
    pic->w = picref->video->w = mpi->w;
644
    pic->h = picref->video->h = mpi->h;
645
646
    /* make sure the buffer gets read permission or it's useless for output */
647
    picref->perms = AV_PERM_READ | AV_PERM_REUSE2;
648
//    av_assert0(mpi->flags&MP_IMGFLAG_READABLE);
649
    if(!(mpi->flags&MP_IMGFLAG_PRESERVE))
650
        picref->perms |= AV_PERM_WRITE;
651
652
    pic->refcount = 1;
653
    picref->type = AVMEDIA_TYPE_VIDEO;
654
655
    for(i=0; conversion_map[i].fmt && mpi->imgfmt != conversion_map[i].fmt; i++);
656
    pic->format = picref->format = conversion_map[i].pix_fmt;
657
658
    memcpy(pic->data,        mpi->planes,   FFMIN(sizeof(pic->data)    , sizeof(mpi->planes)));
659
    memcpy(pic->linesize,    mpi->stride,   FFMIN(sizeof(pic->linesize), sizeof(mpi->stride)));
660
    memcpy(picref->data,     pic->data,     sizeof(picref->data));
661
    memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
662
663
    if(pts != MP_NOPTS_VALUE)
664
        picref->pts= pts * av_q2d(outlink->time_base);
665
666
    avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
667
    avfilter_draw_slice(outlink, 0, picref->video->h, 1);
668
    avfilter_end_frame(outlink);
669
    avfilter_unref_buffer(picref);
670
    m->frame_returned++;
671
672
    return 1;
673
fail:
674
    if (picref && picref->video)
675
        av_free(picref->video);
676
    av_free(picref);
677
    av_free(pic);
678
    return 0;
679
}
680
681
int vf_next_config(struct vf_instance *vf,
682
        int width, int height, int d_width, int d_height,
683
        unsigned int voflags, unsigned int outfmt){
684
685
    av_assert0(width>0 && height>0);
686
    vf->next->w = width; vf->next->h = height;
687
688
    return 1;
689
#if 0
690
    int flags=vf->next->query_format(vf->next,outfmt);
691
    if(!flags){
692
        // hmm. colorspace mismatch!!!
693
        //this is fatal for us ATM
694
        return 0;
695
    }
696
    mp_msg(MSGT_VFILTER,MSGL_V,"REQ: flags=0x%X  req=0x%X  \n",flags,vf->default_reqs);
697
    miss=vf->default_reqs - (flags&vf->default_reqs);
698
    if(miss&VFCAP_ACCEPT_STRIDE){
699
        // vf requires stride support but vf->next doesn't support it!
700
        // let's insert the 'expand' filter, it does the job for us:
701
        vf_instance_t* vf2=vf_open_filter(vf->next,"expand",NULL);
702
        if(!vf2) return 0; // shouldn't happen!
703
        vf->next=vf2;
704
    }
705
    vf->next->w = width; vf->next->h = height;
706
#endif
707
    return 1;
708
}
709
710
int vf_next_control(struct vf_instance *vf, int request, void* data){
711
    MPContext *m= (void*)vf;
712
    av_log(m->avfctx, AV_LOG_DEBUG, "Received control %d\n", request);
713
    return 0;
714
}
715
716
static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt){
717
    MPContext *m= (void*)vf;
718
    int i;
719
    av_log(m->avfctx, AV_LOG_DEBUG, "query %X\n", fmt);
720
721
    for(i=0; conversion_map[i].fmt; i++){
722
        if(fmt==conversion_map[i].fmt)
723
            return 1; //we suport all
724
    }
725
    return 0;
726
}
727
728
729
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
730
{
731
    MPContext *m = ctx->priv;
732
    char name[256];
733
    int i;
734
735 61d7f8fe Michael Niedermayer
    av_log(ctx, AV_LOG_WARNING,
736
"This is a unholy filter, it will be purified by the ffmpeg exorcist team\n"
737
"which will change its syntax from dark -vf mp to light -vf.\n"
738
"Thou shalst not make spells or scripts that depend on it\n");
739
740 3aa43978 Michael Niedermayer
    m->avfctx= ctx;
741
742 c5099867 Stefano Sabatini
    if(!args || 1!=sscanf(args, "%255[^:=]", name)){
743 3aa43978 Michael Niedermayer
        av_log(ctx, AV_LOG_ERROR, "Invalid parameter.\n");
744
        return AVERROR(EINVAL);
745
    }
746
    args+= strlen(name)+1;
747
748
    for(i=0; ;i++){
749
        if(!filters[i] || !strcmp(name, filters[i]->name))
750
            break;
751
    }
752
753
    if(!filters[i]){
754
        av_log(ctx, AV_LOG_ERROR, "Unknown filter %s\n", name);
755
        return AVERROR(EINVAL);
756
    }
757
758
    memset(&m->vf,0,sizeof(m->vf));
759
    m->vf.info= filters[i];
760
761
    m->vf.next        = &m->next_vf;
762
    m->vf.put_image   = vf_next_put_image;
763
    m->vf.config      = vf_next_config;
764
    m->vf.query_format= vf_default_query_format;
765
    m->vf.control     = vf_next_control;
766
    m->vf.default_caps=VFCAP_ACCEPT_STRIDE;
767
    m->vf.default_reqs=0;
768
    if(m->vf.info->opts)
769
        av_log(ctx, AV_LOG_ERROR, "opts / m_struct_set is unsupported\n");
770
#if 0
771
    if(vf->info->opts) { // vf_vo get some special argument
772
      const m_struct_t* st = vf->info->opts;
773
      void* vf_priv = m_struct_alloc(st);
774
      int n;
775
      for(n = 0 ; args && args[2*n] ; n++)
776
        m_struct_set(st,vf_priv,args[2*n],args[2*n+1]);
777
      vf->priv = vf_priv;
778
      args = NULL;
779
    } else // Otherwise we should have the '_oldargs_'
780
      if(args && !strcmp(args[0],"_oldargs_"))
781
        args = (char**)args[1];
782
      else
783
        args = NULL;
784
#endif
785
    if(m->vf.info->vf_open(&m->vf, args)<=0){
786
        av_log(ctx, AV_LOG_ERROR, "vf_open() of %s with arg=%s failed\n", name, args);
787
        return -1;
788
    }
789
790
    return 0;
791
}
792
793
static int query_formats(AVFilterContext *ctx)
794
{
795
    AVFilterFormats *avfmts=NULL;
796
    MPContext *m = ctx->priv;
797
    int i;
798
799
    for(i=0; conversion_map[i].fmt; i++){
800
        av_log(ctx, AV_LOG_DEBUG, "query: %X\n", conversion_map[i].fmt);
801
        if(m->vf.query_format(&m->vf, conversion_map[i].fmt)){
802
            av_log(ctx, AV_LOG_DEBUG, "supported,adding\n");
803
            avfilter_add_format(&avfmts, conversion_map[i].pix_fmt);
804
        }
805
    }
806
807
    //We assume all allowed input formats are also allowed output formats
808
    avfilter_set_common_formats(ctx, avfmts);
809
    return 0;
810
}
811
812
static int config_inprops(AVFilterLink *inlink)
813
{
814
    MPContext *m = inlink->dst->priv;
815
    int i;
816
    for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
817
818
    av_assert0(conversion_map[i].fmt && inlink->w && inlink->h);
819
820
    m->vf.fmt.have_configured = 1;
821
    m->vf.fmt.orig_height     = inlink->h;
822
    m->vf.fmt.orig_width      = inlink->w;
823
    m->vf.fmt.orig_fmt        = conversion_map[i].fmt;
824
825
    if(m->vf.config(&m->vf, inlink->w, inlink->h, inlink->w, inlink->h, 0, conversion_map[i].fmt)<=0)
826
        return -1;
827
828
    return 0;
829
}
830
831
static int config_outprops(AVFilterLink *outlink)
832
{
833
    MPContext *m = outlink->src->priv;
834
835
    outlink->w = m->next_vf.w;
836
    outlink->h = m->next_vf.h;
837
838
    return 0;
839
}
840
841
static int request_frame(AVFilterLink *outlink)
842
{
843
    MPContext *m = outlink->src->priv;
844
    int ret;
845
846
    av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame\n");
847
848
    for(m->frame_returned=0; !m->frame_returned;){
849
        ret=avfilter_request_frame(outlink->src->inputs[0]);
850
        if(ret<0)
851
            break;
852
    }
853
854
    av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame ret=%d\n", ret);
855
    return ret;
856
}
857
858
static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
859
{
860
}
861
862
static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
863
{
864
}
865
866
static void end_frame(AVFilterLink *inlink)
867
{
868
    MPContext *m = inlink->dst->priv;
869
    AVFilterBufferRef *inpic  = inlink->cur_buf;
870
    int i;
871
    double pts= MP_NOPTS_VALUE;
872
    mp_image_t* mpi = new_mp_image(inpic->video->w, inpic->video->h);
873
874
    if(inpic->pts != AV_NOPTS_VALUE)
875
        pts= inpic->pts / av_q2d(inlink->time_base);
876
877
    for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
878
    mp_image_setfmt(mpi,conversion_map[i].fmt);
879
880
    memcpy(mpi->planes, inpic->data,     FFMIN(sizeof(inpic->data)    , sizeof(mpi->planes)));
881
    memcpy(mpi->stride, inpic->linesize, FFMIN(sizeof(inpic->linesize), sizeof(mpi->stride)));
882
883
    //FIXME pass interleced & tff flags around
884
885
    // mpi->flags|=MP_IMGFLAG_ALLOCATED; ?
886
    mpi->flags |= MP_IMGFLAG_READABLE;
887
    if(!(inpic->perms & AV_PERM_WRITE))
888
        mpi->flags |= MP_IMGFLAG_PRESERVE;
889
    if(m->vf.put_image(&m->vf, mpi, pts) == 0){
890
        av_log(m->avfctx, AV_LOG_DEBUG, "put_image() says skip\n");
891
    }
892
    free_mp_image(mpi);
893
894
//    avfilter_unref_buffer(inpic);
895
}
896
897
AVFilter avfilter_vf_mp = {
898
    .name      = "mp",
899
    .description = NULL_IF_CONFIG_SMALL("libmpcodecs wrapper."),
900
    .init = init,
901
    .priv_size = sizeof(MPContext),
902
    .query_formats = query_formats,
903
904
    .inputs    = (AVFilterPad[]) {{ .name            = "default",
905
                                    .type            = AVMEDIA_TYPE_VIDEO,
906
                                    .start_frame     = start_frame,
907
                                    .draw_slice      = null_draw_slice,
908
                                    .end_frame       = end_frame,
909
                                    .config_props    = config_inprops,
910
                                    .min_perms       = AV_PERM_READ, },
911
                                  { .name = NULL}},
912
    .outputs   = (AVFilterPad[]) {{ .name            = "default",
913
                                    .type            = AVMEDIA_TYPE_VIDEO,
914
                                    .request_frame   = request_frame,
915
                                    .config_props    = config_outprops, },
916
                                  { .name = NULL}},
917
};