]> git.sesse.net Git - ffmpeg/blob - libavfilter/vf_mp.c
lavfi/mp: remove framestep wrapped filter
[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
36 #include "libmpcodecs/vf.h"
37 #include "libmpcodecs/img_format.h"
38 #include "libmpcodecs/cpudetect.h"
39 #include "libmpcodecs/vd_ffmpeg.h"
40 #include "libmpcodecs/vf_scale.h"
41 #include "libmpcodecs/libvo/fastmemcpy.h"
42
43 #include "libswscale/swscale.h"
44
45
46 //FIXME maybe link the orig in
47 //XXX: identical pix_fmt must be following with each others
48 static const struct {
49     int fmt;
50     enum PixelFormat pix_fmt;
51 } conversion_map[] = {
52     {IMGFMT_ARGB, PIX_FMT_ARGB},
53     {IMGFMT_BGRA, PIX_FMT_BGRA},
54     {IMGFMT_BGR24, PIX_FMT_BGR24},
55     {IMGFMT_BGR16BE, PIX_FMT_RGB565BE},
56     {IMGFMT_BGR16LE, PIX_FMT_RGB565LE},
57     {IMGFMT_BGR15BE, PIX_FMT_RGB555BE},
58     {IMGFMT_BGR15LE, PIX_FMT_RGB555LE},
59     {IMGFMT_BGR12BE, PIX_FMT_RGB444BE},
60     {IMGFMT_BGR12LE, PIX_FMT_RGB444LE},
61     {IMGFMT_BGR8,  PIX_FMT_RGB8},
62     {IMGFMT_BGR4,  PIX_FMT_RGB4},
63     {IMGFMT_BGR1,  PIX_FMT_MONOBLACK},
64     {IMGFMT_RGB1,  PIX_FMT_MONOBLACK},
65     {IMGFMT_RG4B,  PIX_FMT_BGR4_BYTE},
66     {IMGFMT_BG4B,  PIX_FMT_RGB4_BYTE},
67     {IMGFMT_RGB48LE, PIX_FMT_RGB48LE},
68     {IMGFMT_RGB48BE, PIX_FMT_RGB48BE},
69     {IMGFMT_ABGR, PIX_FMT_ABGR},
70     {IMGFMT_RGBA, PIX_FMT_RGBA},
71     {IMGFMT_RGB24, PIX_FMT_RGB24},
72     {IMGFMT_RGB16BE, PIX_FMT_BGR565BE},
73     {IMGFMT_RGB16LE, PIX_FMT_BGR565LE},
74     {IMGFMT_RGB15BE, PIX_FMT_BGR555BE},
75     {IMGFMT_RGB15LE, PIX_FMT_BGR555LE},
76     {IMGFMT_RGB12BE, PIX_FMT_BGR444BE},
77     {IMGFMT_RGB12LE, PIX_FMT_BGR444LE},
78     {IMGFMT_RGB8,  PIX_FMT_BGR8},
79     {IMGFMT_RGB4,  PIX_FMT_BGR4},
80     {IMGFMT_BGR8,  PIX_FMT_PAL8},
81     {IMGFMT_YUY2,  PIX_FMT_YUYV422},
82     {IMGFMT_UYVY,  PIX_FMT_UYVY422},
83     {IMGFMT_NV12,  PIX_FMT_NV12},
84     {IMGFMT_NV21,  PIX_FMT_NV21},
85     {IMGFMT_Y800,  PIX_FMT_GRAY8},
86     {IMGFMT_Y8,    PIX_FMT_GRAY8},
87     {IMGFMT_YVU9,  PIX_FMT_YUV410P},
88     {IMGFMT_IF09,  PIX_FMT_YUV410P},
89     {IMGFMT_YV12,  PIX_FMT_YUV420P},
90     {IMGFMT_I420,  PIX_FMT_YUV420P},
91     {IMGFMT_IYUV,  PIX_FMT_YUV420P},
92     {IMGFMT_411P,  PIX_FMT_YUV411P},
93     {IMGFMT_422P,  PIX_FMT_YUV422P},
94     {IMGFMT_444P,  PIX_FMT_YUV444P},
95     {IMGFMT_440P,  PIX_FMT_YUV440P},
96
97     {IMGFMT_420A,  PIX_FMT_YUVA420P},
98
99     {IMGFMT_420P16_LE,  PIX_FMT_YUV420P16LE},
100     {IMGFMT_420P16_BE,  PIX_FMT_YUV420P16BE},
101     {IMGFMT_422P16_LE,  PIX_FMT_YUV422P16LE},
102     {IMGFMT_422P16_BE,  PIX_FMT_YUV422P16BE},
103     {IMGFMT_444P16_LE,  PIX_FMT_YUV444P16LE},
104     {IMGFMT_444P16_BE,  PIX_FMT_YUV444P16BE},
105
106     // YUVJ are YUV formats that use the full Y range and not just
107     // 16 - 235 (see colorspaces.txt).
108     // Currently they are all treated the same way.
109     {IMGFMT_YV12,  PIX_FMT_YUVJ420P},
110     {IMGFMT_422P,  PIX_FMT_YUVJ422P},
111     {IMGFMT_444P,  PIX_FMT_YUVJ444P},
112     {IMGFMT_440P,  PIX_FMT_YUVJ440P},
113
114     {IMGFMT_XVMC_MOCO_MPEG2, PIX_FMT_XVMC_MPEG2_MC},
115     {IMGFMT_XVMC_IDCT_MPEG2, PIX_FMT_XVMC_MPEG2_IDCT},
116     {IMGFMT_VDPAU_MPEG1,     PIX_FMT_VDPAU_MPEG1},
117     {IMGFMT_VDPAU_MPEG2,     PIX_FMT_VDPAU_MPEG2},
118     {IMGFMT_VDPAU_H264,      PIX_FMT_VDPAU_H264},
119     {IMGFMT_VDPAU_WMV3,      PIX_FMT_VDPAU_WMV3},
120     {IMGFMT_VDPAU_VC1,       PIX_FMT_VDPAU_VC1},
121     {IMGFMT_VDPAU_MPEG4,     PIX_FMT_VDPAU_MPEG4},
122     {0, PIX_FMT_NONE}
123 };
124
125 //copied from vf.c
126 extern const vf_info_t vf_info_1bpp;
127 extern const vf_info_t vf_info_ass;
128 extern const vf_info_t vf_info_bmovl;
129 extern const vf_info_t vf_info_crop;
130 extern const vf_info_t vf_info_decimate;
131 extern const vf_info_t vf_info_denoise3d;
132 extern const vf_info_t vf_info_detc;
133 extern const vf_info_t vf_info_dint;
134 extern const vf_info_t vf_info_divtc;
135 extern const vf_info_t vf_info_down3dright;
136 extern const vf_info_t vf_info_dsize;
137 extern const vf_info_t vf_info_dvbscale;
138 extern const vf_info_t vf_info_eq2;
139 extern const vf_info_t vf_info_eq;
140 extern const vf_info_t vf_info_expand;
141 extern const vf_info_t vf_info_field;
142 extern const vf_info_t vf_info_fil;
143 extern const vf_info_t vf_info_filmdint;
144 extern const vf_info_t vf_info_fixpts;
145 extern const vf_info_t vf_info_flip;
146 extern const vf_info_t vf_info_format;
147 extern const vf_info_t vf_info_fspp;
148 extern const vf_info_t vf_info_geq;
149 extern const vf_info_t vf_info_halfpack;
150 extern const vf_info_t vf_info_harddup;
151 extern const vf_info_t vf_info_hqdn3d;
152 extern const vf_info_t vf_info_il;
153 extern const vf_info_t vf_info_ilpack;
154 extern const vf_info_t vf_info_ivtc;
155 extern const vf_info_t vf_info_kerndeint;
156 extern const vf_info_t vf_info_lavc;
157 extern const vf_info_t vf_info_lavcdeint;
158 extern const vf_info_t vf_info_mcdeint;
159 extern const vf_info_t vf_info_noformat;
160 extern const vf_info_t vf_info_noise;
161 extern const vf_info_t vf_info_ow;
162 extern const vf_info_t vf_info_palette;
163 extern const vf_info_t vf_info_perspective;
164 extern const vf_info_t vf_info_phase;
165 extern const vf_info_t vf_info_pp7;
166 extern const vf_info_t vf_info_pp;
167 extern const vf_info_t vf_info_pullup;
168 extern const vf_info_t vf_info_qp;
169 extern const vf_info_t vf_info_rectangle;
170 extern const vf_info_t vf_info_rotate;
171 extern const vf_info_t vf_info_sab;
172 extern const vf_info_t vf_info_scale;
173 extern const vf_info_t vf_info_smartblur;
174 extern const vf_info_t vf_info_softpulldown;
175 extern const vf_info_t vf_info_softskip;
176 extern const vf_info_t vf_info_spp;
177 extern const vf_info_t vf_info_stereo3d;
178 extern const vf_info_t vf_info_telecine;
179 extern const vf_info_t vf_info_test;
180 extern const vf_info_t vf_info_tfields;
181 extern const vf_info_t vf_info_tile;
182 extern const vf_info_t vf_info_tinterlace;
183 extern const vf_info_t vf_info_unsharp;
184 extern const vf_info_t vf_info_uspp;
185 extern const vf_info_t vf_info_vo;
186 extern const vf_info_t vf_info_yadif;
187 extern const vf_info_t vf_info_yuvcsp;
188 extern const vf_info_t vf_info_yvu9;
189 extern const vf_info_t vf_info_zrmjpeg;
190
191
192 static const vf_info_t* const filters[]={
193     &vf_info_decimate,
194     &vf_info_denoise3d,
195     &vf_info_detc,
196     &vf_info_dint,
197     &vf_info_divtc,
198     &vf_info_down3dright,
199     &vf_info_dsize,
200     &vf_info_eq2,
201     &vf_info_eq,
202     &vf_info_field,
203     &vf_info_fil,
204 //    &vf_info_filmdint, cmmx.h vd.h ‘opt_screen_size_x’
205     &vf_info_fixpts,
206     &vf_info_fspp,
207     &vf_info_geq,
208     &vf_info_harddup,
209     &vf_info_hqdn3d,
210     &vf_info_il,
211     &vf_info_ilpack,
212     &vf_info_ivtc,
213     &vf_info_kerndeint,
214     &vf_info_mcdeint,
215     &vf_info_noise,
216     &vf_info_ow,
217     &vf_info_palette,
218     &vf_info_perspective,
219     &vf_info_phase,
220     &vf_info_pp,
221     &vf_info_pp7,
222     &vf_info_pullup,
223     &vf_info_qp,
224     &vf_info_rectangle,
225     &vf_info_rotate,
226     &vf_info_sab,
227     &vf_info_smartblur,
228     &vf_info_softpulldown,
229     &vf_info_softskip,
230     &vf_info_spp,
231     &vf_info_stereo3d,
232     &vf_info_telecine,
233     &vf_info_tile,
234     &vf_info_tinterlace,
235     &vf_info_unsharp,
236     &vf_info_uspp,
237     &vf_info_yuvcsp,
238     &vf_info_yvu9,
239
240     NULL
241 };
242
243 /*
244 Unsupported filters
245 1bpp
246 ass
247 bmovl
248 crop
249 dvbscale
250 flip
251 expand
252 format
253 halfpack
254 lavc
255 lavcdeint
256 noformat
257 pp
258 scale
259 tfields
260 vo
261 yadif
262 zrmjpeg
263 */
264
265 CpuCaps gCpuCaps; //FIXME initialize this so optims work
266
267
268 static void sws_getFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, SwsFilter **dstFilterParam)
269 {
270         static int firstTime=1;
271         *flags=0;
272
273 #if ARCH_X86
274         if(gCpuCaps.hasMMX)
275                 __asm__ volatile("emms\n\t"::: "memory"); //FIXME this should not be required but it IS (even for non-MMX versions)
276 #endif
277         if(firstTime)
278         {
279                 firstTime=0;
280                 *flags= SWS_PRINT_INFO;
281         }
282         else if( mp_msg_test(MSGT_VFILTER,MSGL_DBG2) ) *flags= SWS_PRINT_INFO;
283
284         switch(SWS_BILINEAR)
285         {
286                 case 0: *flags|= SWS_FAST_BILINEAR; break;
287                 case 1: *flags|= SWS_BILINEAR; break;
288                 case 2: *flags|= SWS_BICUBIC; break;
289                 case 3: *flags|= SWS_X; break;
290                 case 4: *flags|= SWS_POINT; break;
291                 case 5: *flags|= SWS_AREA; break;
292                 case 6: *flags|= SWS_BICUBLIN; break;
293                 case 7: *flags|= SWS_GAUSS; break;
294                 case 8: *flags|= SWS_SINC; break;
295                 case 9: *flags|= SWS_LANCZOS; break;
296                 case 10:*flags|= SWS_SPLINE; break;
297                 default:*flags|= SWS_BILINEAR; break;
298         }
299
300         *srcFilterParam= NULL;
301         *dstFilterParam= NULL;
302 }
303
304 //exact copy from vf_scale.c
305 // will use sws_flags & src_filter (from cmd line)
306 struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat)
307 {
308         int flags, i;
309         SwsFilter *dstFilterParam, *srcFilterParam;
310         enum PixelFormat dfmt, sfmt;
311
312         for(i=0; conversion_map[i].fmt && dstFormat != conversion_map[i].fmt; i++);
313         dfmt= conversion_map[i].pix_fmt;
314         for(i=0; conversion_map[i].fmt && srcFormat != conversion_map[i].fmt; i++);
315         sfmt= conversion_map[i].pix_fmt;
316
317         if (srcFormat == IMGFMT_RGB8 || srcFormat == IMGFMT_BGR8) sfmt = PIX_FMT_PAL8;
318         sws_getFlagsAndFilterFromCmdLine(&flags, &srcFilterParam, &dstFilterParam);
319
320         return sws_getContext(srcW, srcH, sfmt, dstW, dstH, dfmt, flags , srcFilterParam, dstFilterParam, NULL);
321 }
322
323 typedef struct {
324     vf_instance_t vf;
325     vf_instance_t next_vf;
326     AVFilterContext *avfctx;
327     int frame_returned;
328 } MPContext;
329
330 void mp_msg(int mod, int lev, const char *format, ... ){
331     va_list va;
332     va_start(va, format);
333     //FIXME convert lev/mod
334     av_vlog(NULL, AV_LOG_DEBUG, format, va);
335     va_end(va);
336 }
337
338 int mp_msg_test(int mod, int lev){
339     return 123;
340 }
341
342 void init_avcodec(void)
343 {
344     //we maybe should init but its kinda 1. unneeded 2. a bit inpolite from here
345 }
346
347 //Exact copy of vf.c
348 void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src){
349     dst->pict_type= src->pict_type;
350     dst->fields = src->fields;
351     dst->qscale_type= src->qscale_type;
352     if(dst->width == src->width && dst->height == src->height){
353         dst->qstride= src->qstride;
354         dst->qscale= src->qscale;
355     }
356 }
357
358 //Exact copy of vf.c
359 void vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){
360     if (vf->next->draw_slice) {
361         vf->next->draw_slice(vf->next,src,stride,w,h,x,y);
362         return;
363     }
364     if (!vf->dmpi) {
365         mp_msg(MSGT_VFILTER,MSGL_ERR,"draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
366         return;
367     }
368     if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) {
369         memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+vf->dmpi->bpp/8*x,
370             src[0], vf->dmpi->bpp/8*w, h, vf->dmpi->stride[0], stride[0]);
371         return;
372     }
373     memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+x, src[0],
374         w, h, vf->dmpi->stride[0], stride[0]);
375     memcpy_pic(vf->dmpi->planes[1]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[1]+(x>>vf->dmpi->chroma_x_shift),
376         src[1], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]);
377     memcpy_pic(vf->dmpi->planes[2]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[2]+(x>>vf->dmpi->chroma_x_shift),
378         src[2], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]);
379 }
380
381 //Exact copy of vf.c
382 void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h){
383     int y;
384     if(mpi->flags&MP_IMGFLAG_PLANAR){
385         y0&=~1;h+=h&1;
386         if(x0==0 && w==mpi->width){
387             // full width clear:
388             memset(mpi->planes[0]+mpi->stride[0]*y0,0,mpi->stride[0]*h);
389             memset(mpi->planes[1]+mpi->stride[1]*(y0>>mpi->chroma_y_shift),128,mpi->stride[1]*(h>>mpi->chroma_y_shift));
390             memset(mpi->planes[2]+mpi->stride[2]*(y0>>mpi->chroma_y_shift),128,mpi->stride[2]*(h>>mpi->chroma_y_shift));
391         } else
392         for(y=y0;y<y0+h;y+=2){
393             memset(mpi->planes[0]+x0+mpi->stride[0]*y,0,w);
394             memset(mpi->planes[0]+x0+mpi->stride[0]*(y+1),0,w);
395             memset(mpi->planes[1]+(x0>>mpi->chroma_x_shift)+mpi->stride[1]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
396             memset(mpi->planes[2]+(x0>>mpi->chroma_x_shift)+mpi->stride[2]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
397         }
398         return;
399     }
400     // packed:
401     for(y=y0;y<y0+h;y++){
402         unsigned char* dst=mpi->planes[0]+mpi->stride[0]*y+(mpi->bpp>>3)*x0;
403         if(mpi->flags&MP_IMGFLAG_YUV){
404             unsigned int* p=(unsigned int*) dst;
405             int size=(mpi->bpp>>3)*w/4;
406             int i;
407 #if HAVE_BIGENDIAN
408 #define CLEAR_PACKEDYUV_PATTERN 0x00800080
409 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x80008000
410 #else
411 #define CLEAR_PACKEDYUV_PATTERN 0x80008000
412 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x00800080
413 #endif
414             if(mpi->flags&MP_IMGFLAG_SWAPPED){
415                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
416                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
417             } else {
418                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN;
419                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN;
420             }
421         } else
422             memset(dst,0,(mpi->bpp>>3)*w);
423     }
424 }
425
426 int vf_next_query_format(struct vf_instance *vf, unsigned int fmt){
427     return 1;
428 }
429
430 //used by delogo
431 unsigned int vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred){
432     return preferred;
433 }
434
435 mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h){
436     MPContext *m= (MPContext*)(((uint8_t*)vf) - offsetof(MPContext, next_vf));
437   mp_image_t* mpi=NULL;
438   int w2;
439   int number = mp_imgtype >> 16;
440
441   av_assert0(vf->next == NULL); // all existing filters call this just on next
442
443   //vf_dint needs these as it calls vf_get_image() before configuring the output
444   if(vf->w==0 && w>0) vf->w=w;
445   if(vf->h==0 && h>0) vf->h=h;
446
447   av_assert0(w == -1 || w >= vf->w);
448   av_assert0(h == -1 || h >= vf->h);
449   av_assert0(vf->w > 0);
450   av_assert0(vf->h > 0);
451
452   av_log(m->avfctx, AV_LOG_DEBUG, "get_image: %d:%d, vf: %d:%d\n", w,h,vf->w,vf->h);
453
454   if (w == -1) w = vf->w;
455   if (h == -1) h = vf->h;
456
457   w2=(mp_imgflag&MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE)?((w+15)&(~15)):w;
458
459   // Note: we should call libvo first to check if it supports direct rendering
460   // and if not, then fallback to software buffers:
461   switch(mp_imgtype & 0xff){
462   case MP_IMGTYPE_EXPORT:
463     if(!vf->imgctx.export_images[0]) vf->imgctx.export_images[0]=new_mp_image(w2,h);
464     mpi=vf->imgctx.export_images[0];
465     break;
466   case MP_IMGTYPE_STATIC:
467     if(!vf->imgctx.static_images[0]) vf->imgctx.static_images[0]=new_mp_image(w2,h);
468     mpi=vf->imgctx.static_images[0];
469     break;
470   case MP_IMGTYPE_TEMP:
471     if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
472     mpi=vf->imgctx.temp_images[0];
473     break;
474   case MP_IMGTYPE_IPB:
475     if(!(mp_imgflag&MP_IMGFLAG_READABLE)){ // B frame:
476       if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
477       mpi=vf->imgctx.temp_images[0];
478       break;
479     }
480   case MP_IMGTYPE_IP:
481     if(!vf->imgctx.static_images[vf->imgctx.static_idx]) vf->imgctx.static_images[vf->imgctx.static_idx]=new_mp_image(w2,h);
482     mpi=vf->imgctx.static_images[vf->imgctx.static_idx];
483     vf->imgctx.static_idx^=1;
484     break;
485   case MP_IMGTYPE_NUMBERED:
486     if (number == -1) {
487       int i;
488       for (i = 0; i < NUM_NUMBERED_MPI; i++)
489         if (!vf->imgctx.numbered_images[i] || !vf->imgctx.numbered_images[i]->usage_count)
490           break;
491       number = i;
492     }
493     if (number < 0 || number >= NUM_NUMBERED_MPI) return NULL;
494     if (!vf->imgctx.numbered_images[number]) vf->imgctx.numbered_images[number] = new_mp_image(w2,h);
495     mpi = vf->imgctx.numbered_images[number];
496     mpi->number = number;
497     break;
498   }
499   if(mpi){
500     mpi->type=mp_imgtype;
501     mpi->w=vf->w; mpi->h=vf->h;
502     // keep buffer allocation status & color flags only:
503 //    mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE|MP_IMGFLAG_DIRECT);
504     mpi->flags&=MP_IMGFLAG_ALLOCATED|MP_IMGFLAG_TYPE_DISPLAYED|MP_IMGFLAGMASK_COLORS;
505     // accept restrictions, draw_slice and palette flags only:
506     mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK|MP_IMGFLAG_RGB_PALETTE);
507     if(!vf->draw_slice) mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK;
508     if(mpi->width!=w2 || mpi->height!=h){
509 //      printf("vf.c: MPI parameters changed!  %dx%d -> %dx%d   \n", mpi->width,mpi->height,w2,h);
510         if(mpi->flags&MP_IMGFLAG_ALLOCATED){
511             if(mpi->width<w2 || mpi->height<h){
512                 // need to re-allocate buffer memory:
513                 av_free(mpi->planes[0]);
514                 mpi->flags&=~MP_IMGFLAG_ALLOCATED;
515                 mp_msg(MSGT_VFILTER,MSGL_V,"vf.c: have to REALLOCATE buffer memory :(\n");
516             }
517 //      } else {
518         } {
519             mpi->width=w2; mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
520             mpi->height=h; mpi->chroma_height=(h + (1<<mpi->chroma_y_shift) - 1)>>mpi->chroma_y_shift;
521         }
522     }
523     if(!mpi->bpp) mp_image_setfmt(mpi,outfmt);
524     if(!(mpi->flags&MP_IMGFLAG_ALLOCATED) && mpi->type>MP_IMGTYPE_EXPORT){
525
526         av_assert0(!vf->get_image);
527         // check libvo first!
528         if(vf->get_image) vf->get_image(vf,mpi);
529
530         if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
531           // non-direct and not yet allocated image. allocate it!
532           if (!mpi->bpp) { // no way we can allocate this
533               mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
534                      "vf_get_image: Tried to allocate a format that can not be allocated!\n");
535               return NULL;
536           }
537
538           // check if codec prefer aligned stride:
539           if(mp_imgflag&MP_IMGFLAG_PREFER_ALIGNED_STRIDE){
540               int align=(mpi->flags&MP_IMGFLAG_PLANAR &&
541                          mpi->flags&MP_IMGFLAG_YUV) ?
542                          (8<<mpi->chroma_x_shift)-1 : 15; // -- maybe FIXME
543               w2=((w+align)&(~align));
544               if(mpi->width!=w2){
545 #if 0
546                   // we have to change width... check if we CAN co it:
547                   int flags=vf->query_format(vf,outfmt); // should not fail
548                   if(!(flags&3)) mp_msg(MSGT_DECVIDEO,MSGL_WARN,"??? vf_get_image{vf->query_format(outfmt)} failed!\n");
549 //                printf("query -> 0x%X    \n",flags);
550                   if(flags&VFCAP_ACCEPT_STRIDE){
551 #endif
552                       mpi->width=w2;
553                       mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
554 //                  }
555               }
556           }
557
558           mp_image_alloc_planes(mpi);
559 //        printf("clearing img!\n");
560           vf_mpi_clear(mpi,0,0,mpi->width,mpi->height);
561         }
562     }
563     av_assert0(!vf->start_slice);
564     if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)
565         if(vf->start_slice) vf->start_slice(vf,mpi);
566     if(!(mpi->flags&MP_IMGFLAG_TYPE_DISPLAYED)){
567             mp_msg(MSGT_DECVIDEO,MSGL_V,"*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
568                   "NULL"/*vf->info->name*/,
569                   (mpi->type==MP_IMGTYPE_EXPORT)?"Exporting":
570                   ((mpi->flags&MP_IMGFLAG_DIRECT)?"Direct Rendering":"Allocating"),
571                   (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)?" (slices)":"",
572                   mpi->width,mpi->height,mpi->bpp,
573                   (mpi->flags&MP_IMGFLAG_YUV)?"YUV":((mpi->flags&MP_IMGFLAG_SWAPPED)?"BGR":"RGB"),
574                   (mpi->flags&MP_IMGFLAG_PLANAR)?"planar":"packed",
575                   mpi->bpp*mpi->width*mpi->height/8);
576             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",
577                 mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
578                 mpi->stride[0], mpi->stride[1], mpi->stride[2],
579                 mpi->chroma_width, mpi->chroma_height, mpi->chroma_x_shift, mpi->chroma_y_shift);
580             mpi->flags|=MP_IMGFLAG_TYPE_DISPLAYED;
581     }
582
583   mpi->qscale = NULL;
584   }
585   mpi->usage_count++;
586 //    printf("\rVF_MPI: %p %p %p %d %d %d    \n",
587 //      mpi->planes[0],mpi->planes[1],mpi->planes[2],
588 //      mpi->stride[0],mpi->stride[1],mpi->stride[2]);
589   return mpi;
590 }
591
592
593 int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){
594     MPContext *m= (void*)vf;
595     AVFilterLink *outlink     = m->avfctx->outputs[0];
596     AVFilterBuffer    *pic    = av_mallocz(sizeof(AVFilterBuffer));
597     AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef));
598     int i;
599
600     av_assert0(vf->next);
601
602     av_log(m->avfctx, AV_LOG_DEBUG, "vf_next_put_image\n");
603
604     if (!pic || !picref)
605         goto fail;
606
607     picref->buf = pic;
608     picref->buf->please_use_av_free= (void*)av_free;
609     if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps))))
610         goto fail;
611
612     pic->w = picref->video->w = mpi->w;
613     pic->h = picref->video->h = mpi->h;
614
615     /* make sure the buffer gets read permission or it's useless for output */
616     picref->perms = AV_PERM_READ | AV_PERM_REUSE2;
617 //    av_assert0(mpi->flags&MP_IMGFLAG_READABLE);
618     if(!(mpi->flags&MP_IMGFLAG_PRESERVE))
619         picref->perms |= AV_PERM_WRITE;
620
621     pic->refcount = 1;
622     picref->type = AVMEDIA_TYPE_VIDEO;
623
624     for(i=0; conversion_map[i].fmt && mpi->imgfmt != conversion_map[i].fmt; i++);
625     pic->format = picref->format = conversion_map[i].pix_fmt;
626
627     memcpy(pic->data,        mpi->planes,   FFMIN(sizeof(pic->data)    , sizeof(mpi->planes)));
628     memcpy(pic->linesize,    mpi->stride,   FFMIN(sizeof(pic->linesize), sizeof(mpi->stride)));
629     memcpy(picref->data,     pic->data,     sizeof(picref->data));
630     memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
631
632     if(pts != MP_NOPTS_VALUE)
633         picref->pts= pts * av_q2d(outlink->time_base);
634
635     ff_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
636     ff_draw_slice(outlink, 0, picref->video->h, 1);
637     ff_end_frame(outlink);
638     avfilter_unref_buffer(picref);
639     m->frame_returned++;
640
641     return 1;
642 fail:
643     if (picref && picref->video)
644         av_free(picref->video);
645     av_free(picref);
646     av_free(pic);
647     return 0;
648 }
649
650 int vf_next_config(struct vf_instance *vf,
651         int width, int height, int d_width, int d_height,
652         unsigned int voflags, unsigned int outfmt){
653
654     av_assert0(width>0 && height>0);
655     vf->next->w = width; vf->next->h = height;
656
657     return 1;
658 #if 0
659     int flags=vf->next->query_format(vf->next,outfmt);
660     if(!flags){
661         // hmm. colorspace mismatch!!!
662         //this is fatal for us ATM
663         return 0;
664     }
665     mp_msg(MSGT_VFILTER,MSGL_V,"REQ: flags=0x%X  req=0x%X  \n",flags,vf->default_reqs);
666     miss=vf->default_reqs - (flags&vf->default_reqs);
667     if(miss&VFCAP_ACCEPT_STRIDE){
668         // vf requires stride support but vf->next doesn't support it!
669         // let's insert the 'expand' filter, it does the job for us:
670         vf_instance_t* vf2=vf_open_filter(vf->next,"expand",NULL);
671         if(!vf2) return 0; // shouldn't happen!
672         vf->next=vf2;
673     }
674     vf->next->w = width; vf->next->h = height;
675 #endif
676     return 1;
677 }
678
679 int vf_next_control(struct vf_instance *vf, int request, void* data){
680     MPContext *m= (void*)vf;
681     av_log(m->avfctx, AV_LOG_DEBUG, "Received control %d\n", request);
682     return 0;
683 }
684
685 static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt){
686     MPContext *m= (void*)vf;
687     int i;
688     av_log(m->avfctx, AV_LOG_DEBUG, "query %X\n", fmt);
689
690     for(i=0; conversion_map[i].fmt; i++){
691         if(fmt==conversion_map[i].fmt)
692             return 1; //we suport all
693     }
694     return 0;
695 }
696
697
698 static av_cold int init(AVFilterContext *ctx, const char *args)
699 {
700     MPContext *m = ctx->priv;
701     char name[256];
702     int i;
703
704     m->avfctx= ctx;
705
706     if(!args || 1!=sscanf(args, "%255[^:=]", name)){
707         av_log(ctx, AV_LOG_ERROR, "Invalid parameter.\n");
708         return AVERROR(EINVAL);
709     }
710     args+= strlen(name)+1;
711
712     for(i=0; ;i++){
713         if(!filters[i] || !strcmp(name, filters[i]->name))
714             break;
715     }
716
717     if(!filters[i]){
718         av_log(ctx, AV_LOG_ERROR, "Unknown filter %s\n", name);
719         return AVERROR(EINVAL);
720     }
721
722     av_log(ctx, AV_LOG_WARNING,
723            "'%s' is a wrapped MPlayer filter (libmpcodecs). This filter may be removed\n"
724            "once it has been ported to a native libavfilter.\n", name);
725
726     memset(&m->vf,0,sizeof(m->vf));
727     m->vf.info= filters[i];
728
729     m->vf.next        = &m->next_vf;
730     m->vf.put_image   = vf_next_put_image;
731     m->vf.config      = vf_next_config;
732     m->vf.query_format= vf_default_query_format;
733     m->vf.control     = vf_next_control;
734     m->vf.default_caps=VFCAP_ACCEPT_STRIDE;
735     m->vf.default_reqs=0;
736     if(m->vf.info->opts)
737         av_log(ctx, AV_LOG_ERROR, "opts / m_struct_set is unsupported\n");
738 #if 0
739     if(vf->info->opts) { // vf_vo get some special argument
740       const m_struct_t* st = vf->info->opts;
741       void* vf_priv = m_struct_alloc(st);
742       int n;
743       for(n = 0 ; args && args[2*n] ; n++)
744         m_struct_set(st,vf_priv,args[2*n],args[2*n+1]);
745       vf->priv = vf_priv;
746       args = NULL;
747     } else // Otherwise we should have the '_oldargs_'
748       if(args && !strcmp(args[0],"_oldargs_"))
749         args = (char**)args[1];
750       else
751         args = NULL;
752 #endif
753     if(m->vf.info->vf_open(&m->vf, args)<=0){
754         av_log(ctx, AV_LOG_ERROR, "vf_open() of %s with arg=%s failed\n", name, args);
755         return -1;
756     }
757
758     return 0;
759 }
760
761 static av_cold void uninit(AVFilterContext *ctx)
762 {
763     MPContext *m = ctx->priv;
764     vf_instance_t *vf = &m->vf;
765
766     while(vf){
767         vf_instance_t *next = vf->next;
768         if(vf->uninit)
769             vf->uninit(vf);
770         free_mp_image(vf->imgctx.static_images[0]);
771         free_mp_image(vf->imgctx.static_images[1]);
772         free_mp_image(vf->imgctx.temp_images[0]);
773         free_mp_image(vf->imgctx.export_images[0]);
774         vf = next;
775     }
776 }
777
778 static int query_formats(AVFilterContext *ctx)
779 {
780     AVFilterFormats *avfmts=NULL;
781     MPContext *m = ctx->priv;
782     enum PixelFormat lastpixfmt = PIX_FMT_NONE;
783     int i;
784
785     for(i=0; conversion_map[i].fmt; i++){
786         av_log(ctx, AV_LOG_DEBUG, "query: %X\n", conversion_map[i].fmt);
787         if(m->vf.query_format(&m->vf, conversion_map[i].fmt)){
788             av_log(ctx, AV_LOG_DEBUG, "supported,adding\n");
789             if (conversion_map[i].pix_fmt != lastpixfmt) {
790                 ff_add_format(&avfmts, conversion_map[i].pix_fmt);
791                 lastpixfmt = conversion_map[i].pix_fmt;
792             }
793         }
794     }
795
796     //We assume all allowed input formats are also allowed output formats
797     ff_set_common_formats(ctx, avfmts);
798     return 0;
799 }
800
801 static int config_inprops(AVFilterLink *inlink)
802 {
803     MPContext *m = inlink->dst->priv;
804     int i;
805     for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
806
807     av_assert0(conversion_map[i].fmt && inlink->w && inlink->h);
808
809     m->vf.fmt.have_configured = 1;
810     m->vf.fmt.orig_height     = inlink->h;
811     m->vf.fmt.orig_width      = inlink->w;
812     m->vf.fmt.orig_fmt        = conversion_map[i].fmt;
813
814     if(m->vf.config(&m->vf, inlink->w, inlink->h, inlink->w, inlink->h, 0, conversion_map[i].fmt)<=0)
815         return -1;
816
817     return 0;
818 }
819
820 static int config_outprops(AVFilterLink *outlink)
821 {
822     MPContext *m = outlink->src->priv;
823
824     outlink->w = m->next_vf.w;
825     outlink->h = m->next_vf.h;
826
827     return 0;
828 }
829
830 static int request_frame(AVFilterLink *outlink)
831 {
832     MPContext *m = outlink->src->priv;
833     int ret;
834
835     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame\n");
836
837     for(m->frame_returned=0; !m->frame_returned;){
838         ret=ff_request_frame(outlink->src->inputs[0]);
839         if(ret<0)
840             break;
841     }
842
843     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame ret=%d\n", ret);
844     return ret;
845 }
846
847 static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
848 {
849     return 0;
850 }
851
852 static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
853 {
854     return 0;
855 }
856
857 static int end_frame(AVFilterLink *inlink)
858 {
859     MPContext *m = inlink->dst->priv;
860     AVFilterBufferRef *inpic  = inlink->cur_buf;
861     int i;
862     double pts= MP_NOPTS_VALUE;
863     mp_image_t* mpi = new_mp_image(inpic->video->w, inpic->video->h);
864
865     if(inpic->pts != AV_NOPTS_VALUE)
866         pts= inpic->pts / av_q2d(inlink->time_base);
867
868     for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
869     mp_image_setfmt(mpi,conversion_map[i].fmt);
870
871     memcpy(mpi->planes, inpic->data,     FFMIN(sizeof(inpic->data)    , sizeof(mpi->planes)));
872     memcpy(mpi->stride, inpic->linesize, FFMIN(sizeof(inpic->linesize), sizeof(mpi->stride)));
873
874     //FIXME pass interleced & tff flags around
875
876     // mpi->flags|=MP_IMGFLAG_ALLOCATED; ?
877     mpi->flags |= MP_IMGFLAG_READABLE;
878     if(!(inpic->perms & AV_PERM_WRITE))
879         mpi->flags |= MP_IMGFLAG_PRESERVE;
880     if(m->vf.put_image(&m->vf, mpi, pts) == 0){
881         av_log(m->avfctx, AV_LOG_DEBUG, "put_image() says skip\n");
882     }
883     free_mp_image(mpi);
884     return 0;
885 }
886
887 AVFilter avfilter_vf_mp = {
888     .name      = "mp",
889     .description = NULL_IF_CONFIG_SMALL("Apply a libmpcodecs filter to the input video."),
890     .init = init,
891     .uninit = uninit,
892     .priv_size = sizeof(MPContext),
893     .query_formats = query_formats,
894
895     .inputs    = (const AVFilterPad[]) {{ .name      = "default",
896                                     .type            = AVMEDIA_TYPE_VIDEO,
897                                     .start_frame     = start_frame,
898                                     .draw_slice      = null_draw_slice,
899                                     .end_frame       = end_frame,
900                                     .config_props    = config_inprops,
901                                     .min_perms       = AV_PERM_READ, },
902                                   { .name = NULL}},
903     .outputs   = (const AVFilterPad[]) {{ .name      = "default",
904                                     .type            = AVMEDIA_TYPE_VIDEO,
905                                     .request_frame   = request_frame,
906                                     .config_props    = config_outprops, },
907                                   { .name = NULL}},
908 };