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