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