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