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