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