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