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