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