OSDN Git Service

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