63fdedd6997d7b33c947cb76b87ea1667d6beac0
[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 #include "libavutil/opt.h"
36
37 #include "libmpcodecs/vf.h"
38 #include "libmpcodecs/img_format.h"
39 #include "libmpcodecs/cpudetect.h"
40 #include "libmpcodecs/libvo/fastmemcpy.h"
41
42 #include "libswscale/swscale.h"
43
44
45 //FIXME maybe link the orig in
46 //XXX: identical pix_fmt must be following with each others
47 static const struct {
48     int fmt;
49     enum AVPixelFormat pix_fmt;
50 } conversion_map[] = {
51     {IMGFMT_ARGB, AV_PIX_FMT_ARGB},
52     {IMGFMT_BGRA, AV_PIX_FMT_BGRA},
53     {IMGFMT_BGR24, AV_PIX_FMT_BGR24},
54     {IMGFMT_BGR16BE, AV_PIX_FMT_RGB565BE},
55     {IMGFMT_BGR16LE, AV_PIX_FMT_RGB565LE},
56     {IMGFMT_BGR15BE, AV_PIX_FMT_RGB555BE},
57     {IMGFMT_BGR15LE, AV_PIX_FMT_RGB555LE},
58     {IMGFMT_BGR12BE, AV_PIX_FMT_RGB444BE},
59     {IMGFMT_BGR12LE, AV_PIX_FMT_RGB444LE},
60     {IMGFMT_BGR8,  AV_PIX_FMT_RGB8},
61     {IMGFMT_BGR4,  AV_PIX_FMT_RGB4},
62     {IMGFMT_BGR1,  AV_PIX_FMT_MONOBLACK},
63     {IMGFMT_RGB1,  AV_PIX_FMT_MONOBLACK},
64     {IMGFMT_RG4B,  AV_PIX_FMT_BGR4_BYTE},
65     {IMGFMT_BG4B,  AV_PIX_FMT_RGB4_BYTE},
66     {IMGFMT_RGB48LE, AV_PIX_FMT_RGB48LE},
67     {IMGFMT_RGB48BE, AV_PIX_FMT_RGB48BE},
68     {IMGFMT_ABGR, AV_PIX_FMT_ABGR},
69     {IMGFMT_RGBA, AV_PIX_FMT_RGBA},
70     {IMGFMT_RGB24, AV_PIX_FMT_RGB24},
71     {IMGFMT_RGB16BE, AV_PIX_FMT_BGR565BE},
72     {IMGFMT_RGB16LE, AV_PIX_FMT_BGR565LE},
73     {IMGFMT_RGB15BE, AV_PIX_FMT_BGR555BE},
74     {IMGFMT_RGB15LE, AV_PIX_FMT_BGR555LE},
75     {IMGFMT_RGB12BE, AV_PIX_FMT_BGR444BE},
76     {IMGFMT_RGB12LE, AV_PIX_FMT_BGR444LE},
77     {IMGFMT_RGB8,  AV_PIX_FMT_BGR8},
78     {IMGFMT_RGB4,  AV_PIX_FMT_BGR4},
79     {IMGFMT_BGR8,  AV_PIX_FMT_PAL8},
80     {IMGFMT_YUY2,  AV_PIX_FMT_YUYV422},
81     {IMGFMT_UYVY,  AV_PIX_FMT_UYVY422},
82     {IMGFMT_NV12,  AV_PIX_FMT_NV12},
83     {IMGFMT_NV21,  AV_PIX_FMT_NV21},
84     {IMGFMT_Y800,  AV_PIX_FMT_GRAY8},
85     {IMGFMT_Y8,    AV_PIX_FMT_GRAY8},
86     {IMGFMT_YVU9,  AV_PIX_FMT_YUV410P},
87     {IMGFMT_IF09,  AV_PIX_FMT_YUV410P},
88     {IMGFMT_YV12,  AV_PIX_FMT_YUV420P},
89     {IMGFMT_I420,  AV_PIX_FMT_YUV420P},
90     {IMGFMT_IYUV,  AV_PIX_FMT_YUV420P},
91     {IMGFMT_411P,  AV_PIX_FMT_YUV411P},
92     {IMGFMT_422P,  AV_PIX_FMT_YUV422P},
93     {IMGFMT_444P,  AV_PIX_FMT_YUV444P},
94     {IMGFMT_440P,  AV_PIX_FMT_YUV440P},
95
96     {IMGFMT_420A,  AV_PIX_FMT_YUVA420P},
97
98     {IMGFMT_420P16_LE,  AV_PIX_FMT_YUV420P16LE},
99     {IMGFMT_420P16_BE,  AV_PIX_FMT_YUV420P16BE},
100     {IMGFMT_422P16_LE,  AV_PIX_FMT_YUV422P16LE},
101     {IMGFMT_422P16_BE,  AV_PIX_FMT_YUV422P16BE},
102     {IMGFMT_444P16_LE,  AV_PIX_FMT_YUV444P16LE},
103     {IMGFMT_444P16_BE,  AV_PIX_FMT_YUV444P16BE},
104
105     // YUVJ are YUV formats that use the full Y range and not just
106     // 16 - 235 (see colorspaces.txt).
107     // Currently they are all treated the same way.
108     {IMGFMT_YV12,  AV_PIX_FMT_YUVJ420P},
109     {IMGFMT_422P,  AV_PIX_FMT_YUVJ422P},
110     {IMGFMT_444P,  AV_PIX_FMT_YUVJ444P},
111     {IMGFMT_440P,  AV_PIX_FMT_YUVJ440P},
112
113 #if FF_API_XVMC
114     {IMGFMT_XVMC_MOCO_MPEG2, AV_PIX_FMT_XVMC_MPEG2_MC},
115     {IMGFMT_XVMC_IDCT_MPEG2, AV_PIX_FMT_XVMC_MPEG2_IDCT},
116 #endif /* FF_API_XVMC */
117
118     {IMGFMT_VDPAU_MPEG1,     AV_PIX_FMT_VDPAU_MPEG1},
119     {IMGFMT_VDPAU_MPEG2,     AV_PIX_FMT_VDPAU_MPEG2},
120     {IMGFMT_VDPAU_H264,      AV_PIX_FMT_VDPAU_H264},
121     {IMGFMT_VDPAU_WMV3,      AV_PIX_FMT_VDPAU_WMV3},
122     {IMGFMT_VDPAU_VC1,       AV_PIX_FMT_VDPAU_VC1},
123     {IMGFMT_VDPAU_MPEG4,     AV_PIX_FMT_VDPAU_MPEG4},
124     {0, AV_PIX_FMT_NONE}
125 };
126
127 extern const vf_info_t ff_vf_info_softpulldown;
128
129 static const vf_info_t* const filters[]={
130     &ff_vf_info_softpulldown,
131     NULL
132 };
133
134 /*
135 Unsupported filters
136 1bpp
137 ass
138 bmovl
139 crop
140 dvbscale
141 flip
142 expand
143 format
144 halfpack
145 lavc
146 lavcdeint
147 noformat
148 pp
149 scale
150 tfields
151 vo
152 yadif
153 zrmjpeg
154 */
155
156 CpuCaps ff_gCpuCaps; //FIXME initialize this so optims work
157
158 enum AVPixelFormat ff_mp2ff_pix_fmt(int mp){
159     int i;
160     for(i=0; conversion_map[i].fmt && mp != conversion_map[i].fmt; i++)
161         ;
162     return mp == conversion_map[i].fmt ? conversion_map[i].pix_fmt : AV_PIX_FMT_NONE;
163 }
164
165 typedef struct {
166     const AVClass *class;
167     vf_instance_t vf;
168     vf_instance_t next_vf;
169     AVFilterContext *avfctx;
170     int frame_returned;
171     char *filter;
172     enum AVPixelFormat in_pix_fmt;
173 } MPContext;
174
175 #define OFFSET(x) offsetof(MPContext, x)
176 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
177 static const AVOption mp_options[] = {
178     { "filter", "set MPlayer filter name and parameters", OFFSET(filter), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
179     { NULL }
180 };
181
182 AVFILTER_DEFINE_CLASS(mp);
183
184 void ff_mp_msg(int mod, int lev, const char *format, ... ){
185     va_list va;
186     va_start(va, format);
187     //FIXME convert lev/mod
188     av_vlog(NULL, AV_LOG_DEBUG, format, va);
189     va_end(va);
190 }
191
192 int ff_mp_msg_test(int mod, int lev){
193     return 123;
194 }
195
196 //Exact copy of vf.c
197 void ff_vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src){
198     dst->pict_type= src->pict_type;
199     dst->fields = src->fields;
200     dst->qscale_type= src->qscale_type;
201     if(dst->width == src->width && dst->height == src->height){
202         dst->qstride= src->qstride;
203         dst->qscale= src->qscale;
204     }
205 }
206
207 //Exact copy of vf.c
208 void ff_vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){
209     if (vf->next->draw_slice) {
210         vf->next->draw_slice(vf->next,src,stride,w,h,x,y);
211         return;
212     }
213     if (!vf->dmpi) {
214         ff_mp_msg(MSGT_VFILTER,MSGL_ERR,"draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
215         return;
216     }
217     if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) {
218         memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+vf->dmpi->bpp/8*x,
219             src[0], vf->dmpi->bpp/8*w, h, vf->dmpi->stride[0], stride[0]);
220         return;
221     }
222     memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+x, src[0],
223         w, h, vf->dmpi->stride[0], stride[0]);
224     memcpy_pic(vf->dmpi->planes[1]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[1]+(x>>vf->dmpi->chroma_x_shift),
225         src[1], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]);
226     memcpy_pic(vf->dmpi->planes[2]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[2]+(x>>vf->dmpi->chroma_x_shift),
227         src[2], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]);
228 }
229
230 //Exact copy of vf.c
231 void ff_vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h){
232     int y;
233     if(mpi->flags&MP_IMGFLAG_PLANAR){
234         y0&=~1;h+=h&1;
235         if(x0==0 && w==mpi->width){
236             // full width clear:
237             memset(mpi->planes[0]+mpi->stride[0]*y0,0,mpi->stride[0]*h);
238             memset(mpi->planes[1]+mpi->stride[1]*(y0>>mpi->chroma_y_shift),128,mpi->stride[1]*(h>>mpi->chroma_y_shift));
239             memset(mpi->planes[2]+mpi->stride[2]*(y0>>mpi->chroma_y_shift),128,mpi->stride[2]*(h>>mpi->chroma_y_shift));
240         } else
241         for(y=y0;y<y0+h;y+=2){
242             memset(mpi->planes[0]+x0+mpi->stride[0]*y,0,w);
243             memset(mpi->planes[0]+x0+mpi->stride[0]*(y+1),0,w);
244             memset(mpi->planes[1]+(x0>>mpi->chroma_x_shift)+mpi->stride[1]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
245             memset(mpi->planes[2]+(x0>>mpi->chroma_x_shift)+mpi->stride[2]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
246         }
247         return;
248     }
249     // packed:
250     for(y=y0;y<y0+h;y++){
251         unsigned char* dst=mpi->planes[0]+mpi->stride[0]*y+(mpi->bpp>>3)*x0;
252         if(mpi->flags&MP_IMGFLAG_YUV){
253             unsigned int* p=(unsigned int*) dst;
254             int size=(mpi->bpp>>3)*w/4;
255             int i;
256 #if HAVE_BIGENDIAN
257 #define CLEAR_PACKEDYUV_PATTERN 0x00800080
258 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x80008000
259 #else
260 #define CLEAR_PACKEDYUV_PATTERN 0x80008000
261 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x00800080
262 #endif
263             if(mpi->flags&MP_IMGFLAG_SWAPPED){
264                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
265                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
266             } else {
267                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN;
268                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN;
269             }
270         } else
271             memset(dst,0,(mpi->bpp>>3)*w);
272     }
273 }
274
275 int ff_vf_next_query_format(struct vf_instance *vf, unsigned int fmt){
276     return 1;
277 }
278
279 //used by delogo
280 unsigned int ff_vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred){
281     return preferred;
282 }
283
284 mp_image_t* ff_vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h){
285     MPContext *m= (MPContext*)(((uint8_t*)vf) - offsetof(MPContext, next_vf));
286   mp_image_t* mpi=NULL;
287   int w2;
288   int number = mp_imgtype >> 16;
289
290   av_assert0(vf->next == NULL); // all existing filters call this just on next
291
292   //vf_dint needs these as it calls ff_vf_get_image() before configuring the output
293   if(vf->w==0 && w>0) vf->w=w;
294   if(vf->h==0 && h>0) vf->h=h;
295
296   av_assert0(w == -1 || w >= vf->w);
297   av_assert0(h == -1 || h >= vf->h);
298   av_assert0(vf->w > 0);
299   av_assert0(vf->h > 0);
300
301   av_log(m->avfctx, AV_LOG_DEBUG, "get_image: %d:%d, vf: %d:%d\n", w,h,vf->w,vf->h);
302
303   if (w == -1) w = vf->w;
304   if (h == -1) h = vf->h;
305
306   w2=(mp_imgflag&MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE)?((w+15)&(~15)):w;
307
308   // Note: we should call libvo first to check if it supports direct rendering
309   // and if not, then fallback to software buffers:
310   switch(mp_imgtype & 0xff){
311   case MP_IMGTYPE_EXPORT:
312     if(!vf->imgctx.export_images[0]) vf->imgctx.export_images[0]=ff_new_mp_image(w2,h);
313     mpi=vf->imgctx.export_images[0];
314     break;
315   case MP_IMGTYPE_STATIC:
316     if(!vf->imgctx.static_images[0]) vf->imgctx.static_images[0]=ff_new_mp_image(w2,h);
317     mpi=vf->imgctx.static_images[0];
318     break;
319   case MP_IMGTYPE_TEMP:
320     if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=ff_new_mp_image(w2,h);
321     mpi=vf->imgctx.temp_images[0];
322     break;
323   case MP_IMGTYPE_IPB:
324     if(!(mp_imgflag&MP_IMGFLAG_READABLE)){ // B frame:
325       if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=ff_new_mp_image(w2,h);
326       mpi=vf->imgctx.temp_images[0];
327       break;
328     }
329   case MP_IMGTYPE_IP:
330     if(!vf->imgctx.static_images[vf->imgctx.static_idx]) vf->imgctx.static_images[vf->imgctx.static_idx]=ff_new_mp_image(w2,h);
331     mpi=vf->imgctx.static_images[vf->imgctx.static_idx];
332     vf->imgctx.static_idx^=1;
333     break;
334   case MP_IMGTYPE_NUMBERED:
335     if (number == -1) {
336       int i;
337       for (i = 0; i < NUM_NUMBERED_MPI; i++)
338         if (!vf->imgctx.numbered_images[i] || !vf->imgctx.numbered_images[i]->usage_count)
339           break;
340       number = i;
341     }
342     if (number < 0 || number >= NUM_NUMBERED_MPI) return NULL;
343     if (!vf->imgctx.numbered_images[number]) vf->imgctx.numbered_images[number] = ff_new_mp_image(w2,h);
344     mpi = vf->imgctx.numbered_images[number];
345     mpi->number = number;
346     break;
347   }
348   if(mpi){
349     mpi->type=mp_imgtype;
350     mpi->w=vf->w; mpi->h=vf->h;
351     // keep buffer allocation status & color flags only:
352 //    mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE|MP_IMGFLAG_DIRECT);
353     mpi->flags&=MP_IMGFLAG_ALLOCATED|MP_IMGFLAG_TYPE_DISPLAYED|MP_IMGFLAGMASK_COLORS;
354     // accept restrictions, draw_slice and palette flags only:
355     mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK|MP_IMGFLAG_RGB_PALETTE);
356     if(!vf->draw_slice) mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK;
357     if(mpi->width!=w2 || mpi->height!=h){
358 //      printf("vf.c: MPI parameters changed!  %dx%d -> %dx%d   \n", mpi->width,mpi->height,w2,h);
359         if(mpi->flags&MP_IMGFLAG_ALLOCATED){
360             if(mpi->width<w2 || mpi->height<h){
361                 // need to re-allocate buffer memory:
362                 av_free(mpi->planes[0]);
363                 mpi->flags&=~MP_IMGFLAG_ALLOCATED;
364                 ff_mp_msg(MSGT_VFILTER,MSGL_V,"vf.c: have to REALLOCATE buffer memory :(\n");
365             }
366 //      } else {
367         } {
368             mpi->width=w2; mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
369             mpi->height=h; mpi->chroma_height=(h + (1<<mpi->chroma_y_shift) - 1)>>mpi->chroma_y_shift;
370         }
371     }
372     if(!mpi->bpp) ff_mp_image_setfmt(mpi,outfmt);
373     if(!(mpi->flags&MP_IMGFLAG_ALLOCATED) && mpi->type>MP_IMGTYPE_EXPORT){
374
375         av_assert0(!vf->get_image);
376         // check libvo first!
377         if(vf->get_image) vf->get_image(vf,mpi);
378
379         if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
380           // non-direct and not yet allocated image. allocate it!
381           if (!mpi->bpp) { // no way we can allocate this
382               ff_mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
383                      "ff_vf_get_image: Tried to allocate a format that can not be allocated!\n");
384               return NULL;
385           }
386
387           // check if codec prefer aligned stride:
388           if(mp_imgflag&MP_IMGFLAG_PREFER_ALIGNED_STRIDE){
389               int align=(mpi->flags&MP_IMGFLAG_PLANAR &&
390                          mpi->flags&MP_IMGFLAG_YUV) ?
391                          (8<<mpi->chroma_x_shift)-1 : 15; // -- maybe FIXME
392               w2=((w+align)&(~align));
393               if(mpi->width!=w2){
394 #if 0
395                   // we have to change width... check if we CAN co it:
396                   int flags=vf->query_format(vf,outfmt); // should not fail
397                   if(!(flags&3)) ff_mp_msg(MSGT_DECVIDEO,MSGL_WARN,"??? ff_vf_get_image{vf->query_format(outfmt)} failed!\n");
398 //                printf("query -> 0x%X    \n",flags);
399                   if(flags&VFCAP_ACCEPT_STRIDE){
400 #endif
401                       mpi->width=w2;
402                       mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
403 //                  }
404               }
405           }
406
407           ff_mp_image_alloc_planes(mpi);
408 //        printf("clearing img!\n");
409           ff_vf_mpi_clear(mpi,0,0,mpi->width,mpi->height);
410         }
411     }
412     av_assert0(!vf->start_slice);
413     if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)
414         if(vf->start_slice) vf->start_slice(vf,mpi);
415     if(!(mpi->flags&MP_IMGFLAG_TYPE_DISPLAYED)){
416             ff_mp_msg(MSGT_DECVIDEO,MSGL_V,"*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
417                   "NULL"/*vf->info->name*/,
418                   (mpi->type==MP_IMGTYPE_EXPORT)?"Exporting":
419                   ((mpi->flags&MP_IMGFLAG_DIRECT)?"Direct Rendering":"Allocating"),
420                   (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)?" (slices)":"",
421                   mpi->width,mpi->height,mpi->bpp,
422                   (mpi->flags&MP_IMGFLAG_YUV)?"YUV":((mpi->flags&MP_IMGFLAG_SWAPPED)?"BGR":"RGB"),
423                   (mpi->flags&MP_IMGFLAG_PLANAR)?"planar":"packed",
424                   mpi->bpp*mpi->width*mpi->height/8);
425             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",
426                 mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
427                 mpi->stride[0], mpi->stride[1], mpi->stride[2],
428                 mpi->chroma_width, mpi->chroma_height, mpi->chroma_x_shift, mpi->chroma_y_shift);
429             mpi->flags|=MP_IMGFLAG_TYPE_DISPLAYED;
430     }
431
432   mpi->qscale = NULL;
433   mpi->usage_count++;
434   }
435 //    printf("\rVF_MPI: %p %p %p %d %d %d    \n",
436 //      mpi->planes[0],mpi->planes[1],mpi->planes[2],
437 //      mpi->stride[0],mpi->stride[1],mpi->stride[2]);
438   return mpi;
439 }
440
441 int ff_vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){
442     MPContext *m= (MPContext*)(((uint8_t*)vf) - offsetof(MPContext, vf));
443     AVFilterLink *outlink     = m->avfctx->outputs[0];
444     AVFrame *picref = av_frame_alloc();
445     int i;
446
447     av_assert0(vf->next);
448
449     av_log(m->avfctx, AV_LOG_DEBUG, "ff_vf_next_put_image\n");
450
451     if (!picref)
452         goto fail;
453
454     picref->width  = mpi->w;
455     picref->height = mpi->h;
456
457     for(i=0; conversion_map[i].fmt && mpi->imgfmt != conversion_map[i].fmt; i++);
458     picref->format = conversion_map[i].pix_fmt;
459
460     for(i=0; conversion_map[i].fmt && m->in_pix_fmt != conversion_map[i].pix_fmt; i++);
461     if (mpi->imgfmt == conversion_map[i].fmt)
462         picref->format = conversion_map[i].pix_fmt;
463
464     memcpy(picref->linesize, mpi->stride, FFMIN(sizeof(picref->linesize), sizeof(mpi->stride)));
465
466     for(i=0; i<4 && mpi->stride[i]; i++){
467         picref->data[i] = mpi->planes[i];
468     }
469
470     if(pts != MP_NOPTS_VALUE)
471         picref->pts= pts * av_q2d(outlink->time_base);
472
473     if(1) { // mp buffers are currently unsupported in libavfilter, we thus must copy
474         AVFrame *tofree = picref;
475         picref = av_frame_clone(picref);
476         av_frame_free(&tofree);
477     }
478
479     ff_filter_frame(outlink, picref);
480     m->frame_returned++;
481
482     return 1;
483 fail:
484     av_frame_free(&picref);
485     return 0;
486 }
487
488 int ff_vf_next_config(struct vf_instance *vf,
489         int width, int height, int d_width, int d_height,
490         unsigned int voflags, unsigned int outfmt){
491
492     av_assert0(width>0 && height>0);
493     vf->next->w = width; vf->next->h = height;
494
495     return 1;
496 #if 0
497     int flags=vf->next->query_format(vf->next,outfmt);
498     if(!flags){
499         // hmm. colorspace mismatch!!!
500         //this is fatal for us ATM
501         return 0;
502     }
503     ff_mp_msg(MSGT_VFILTER,MSGL_V,"REQ: flags=0x%X  req=0x%X  \n",flags,vf->default_reqs);
504     miss=vf->default_reqs - (flags&vf->default_reqs);
505     if(miss&VFCAP_ACCEPT_STRIDE){
506         // vf requires stride support but vf->next doesn't support it!
507         // let's insert the 'expand' filter, it does the job for us:
508         vf_instance_t* vf2=vf_open_filter(vf->next,"expand",NULL);
509         if(!vf2) return 0; // shouldn't happen!
510         vf->next=vf2;
511     }
512     vf->next->w = width; vf->next->h = height;
513     return 1;
514 #endif
515 }
516
517 int ff_vf_next_control(struct vf_instance *vf, int request, void* data){
518     MPContext *m= (MPContext*)(((uint8_t*)vf) - offsetof(MPContext, vf));
519     av_log(m->avfctx, AV_LOG_DEBUG, "Received control %d\n", request);
520     return 0;
521 }
522
523 static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt){
524     MPContext *m= (MPContext*)(((uint8_t*)vf) - offsetof(MPContext, vf));
525     int i;
526     av_log(m->avfctx, AV_LOG_DEBUG, "query %X\n", fmt);
527
528     for(i=0; conversion_map[i].fmt; i++){
529         if(fmt==conversion_map[i].fmt)
530             return 1; //we suport all
531     }
532     return 0;
533 }
534
535
536 static av_cold int init(AVFilterContext *ctx)
537 {
538     MPContext *m = ctx->priv;
539     int cpu_flags = av_get_cpu_flags();
540     char name[256];
541     const char *args;
542     int i;
543
544     ff_gCpuCaps.hasMMX      = cpu_flags & AV_CPU_FLAG_MMX;
545     ff_gCpuCaps.hasMMX2     = cpu_flags & AV_CPU_FLAG_MMX2;
546     ff_gCpuCaps.hasSSE      = cpu_flags & AV_CPU_FLAG_SSE;
547     ff_gCpuCaps.hasSSE2     = cpu_flags & AV_CPU_FLAG_SSE2;
548     ff_gCpuCaps.hasSSE3     = cpu_flags & AV_CPU_FLAG_SSE3;
549     ff_gCpuCaps.hasSSSE3    = cpu_flags & AV_CPU_FLAG_SSSE3;
550     ff_gCpuCaps.hasSSE4     = cpu_flags & AV_CPU_FLAG_SSE4;
551     ff_gCpuCaps.hasSSE42    = cpu_flags & AV_CPU_FLAG_SSE42;
552     ff_gCpuCaps.hasAVX      = cpu_flags & AV_CPU_FLAG_AVX;
553     ff_gCpuCaps.has3DNow    = cpu_flags & AV_CPU_FLAG_3DNOW;
554     ff_gCpuCaps.has3DNowExt = cpu_flags & AV_CPU_FLAG_3DNOWEXT;
555
556     m->avfctx= ctx;
557
558     args = m->filter;
559     if(!args || 1!=sscanf(args, "%255[^:=]", name)){
560         av_log(ctx, AV_LOG_ERROR, "Invalid parameter.\n");
561         return AVERROR(EINVAL);
562     }
563     args += strlen(name);
564     if (args[0] == '=')
565         args++;
566
567     for(i=0; ;i++){
568         if(!filters[i] || !strcmp(name, filters[i]->name))
569             break;
570     }
571
572     if(!filters[i]){
573         av_log(ctx, AV_LOG_ERROR, "Unknown filter %s\n", name);
574         return AVERROR(EINVAL);
575     }
576
577     av_log(ctx, AV_LOG_WARNING,
578            "'%s' is a wrapped MPlayer filter (libmpcodecs). This filter may be removed\n"
579            "once it has been ported to a native libavfilter.\n", name);
580
581     memset(&m->vf,0,sizeof(m->vf));
582     m->vf.info= filters[i];
583
584     m->vf.next        = &m->next_vf;
585     m->vf.put_image   = ff_vf_next_put_image;
586     m->vf.config      = ff_vf_next_config;
587     m->vf.query_format= vf_default_query_format;
588     m->vf.control     = ff_vf_next_control;
589     m->vf.default_caps=VFCAP_ACCEPT_STRIDE;
590     m->vf.default_reqs=0;
591     if(m->vf.info->opts)
592         av_log(ctx, AV_LOG_ERROR, "opts / m_struct_set is unsupported\n");
593 #if 0
594     if(vf->info->opts) { // vf_vo get some special argument
595       const m_struct_t* st = vf->info->opts;
596       void* vf_priv = m_struct_alloc(st);
597       int n;
598       for(n = 0 ; args && args[2*n] ; n++)
599         m_struct_set(st,vf_priv,args[2*n],args[2*n+1]);
600       vf->priv = vf_priv;
601       args = NULL;
602     } else // Otherwise we should have the '_oldargs_'
603       if(args && !strcmp(args[0],"_oldargs_"))
604         args = (char**)args[1];
605       else
606         args = NULL;
607 #endif
608     if(m->vf.info->vf_open(&m->vf, (char*)args)<=0){
609         av_log(ctx, AV_LOG_ERROR, "vf_open() of %s with arg=%s failed\n", name, args);
610         return -1;
611     }
612
613     return 0;
614 }
615
616 static av_cold void uninit(AVFilterContext *ctx)
617 {
618     MPContext *m = ctx->priv;
619     vf_instance_t *vf = &m->vf;
620
621     while(vf){
622         vf_instance_t *next = vf->next;
623         if(vf->uninit)
624             vf->uninit(vf);
625         ff_free_mp_image(vf->imgctx.static_images[0]);
626         ff_free_mp_image(vf->imgctx.static_images[1]);
627         ff_free_mp_image(vf->imgctx.temp_images[0]);
628         ff_free_mp_image(vf->imgctx.export_images[0]);
629         vf = next;
630     }
631 }
632
633 static int query_formats(AVFilterContext *ctx)
634 {
635     AVFilterFormats *avfmts=NULL;
636     MPContext *m = ctx->priv;
637     enum AVPixelFormat lastpixfmt = AV_PIX_FMT_NONE;
638     int i;
639
640     for(i=0; conversion_map[i].fmt; i++){
641         av_log(ctx, AV_LOG_DEBUG, "query: %X\n", conversion_map[i].fmt);
642         if(m->vf.query_format(&m->vf, conversion_map[i].fmt)){
643             av_log(ctx, AV_LOG_DEBUG, "supported,adding\n");
644             if (conversion_map[i].pix_fmt != lastpixfmt) {
645                 ff_add_format(&avfmts, conversion_map[i].pix_fmt);
646                 lastpixfmt = conversion_map[i].pix_fmt;
647             }
648         }
649     }
650
651     if (!avfmts)
652         return -1;
653
654     //We assume all allowed input formats are also allowed output formats
655     ff_set_common_formats(ctx, avfmts);
656     return 0;
657 }
658
659 static int config_inprops(AVFilterLink *inlink)
660 {
661     MPContext *m = inlink->dst->priv;
662     int i;
663     for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
664
665     av_assert0(conversion_map[i].fmt && inlink->w && inlink->h);
666
667     m->vf.fmt.have_configured = 1;
668     m->vf.fmt.orig_height     = inlink->h;
669     m->vf.fmt.orig_width      = inlink->w;
670     m->vf.fmt.orig_fmt        = conversion_map[i].fmt;
671
672     if(m->vf.config(&m->vf, inlink->w, inlink->h, inlink->w, inlink->h, 0, conversion_map[i].fmt)<=0)
673         return -1;
674
675     return 0;
676 }
677
678 static int config_outprops(AVFilterLink *outlink)
679 {
680     MPContext *m = outlink->src->priv;
681
682     outlink->w = m->next_vf.w;
683     outlink->h = m->next_vf.h;
684
685     return 0;
686 }
687
688 static int request_frame(AVFilterLink *outlink)
689 {
690     MPContext *m = outlink->src->priv;
691     int ret;
692
693     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame\n");
694
695     for(m->frame_returned=0; !m->frame_returned;){
696         ret=ff_request_frame(outlink->src->inputs[0]);
697         if(ret<0)
698             break;
699     }
700
701     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame ret=%d\n", ret);
702     return ret;
703 }
704
705 static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
706 {
707     MPContext *m = inlink->dst->priv;
708     int i;
709     double pts= MP_NOPTS_VALUE;
710     mp_image_t* mpi = ff_new_mp_image(inpic->width, inpic->height);
711
712     if(inpic->pts != AV_NOPTS_VALUE)
713         pts= inpic->pts / av_q2d(inlink->time_base);
714
715     for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
716     ff_mp_image_setfmt(mpi,conversion_map[i].fmt);
717     m->in_pix_fmt = inlink->format;
718
719     memcpy(mpi->planes, inpic->data,     FFMIN(sizeof(inpic->data)    , sizeof(mpi->planes)));
720     memcpy(mpi->stride, inpic->linesize, FFMIN(sizeof(inpic->linesize), sizeof(mpi->stride)));
721
722     if (inpic->interlaced_frame)
723         mpi->fields |= MP_IMGFIELD_INTERLACED;
724     if (inpic->top_field_first)
725         mpi->fields |= MP_IMGFIELD_TOP_FIRST;
726     if (inpic->repeat_pict)
727         mpi->fields |= MP_IMGFIELD_REPEAT_FIRST;
728
729     // mpi->flags|=MP_IMGFLAG_ALLOCATED; ?
730     mpi->flags |= MP_IMGFLAG_READABLE;
731     if(!av_frame_is_writable(inpic))
732         mpi->flags |= MP_IMGFLAG_PRESERVE;
733     if(m->vf.put_image(&m->vf, mpi, pts) == 0){
734         av_log(m->avfctx, AV_LOG_DEBUG, "put_image() says skip\n");
735     }else{
736         av_frame_free(&inpic);
737     }
738     ff_free_mp_image(mpi);
739     return 0;
740 }
741
742 static const AVFilterPad mp_inputs[] = {
743     {
744         .name         = "default",
745         .type         = AVMEDIA_TYPE_VIDEO,
746         .filter_frame = filter_frame,
747         .config_props = config_inprops,
748     },
749     { NULL }
750 };
751
752 static const AVFilterPad mp_outputs[] = {
753     {
754         .name          = "default",
755         .type          = AVMEDIA_TYPE_VIDEO,
756         .request_frame = request_frame,
757         .config_props  = config_outprops,
758     },
759     { NULL }
760 };
761
762 AVFilter ff_vf_mp = {
763     .name          = "mp",
764     .description   = NULL_IF_CONFIG_SMALL("Apply a libmpcodecs filter to the input video."),
765     .init          = init,
766     .uninit        = uninit,
767     .priv_size     = sizeof(MPContext),
768     .query_formats = query_formats,
769     .inputs        = mp_inputs,
770     .outputs       = mp_outputs,
771     .priv_class    = &mp_class,
772 };