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