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