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