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