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