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