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