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