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