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