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