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