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