]> 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_1bpp;
124 extern const vf_info_t vf_info_ass;
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_decimate;
128 extern const vf_info_t vf_info_denoise3d;
129 extern const vf_info_t vf_info_detc;
130 extern const vf_info_t vf_info_dint;
131 extern const vf_info_t vf_info_divtc;
132 extern const vf_info_t vf_info_down3dright;
133 extern const vf_info_t vf_info_dsize;
134 extern const vf_info_t vf_info_dvbscale;
135 extern const vf_info_t vf_info_eq2;
136 extern const vf_info_t vf_info_eq;
137 extern const vf_info_t vf_info_expand;
138 extern const vf_info_t vf_info_field;
139 extern const vf_info_t vf_info_fil;
140 extern const vf_info_t vf_info_filmdint;
141 extern const vf_info_t vf_info_fixpts;
142 extern const vf_info_t vf_info_flip;
143 extern const vf_info_t vf_info_format;
144 extern const vf_info_t vf_info_framestep;
145 extern const vf_info_t vf_info_fspp;
146 extern const vf_info_t vf_info_geq;
147 extern const vf_info_t vf_info_halfpack;
148 extern const vf_info_t vf_info_harddup;
149 extern const vf_info_t vf_info_hqdn3d;
150 extern const vf_info_t vf_info_hue;
151 extern const vf_info_t vf_info_il;
152 extern const vf_info_t vf_info_ilpack;
153 extern const vf_info_t vf_info_ivtc;
154 extern const vf_info_t vf_info_kerndeint;
155 extern const vf_info_t vf_info_lavc;
156 extern const vf_info_t vf_info_lavcdeint;
157 extern const vf_info_t vf_info_mcdeint;
158 extern const vf_info_t vf_info_noformat;
159 extern const vf_info_t vf_info_noise;
160 extern const vf_info_t vf_info_ow;
161 extern const vf_info_t vf_info_palette;
162 extern const vf_info_t vf_info_perspective;
163 extern const vf_info_t vf_info_phase;
164 extern const vf_info_t vf_info_pp7;
165 extern const vf_info_t vf_info_pp;
166 extern const vf_info_t vf_info_pullup;
167 extern const vf_info_t vf_info_qp;
168 extern const vf_info_t vf_info_rectangle;
169 extern const vf_info_t vf_info_rotate;
170 extern const vf_info_t vf_info_sab;
171 extern const vf_info_t vf_info_scale;
172 extern const vf_info_t vf_info_smartblur;
173 extern const vf_info_t vf_info_softpulldown;
174 extern const vf_info_t vf_info_softskip;
175 extern const vf_info_t vf_info_spp;
176 extern const vf_info_t vf_info_stereo3d;
177 extern const vf_info_t vf_info_telecine;
178 extern const vf_info_t vf_info_test;
179 extern const vf_info_t vf_info_tfields;
180 extern const vf_info_t vf_info_tile;
181 extern const vf_info_t vf_info_tinterlace;
182 extern const vf_info_t vf_info_unsharp;
183 extern const vf_info_t vf_info_uspp;
184 extern const vf_info_t vf_info_vo;
185 extern const vf_info_t vf_info_yadif;
186 extern const vf_info_t vf_info_yuvcsp;
187 extern const vf_info_t vf_info_yvu9;
188 extern const vf_info_t vf_info_zrmjpeg;
189
190
191 static const vf_info_t* const filters[]={
192     &vf_info_decimate,
193     &vf_info_denoise3d,
194     &vf_info_detc,
195     &vf_info_dint,
196     &vf_info_divtc,
197     &vf_info_down3dright,
198     &vf_info_dsize,
199     &vf_info_eq2,
200     &vf_info_eq,
201     &vf_info_field,
202     &vf_info_fil,
203 //    &vf_info_filmdint, cmmx.h vd.h ‘opt_screen_size_x’
204     &vf_info_fixpts,
205     &vf_info_framestep,
206     &vf_info_fspp,
207     &vf_info_geq,
208     &vf_info_harddup,
209     &vf_info_hqdn3d,
210     &vf_info_hue,
211     &vf_info_il,
212     &vf_info_ilpack,
213     &vf_info_ivtc,
214     &vf_info_kerndeint,
215     &vf_info_mcdeint,
216     &vf_info_noise,
217     &vf_info_ow,
218     &vf_info_palette,
219     &vf_info_perspective,
220     &vf_info_phase,
221     &vf_info_pp,
222     &vf_info_pp7,
223     &vf_info_pullup,
224     &vf_info_qp,
225     &vf_info_rectangle,
226     &vf_info_rotate,
227     &vf_info_sab,
228     &vf_info_smartblur,
229     &vf_info_softpulldown,
230     &vf_info_softskip,
231     &vf_info_spp,
232     &vf_info_stereo3d,
233     &vf_info_telecine,
234     &vf_info_tile,
235     &vf_info_tinterlace,
236     &vf_info_unsharp,
237     &vf_info_uspp,
238     &vf_info_yuvcsp,
239     &vf_info_yvu9,
240
241     NULL
242 };
243
244 /*
245 Unsupported filters
246 1bpp
247 ass
248 bmovl
249 crop
250 dvbscale
251 flip
252 expand
253 format
254 halfpack
255 lavc
256 lavcdeint
257 noformat
258 pp
259 scale
260 tfields
261 vo
262 yadif
263 zrmjpeg
264 */
265
266 CpuCaps gCpuCaps; //FIXME initialize this so optims work
267
268
269 static void sws_getFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, SwsFilter **dstFilterParam)
270 {
271         static int firstTime=1;
272         *flags=0;
273
274 #if ARCH_X86
275         if(gCpuCaps.hasMMX)
276                 __asm__ volatile("emms\n\t"::: "memory"); //FIXME this should not be required but it IS (even for non-MMX versions)
277 #endif
278         if(firstTime)
279         {
280                 firstTime=0;
281                 *flags= SWS_PRINT_INFO;
282         }
283         else if( mp_msg_test(MSGT_VFILTER,MSGL_DBG2) ) *flags= SWS_PRINT_INFO;
284
285         switch(SWS_BILINEAR)
286         {
287                 case 0: *flags|= SWS_FAST_BILINEAR; break;
288                 case 1: *flags|= SWS_BILINEAR; break;
289                 case 2: *flags|= SWS_BICUBIC; break;
290                 case 3: *flags|= SWS_X; break;
291                 case 4: *flags|= SWS_POINT; break;
292                 case 5: *flags|= SWS_AREA; break;
293                 case 6: *flags|= SWS_BICUBLIN; break;
294                 case 7: *flags|= SWS_GAUSS; break;
295                 case 8: *flags|= SWS_SINC; break;
296                 case 9: *flags|= SWS_LANCZOS; break;
297                 case 10:*flags|= SWS_SPLINE; break;
298                 default:*flags|= SWS_BILINEAR; break;
299         }
300
301         *srcFilterParam= NULL;
302         *dstFilterParam= NULL;
303 }
304
305 //exact copy from vf_scale.c
306 // will use sws_flags & src_filter (from cmd line)
307 struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat)
308 {
309         int flags, i;
310         SwsFilter *dstFilterParam, *srcFilterParam;
311         enum PixelFormat dfmt, sfmt;
312
313         for(i=0; conversion_map[i].fmt && dstFormat != conversion_map[i].fmt; i++);
314         dfmt= conversion_map[i].pix_fmt;
315         for(i=0; conversion_map[i].fmt && srcFormat != conversion_map[i].fmt; i++);
316         sfmt= conversion_map[i].pix_fmt;
317
318         if (srcFormat == IMGFMT_RGB8 || srcFormat == IMGFMT_BGR8) sfmt = PIX_FMT_PAL8;
319         sws_getFlagsAndFilterFromCmdLine(&flags, &srcFilterParam, &dstFilterParam);
320
321         return sws_getContext(srcW, srcH, sfmt, dstW, dstH, dfmt, flags , srcFilterParam, dstFilterParam, NULL);
322 }
323
324 typedef struct {
325     vf_instance_t vf;
326     vf_instance_t next_vf;
327     AVFilterContext *avfctx;
328     int frame_returned;
329 } MPContext;
330
331 void mp_msg(int mod, int lev, const char *format, ... ){
332     va_list va;
333     va_start(va, format);
334     //FIXME convert lev/mod
335     av_vlog(NULL, AV_LOG_DEBUG, format, va);
336     va_end(va);
337 }
338
339 int mp_msg_test(int mod, int lev){
340     return 123;
341 }
342
343 void init_avcodec(void)
344 {
345     //we maybe should init but its kinda 1. unneeded 2. a bit inpolite from here
346 }
347
348 //Exact copy of vf.c
349 void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src){
350     dst->pict_type= src->pict_type;
351     dst->fields = src->fields;
352     dst->qscale_type= src->qscale_type;
353     if(dst->width == src->width && dst->height == src->height){
354         dst->qstride= src->qstride;
355         dst->qscale= src->qscale;
356     }
357 }
358
359 //Exact copy of vf.c
360 void vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){
361     if (vf->next->draw_slice) {
362         vf->next->draw_slice(vf->next,src,stride,w,h,x,y);
363         return;
364     }
365     if (!vf->dmpi) {
366         mp_msg(MSGT_VFILTER,MSGL_ERR,"draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
367         return;
368     }
369     if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) {
370         memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+vf->dmpi->bpp/8*x,
371             src[0], vf->dmpi->bpp/8*w, h, vf->dmpi->stride[0], stride[0]);
372         return;
373     }
374     memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+x, src[0],
375         w, h, vf->dmpi->stride[0], stride[0]);
376     memcpy_pic(vf->dmpi->planes[1]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[1]+(x>>vf->dmpi->chroma_x_shift),
377         src[1], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]);
378     memcpy_pic(vf->dmpi->planes[2]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[2]+(x>>vf->dmpi->chroma_x_shift),
379         src[2], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]);
380 }
381
382 //Exact copy of vf.c
383 void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h){
384     int y;
385     if(mpi->flags&MP_IMGFLAG_PLANAR){
386         y0&=~1;h+=h&1;
387         if(x0==0 && w==mpi->width){
388             // full width clear:
389             memset(mpi->planes[0]+mpi->stride[0]*y0,0,mpi->stride[0]*h);
390             memset(mpi->planes[1]+mpi->stride[1]*(y0>>mpi->chroma_y_shift),128,mpi->stride[1]*(h>>mpi->chroma_y_shift));
391             memset(mpi->planes[2]+mpi->stride[2]*(y0>>mpi->chroma_y_shift),128,mpi->stride[2]*(h>>mpi->chroma_y_shift));
392         } else
393         for(y=y0;y<y0+h;y+=2){
394             memset(mpi->planes[0]+x0+mpi->stride[0]*y,0,w);
395             memset(mpi->planes[0]+x0+mpi->stride[0]*(y+1),0,w);
396             memset(mpi->planes[1]+(x0>>mpi->chroma_x_shift)+mpi->stride[1]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
397             memset(mpi->planes[2]+(x0>>mpi->chroma_x_shift)+mpi->stride[2]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
398         }
399         return;
400     }
401     // packed:
402     for(y=y0;y<y0+h;y++){
403         unsigned char* dst=mpi->planes[0]+mpi->stride[0]*y+(mpi->bpp>>3)*x0;
404         if(mpi->flags&MP_IMGFLAG_YUV){
405             unsigned int* p=(unsigned int*) dst;
406             int size=(mpi->bpp>>3)*w/4;
407             int i;
408 #if HAVE_BIGENDIAN
409 #define CLEAR_PACKEDYUV_PATTERN 0x00800080
410 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x80008000
411 #else
412 #define CLEAR_PACKEDYUV_PATTERN 0x80008000
413 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x00800080
414 #endif
415             if(mpi->flags&MP_IMGFLAG_SWAPPED){
416                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
417                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
418             } else {
419                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN;
420                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN;
421             }
422         } else
423             memset(dst,0,(mpi->bpp>>3)*w);
424     }
425 }
426
427 int vf_next_query_format(struct vf_instance *vf, unsigned int fmt){
428     return 1;
429 }
430
431 //used by delogo
432 unsigned int vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred){
433     return preferred;
434 }
435
436 mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h){
437     MPContext *m= (MPContext*)(((uint8_t*)vf) - offsetof(MPContext, next_vf));
438   mp_image_t* mpi=NULL;
439   int w2;
440   int number = mp_imgtype >> 16;
441
442   av_assert0(vf->next == NULL); // all existing filters call this just on next
443
444   //vf_dint needs these as it calls vf_get_image() before configuring the output
445   if(vf->w==0 && w>0) vf->w=w;
446   if(vf->h==0 && h>0) vf->h=h;
447
448   av_assert0(w == -1 || w >= vf->w);
449   av_assert0(h == -1 || h >= vf->h);
450   av_assert0(vf->w > 0);
451   av_assert0(vf->h > 0);
452
453   av_log(m->avfctx, AV_LOG_DEBUG, "get_image: %d:%d, vf: %d:%d\n", w,h,vf->w,vf->h);
454
455   if (w == -1) w = vf->w;
456   if (h == -1) h = vf->h;
457
458   w2=(mp_imgflag&MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE)?((w+15)&(~15)):w;
459
460   // Note: we should call libvo first to check if it supports direct rendering
461   // and if not, then fallback to software buffers:
462   switch(mp_imgtype & 0xff){
463   case MP_IMGTYPE_EXPORT:
464     if(!vf->imgctx.export_images[0]) vf->imgctx.export_images[0]=new_mp_image(w2,h);
465     mpi=vf->imgctx.export_images[0];
466     break;
467   case MP_IMGTYPE_STATIC:
468     if(!vf->imgctx.static_images[0]) vf->imgctx.static_images[0]=new_mp_image(w2,h);
469     mpi=vf->imgctx.static_images[0];
470     break;
471   case MP_IMGTYPE_TEMP:
472     if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
473     mpi=vf->imgctx.temp_images[0];
474     break;
475   case MP_IMGTYPE_IPB:
476     if(!(mp_imgflag&MP_IMGFLAG_READABLE)){ // B frame:
477       if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
478       mpi=vf->imgctx.temp_images[0];
479       break;
480     }
481   case MP_IMGTYPE_IP:
482     if(!vf->imgctx.static_images[vf->imgctx.static_idx]) vf->imgctx.static_images[vf->imgctx.static_idx]=new_mp_image(w2,h);
483     mpi=vf->imgctx.static_images[vf->imgctx.static_idx];
484     vf->imgctx.static_idx^=1;
485     break;
486   case MP_IMGTYPE_NUMBERED:
487     if (number == -1) {
488       int i;
489       for (i = 0; i < NUM_NUMBERED_MPI; i++)
490         if (!vf->imgctx.numbered_images[i] || !vf->imgctx.numbered_images[i]->usage_count)
491           break;
492       number = i;
493     }
494     if (number < 0 || number >= NUM_NUMBERED_MPI) return NULL;
495     if (!vf->imgctx.numbered_images[number]) vf->imgctx.numbered_images[number] = new_mp_image(w2,h);
496     mpi = vf->imgctx.numbered_images[number];
497     mpi->number = number;
498     break;
499   }
500   if(mpi){
501     mpi->type=mp_imgtype;
502     mpi->w=vf->w; mpi->h=vf->h;
503     // keep buffer allocation status & color flags only:
504 //    mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE|MP_IMGFLAG_DIRECT);
505     mpi->flags&=MP_IMGFLAG_ALLOCATED|MP_IMGFLAG_TYPE_DISPLAYED|MP_IMGFLAGMASK_COLORS;
506     // accept restrictions, draw_slice and palette flags only:
507     mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK|MP_IMGFLAG_RGB_PALETTE);
508     if(!vf->draw_slice) mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK;
509     if(mpi->width!=w2 || mpi->height!=h){
510 //      printf("vf.c: MPI parameters changed!  %dx%d -> %dx%d   \n", mpi->width,mpi->height,w2,h);
511         if(mpi->flags&MP_IMGFLAG_ALLOCATED){
512             if(mpi->width<w2 || mpi->height<h){
513                 // need to re-allocate buffer memory:
514                 av_free(mpi->planes[0]);
515                 mpi->flags&=~MP_IMGFLAG_ALLOCATED;
516                 mp_msg(MSGT_VFILTER,MSGL_V,"vf.c: have to REALLOCATE buffer memory :(\n");
517             }
518 //      } else {
519         } {
520             mpi->width=w2; mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
521             mpi->height=h; mpi->chroma_height=(h + (1<<mpi->chroma_y_shift) - 1)>>mpi->chroma_y_shift;
522         }
523     }
524     if(!mpi->bpp) mp_image_setfmt(mpi,outfmt);
525     if(!(mpi->flags&MP_IMGFLAG_ALLOCATED) && mpi->type>MP_IMGTYPE_EXPORT){
526
527         av_assert0(!vf->get_image);
528         // check libvo first!
529         if(vf->get_image) vf->get_image(vf,mpi);
530
531         if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
532           // non-direct and not yet allocated image. allocate it!
533           if (!mpi->bpp) { // no way we can allocate this
534               mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
535                      "vf_get_image: Tried to allocate a format that can not be allocated!\n");
536               return NULL;
537           }
538
539           // check if codec prefer aligned stride:
540           if(mp_imgflag&MP_IMGFLAG_PREFER_ALIGNED_STRIDE){
541               int align=(mpi->flags&MP_IMGFLAG_PLANAR &&
542                          mpi->flags&MP_IMGFLAG_YUV) ?
543                          (8<<mpi->chroma_x_shift)-1 : 15; // -- maybe FIXME
544               w2=((w+align)&(~align));
545               if(mpi->width!=w2){
546 #if 0
547                   // we have to change width... check if we CAN co it:
548                   int flags=vf->query_format(vf,outfmt); // should not fail
549                   if(!(flags&3)) mp_msg(MSGT_DECVIDEO,MSGL_WARN,"??? vf_get_image{vf->query_format(outfmt)} failed!\n");
550 //                printf("query -> 0x%X    \n",flags);
551                   if(flags&VFCAP_ACCEPT_STRIDE){
552 #endif
553                       mpi->width=w2;
554                       mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
555 //                  }
556               }
557           }
558
559           mp_image_alloc_planes(mpi);
560 //        printf("clearing img!\n");
561           vf_mpi_clear(mpi,0,0,mpi->width,mpi->height);
562         }
563     }
564     av_assert0(!vf->start_slice);
565     if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)
566         if(vf->start_slice) vf->start_slice(vf,mpi);
567     if(!(mpi->flags&MP_IMGFLAG_TYPE_DISPLAYED)){
568             mp_msg(MSGT_DECVIDEO,MSGL_V,"*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
569                   "NULL"/*vf->info->name*/,
570                   (mpi->type==MP_IMGTYPE_EXPORT)?"Exporting":
571                   ((mpi->flags&MP_IMGFLAG_DIRECT)?"Direct Rendering":"Allocating"),
572                   (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)?" (slices)":"",
573                   mpi->width,mpi->height,mpi->bpp,
574                   (mpi->flags&MP_IMGFLAG_YUV)?"YUV":((mpi->flags&MP_IMGFLAG_SWAPPED)?"BGR":"RGB"),
575                   (mpi->flags&MP_IMGFLAG_PLANAR)?"planar":"packed",
576                   mpi->bpp*mpi->width*mpi->height/8);
577             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",
578                 mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
579                 mpi->stride[0], mpi->stride[1], mpi->stride[2],
580                 mpi->chroma_width, mpi->chroma_height, mpi->chroma_x_shift, mpi->chroma_y_shift);
581             mpi->flags|=MP_IMGFLAG_TYPE_DISPLAYED;
582     }
583
584   mpi->qscale = NULL;
585   }
586   mpi->usage_count++;
587 //    printf("\rVF_MPI: %p %p %p %d %d %d    \n",
588 //      mpi->planes[0],mpi->planes[1],mpi->planes[2],
589 //      mpi->stride[0],mpi->stride[1],mpi->stride[2]);
590   return mpi;
591 }
592
593
594 int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){
595     MPContext *m= (void*)vf;
596     AVFilterLink *outlink     = m->avfctx->outputs[0];
597     AVFilterBuffer    *pic    = av_mallocz(sizeof(AVFilterBuffer));
598     AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef));
599     int i;
600
601     av_assert0(vf->next);
602
603     av_log(m->avfctx, AV_LOG_DEBUG, "vf_next_put_image\n");
604
605     if (!pic || !picref)
606         goto fail;
607
608     picref->buf = pic;
609     picref->buf->please_use_av_free= (void*)av_free;
610     if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps))))
611         goto fail;
612
613     pic->w = picref->video->w = mpi->w;
614     pic->h = picref->video->h = mpi->h;
615
616     /* make sure the buffer gets read permission or it's useless for output */
617     picref->perms = AV_PERM_READ | AV_PERM_REUSE2;
618 //    av_assert0(mpi->flags&MP_IMGFLAG_READABLE);
619     if(!(mpi->flags&MP_IMGFLAG_PRESERVE))
620         picref->perms |= AV_PERM_WRITE;
621
622     pic->refcount = 1;
623     picref->type = AVMEDIA_TYPE_VIDEO;
624
625     for(i=0; conversion_map[i].fmt && mpi->imgfmt != conversion_map[i].fmt; i++);
626     pic->format = picref->format = conversion_map[i].pix_fmt;
627
628     memcpy(pic->data,        mpi->planes,   FFMIN(sizeof(pic->data)    , sizeof(mpi->planes)));
629     memcpy(pic->linesize,    mpi->stride,   FFMIN(sizeof(pic->linesize), sizeof(mpi->stride)));
630     memcpy(picref->data,     pic->data,     sizeof(picref->data));
631     memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
632
633     if(pts != MP_NOPTS_VALUE)
634         picref->pts= pts * av_q2d(outlink->time_base);
635
636     avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
637     avfilter_draw_slice(outlink, 0, picref->video->h, 1);
638     avfilter_end_frame(outlink);
639     avfilter_unref_buffer(picref);
640     m->frame_returned++;
641
642     return 1;
643 fail:
644     if (picref && picref->video)
645         av_free(picref->video);
646     av_free(picref);
647     av_free(pic);
648     return 0;
649 }
650
651 int vf_next_config(struct vf_instance *vf,
652         int width, int height, int d_width, int d_height,
653         unsigned int voflags, unsigned int outfmt){
654
655     av_assert0(width>0 && height>0);
656     vf->next->w = width; vf->next->h = height;
657
658     return 1;
659 #if 0
660     int flags=vf->next->query_format(vf->next,outfmt);
661     if(!flags){
662         // hmm. colorspace mismatch!!!
663         //this is fatal for us ATM
664         return 0;
665     }
666     mp_msg(MSGT_VFILTER,MSGL_V,"REQ: flags=0x%X  req=0x%X  \n",flags,vf->default_reqs);
667     miss=vf->default_reqs - (flags&vf->default_reqs);
668     if(miss&VFCAP_ACCEPT_STRIDE){
669         // vf requires stride support but vf->next doesn't support it!
670         // let's insert the 'expand' filter, it does the job for us:
671         vf_instance_t* vf2=vf_open_filter(vf->next,"expand",NULL);
672         if(!vf2) return 0; // shouldn't happen!
673         vf->next=vf2;
674     }
675     vf->next->w = width; vf->next->h = height;
676 #endif
677     return 1;
678 }
679
680 int vf_next_control(struct vf_instance *vf, int request, void* data){
681     MPContext *m= (void*)vf;
682     av_log(m->avfctx, AV_LOG_DEBUG, "Received control %d\n", request);
683     return 0;
684 }
685
686 static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt){
687     MPContext *m= (void*)vf;
688     int i;
689     av_log(m->avfctx, AV_LOG_DEBUG, "query %X\n", fmt);
690
691     for(i=0; conversion_map[i].fmt; i++){
692         if(fmt==conversion_map[i].fmt)
693             return 1; //we suport all
694     }
695     return 0;
696 }
697
698
699 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
700 {
701     MPContext *m = ctx->priv;
702     char name[256];
703     int i;
704
705     m->avfctx= ctx;
706
707     if(!args || 1!=sscanf(args, "%255[^:=]", name)){
708         av_log(ctx, AV_LOG_ERROR, "Invalid parameter.\n");
709         return AVERROR(EINVAL);
710     }
711     args+= strlen(name)+1;
712
713     for(i=0; ;i++){
714         if(!filters[i] || !strcmp(name, filters[i]->name))
715             break;
716     }
717
718     if(!filters[i]){
719         av_log(ctx, AV_LOG_ERROR, "Unknown filter %s\n", name);
720         return AVERROR(EINVAL);
721     }
722
723     av_log(ctx, AV_LOG_WARNING,
724            "'%s' is a wrapped MPlayer filter (libmpcodecs). This filter may be removed\n"
725            "once it has been ported to a native libavfilter.\n", name);
726
727     memset(&m->vf,0,sizeof(m->vf));
728     m->vf.info= filters[i];
729
730     m->vf.next        = &m->next_vf;
731     m->vf.put_image   = vf_next_put_image;
732     m->vf.config      = vf_next_config;
733     m->vf.query_format= vf_default_query_format;
734     m->vf.control     = vf_next_control;
735     m->vf.default_caps=VFCAP_ACCEPT_STRIDE;
736     m->vf.default_reqs=0;
737     if(m->vf.info->opts)
738         av_log(ctx, AV_LOG_ERROR, "opts / m_struct_set is unsupported\n");
739 #if 0
740     if(vf->info->opts) { // vf_vo get some special argument
741       const m_struct_t* st = vf->info->opts;
742       void* vf_priv = m_struct_alloc(st);
743       int n;
744       for(n = 0 ; args && args[2*n] ; n++)
745         m_struct_set(st,vf_priv,args[2*n],args[2*n+1]);
746       vf->priv = vf_priv;
747       args = NULL;
748     } else // Otherwise we should have the '_oldargs_'
749       if(args && !strcmp(args[0],"_oldargs_"))
750         args = (char**)args[1];
751       else
752         args = NULL;
753 #endif
754     if(m->vf.info->vf_open(&m->vf, args)<=0){
755         av_log(ctx, AV_LOG_ERROR, "vf_open() of %s with arg=%s failed\n", name, args);
756         return -1;
757     }
758
759     return 0;
760 }
761
762 static av_cold void uninit(AVFilterContext *ctx)
763 {
764     MPContext *m = ctx->priv;
765     vf_instance_t *vf = &m->vf;
766
767     while(vf){
768         vf_instance_t *next = vf->next;
769         if(vf->uninit)
770             vf->uninit(vf);
771         free_mp_image(vf->imgctx.static_images[0]);
772         free_mp_image(vf->imgctx.static_images[1]);
773         free_mp_image(vf->imgctx.temp_images[0]);
774         free_mp_image(vf->imgctx.export_images[0]);
775         vf = next;
776     }
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("Apply a libmpcodecs filter to the input video."),
890     .init = init,
891     .uninit = uninit,
892     .priv_size = sizeof(MPContext),
893     .query_formats = query_formats,
894
895     .inputs    = (const 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   = (const AVFilterPad[]) {{ .name      = "default",
904                                     .type            = AVMEDIA_TYPE_VIDEO,
905                                     .request_frame   = request_frame,
906                                     .config_props    = config_outprops, },
907                                   { .name = NULL}},
908 };