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