lavfi/mp: remove mp=pullup
[ffmpeg.git] / libavfilter / vf_mp.c
1 /*
2  * Copyright (c) 2011 Michael Niedermayer
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  * Parts of this file have been stolen from mplayer
21  */
22
23 /**
24  * @file
25  */
26
27 #include "avfilter.h"
28 #include "video.h"
29 #include "formats.h"
30 #include "internal.h"
31 #include "libavutil/avassert.h"
32 #include "libavutil/pixdesc.h"
33 #include "libavutil/intreadwrite.h"
34 #include "libavutil/imgutils.h"
35 #include "libavutil/opt.h"
36
37 #include "libmpcodecs/vf.h"
38 #include "libmpcodecs/img_format.h"
39 #include "libmpcodecs/cpudetect.h"
40 #include "libmpcodecs/av_helpers.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_eq2;
126 extern const vf_info_t ff_vf_info_eq;
127 extern const vf_info_t ff_vf_info_fspp;
128 extern const vf_info_t ff_vf_info_ilpack;
129 extern const vf_info_t ff_vf_info_pp7;
130 extern const vf_info_t ff_vf_info_qp;
131 extern const vf_info_t ff_vf_info_softpulldown;
132 extern const vf_info_t ff_vf_info_uspp;
133
134
135 static const vf_info_t* const filters[]={
136     &ff_vf_info_eq2,
137     &ff_vf_info_eq,
138     &ff_vf_info_fspp,
139     &ff_vf_info_ilpack,
140     &ff_vf_info_pp7,
141     &ff_vf_info_qp,
142     &ff_vf_info_softpulldown,
143     &ff_vf_info_uspp,
144
145     NULL
146 };
147
148 /*
149 Unsupported filters
150 1bpp
151 ass
152 bmovl
153 crop
154 dvbscale
155 flip
156 expand
157 format
158 halfpack
159 lavc
160 lavcdeint
161 noformat
162 pp
163 scale
164 tfields
165 vo
166 yadif
167 zrmjpeg
168 */
169
170 CpuCaps ff_gCpuCaps; //FIXME initialize this so optims work
171
172 enum AVPixelFormat ff_mp2ff_pix_fmt(int mp){
173     int i;
174     for(i=0; conversion_map[i].fmt && mp != conversion_map[i].fmt; i++)
175         ;
176     return mp == conversion_map[i].fmt ? conversion_map[i].pix_fmt : AV_PIX_FMT_NONE;
177 }
178
179 typedef struct {
180     const AVClass *class;
181     vf_instance_t vf;
182     vf_instance_t next_vf;
183     AVFilterContext *avfctx;
184     int frame_returned;
185     char *filter;
186     enum AVPixelFormat in_pix_fmt;
187 } MPContext;
188
189 #define OFFSET(x) offsetof(MPContext, x)
190 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
191 static const AVOption mp_options[] = {
192     { "filter", "set MPlayer filter name and parameters", OFFSET(filter), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
193     { NULL }
194 };
195
196 AVFILTER_DEFINE_CLASS(mp);
197
198 void ff_mp_msg(int mod, int lev, const char *format, ... ){
199     va_list va;
200     va_start(va, format);
201     //FIXME convert lev/mod
202     av_vlog(NULL, AV_LOG_DEBUG, format, va);
203     va_end(va);
204 }
205
206 int ff_mp_msg_test(int mod, int lev){
207     return 123;
208 }
209
210 void ff_init_avcodec(void)
211 {
212     //we maybe should init but its kinda 1. unneeded 2. a bit inpolite from here
213 }
214
215 //Exact copy of vf.c
216 void ff_vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src){
217     dst->pict_type= src->pict_type;
218     dst->fields = src->fields;
219     dst->qscale_type= src->qscale_type;
220     if(dst->width == src->width && dst->height == src->height){
221         dst->qstride= src->qstride;
222         dst->qscale= src->qscale;
223     }
224 }
225
226 //Exact copy of vf.c
227 void ff_vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){
228     if (vf->next->draw_slice) {
229         vf->next->draw_slice(vf->next,src,stride,w,h,x,y);
230         return;
231     }
232     if (!vf->dmpi) {
233         ff_mp_msg(MSGT_VFILTER,MSGL_ERR,"draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
234         return;
235     }
236     if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) {
237         memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+vf->dmpi->bpp/8*x,
238             src[0], vf->dmpi->bpp/8*w, h, vf->dmpi->stride[0], stride[0]);
239         return;
240     }
241     memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+x, src[0],
242         w, h, vf->dmpi->stride[0], stride[0]);
243     memcpy_pic(vf->dmpi->planes[1]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[1]+(x>>vf->dmpi->chroma_x_shift),
244         src[1], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]);
245     memcpy_pic(vf->dmpi->planes[2]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[2]+(x>>vf->dmpi->chroma_x_shift),
246         src[2], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]);
247 }
248
249 //Exact copy of vf.c
250 void ff_vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h){
251     int y;
252     if(mpi->flags&MP_IMGFLAG_PLANAR){
253         y0&=~1;h+=h&1;
254         if(x0==0 && w==mpi->width){
255             // full width clear:
256             memset(mpi->planes[0]+mpi->stride[0]*y0,0,mpi->stride[0]*h);
257             memset(mpi->planes[1]+mpi->stride[1]*(y0>>mpi->chroma_y_shift),128,mpi->stride[1]*(h>>mpi->chroma_y_shift));
258             memset(mpi->planes[2]+mpi->stride[2]*(y0>>mpi->chroma_y_shift),128,mpi->stride[2]*(h>>mpi->chroma_y_shift));
259         } else
260         for(y=y0;y<y0+h;y+=2){
261             memset(mpi->planes[0]+x0+mpi->stride[0]*y,0,w);
262             memset(mpi->planes[0]+x0+mpi->stride[0]*(y+1),0,w);
263             memset(mpi->planes[1]+(x0>>mpi->chroma_x_shift)+mpi->stride[1]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
264             memset(mpi->planes[2]+(x0>>mpi->chroma_x_shift)+mpi->stride[2]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
265         }
266         return;
267     }
268     // packed:
269     for(y=y0;y<y0+h;y++){
270         unsigned char* dst=mpi->planes[0]+mpi->stride[0]*y+(mpi->bpp>>3)*x0;
271         if(mpi->flags&MP_IMGFLAG_YUV){
272             unsigned int* p=(unsigned int*) dst;
273             int size=(mpi->bpp>>3)*w/4;
274             int i;
275 #if HAVE_BIGENDIAN
276 #define CLEAR_PACKEDYUV_PATTERN 0x00800080
277 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x80008000
278 #else
279 #define CLEAR_PACKEDYUV_PATTERN 0x80008000
280 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x00800080
281 #endif
282             if(mpi->flags&MP_IMGFLAG_SWAPPED){
283                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
284                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
285             } else {
286                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN;
287                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN;
288             }
289         } else
290             memset(dst,0,(mpi->bpp>>3)*w);
291     }
292 }
293
294 int ff_vf_next_query_format(struct vf_instance *vf, unsigned int fmt){
295     return 1;
296 }
297
298 //used by delogo
299 unsigned int ff_vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred){
300     return preferred;
301 }
302
303 mp_image_t* ff_vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h){
304     MPContext *m= (MPContext*)(((uint8_t*)vf) - offsetof(MPContext, next_vf));
305   mp_image_t* mpi=NULL;
306   int w2;
307   int number = mp_imgtype >> 16;
308
309   av_assert0(vf->next == NULL); // all existing filters call this just on next
310
311   //vf_dint needs these as it calls ff_vf_get_image() before configuring the output
312   if(vf->w==0 && w>0) vf->w=w;
313   if(vf->h==0 && h>0) vf->h=h;
314
315   av_assert0(w == -1 || w >= vf->w);
316   av_assert0(h == -1 || h >= vf->h);
317   av_assert0(vf->w > 0);
318   av_assert0(vf->h > 0);
319
320   av_log(m->avfctx, AV_LOG_DEBUG, "get_image: %d:%d, vf: %d:%d\n", w,h,vf->w,vf->h);
321
322   if (w == -1) w = vf->w;
323   if (h == -1) h = vf->h;
324
325   w2=(mp_imgflag&MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE)?((w+15)&(~15)):w;
326
327   // Note: we should call libvo first to check if it supports direct rendering
328   // and if not, then fallback to software buffers:
329   switch(mp_imgtype & 0xff){
330   case MP_IMGTYPE_EXPORT:
331     if(!vf->imgctx.export_images[0]) vf->imgctx.export_images[0]=ff_new_mp_image(w2,h);
332     mpi=vf->imgctx.export_images[0];
333     break;
334   case MP_IMGTYPE_STATIC:
335     if(!vf->imgctx.static_images[0]) vf->imgctx.static_images[0]=ff_new_mp_image(w2,h);
336     mpi=vf->imgctx.static_images[0];
337     break;
338   case MP_IMGTYPE_TEMP:
339     if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=ff_new_mp_image(w2,h);
340     mpi=vf->imgctx.temp_images[0];
341     break;
342   case MP_IMGTYPE_IPB:
343     if(!(mp_imgflag&MP_IMGFLAG_READABLE)){ // B frame:
344       if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=ff_new_mp_image(w2,h);
345       mpi=vf->imgctx.temp_images[0];
346       break;
347     }
348   case MP_IMGTYPE_IP:
349     if(!vf->imgctx.static_images[vf->imgctx.static_idx]) vf->imgctx.static_images[vf->imgctx.static_idx]=ff_new_mp_image(w2,h);
350     mpi=vf->imgctx.static_images[vf->imgctx.static_idx];
351     vf->imgctx.static_idx^=1;
352     break;
353   case MP_IMGTYPE_NUMBERED:
354     if (number == -1) {
355       int i;
356       for (i = 0; i < NUM_NUMBERED_MPI; i++)
357         if (!vf->imgctx.numbered_images[i] || !vf->imgctx.numbered_images[i]->usage_count)
358           break;
359       number = i;
360     }
361     if (number < 0 || number >= NUM_NUMBERED_MPI) return NULL;
362     if (!vf->imgctx.numbered_images[number]) vf->imgctx.numbered_images[number] = ff_new_mp_image(w2,h);
363     mpi = vf->imgctx.numbered_images[number];
364     mpi->number = number;
365     break;
366   }
367   if(mpi){
368     mpi->type=mp_imgtype;
369     mpi->w=vf->w; mpi->h=vf->h;
370     // keep buffer allocation status & color flags only:
371 //    mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE|MP_IMGFLAG_DIRECT);
372     mpi->flags&=MP_IMGFLAG_ALLOCATED|MP_IMGFLAG_TYPE_DISPLAYED|MP_IMGFLAGMASK_COLORS;
373     // accept restrictions, draw_slice and palette flags only:
374     mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK|MP_IMGFLAG_RGB_PALETTE);
375     if(!vf->draw_slice) mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK;
376     if(mpi->width!=w2 || mpi->height!=h){
377 //      printf("vf.c: MPI parameters changed!  %dx%d -> %dx%d   \n", mpi->width,mpi->height,w2,h);
378         if(mpi->flags&MP_IMGFLAG_ALLOCATED){
379             if(mpi->width<w2 || mpi->height<h){
380                 // need to re-allocate buffer memory:
381                 av_free(mpi->planes[0]);
382                 mpi->flags&=~MP_IMGFLAG_ALLOCATED;
383                 ff_mp_msg(MSGT_VFILTER,MSGL_V,"vf.c: have to REALLOCATE buffer memory :(\n");
384             }
385 //      } else {
386         } {
387             mpi->width=w2; mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
388             mpi->height=h; mpi->chroma_height=(h + (1<<mpi->chroma_y_shift) - 1)>>mpi->chroma_y_shift;
389         }
390     }
391     if(!mpi->bpp) ff_mp_image_setfmt(mpi,outfmt);
392     if(!(mpi->flags&MP_IMGFLAG_ALLOCATED) && mpi->type>MP_IMGTYPE_EXPORT){
393
394         av_assert0(!vf->get_image);
395         // check libvo first!
396         if(vf->get_image) vf->get_image(vf,mpi);
397
398         if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
399           // non-direct and not yet allocated image. allocate it!
400           if (!mpi->bpp) { // no way we can allocate this
401               ff_mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
402                      "ff_vf_get_image: Tried to allocate a format that can not be allocated!\n");
403               return NULL;
404           }
405
406           // check if codec prefer aligned stride:
407           if(mp_imgflag&MP_IMGFLAG_PREFER_ALIGNED_STRIDE){
408               int align=(mpi->flags&MP_IMGFLAG_PLANAR &&
409                          mpi->flags&MP_IMGFLAG_YUV) ?
410                          (8<<mpi->chroma_x_shift)-1 : 15; // -- maybe FIXME
411               w2=((w+align)&(~align));
412               if(mpi->width!=w2){
413 #if 0
414                   // we have to change width... check if we CAN co it:
415                   int flags=vf->query_format(vf,outfmt); // should not fail
416                   if(!(flags&3)) ff_mp_msg(MSGT_DECVIDEO,MSGL_WARN,"??? ff_vf_get_image{vf->query_format(outfmt)} failed!\n");
417 //                printf("query -> 0x%X    \n",flags);
418                   if(flags&VFCAP_ACCEPT_STRIDE){
419 #endif
420                       mpi->width=w2;
421                       mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
422 //                  }
423               }
424           }
425
426           ff_mp_image_alloc_planes(mpi);
427 //        printf("clearing img!\n");
428           ff_vf_mpi_clear(mpi,0,0,mpi->width,mpi->height);
429         }
430     }
431     av_assert0(!vf->start_slice);
432     if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)
433         if(vf->start_slice) vf->start_slice(vf,mpi);
434     if(!(mpi->flags&MP_IMGFLAG_TYPE_DISPLAYED)){
435             ff_mp_msg(MSGT_DECVIDEO,MSGL_V,"*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
436                   "NULL"/*vf->info->name*/,
437                   (mpi->type==MP_IMGTYPE_EXPORT)?"Exporting":
438                   ((mpi->flags&MP_IMGFLAG_DIRECT)?"Direct Rendering":"Allocating"),
439                   (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)?" (slices)":"",
440                   mpi->width,mpi->height,mpi->bpp,
441                   (mpi->flags&MP_IMGFLAG_YUV)?"YUV":((mpi->flags&MP_IMGFLAG_SWAPPED)?"BGR":"RGB"),
442                   (mpi->flags&MP_IMGFLAG_PLANAR)?"planar":"packed",
443                   mpi->bpp*mpi->width*mpi->height/8);
444             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",
445                 mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
446                 mpi->stride[0], mpi->stride[1], mpi->stride[2],
447                 mpi->chroma_width, mpi->chroma_height, mpi->chroma_x_shift, mpi->chroma_y_shift);
448             mpi->flags|=MP_IMGFLAG_TYPE_DISPLAYED;
449     }
450
451   mpi->qscale = NULL;
452   mpi->usage_count++;
453   }
454 //    printf("\rVF_MPI: %p %p %p %d %d %d    \n",
455 //      mpi->planes[0],mpi->planes[1],mpi->planes[2],
456 //      mpi->stride[0],mpi->stride[1],mpi->stride[2]);
457   return mpi;
458 }
459
460 int ff_vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){
461     MPContext *m= (MPContext*)(((uint8_t*)vf) - offsetof(MPContext, vf));
462     AVFilterLink *outlink     = m->avfctx->outputs[0];
463     AVFrame *picref = av_frame_alloc();
464     int i;
465
466     av_assert0(vf->next);
467
468     av_log(m->avfctx, AV_LOG_DEBUG, "ff_vf_next_put_image\n");
469
470     if (!picref)
471         goto fail;
472
473     picref->width  = mpi->w;
474     picref->height = mpi->h;
475
476     picref->type = AVMEDIA_TYPE_VIDEO;
477
478     for(i=0; conversion_map[i].fmt && mpi->imgfmt != conversion_map[i].fmt; i++);
479     picref->format = conversion_map[i].pix_fmt;
480
481     for(i=0; conversion_map[i].fmt && m->in_pix_fmt != conversion_map[i].pix_fmt; i++);
482     if (mpi->imgfmt == conversion_map[i].fmt)
483         picref->format = conversion_map[i].pix_fmt;
484
485     memcpy(picref->linesize, mpi->stride, FFMIN(sizeof(picref->linesize), sizeof(mpi->stride)));
486
487     for(i=0; i<4 && mpi->stride[i]; i++){
488         picref->data[i] = mpi->planes[i];
489     }
490
491     if(pts != MP_NOPTS_VALUE)
492         picref->pts= pts * av_q2d(outlink->time_base);
493
494     if(1) { // mp buffers are currently unsupported in libavfilter, we thus must copy
495         AVFrame *tofree = picref;
496         picref = av_frame_clone(picref);
497         av_frame_free(&tofree);
498     }
499
500     ff_filter_frame(outlink, picref);
501     m->frame_returned++;
502
503     return 1;
504 fail:
505     av_frame_free(&picref);
506     return 0;
507 }
508
509 int ff_vf_next_config(struct vf_instance *vf,
510         int width, int height, int d_width, int d_height,
511         unsigned int voflags, unsigned int outfmt){
512
513     av_assert0(width>0 && height>0);
514     vf->next->w = width; vf->next->h = height;
515
516     return 1;
517 #if 0
518     int flags=vf->next->query_format(vf->next,outfmt);
519     if(!flags){
520         // hmm. colorspace mismatch!!!
521         //this is fatal for us ATM
522         return 0;
523     }
524     ff_mp_msg(MSGT_VFILTER,MSGL_V,"REQ: flags=0x%X  req=0x%X  \n",flags,vf->default_reqs);
525     miss=vf->default_reqs - (flags&vf->default_reqs);
526     if(miss&VFCAP_ACCEPT_STRIDE){
527         // vf requires stride support but vf->next doesn't support it!
528         // let's insert the 'expand' filter, it does the job for us:
529         vf_instance_t* vf2=vf_open_filter(vf->next,"expand",NULL);
530         if(!vf2) return 0; // shouldn't happen!
531         vf->next=vf2;
532     }
533     vf->next->w = width; vf->next->h = height;
534     return 1;
535 #endif
536 }
537
538 int ff_vf_next_control(struct vf_instance *vf, int request, void* data){
539     MPContext *m= (MPContext*)(((uint8_t*)vf) - offsetof(MPContext, vf));
540     av_log(m->avfctx, AV_LOG_DEBUG, "Received control %d\n", request);
541     return 0;
542 }
543
544 static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt){
545     MPContext *m= (MPContext*)(((uint8_t*)vf) - offsetof(MPContext, vf));
546     int i;
547     av_log(m->avfctx, AV_LOG_DEBUG, "query %X\n", fmt);
548
549     for(i=0; conversion_map[i].fmt; i++){
550         if(fmt==conversion_map[i].fmt)
551             return 1; //we suport all
552     }
553     return 0;
554 }
555
556
557 static av_cold int init(AVFilterContext *ctx)
558 {
559     MPContext *m = ctx->priv;
560     int cpu_flags = av_get_cpu_flags();
561     char name[256];
562     const char *args;
563     int i;
564
565     ff_gCpuCaps.hasMMX      = cpu_flags & AV_CPU_FLAG_MMX;
566     ff_gCpuCaps.hasMMX2     = cpu_flags & AV_CPU_FLAG_MMX2;
567     ff_gCpuCaps.hasSSE      = cpu_flags & AV_CPU_FLAG_SSE;
568     ff_gCpuCaps.hasSSE2     = cpu_flags & AV_CPU_FLAG_SSE2;
569     ff_gCpuCaps.hasSSE3     = cpu_flags & AV_CPU_FLAG_SSE3;
570     ff_gCpuCaps.hasSSSE3    = cpu_flags & AV_CPU_FLAG_SSSE3;
571     ff_gCpuCaps.hasSSE4     = cpu_flags & AV_CPU_FLAG_SSE4;
572     ff_gCpuCaps.hasSSE42    = cpu_flags & AV_CPU_FLAG_SSE42;
573     ff_gCpuCaps.hasAVX      = cpu_flags & AV_CPU_FLAG_AVX;
574     ff_gCpuCaps.has3DNow    = cpu_flags & AV_CPU_FLAG_3DNOW;
575     ff_gCpuCaps.has3DNowExt = cpu_flags & AV_CPU_FLAG_3DNOWEXT;
576
577     m->avfctx= ctx;
578
579     args = m->filter;
580     if(!args || 1!=sscanf(args, "%255[^:=]", name)){
581         av_log(ctx, AV_LOG_ERROR, "Invalid parameter.\n");
582         return AVERROR(EINVAL);
583     }
584     args += strlen(name);
585     if (args[0] == '=')
586         args++;
587
588     for(i=0; ;i++){
589         if(!filters[i] || !strcmp(name, filters[i]->name))
590             break;
591     }
592
593     if(!filters[i]){
594         av_log(ctx, AV_LOG_ERROR, "Unknown filter %s\n", name);
595         return AVERROR(EINVAL);
596     }
597
598     av_log(ctx, AV_LOG_WARNING,
599            "'%s' is a wrapped MPlayer filter (libmpcodecs). This filter may be removed\n"
600            "once it has been ported to a native libavfilter.\n", name);
601
602     memset(&m->vf,0,sizeof(m->vf));
603     m->vf.info= filters[i];
604
605     m->vf.next        = &m->next_vf;
606     m->vf.put_image   = ff_vf_next_put_image;
607     m->vf.config      = ff_vf_next_config;
608     m->vf.query_format= vf_default_query_format;
609     m->vf.control     = ff_vf_next_control;
610     m->vf.default_caps=VFCAP_ACCEPT_STRIDE;
611     m->vf.default_reqs=0;
612     if(m->vf.info->opts)
613         av_log(ctx, AV_LOG_ERROR, "opts / m_struct_set is unsupported\n");
614 #if 0
615     if(vf->info->opts) { // vf_vo get some special argument
616       const m_struct_t* st = vf->info->opts;
617       void* vf_priv = m_struct_alloc(st);
618       int n;
619       for(n = 0 ; args && args[2*n] ; n++)
620         m_struct_set(st,vf_priv,args[2*n],args[2*n+1]);
621       vf->priv = vf_priv;
622       args = NULL;
623     } else // Otherwise we should have the '_oldargs_'
624       if(args && !strcmp(args[0],"_oldargs_"))
625         args = (char**)args[1];
626       else
627         args = NULL;
628 #endif
629     if(m->vf.info->vf_open(&m->vf, (char*)args)<=0){
630         av_log(ctx, AV_LOG_ERROR, "vf_open() of %s with arg=%s failed\n", name, args);
631         return -1;
632     }
633
634     return 0;
635 }
636
637 static av_cold void uninit(AVFilterContext *ctx)
638 {
639     MPContext *m = ctx->priv;
640     vf_instance_t *vf = &m->vf;
641
642     while(vf){
643         vf_instance_t *next = vf->next;
644         if(vf->uninit)
645             vf->uninit(vf);
646         ff_free_mp_image(vf->imgctx.static_images[0]);
647         ff_free_mp_image(vf->imgctx.static_images[1]);
648         ff_free_mp_image(vf->imgctx.temp_images[0]);
649         ff_free_mp_image(vf->imgctx.export_images[0]);
650         vf = next;
651     }
652 }
653
654 static int query_formats(AVFilterContext *ctx)
655 {
656     AVFilterFormats *avfmts=NULL;
657     MPContext *m = ctx->priv;
658     enum AVPixelFormat lastpixfmt = AV_PIX_FMT_NONE;
659     int i;
660
661     for(i=0; conversion_map[i].fmt; i++){
662         av_log(ctx, AV_LOG_DEBUG, "query: %X\n", conversion_map[i].fmt);
663         if(m->vf.query_format(&m->vf, conversion_map[i].fmt)){
664             av_log(ctx, AV_LOG_DEBUG, "supported,adding\n");
665             if (conversion_map[i].pix_fmt != lastpixfmt) {
666                 ff_add_format(&avfmts, conversion_map[i].pix_fmt);
667                 lastpixfmt = conversion_map[i].pix_fmt;
668             }
669         }
670     }
671
672     if (!avfmts)
673         return -1;
674
675     //We assume all allowed input formats are also allowed output formats
676     ff_set_common_formats(ctx, avfmts);
677     return 0;
678 }
679
680 static int config_inprops(AVFilterLink *inlink)
681 {
682     MPContext *m = inlink->dst->priv;
683     int i;
684     for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
685
686     av_assert0(conversion_map[i].fmt && inlink->w && inlink->h);
687
688     m->vf.fmt.have_configured = 1;
689     m->vf.fmt.orig_height     = inlink->h;
690     m->vf.fmt.orig_width      = inlink->w;
691     m->vf.fmt.orig_fmt        = conversion_map[i].fmt;
692
693     if(m->vf.config(&m->vf, inlink->w, inlink->h, inlink->w, inlink->h, 0, conversion_map[i].fmt)<=0)
694         return -1;
695
696     return 0;
697 }
698
699 static int config_outprops(AVFilterLink *outlink)
700 {
701     MPContext *m = outlink->src->priv;
702
703     outlink->w = m->next_vf.w;
704     outlink->h = m->next_vf.h;
705
706     return 0;
707 }
708
709 static int request_frame(AVFilterLink *outlink)
710 {
711     MPContext *m = outlink->src->priv;
712     int ret;
713
714     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame\n");
715
716     for(m->frame_returned=0; !m->frame_returned;){
717         ret=ff_request_frame(outlink->src->inputs[0]);
718         if(ret<0)
719             break;
720     }
721
722     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame ret=%d\n", ret);
723     return ret;
724 }
725
726 static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
727 {
728     MPContext *m = inlink->dst->priv;
729     int i;
730     double pts= MP_NOPTS_VALUE;
731     mp_image_t* mpi = ff_new_mp_image(inpic->width, inpic->height);
732
733     if(inpic->pts != AV_NOPTS_VALUE)
734         pts= inpic->pts / av_q2d(inlink->time_base);
735
736     for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
737     ff_mp_image_setfmt(mpi,conversion_map[i].fmt);
738     m->in_pix_fmt = inlink->format;
739
740     memcpy(mpi->planes, inpic->data,     FFMIN(sizeof(inpic->data)    , sizeof(mpi->planes)));
741     memcpy(mpi->stride, inpic->linesize, FFMIN(sizeof(inpic->linesize), sizeof(mpi->stride)));
742
743     if (inpic->interlaced_frame)
744         mpi->fields |= MP_IMGFIELD_INTERLACED;
745     if (inpic->top_field_first)
746         mpi->fields |= MP_IMGFIELD_TOP_FIRST;
747     if (inpic->repeat_pict)
748         mpi->fields |= MP_IMGFIELD_REPEAT_FIRST;
749
750     // mpi->flags|=MP_IMGFLAG_ALLOCATED; ?
751     mpi->flags |= MP_IMGFLAG_READABLE;
752     if(!av_frame_is_writable(inpic))
753         mpi->flags |= MP_IMGFLAG_PRESERVE;
754     if(m->vf.put_image(&m->vf, mpi, pts) == 0){
755         av_log(m->avfctx, AV_LOG_DEBUG, "put_image() says skip\n");
756     }else{
757         av_frame_free(&inpic);
758     }
759     ff_free_mp_image(mpi);
760     return 0;
761 }
762
763 static const AVFilterPad mp_inputs[] = {
764     {
765         .name         = "default",
766         .type         = AVMEDIA_TYPE_VIDEO,
767         .filter_frame = filter_frame,
768         .config_props = config_inprops,
769     },
770     { NULL }
771 };
772
773 static const AVFilterPad mp_outputs[] = {
774     {
775         .name          = "default",
776         .type          = AVMEDIA_TYPE_VIDEO,
777         .request_frame = request_frame,
778         .config_props  = config_outprops,
779     },
780     { NULL }
781 };
782
783 AVFilter avfilter_vf_mp = {
784     .name          = "mp",
785     .description   = NULL_IF_CONFIG_SMALL("Apply a libmpcodecs filter to the input video."),
786     .init          = init,
787     .uninit        = uninit,
788     .priv_size     = sizeof(MPContext),
789     .query_formats = query_formats,
790     .inputs        = mp_inputs,
791     .outputs       = mp_outputs,
792     .priv_class    = &mp_class,
793 };