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