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