lavfi: remove mp=fixpts filter.
[ffmpeg.git] / libavfilter / vf_mp.c
1 /*
2  * Copyright (c) 2011 Michael Niedermayer
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  * Parts of this file have been stolen from mplayer
21  */
22
23 /**
24  * @file
25  */
26
27 #include "avfilter.h"
28 #include "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_geq;
146 extern const vf_info_t vf_info_halfpack;
147 extern const vf_info_t vf_info_harddup;
148 extern const vf_info_t vf_info_il;
149 extern const vf_info_t vf_info_ilpack;
150 extern const vf_info_t vf_info_ivtc;
151 extern const vf_info_t vf_info_kerndeint;
152 extern const vf_info_t vf_info_lavc;
153 extern const vf_info_t vf_info_lavcdeint;
154 extern const vf_info_t vf_info_mcdeint;
155 extern const vf_info_t vf_info_noformat;
156 extern const vf_info_t vf_info_noise;
157 extern const vf_info_t vf_info_ow;
158 extern const vf_info_t vf_info_perspective;
159 extern const vf_info_t vf_info_phase;
160 extern const vf_info_t vf_info_pp7;
161 extern const vf_info_t vf_info_pp;
162 extern const vf_info_t vf_info_pullup;
163 extern const vf_info_t vf_info_qp;
164 extern const vf_info_t vf_info_sab;
165 extern const vf_info_t vf_info_scale;
166 extern const vf_info_t vf_info_softpulldown;
167 extern const vf_info_t vf_info_softskip;
168 extern const vf_info_t vf_info_spp;
169 extern const vf_info_t vf_info_stereo3d;
170 extern const vf_info_t vf_info_telecine;
171 extern const vf_info_t vf_info_test;
172 extern const vf_info_t vf_info_tfields;
173 extern const vf_info_t vf_info_tinterlace;
174 extern const vf_info_t vf_info_unsharp;
175 extern const vf_info_t vf_info_uspp;
176 extern const vf_info_t vf_info_vo;
177 extern const vf_info_t vf_info_yadif;
178 extern const vf_info_t vf_info_zrmjpeg;
179
180
181 static const vf_info_t* const filters[]={
182     &vf_info_denoise3d,
183     &vf_info_detc,
184     &vf_info_dint,
185     &vf_info_divtc,
186     &vf_info_down3dright,
187     &vf_info_dsize,
188     &vf_info_eq2,
189     &vf_info_eq,
190     &vf_info_fil,
191 //    &vf_info_filmdint, cmmx.h vd.h ‘opt_screen_size_x’
192     &vf_info_fspp,
193     &vf_info_geq,
194     &vf_info_harddup,
195     &vf_info_il,
196     &vf_info_ilpack,
197     &vf_info_ivtc,
198     &vf_info_kerndeint,
199     &vf_info_mcdeint,
200     &vf_info_noise,
201     &vf_info_ow,
202     &vf_info_perspective,
203     &vf_info_phase,
204     &vf_info_pp,
205     &vf_info_pp7,
206     &vf_info_pullup,
207     &vf_info_qp,
208     &vf_info_sab,
209     &vf_info_softpulldown,
210     &vf_info_softskip,
211     &vf_info_spp,
212     &vf_info_stereo3d,
213     &vf_info_telecine,
214     &vf_info_tinterlace,
215     &vf_info_unsharp,
216     &vf_info_uspp,
217
218     NULL
219 };
220
221 /*
222 Unsupported filters
223 1bpp
224 ass
225 bmovl
226 crop
227 dvbscale
228 flip
229 expand
230 format
231 halfpack
232 lavc
233 lavcdeint
234 noformat
235 pp
236 scale
237 tfields
238 vo
239 yadif
240 zrmjpeg
241 */
242
243 CpuCaps gCpuCaps; //FIXME initialize this so optims work
244
245
246 static void sws_getFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, SwsFilter **dstFilterParam)
247 {
248         static int firstTime=1;
249         *flags=0;
250
251 #if ARCH_X86
252         if(gCpuCaps.hasMMX)
253                 __asm__ volatile("emms\n\t"::: "memory"); //FIXME this should not be required but it IS (even for non-MMX versions)
254 #endif
255         if(firstTime)
256         {
257                 firstTime=0;
258                 *flags= SWS_PRINT_INFO;
259         }
260         else if( mp_msg_test(MSGT_VFILTER,MSGL_DBG2) ) *flags= SWS_PRINT_INFO;
261
262         switch(SWS_BILINEAR)
263         {
264                 case 0: *flags|= SWS_FAST_BILINEAR; break;
265                 case 1: *flags|= SWS_BILINEAR; break;
266                 case 2: *flags|= SWS_BICUBIC; break;
267                 case 3: *flags|= SWS_X; break;
268                 case 4: *flags|= SWS_POINT; break;
269                 case 5: *flags|= SWS_AREA; break;
270                 case 6: *flags|= SWS_BICUBLIN; break;
271                 case 7: *flags|= SWS_GAUSS; break;
272                 case 8: *flags|= SWS_SINC; break;
273                 case 9: *flags|= SWS_LANCZOS; break;
274                 case 10:*flags|= SWS_SPLINE; break;
275                 default:*flags|= SWS_BILINEAR; break;
276         }
277
278         *srcFilterParam= NULL;
279         *dstFilterParam= NULL;
280 }
281
282 //exact copy from vf_scale.c
283 // will use sws_flags & src_filter (from cmd line)
284 struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat)
285 {
286         int flags, i;
287         SwsFilter *dstFilterParam, *srcFilterParam;
288         enum AVPixelFormat dfmt, sfmt;
289
290         for(i=0; conversion_map[i].fmt && dstFormat != conversion_map[i].fmt; i++);
291         dfmt= conversion_map[i].pix_fmt;
292         for(i=0; conversion_map[i].fmt && srcFormat != conversion_map[i].fmt; i++);
293         sfmt= conversion_map[i].pix_fmt;
294
295         if (srcFormat == IMGFMT_RGB8 || srcFormat == IMGFMT_BGR8) sfmt = AV_PIX_FMT_PAL8;
296         sws_getFlagsAndFilterFromCmdLine(&flags, &srcFilterParam, &dstFilterParam);
297
298         return sws_getContext(srcW, srcH, sfmt, dstW, dstH, dfmt, flags , srcFilterParam, dstFilterParam, NULL);
299 }
300
301 typedef struct {
302     vf_instance_t vf;
303     vf_instance_t next_vf;
304     AVFilterContext *avfctx;
305     int frame_returned;
306 } MPContext;
307
308 void mp_msg(int mod, int lev, const char *format, ... ){
309     va_list va;
310     va_start(va, format);
311     //FIXME convert lev/mod
312     av_vlog(NULL, AV_LOG_DEBUG, format, va);
313     va_end(va);
314 }
315
316 int mp_msg_test(int mod, int lev){
317     return 123;
318 }
319
320 void init_avcodec(void)
321 {
322     //we maybe should init but its kinda 1. unneeded 2. a bit inpolite from here
323 }
324
325 //Exact copy of vf.c
326 void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src){
327     dst->pict_type= src->pict_type;
328     dst->fields = src->fields;
329     dst->qscale_type= src->qscale_type;
330     if(dst->width == src->width && dst->height == src->height){
331         dst->qstride= src->qstride;
332         dst->qscale= src->qscale;
333     }
334 }
335
336 //Exact copy of vf.c
337 void vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){
338     if (vf->next->draw_slice) {
339         vf->next->draw_slice(vf->next,src,stride,w,h,x,y);
340         return;
341     }
342     if (!vf->dmpi) {
343         mp_msg(MSGT_VFILTER,MSGL_ERR,"draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
344         return;
345     }
346     if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) {
347         memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+vf->dmpi->bpp/8*x,
348             src[0], vf->dmpi->bpp/8*w, h, vf->dmpi->stride[0], stride[0]);
349         return;
350     }
351     memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+x, src[0],
352         w, h, vf->dmpi->stride[0], stride[0]);
353     memcpy_pic(vf->dmpi->planes[1]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[1]+(x>>vf->dmpi->chroma_x_shift),
354         src[1], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]);
355     memcpy_pic(vf->dmpi->planes[2]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[2]+(x>>vf->dmpi->chroma_x_shift),
356         src[2], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]);
357 }
358
359 //Exact copy of vf.c
360 void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h){
361     int y;
362     if(mpi->flags&MP_IMGFLAG_PLANAR){
363         y0&=~1;h+=h&1;
364         if(x0==0 && w==mpi->width){
365             // full width clear:
366             memset(mpi->planes[0]+mpi->stride[0]*y0,0,mpi->stride[0]*h);
367             memset(mpi->planes[1]+mpi->stride[1]*(y0>>mpi->chroma_y_shift),128,mpi->stride[1]*(h>>mpi->chroma_y_shift));
368             memset(mpi->planes[2]+mpi->stride[2]*(y0>>mpi->chroma_y_shift),128,mpi->stride[2]*(h>>mpi->chroma_y_shift));
369         } else
370         for(y=y0;y<y0+h;y+=2){
371             memset(mpi->planes[0]+x0+mpi->stride[0]*y,0,w);
372             memset(mpi->planes[0]+x0+mpi->stride[0]*(y+1),0,w);
373             memset(mpi->planes[1]+(x0>>mpi->chroma_x_shift)+mpi->stride[1]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
374             memset(mpi->planes[2]+(x0>>mpi->chroma_x_shift)+mpi->stride[2]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
375         }
376         return;
377     }
378     // packed:
379     for(y=y0;y<y0+h;y++){
380         unsigned char* dst=mpi->planes[0]+mpi->stride[0]*y+(mpi->bpp>>3)*x0;
381         if(mpi->flags&MP_IMGFLAG_YUV){
382             unsigned int* p=(unsigned int*) dst;
383             int size=(mpi->bpp>>3)*w/4;
384             int i;
385 #if HAVE_BIGENDIAN
386 #define CLEAR_PACKEDYUV_PATTERN 0x00800080
387 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x80008000
388 #else
389 #define CLEAR_PACKEDYUV_PATTERN 0x80008000
390 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x00800080
391 #endif
392             if(mpi->flags&MP_IMGFLAG_SWAPPED){
393                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
394                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
395             } else {
396                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN;
397                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN;
398             }
399         } else
400             memset(dst,0,(mpi->bpp>>3)*w);
401     }
402 }
403
404 int vf_next_query_format(struct vf_instance *vf, unsigned int fmt){
405     return 1;
406 }
407
408 //used by delogo
409 unsigned int vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred){
410     return preferred;
411 }
412
413 mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h){
414     MPContext *m= (MPContext*)(((uint8_t*)vf) - offsetof(MPContext, next_vf));
415   mp_image_t* mpi=NULL;
416   int w2;
417   int number = mp_imgtype >> 16;
418
419   av_assert0(vf->next == NULL); // all existing filters call this just on next
420
421   //vf_dint needs these as it calls vf_get_image() before configuring the output
422   if(vf->w==0 && w>0) vf->w=w;
423   if(vf->h==0 && h>0) vf->h=h;
424
425   av_assert0(w == -1 || w >= vf->w);
426   av_assert0(h == -1 || h >= vf->h);
427   av_assert0(vf->w > 0);
428   av_assert0(vf->h > 0);
429
430   av_log(m->avfctx, AV_LOG_DEBUG, "get_image: %d:%d, vf: %d:%d\n", w,h,vf->w,vf->h);
431
432   if (w == -1) w = vf->w;
433   if (h == -1) h = vf->h;
434
435   w2=(mp_imgflag&MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE)?((w+15)&(~15)):w;
436
437   // Note: we should call libvo first to check if it supports direct rendering
438   // and if not, then fallback to software buffers:
439   switch(mp_imgtype & 0xff){
440   case MP_IMGTYPE_EXPORT:
441     if(!vf->imgctx.export_images[0]) vf->imgctx.export_images[0]=new_mp_image(w2,h);
442     mpi=vf->imgctx.export_images[0];
443     break;
444   case MP_IMGTYPE_STATIC:
445     if(!vf->imgctx.static_images[0]) vf->imgctx.static_images[0]=new_mp_image(w2,h);
446     mpi=vf->imgctx.static_images[0];
447     break;
448   case MP_IMGTYPE_TEMP:
449     if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
450     mpi=vf->imgctx.temp_images[0];
451     break;
452   case MP_IMGTYPE_IPB:
453     if(!(mp_imgflag&MP_IMGFLAG_READABLE)){ // B frame:
454       if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
455       mpi=vf->imgctx.temp_images[0];
456       break;
457     }
458   case MP_IMGTYPE_IP:
459     if(!vf->imgctx.static_images[vf->imgctx.static_idx]) vf->imgctx.static_images[vf->imgctx.static_idx]=new_mp_image(w2,h);
460     mpi=vf->imgctx.static_images[vf->imgctx.static_idx];
461     vf->imgctx.static_idx^=1;
462     break;
463   case MP_IMGTYPE_NUMBERED:
464     if (number == -1) {
465       int i;
466       for (i = 0; i < NUM_NUMBERED_MPI; i++)
467         if (!vf->imgctx.numbered_images[i] || !vf->imgctx.numbered_images[i]->usage_count)
468           break;
469       number = i;
470     }
471     if (number < 0 || number >= NUM_NUMBERED_MPI) return NULL;
472     if (!vf->imgctx.numbered_images[number]) vf->imgctx.numbered_images[number] = new_mp_image(w2,h);
473     mpi = vf->imgctx.numbered_images[number];
474     mpi->number = number;
475     break;
476   }
477   if(mpi){
478     mpi->type=mp_imgtype;
479     mpi->w=vf->w; mpi->h=vf->h;
480     // keep buffer allocation status & color flags only:
481 //    mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE|MP_IMGFLAG_DIRECT);
482     mpi->flags&=MP_IMGFLAG_ALLOCATED|MP_IMGFLAG_TYPE_DISPLAYED|MP_IMGFLAGMASK_COLORS;
483     // accept restrictions, draw_slice and palette flags only:
484     mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK|MP_IMGFLAG_RGB_PALETTE);
485     if(!vf->draw_slice) mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK;
486     if(mpi->width!=w2 || mpi->height!=h){
487 //      printf("vf.c: MPI parameters changed!  %dx%d -> %dx%d   \n", mpi->width,mpi->height,w2,h);
488         if(mpi->flags&MP_IMGFLAG_ALLOCATED){
489             if(mpi->width<w2 || mpi->height<h){
490                 // need to re-allocate buffer memory:
491                 av_free(mpi->planes[0]);
492                 mpi->flags&=~MP_IMGFLAG_ALLOCATED;
493                 mp_msg(MSGT_VFILTER,MSGL_V,"vf.c: have to REALLOCATE buffer memory :(\n");
494             }
495 //      } else {
496         } {
497             mpi->width=w2; mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
498             mpi->height=h; mpi->chroma_height=(h + (1<<mpi->chroma_y_shift) - 1)>>mpi->chroma_y_shift;
499         }
500     }
501     if(!mpi->bpp) mp_image_setfmt(mpi,outfmt);
502     if(!(mpi->flags&MP_IMGFLAG_ALLOCATED) && mpi->type>MP_IMGTYPE_EXPORT){
503
504         av_assert0(!vf->get_image);
505         // check libvo first!
506         if(vf->get_image) vf->get_image(vf,mpi);
507
508         if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
509           // non-direct and not yet allocated image. allocate it!
510           if (!mpi->bpp) { // no way we can allocate this
511               mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
512                      "vf_get_image: Tried to allocate a format that can not be allocated!\n");
513               return NULL;
514           }
515
516           // check if codec prefer aligned stride:
517           if(mp_imgflag&MP_IMGFLAG_PREFER_ALIGNED_STRIDE){
518               int align=(mpi->flags&MP_IMGFLAG_PLANAR &&
519                          mpi->flags&MP_IMGFLAG_YUV) ?
520                          (8<<mpi->chroma_x_shift)-1 : 15; // -- maybe FIXME
521               w2=((w+align)&(~align));
522               if(mpi->width!=w2){
523 #if 0
524                   // we have to change width... check if we CAN co it:
525                   int flags=vf->query_format(vf,outfmt); // should not fail
526                   if(!(flags&3)) mp_msg(MSGT_DECVIDEO,MSGL_WARN,"??? vf_get_image{vf->query_format(outfmt)} failed!\n");
527 //                printf("query -> 0x%X    \n",flags);
528                   if(flags&VFCAP_ACCEPT_STRIDE){
529 #endif
530                       mpi->width=w2;
531                       mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
532 //                  }
533               }
534           }
535
536           mp_image_alloc_planes(mpi);
537 //        printf("clearing img!\n");
538           vf_mpi_clear(mpi,0,0,mpi->width,mpi->height);
539         }
540     }
541     av_assert0(!vf->start_slice);
542     if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)
543         if(vf->start_slice) vf->start_slice(vf,mpi);
544     if(!(mpi->flags&MP_IMGFLAG_TYPE_DISPLAYED)){
545             mp_msg(MSGT_DECVIDEO,MSGL_V,"*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
546                   "NULL"/*vf->info->name*/,
547                   (mpi->type==MP_IMGTYPE_EXPORT)?"Exporting":
548                   ((mpi->flags&MP_IMGFLAG_DIRECT)?"Direct Rendering":"Allocating"),
549                   (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)?" (slices)":"",
550                   mpi->width,mpi->height,mpi->bpp,
551                   (mpi->flags&MP_IMGFLAG_YUV)?"YUV":((mpi->flags&MP_IMGFLAG_SWAPPED)?"BGR":"RGB"),
552                   (mpi->flags&MP_IMGFLAG_PLANAR)?"planar":"packed",
553                   mpi->bpp*mpi->width*mpi->height/8);
554             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",
555                 mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
556                 mpi->stride[0], mpi->stride[1], mpi->stride[2],
557                 mpi->chroma_width, mpi->chroma_height, mpi->chroma_x_shift, mpi->chroma_y_shift);
558             mpi->flags|=MP_IMGFLAG_TYPE_DISPLAYED;
559     }
560
561   mpi->qscale = NULL;
562   mpi->usage_count++;
563   }
564 //    printf("\rVF_MPI: %p %p %p %d %d %d    \n",
565 //      mpi->planes[0],mpi->planes[1],mpi->planes[2],
566 //      mpi->stride[0],mpi->stride[1],mpi->stride[2]);
567   return mpi;
568 }
569
570
571 int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){
572     MPContext *m= (void*)vf;
573     AVFilterLink *outlink     = m->avfctx->outputs[0];
574     AVFilterBuffer    *pic    = av_mallocz(sizeof(AVFilterBuffer));
575     AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef));
576     int i;
577
578     av_assert0(vf->next);
579
580     av_log(m->avfctx, AV_LOG_DEBUG, "vf_next_put_image\n");
581
582     if (!pic || !picref)
583         goto fail;
584
585     picref->buf = pic;
586     picref->buf->please_use_av_free= (void*)av_free;
587     if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps))))
588         goto fail;
589
590     pic->w = picref->video->w = mpi->w;
591     pic->h = picref->video->h = mpi->h;
592
593     /* make sure the buffer gets read permission or it's useless for output */
594     picref->perms = AV_PERM_READ | AV_PERM_REUSE2;
595 //    av_assert0(mpi->flags&MP_IMGFLAG_READABLE);
596     if(!(mpi->flags&MP_IMGFLAG_PRESERVE))
597         picref->perms |= AV_PERM_WRITE;
598
599     pic->refcount = 1;
600     picref->type = AVMEDIA_TYPE_VIDEO;
601
602     for(i=0; conversion_map[i].fmt && mpi->imgfmt != conversion_map[i].fmt; i++);
603     pic->format = picref->format = conversion_map[i].pix_fmt;
604
605     memcpy(pic->data,        mpi->planes,   FFMIN(sizeof(pic->data)    , sizeof(mpi->planes)));
606     memcpy(pic->linesize,    mpi->stride,   FFMIN(sizeof(pic->linesize), sizeof(mpi->stride)));
607     memcpy(picref->data,     pic->data,     sizeof(picref->data));
608     memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
609
610     if(pts != MP_NOPTS_VALUE)
611         picref->pts= pts * av_q2d(outlink->time_base);
612
613     ff_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
614     ff_draw_slice(outlink, 0, picref->video->h, 1);
615     ff_end_frame(outlink);
616     avfilter_unref_buffer(picref);
617     m->frame_returned++;
618
619     return 1;
620 fail:
621     if (picref && picref->video)
622         av_free(picref->video);
623     av_free(picref);
624     av_free(pic);
625     return 0;
626 }
627
628 int vf_next_config(struct vf_instance *vf,
629         int width, int height, int d_width, int d_height,
630         unsigned int voflags, unsigned int outfmt){
631
632     av_assert0(width>0 && height>0);
633     vf->next->w = width; vf->next->h = height;
634
635     return 1;
636 #if 0
637     int flags=vf->next->query_format(vf->next,outfmt);
638     if(!flags){
639         // hmm. colorspace mismatch!!!
640         //this is fatal for us ATM
641         return 0;
642     }
643     mp_msg(MSGT_VFILTER,MSGL_V,"REQ: flags=0x%X  req=0x%X  \n",flags,vf->default_reqs);
644     miss=vf->default_reqs - (flags&vf->default_reqs);
645     if(miss&VFCAP_ACCEPT_STRIDE){
646         // vf requires stride support but vf->next doesn't support it!
647         // let's insert the 'expand' filter, it does the job for us:
648         vf_instance_t* vf2=vf_open_filter(vf->next,"expand",NULL);
649         if(!vf2) return 0; // shouldn't happen!
650         vf->next=vf2;
651     }
652     vf->next->w = width; vf->next->h = height;
653     return 1;
654 #endif
655 }
656
657 int vf_next_control(struct vf_instance *vf, int request, void* data){
658     MPContext *m= (void*)vf;
659     av_log(m->avfctx, AV_LOG_DEBUG, "Received control %d\n", request);
660     return 0;
661 }
662
663 static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt){
664     MPContext *m= (void*)vf;
665     int i;
666     av_log(m->avfctx, AV_LOG_DEBUG, "query %X\n", fmt);
667
668     for(i=0; conversion_map[i].fmt; i++){
669         if(fmt==conversion_map[i].fmt)
670             return 1; //we suport all
671     }
672     return 0;
673 }
674
675
676 static av_cold int init(AVFilterContext *ctx, const char *args)
677 {
678     MPContext *m = ctx->priv;
679     char name[256];
680     int i;
681
682     m->avfctx= ctx;
683
684     if(!args || 1!=sscanf(args, "%255[^:=]", name)){
685         av_log(ctx, AV_LOG_ERROR, "Invalid parameter.\n");
686         return AVERROR(EINVAL);
687     }
688     args+= strlen(name)+1;
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 AVFilter avfilter_vf_mp = {
869     .name      = "mp",
870     .description = NULL_IF_CONFIG_SMALL("Apply a libmpcodecs filter to the input video."),
871     .init = init,
872     .uninit = uninit,
873     .priv_size = sizeof(MPContext),
874     .query_formats = query_formats,
875
876     .inputs    = (const AVFilterPad[]) {{ .name      = "default",
877                                     .type            = AVMEDIA_TYPE_VIDEO,
878                                     .start_frame     = start_frame,
879                                     .draw_slice      = null_draw_slice,
880                                     .end_frame       = end_frame,
881                                     .config_props    = config_inprops,
882                                     .min_perms       = AV_PERM_READ, },
883                                   { .name = NULL}},
884     .outputs   = (const AVFilterPad[]) {{ .name      = "default",
885                                     .type            = AVMEDIA_TYPE_VIDEO,
886                                     .request_frame   = request_frame,
887                                     .config_props    = config_outprops, },
888                                   { .name = NULL}},
889 };