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