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