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