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