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