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