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