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