]> git.sesse.net Git - ffmpeg/blob - libavfilter/vf_mp.c
fate: disable vf_gradfun test
[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);
687     if (args[0] == '=')
688         args++;
689
690     for(i=0; ;i++){
691         if(!filters[i] || !strcmp(name, filters[i]->name))
692             break;
693     }
694
695     if(!filters[i]){
696         av_log(ctx, AV_LOG_ERROR, "Unknown filter %s\n", name);
697         return AVERROR(EINVAL);
698     }
699
700     av_log(ctx, AV_LOG_WARNING,
701            "'%s' is a wrapped MPlayer filter (libmpcodecs). This filter may be removed\n"
702            "once it has been ported to a native libavfilter.\n", name);
703
704     memset(&m->vf,0,sizeof(m->vf));
705     m->vf.info= filters[i];
706
707     m->vf.next        = &m->next_vf;
708     m->vf.put_image   = vf_next_put_image;
709     m->vf.config      = vf_next_config;
710     m->vf.query_format= vf_default_query_format;
711     m->vf.control     = vf_next_control;
712     m->vf.default_caps=VFCAP_ACCEPT_STRIDE;
713     m->vf.default_reqs=0;
714     if(m->vf.info->opts)
715         av_log(ctx, AV_LOG_ERROR, "opts / m_struct_set is unsupported\n");
716 #if 0
717     if(vf->info->opts) { // vf_vo get some special argument
718       const m_struct_t* st = vf->info->opts;
719       void* vf_priv = m_struct_alloc(st);
720       int n;
721       for(n = 0 ; args && args[2*n] ; n++)
722         m_struct_set(st,vf_priv,args[2*n],args[2*n+1]);
723       vf->priv = vf_priv;
724       args = NULL;
725     } else // Otherwise we should have the '_oldargs_'
726       if(args && !strcmp(args[0],"_oldargs_"))
727         args = (char**)args[1];
728       else
729         args = NULL;
730 #endif
731     if(m->vf.info->vf_open(&m->vf, args)<=0){
732         av_log(ctx, AV_LOG_ERROR, "vf_open() of %s with arg=%s failed\n", name, args);
733         return -1;
734     }
735
736     return 0;
737 }
738
739 static av_cold void uninit(AVFilterContext *ctx)
740 {
741     MPContext *m = ctx->priv;
742     vf_instance_t *vf = &m->vf;
743
744     while(vf){
745         vf_instance_t *next = vf->next;
746         if(vf->uninit)
747             vf->uninit(vf);
748         free_mp_image(vf->imgctx.static_images[0]);
749         free_mp_image(vf->imgctx.static_images[1]);
750         free_mp_image(vf->imgctx.temp_images[0]);
751         free_mp_image(vf->imgctx.export_images[0]);
752         vf = next;
753     }
754 }
755
756 static int query_formats(AVFilterContext *ctx)
757 {
758     AVFilterFormats *avfmts=NULL;
759     MPContext *m = ctx->priv;
760     enum AVPixelFormat lastpixfmt = AV_PIX_FMT_NONE;
761     int i;
762
763     for(i=0; conversion_map[i].fmt; i++){
764         av_log(ctx, AV_LOG_DEBUG, "query: %X\n", conversion_map[i].fmt);
765         if(m->vf.query_format(&m->vf, conversion_map[i].fmt)){
766             av_log(ctx, AV_LOG_DEBUG, "supported,adding\n");
767             if (conversion_map[i].pix_fmt != lastpixfmt) {
768                 ff_add_format(&avfmts, conversion_map[i].pix_fmt);
769                 lastpixfmt = conversion_map[i].pix_fmt;
770             }
771         }
772     }
773
774     if (!avfmts)
775         return -1;
776
777     //We assume all allowed input formats are also allowed output formats
778     ff_set_common_formats(ctx, avfmts);
779     return 0;
780 }
781
782 static int config_inprops(AVFilterLink *inlink)
783 {
784     MPContext *m = inlink->dst->priv;
785     int i;
786     for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
787
788     av_assert0(conversion_map[i].fmt && inlink->w && inlink->h);
789
790     m->vf.fmt.have_configured = 1;
791     m->vf.fmt.orig_height     = inlink->h;
792     m->vf.fmt.orig_width      = inlink->w;
793     m->vf.fmt.orig_fmt        = conversion_map[i].fmt;
794
795     if(m->vf.config(&m->vf, inlink->w, inlink->h, inlink->w, inlink->h, 0, conversion_map[i].fmt)<=0)
796         return -1;
797
798     return 0;
799 }
800
801 static int config_outprops(AVFilterLink *outlink)
802 {
803     MPContext *m = outlink->src->priv;
804
805     outlink->w = m->next_vf.w;
806     outlink->h = m->next_vf.h;
807
808     return 0;
809 }
810
811 static int request_frame(AVFilterLink *outlink)
812 {
813     MPContext *m = outlink->src->priv;
814     int ret;
815
816     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame\n");
817
818     for(m->frame_returned=0; !m->frame_returned;){
819         ret=ff_request_frame(outlink->src->inputs[0]);
820         if(ret<0)
821             break;
822     }
823
824     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame ret=%d\n", ret);
825     return ret;
826 }
827
828 static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
829 {
830     return 0;
831 }
832
833 static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
834 {
835     return 0;
836 }
837
838 static int end_frame(AVFilterLink *inlink)
839 {
840     MPContext *m = inlink->dst->priv;
841     AVFilterBufferRef *inpic  = inlink->cur_buf;
842     int i;
843     double pts= MP_NOPTS_VALUE;
844     mp_image_t* mpi = new_mp_image(inpic->video->w, inpic->video->h);
845
846     if(inpic->pts != AV_NOPTS_VALUE)
847         pts= inpic->pts / av_q2d(inlink->time_base);
848
849     for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
850     mp_image_setfmt(mpi,conversion_map[i].fmt);
851
852     memcpy(mpi->planes, inpic->data,     FFMIN(sizeof(inpic->data)    , sizeof(mpi->planes)));
853     memcpy(mpi->stride, inpic->linesize, FFMIN(sizeof(inpic->linesize), sizeof(mpi->stride)));
854
855     //FIXME pass interleced & tff flags around
856
857     // mpi->flags|=MP_IMGFLAG_ALLOCATED; ?
858     mpi->flags |= MP_IMGFLAG_READABLE;
859     if(!(inpic->perms & AV_PERM_WRITE))
860         mpi->flags |= MP_IMGFLAG_PRESERVE;
861     if(m->vf.put_image(&m->vf, mpi, pts) == 0){
862         av_log(m->avfctx, AV_LOG_DEBUG, "put_image() says skip\n");
863     }
864     free_mp_image(mpi);
865     return 0;
866 }
867
868 static const AVFilterPad mp_inputs[] = {
869     {
870         .name         = "default",
871         .type         = AVMEDIA_TYPE_VIDEO,
872         .start_frame  = start_frame,
873         .draw_slice   = null_draw_slice,
874         .end_frame    = end_frame,
875         .config_props = config_inprops,
876         .min_perms    = AV_PERM_READ,
877     },
878     { NULL }
879 };
880
881 static const AVFilterPad mp_outputs[] = {
882     {
883         .name          = "default",
884         .type          = AVMEDIA_TYPE_VIDEO,
885         .request_frame = request_frame,
886         .config_props  = config_outprops,
887     },
888     { NULL }
889 };
890
891 AVFilter avfilter_vf_mp = {
892     .name      = "mp",
893     .description = NULL_IF_CONFIG_SMALL("Apply a libmpcodecs filter to the input video."),
894     .init = init,
895     .uninit = uninit,
896     .priv_size = sizeof(MPContext),
897     .query_formats = query_formats,
898     .inputs        = mp_inputs,
899     .outputs       = mp_outputs,
900 };