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