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