• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavfilter/vf_mp.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Michael Niedermayer
00003  *
00004  * This file is part of FFmpeg.
00005  *
00006  * FFmpeg is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * FFmpeg is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with FFmpeg; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  *
00020  * Parts of this file have been stolen from mplayer
00021  */
00022 
00027 #include "avfilter.h"
00028 #include "libavutil/avassert.h"
00029 #include "libavutil/pixdesc.h"
00030 #include "libavutil/intreadwrite.h"
00031 #include "libavutil/imgutils.h"
00032 
00033 #include "libmpcodecs/vf.h"
00034 #include "libmpcodecs/img_format.h"
00035 #include "libmpcodecs/cpudetect.h"
00036 #include "libmpcodecs/vd_ffmpeg.h"
00037 #include "libmpcodecs/vf_scale.h"
00038 #include "libmpcodecs/libvo/fastmemcpy.h"
00039 
00040 #include "libswscale/swscale.h"
00041 
00042 
00043 //FIXME maybe link the orig in
00044 //XXX: identical pix_fmt must be following with each others
00045 static const struct {
00046     int fmt;
00047     enum PixelFormat pix_fmt;
00048 } conversion_map[] = {
00049     {IMGFMT_ARGB, PIX_FMT_ARGB},
00050     {IMGFMT_BGRA, PIX_FMT_BGRA},
00051     {IMGFMT_BGR24, PIX_FMT_BGR24},
00052     {IMGFMT_BGR16BE, PIX_FMT_RGB565BE},
00053     {IMGFMT_BGR16LE, PIX_FMT_RGB565LE},
00054     {IMGFMT_BGR15BE, PIX_FMT_RGB555BE},
00055     {IMGFMT_BGR15LE, PIX_FMT_RGB555LE},
00056     {IMGFMT_BGR12BE, PIX_FMT_RGB444BE},
00057     {IMGFMT_BGR12LE, PIX_FMT_RGB444LE},
00058     {IMGFMT_BGR8,  PIX_FMT_RGB8},
00059     {IMGFMT_BGR4,  PIX_FMT_RGB4},
00060     {IMGFMT_BGR1,  PIX_FMT_MONOBLACK},
00061     {IMGFMT_RGB1,  PIX_FMT_MONOBLACK},
00062     {IMGFMT_RG4B,  PIX_FMT_BGR4_BYTE},
00063     {IMGFMT_BG4B,  PIX_FMT_RGB4_BYTE},
00064     {IMGFMT_RGB48LE, PIX_FMT_RGB48LE},
00065     {IMGFMT_RGB48BE, PIX_FMT_RGB48BE},
00066     {IMGFMT_ABGR, PIX_FMT_ABGR},
00067     {IMGFMT_RGBA, PIX_FMT_RGBA},
00068     {IMGFMT_RGB24, PIX_FMT_RGB24},
00069     {IMGFMT_RGB16BE, PIX_FMT_BGR565BE},
00070     {IMGFMT_RGB16LE, PIX_FMT_BGR565LE},
00071     {IMGFMT_RGB15BE, PIX_FMT_BGR555BE},
00072     {IMGFMT_RGB15LE, PIX_FMT_BGR555LE},
00073     {IMGFMT_RGB12BE, PIX_FMT_BGR444BE},
00074     {IMGFMT_RGB12LE, PIX_FMT_BGR444LE},
00075     {IMGFMT_RGB8,  PIX_FMT_BGR8},
00076     {IMGFMT_RGB4,  PIX_FMT_BGR4},
00077     {IMGFMT_BGR8,  PIX_FMT_PAL8},
00078     {IMGFMT_YUY2,  PIX_FMT_YUYV422},
00079     {IMGFMT_UYVY,  PIX_FMT_UYVY422},
00080     {IMGFMT_NV12,  PIX_FMT_NV12},
00081     {IMGFMT_NV21,  PIX_FMT_NV21},
00082     {IMGFMT_Y800,  PIX_FMT_GRAY8},
00083     {IMGFMT_Y8,    PIX_FMT_GRAY8},
00084     {IMGFMT_YVU9,  PIX_FMT_YUV410P},
00085     {IMGFMT_IF09,  PIX_FMT_YUV410P},
00086     {IMGFMT_YV12,  PIX_FMT_YUV420P},
00087     {IMGFMT_I420,  PIX_FMT_YUV420P},
00088     {IMGFMT_IYUV,  PIX_FMT_YUV420P},
00089     {IMGFMT_411P,  PIX_FMT_YUV411P},
00090     {IMGFMT_422P,  PIX_FMT_YUV422P},
00091     {IMGFMT_444P,  PIX_FMT_YUV444P},
00092     {IMGFMT_440P,  PIX_FMT_YUV440P},
00093 
00094     {IMGFMT_420A,  PIX_FMT_YUVA420P},
00095 
00096     {IMGFMT_420P16_LE,  PIX_FMT_YUV420P16LE},
00097     {IMGFMT_420P16_BE,  PIX_FMT_YUV420P16BE},
00098     {IMGFMT_422P16_LE,  PIX_FMT_YUV422P16LE},
00099     {IMGFMT_422P16_BE,  PIX_FMT_YUV422P16BE},
00100     {IMGFMT_444P16_LE,  PIX_FMT_YUV444P16LE},
00101     {IMGFMT_444P16_BE,  PIX_FMT_YUV444P16BE},
00102 
00103     // YUVJ are YUV formats that use the full Y range and not just
00104     // 16 - 235 (see colorspaces.txt).
00105     // Currently they are all treated the same way.
00106     {IMGFMT_YV12,  PIX_FMT_YUVJ420P},
00107     {IMGFMT_422P,  PIX_FMT_YUVJ422P},
00108     {IMGFMT_444P,  PIX_FMT_YUVJ444P},
00109     {IMGFMT_440P,  PIX_FMT_YUVJ440P},
00110 
00111     {IMGFMT_XVMC_MOCO_MPEG2, PIX_FMT_XVMC_MPEG2_MC},
00112     {IMGFMT_XVMC_IDCT_MPEG2, PIX_FMT_XVMC_MPEG2_IDCT},
00113     {IMGFMT_VDPAU_MPEG1,     PIX_FMT_VDPAU_MPEG1},
00114     {IMGFMT_VDPAU_MPEG2,     PIX_FMT_VDPAU_MPEG2},
00115     {IMGFMT_VDPAU_H264,      PIX_FMT_VDPAU_H264},
00116     {IMGFMT_VDPAU_WMV3,      PIX_FMT_VDPAU_WMV3},
00117     {IMGFMT_VDPAU_VC1,       PIX_FMT_VDPAU_VC1},
00118     {IMGFMT_VDPAU_MPEG4,     PIX_FMT_VDPAU_MPEG4},
00119     {0, PIX_FMT_NONE}
00120 };
00121 
00122 //copied from vf.c
00123 extern const vf_info_t vf_info_vo;
00124 extern const vf_info_t vf_info_rectangle;
00125 extern const vf_info_t vf_info_bmovl;
00126 extern const vf_info_t vf_info_crop;
00127 extern const vf_info_t vf_info_expand;
00128 extern const vf_info_t vf_info_pp;
00129 extern const vf_info_t vf_info_scale;
00130 extern const vf_info_t vf_info_format;
00131 extern const vf_info_t vf_info_noformat;
00132 extern const vf_info_t vf_info_flip;
00133 extern const vf_info_t vf_info_rotate;
00134 extern const vf_info_t vf_info_mirror;
00135 extern const vf_info_t vf_info_palette;
00136 extern const vf_info_t vf_info_lavc;
00137 extern const vf_info_t vf_info_zrmjpeg;
00138 extern const vf_info_t vf_info_dvbscale;
00139 extern const vf_info_t vf_info_cropdetect;
00140 extern const vf_info_t vf_info_test;
00141 extern const vf_info_t vf_info_noise;
00142 extern const vf_info_t vf_info_yvu9;
00143 extern const vf_info_t vf_info_lavcdeint;
00144 extern const vf_info_t vf_info_eq;
00145 extern const vf_info_t vf_info_eq2;
00146 extern const vf_info_t vf_info_gradfun;
00147 extern const vf_info_t vf_info_halfpack;
00148 extern const vf_info_t vf_info_dint;
00149 extern const vf_info_t vf_info_1bpp;
00150 extern const vf_info_t vf_info_2xsai;
00151 extern const vf_info_t vf_info_unsharp;
00152 extern const vf_info_t vf_info_swapuv;
00153 extern const vf_info_t vf_info_il;
00154 extern const vf_info_t vf_info_fil;
00155 extern const vf_info_t vf_info_boxblur;
00156 extern const vf_info_t vf_info_sab;
00157 extern const vf_info_t vf_info_smartblur;
00158 extern const vf_info_t vf_info_perspective;
00159 extern const vf_info_t vf_info_down3dright;
00160 extern const vf_info_t vf_info_field;
00161 extern const vf_info_t vf_info_denoise3d;
00162 extern const vf_info_t vf_info_hqdn3d;
00163 extern const vf_info_t vf_info_detc;
00164 extern const vf_info_t vf_info_telecine;
00165 extern const vf_info_t vf_info_tinterlace;
00166 extern const vf_info_t vf_info_tfields;
00167 extern const vf_info_t vf_info_ivtc;
00168 extern const vf_info_t vf_info_ilpack;
00169 extern const vf_info_t vf_info_dsize;
00170 extern const vf_info_t vf_info_decimate;
00171 extern const vf_info_t vf_info_softpulldown;
00172 extern const vf_info_t vf_info_pullup;
00173 extern const vf_info_t vf_info_filmdint;
00174 extern const vf_info_t vf_info_framestep;
00175 extern const vf_info_t vf_info_tile;
00176 extern const vf_info_t vf_info_delogo;
00177 extern const vf_info_t vf_info_remove_logo;
00178 extern const vf_info_t vf_info_hue;
00179 extern const vf_info_t vf_info_spp;
00180 extern const vf_info_t vf_info_uspp;
00181 extern const vf_info_t vf_info_fspp;
00182 extern const vf_info_t vf_info_pp7;
00183 extern const vf_info_t vf_info_yuvcsp;
00184 extern const vf_info_t vf_info_kerndeint;
00185 extern const vf_info_t vf_info_rgbtest;
00186 extern const vf_info_t vf_info_qp;
00187 extern const vf_info_t vf_info_phase;
00188 extern const vf_info_t vf_info_divtc;
00189 extern const vf_info_t vf_info_harddup;
00190 extern const vf_info_t vf_info_softskip;
00191 extern const vf_info_t vf_info_screenshot;
00192 extern const vf_info_t vf_info_ass;
00193 extern const vf_info_t vf_info_mcdeint;
00194 extern const vf_info_t vf_info_yadif;
00195 extern const vf_info_t vf_info_blackframe;
00196 extern const vf_info_t vf_info_geq;
00197 extern const vf_info_t vf_info_ow;
00198 extern const vf_info_t vf_info_fixpts;
00199 extern const vf_info_t vf_info_stereo3d;
00200 
00201 
00202 static const vf_info_t* const filters[]={
00203     &vf_info_2xsai,
00204     &vf_info_blackframe,
00205     &vf_info_boxblur,
00206     &vf_info_cropdetect,
00207     &vf_info_decimate,
00208     &vf_info_delogo,
00209     &vf_info_denoise3d,
00210     &vf_info_detc,
00211     &vf_info_dint,
00212     &vf_info_divtc,
00213     &vf_info_down3dright,
00214     &vf_info_dsize,
00215     &vf_info_eq2,
00216     &vf_info_eq,
00217     &vf_info_field,
00218     &vf_info_fil,
00219 //    &vf_info_filmdint, cmmx.h vd.h ‘opt_screen_size_x’
00220     &vf_info_fixpts,
00221     &vf_info_framestep,
00222     &vf_info_fspp,
00223     &vf_info_geq,
00224     &vf_info_gradfun,
00225     &vf_info_harddup,
00226     &vf_info_hqdn3d,
00227     &vf_info_hue,
00228     &vf_info_il,
00229     &vf_info_ilpack,
00230     &vf_info_ivtc,
00231     &vf_info_kerndeint,
00232     &vf_info_mcdeint,
00233     &vf_info_mirror,
00234     &vf_info_noise,
00235     &vf_info_ow,
00236     &vf_info_palette,
00237     &vf_info_perspective,
00238     &vf_info_phase,
00239     &vf_info_pp7,
00240     &vf_info_pullup,
00241     &vf_info_qp,
00242     &vf_info_rectangle,
00243     &vf_info_remove_logo,
00244     &vf_info_rgbtest,
00245     &vf_info_rotate,
00246     &vf_info_sab,
00247     &vf_info_screenshot,
00248     &vf_info_smartblur,
00249     &vf_info_softpulldown,
00250     &vf_info_softskip,
00251     &vf_info_spp,
00252     &vf_info_swapuv,
00253     &vf_info_telecine,
00254     &vf_info_test,
00255     &vf_info_tile,
00256     &vf_info_tinterlace,
00257     &vf_info_unsharp,
00258     &vf_info_uspp,
00259     &vf_info_yuvcsp,
00260     &vf_info_yvu9,
00261 
00262     NULL
00263 };
00264 
00265 /*
00266 Unsupported filters
00267 1bpp
00268 ass
00269 bmovl
00270 crop
00271 dvbscale
00272 flip
00273 expand
00274 format
00275 halfpack
00276 lavc
00277 lavcdeint
00278 noformat
00279 pp
00280 scale
00281 stereo3d
00282 tfields
00283 vo
00284 yadif
00285 zrmjpeg
00286 */
00287 
00288 CpuCaps gCpuCaps; //FIXME initialize this so optims work
00289 
00290 
00291 static void sws_getFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, SwsFilter **dstFilterParam)
00292 {
00293         static int firstTime=1;
00294         *flags=0;
00295 
00296 #if ARCH_X86
00297         if(gCpuCaps.hasMMX)
00298                 __asm__ volatile("emms\n\t"::: "memory"); //FIXME this should not be required but it IS (even for non-MMX versions)
00299 #endif
00300         if(firstTime)
00301         {
00302                 firstTime=0;
00303                 *flags= SWS_PRINT_INFO;
00304         }
00305         else if( mp_msg_test(MSGT_VFILTER,MSGL_DBG2) ) *flags= SWS_PRINT_INFO;
00306 
00307         switch(SWS_BILINEAR)
00308         {
00309                 case 0: *flags|= SWS_FAST_BILINEAR; break;
00310                 case 1: *flags|= SWS_BILINEAR; break;
00311                 case 2: *flags|= SWS_BICUBIC; break;
00312                 case 3: *flags|= SWS_X; break;
00313                 case 4: *flags|= SWS_POINT; break;
00314                 case 5: *flags|= SWS_AREA; break;
00315                 case 6: *flags|= SWS_BICUBLIN; break;
00316                 case 7: *flags|= SWS_GAUSS; break;
00317                 case 8: *flags|= SWS_SINC; break;
00318                 case 9: *flags|= SWS_LANCZOS; break;
00319                 case 10:*flags|= SWS_SPLINE; break;
00320                 default:*flags|= SWS_BILINEAR; break;
00321         }
00322 
00323         *srcFilterParam= NULL;
00324         *dstFilterParam= NULL;
00325 }
00326 
00327 //exact copy from vf_scale.c
00328 // will use sws_flags & src_filter (from cmd line)
00329 struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat)
00330 {
00331         int flags, i;
00332         SwsFilter *dstFilterParam, *srcFilterParam;
00333         enum PixelFormat dfmt, sfmt;
00334 
00335         for(i=0; conversion_map[i].fmt && dstFormat != conversion_map[i].fmt; i++);
00336         dfmt= conversion_map[i].pix_fmt;
00337         for(i=0; conversion_map[i].fmt && srcFormat != conversion_map[i].fmt; i++);
00338         sfmt= conversion_map[i].pix_fmt;
00339 
00340         if (srcFormat == IMGFMT_RGB8 || srcFormat == IMGFMT_BGR8) sfmt = PIX_FMT_PAL8;
00341         sws_getFlagsAndFilterFromCmdLine(&flags, &srcFilterParam, &dstFilterParam);
00342 
00343         return sws_getContext(srcW, srcH, sfmt, dstW, dstH, dfmt, flags , srcFilterParam, dstFilterParam, NULL);
00344 }
00345 
00346 typedef struct {
00347     vf_instance_t vf;
00348     vf_instance_t next_vf;
00349     AVFilterContext *avfctx;
00350     int frame_returned;
00351 } MPContext;
00352 
00353 void mp_msg(int mod, int lev, const char *format, ... ){
00354     va_list va;
00355     va_start(va, format);
00356     //FIXME convert lev/mod
00357     av_vlog(NULL, AV_LOG_DEBUG, format, va);
00358     va_end(va);
00359 }
00360 
00361 int mp_msg_test(int mod, int lev){
00362     return 123;
00363 }
00364 
00365 void init_avcodec(void)
00366 {
00367     //we maybe should init but its kinda 1. unneeded 2. a bit inpolite from here
00368 }
00369 
00370 //Exact copy of vf.c
00371 void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src){
00372     dst->pict_type= src->pict_type;
00373     dst->fields = src->fields;
00374     dst->qscale_type= src->qscale_type;
00375     if(dst->width == src->width && dst->height == src->height){
00376         dst->qstride= src->qstride;
00377         dst->qscale= src->qscale;
00378     }
00379 }
00380 
00381 //Exact copy of vf.c
00382 void vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){
00383     if (vf->next->draw_slice) {
00384         vf->next->draw_slice(vf->next,src,stride,w,h,x,y);
00385         return;
00386     }
00387     if (!vf->dmpi) {
00388         mp_msg(MSGT_VFILTER,MSGL_ERR,"draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
00389         return;
00390     }
00391     if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) {
00392         memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+vf->dmpi->bpp/8*x,
00393             src[0], vf->dmpi->bpp/8*w, h, vf->dmpi->stride[0], stride[0]);
00394         return;
00395     }
00396     memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+x, src[0],
00397         w, h, vf->dmpi->stride[0], stride[0]);
00398     memcpy_pic(vf->dmpi->planes[1]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[1]+(x>>vf->dmpi->chroma_x_shift),
00399         src[1], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]);
00400     memcpy_pic(vf->dmpi->planes[2]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[2]+(x>>vf->dmpi->chroma_x_shift),
00401         src[2], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]);
00402 }
00403 
00404 //Exact copy of vf.c
00405 void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h){
00406     int y;
00407     if(mpi->flags&MP_IMGFLAG_PLANAR){
00408         y0&=~1;h+=h&1;
00409         if(x0==0 && w==mpi->width){
00410             // full width clear:
00411             memset(mpi->planes[0]+mpi->stride[0]*y0,0,mpi->stride[0]*h);
00412             memset(mpi->planes[1]+mpi->stride[1]*(y0>>mpi->chroma_y_shift),128,mpi->stride[1]*(h>>mpi->chroma_y_shift));
00413             memset(mpi->planes[2]+mpi->stride[2]*(y0>>mpi->chroma_y_shift),128,mpi->stride[2]*(h>>mpi->chroma_y_shift));
00414         } else
00415         for(y=y0;y<y0+h;y+=2){
00416             memset(mpi->planes[0]+x0+mpi->stride[0]*y,0,w);
00417             memset(mpi->planes[0]+x0+mpi->stride[0]*(y+1),0,w);
00418             memset(mpi->planes[1]+(x0>>mpi->chroma_x_shift)+mpi->stride[1]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
00419             memset(mpi->planes[2]+(x0>>mpi->chroma_x_shift)+mpi->stride[2]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
00420         }
00421         return;
00422     }
00423     // packed:
00424     for(y=y0;y<y0+h;y++){
00425         unsigned char* dst=mpi->planes[0]+mpi->stride[0]*y+(mpi->bpp>>3)*x0;
00426         if(mpi->flags&MP_IMGFLAG_YUV){
00427             unsigned int* p=(unsigned int*) dst;
00428             int size=(mpi->bpp>>3)*w/4;
00429             int i;
00430 #if HAVE_BIGENDIAN
00431 #define CLEAR_PACKEDYUV_PATTERN 0x00800080
00432 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x80008000
00433 #else
00434 #define CLEAR_PACKEDYUV_PATTERN 0x80008000
00435 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x00800080
00436 #endif
00437             if(mpi->flags&MP_IMGFLAG_SWAPPED){
00438                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
00439                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
00440             } else {
00441                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN;
00442                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN;
00443             }
00444         } else
00445             memset(dst,0,(mpi->bpp>>3)*w);
00446     }
00447 }
00448 
00449 int vf_next_query_format(struct vf_instance *vf, unsigned int fmt){
00450     return 1;
00451 }
00452 
00453 //used by delogo
00454 unsigned int vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred){
00455     return preferred;
00456 }
00457 
00458 mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h){
00459     MPContext *m= ((uint8_t*)vf) - offsetof(MPContext, next_vf);
00460   mp_image_t* mpi=NULL;
00461   int w2;
00462   int number = mp_imgtype >> 16;
00463 
00464   av_assert0(vf->next == NULL); // all existing filters call this just on next
00465 
00466   //vf_dint needs these as it calls vf_get_image() before configuring the output
00467   if(vf->w==0 && w>0) vf->w=w;
00468   if(vf->h==0 && h>0) vf->h=h;
00469 
00470   av_assert0(w == -1 || w >= vf->w);
00471   av_assert0(h == -1 || h >= vf->h);
00472   av_assert0(vf->w > 0);
00473   av_assert0(vf->h > 0);
00474 
00475   av_log(m->avfctx, AV_LOG_DEBUG, "get_image: %d:%d, vf: %d:%d\n", w,h,vf->w,vf->h);
00476 
00477   if (w == -1) w = vf->w;
00478   if (h == -1) h = vf->h;
00479 
00480   w2=(mp_imgflag&MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE)?((w+15)&(~15)):w;
00481 
00482   // Note: we should call libvo first to check if it supports direct rendering
00483   // and if not, then fallback to software buffers:
00484   switch(mp_imgtype & 0xff){
00485   case MP_IMGTYPE_EXPORT:
00486     if(!vf->imgctx.export_images[0]) vf->imgctx.export_images[0]=new_mp_image(w2,h);
00487     mpi=vf->imgctx.export_images[0];
00488     break;
00489   case MP_IMGTYPE_STATIC:
00490     if(!vf->imgctx.static_images[0]) vf->imgctx.static_images[0]=new_mp_image(w2,h);
00491     mpi=vf->imgctx.static_images[0];
00492     break;
00493   case MP_IMGTYPE_TEMP:
00494     if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
00495     mpi=vf->imgctx.temp_images[0];
00496     break;
00497   case MP_IMGTYPE_IPB:
00498     if(!(mp_imgflag&MP_IMGFLAG_READABLE)){ // B frame:
00499       if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
00500       mpi=vf->imgctx.temp_images[0];
00501       break;
00502     }
00503   case MP_IMGTYPE_IP:
00504     if(!vf->imgctx.static_images[vf->imgctx.static_idx]) vf->imgctx.static_images[vf->imgctx.static_idx]=new_mp_image(w2,h);
00505     mpi=vf->imgctx.static_images[vf->imgctx.static_idx];
00506     vf->imgctx.static_idx^=1;
00507     break;
00508   case MP_IMGTYPE_NUMBERED:
00509     if (number == -1) {
00510       int i;
00511       for (i = 0; i < NUM_NUMBERED_MPI; i++)
00512         if (!vf->imgctx.numbered_images[i] || !vf->imgctx.numbered_images[i]->usage_count)
00513           break;
00514       number = i;
00515     }
00516     if (number < 0 || number >= NUM_NUMBERED_MPI) return NULL;
00517     if (!vf->imgctx.numbered_images[number]) vf->imgctx.numbered_images[number] = new_mp_image(w2,h);
00518     mpi = vf->imgctx.numbered_images[number];
00519     mpi->number = number;
00520     break;
00521   }
00522   if(mpi){
00523     mpi->type=mp_imgtype;
00524     mpi->w=vf->w; mpi->h=vf->h;
00525     // keep buffer allocation status & color flags only:
00526 //    mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE|MP_IMGFLAG_DIRECT);
00527     mpi->flags&=MP_IMGFLAG_ALLOCATED|MP_IMGFLAG_TYPE_DISPLAYED|MP_IMGFLAGMASK_COLORS;
00528     // accept restrictions, draw_slice and palette flags only:
00529     mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK|MP_IMGFLAG_RGB_PALETTE);
00530     if(!vf->draw_slice) mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK;
00531     if(mpi->width!=w2 || mpi->height!=h){
00532 //      printf("vf.c: MPI parameters changed!  %dx%d -> %dx%d   \n", mpi->width,mpi->height,w2,h);
00533         if(mpi->flags&MP_IMGFLAG_ALLOCATED){
00534             if(mpi->width<w2 || mpi->height<h){
00535                 // need to re-allocate buffer memory:
00536                 av_free(mpi->planes[0]);
00537                 mpi->flags&=~MP_IMGFLAG_ALLOCATED;
00538                 mp_msg(MSGT_VFILTER,MSGL_V,"vf.c: have to REALLOCATE buffer memory :(\n");
00539             }
00540 //      } else {
00541         } {
00542             mpi->width=w2; mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
00543             mpi->height=h; mpi->chroma_height=(h + (1<<mpi->chroma_y_shift) - 1)>>mpi->chroma_y_shift;
00544         }
00545     }
00546     if(!mpi->bpp) mp_image_setfmt(mpi,outfmt);
00547     if(!(mpi->flags&MP_IMGFLAG_ALLOCATED) && mpi->type>MP_IMGTYPE_EXPORT){
00548 
00549         av_assert0(!vf->get_image);
00550         // check libvo first!
00551         if(vf->get_image) vf->get_image(vf,mpi);
00552 
00553         if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
00554           // non-direct and not yet allocated image. allocate it!
00555           if (!mpi->bpp) { // no way we can allocate this
00556               mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
00557                      "vf_get_image: Tried to allocate a format that can not be allocated!\n");
00558               return NULL;
00559           }
00560 
00561           // check if codec prefer aligned stride:
00562           if(mp_imgflag&MP_IMGFLAG_PREFER_ALIGNED_STRIDE){
00563               int align=(mpi->flags&MP_IMGFLAG_PLANAR &&
00564                          mpi->flags&MP_IMGFLAG_YUV) ?
00565                          (8<<mpi->chroma_x_shift)-1 : 15; // -- maybe FIXME
00566               w2=((w+align)&(~align));
00567               if(mpi->width!=w2){
00568 #if 0
00569                   // we have to change width... check if we CAN co it:
00570                   int flags=vf->query_format(vf,outfmt); // should not fail
00571                   if(!(flags&3)) mp_msg(MSGT_DECVIDEO,MSGL_WARN,"??? vf_get_image{vf->query_format(outfmt)} failed!\n");
00572 //                printf("query -> 0x%X    \n",flags);
00573                   if(flags&VFCAP_ACCEPT_STRIDE){
00574 #endif
00575                       mpi->width=w2;
00576                       mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
00577 //                  }
00578               }
00579           }
00580 
00581           mp_image_alloc_planes(mpi);
00582 //        printf("clearing img!\n");
00583           vf_mpi_clear(mpi,0,0,mpi->width,mpi->height);
00584         }
00585     }
00586     av_assert0(!vf->start_slice);
00587     if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)
00588         if(vf->start_slice) vf->start_slice(vf,mpi);
00589     if(!(mpi->flags&MP_IMGFLAG_TYPE_DISPLAYED)){
00590             mp_msg(MSGT_DECVIDEO,MSGL_V,"*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
00591                   "NULL"/*vf->info->name*/,
00592                   (mpi->type==MP_IMGTYPE_EXPORT)?"Exporting":
00593                   ((mpi->flags&MP_IMGFLAG_DIRECT)?"Direct Rendering":"Allocating"),
00594                   (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)?" (slices)":"",
00595                   mpi->width,mpi->height,mpi->bpp,
00596                   (mpi->flags&MP_IMGFLAG_YUV)?"YUV":((mpi->flags&MP_IMGFLAG_SWAPPED)?"BGR":"RGB"),
00597                   (mpi->flags&MP_IMGFLAG_PLANAR)?"planar":"packed",
00598                   mpi->bpp*mpi->width*mpi->height/8);
00599             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",
00600                 mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
00601                 mpi->stride[0], mpi->stride[1], mpi->stride[2],
00602                 mpi->chroma_width, mpi->chroma_height, mpi->chroma_x_shift, mpi->chroma_y_shift);
00603             mpi->flags|=MP_IMGFLAG_TYPE_DISPLAYED;
00604     }
00605 
00606   mpi->qscale = NULL;
00607   }
00608   mpi->usage_count++;
00609 //    printf("\rVF_MPI: %p %p %p %d %d %d    \n",
00610 //      mpi->planes[0],mpi->planes[1],mpi->planes[2],
00611 //      mpi->stride[0],mpi->stride[1],mpi->stride[2]);
00612   return mpi;
00613 }
00614 
00615 
00616 int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){
00617     MPContext *m= (void*)vf;
00618     AVFilterLink *outlink     = m->avfctx->outputs[0];
00619     AVFilterBuffer    *pic    = av_mallocz(sizeof(AVFilterBuffer));
00620     AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef));
00621     int i;
00622 
00623     av_assert0(vf->next);
00624 
00625     av_log(m->avfctx, AV_LOG_DEBUG, "vf_next_put_image\n");
00626 
00627     if (!pic || !picref)
00628         goto fail;
00629 
00630     picref->buf = pic;
00631     picref->buf->please_use_av_free= av_free;
00632     if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps))))
00633         goto fail;
00634 
00635     pic->w = picref->video->w = mpi->w;
00636     pic->h = picref->video->h = mpi->h;
00637 
00638     /* make sure the buffer gets read permission or it's useless for output */
00639     picref->perms = AV_PERM_READ | AV_PERM_REUSE2;
00640 //    av_assert0(mpi->flags&MP_IMGFLAG_READABLE);
00641     if(!(mpi->flags&MP_IMGFLAG_PRESERVE))
00642         picref->perms |= AV_PERM_WRITE;
00643 
00644     pic->refcount = 1;
00645     picref->type = AVMEDIA_TYPE_VIDEO;
00646 
00647     for(i=0; conversion_map[i].fmt && mpi->imgfmt != conversion_map[i].fmt; i++);
00648     pic->format = picref->format = conversion_map[i].pix_fmt;
00649 
00650     memcpy(pic->data,        mpi->planes,   FFMIN(sizeof(pic->data)    , sizeof(mpi->planes)));
00651     memcpy(pic->linesize,    mpi->stride,   FFMIN(sizeof(pic->linesize), sizeof(mpi->stride)));
00652     memcpy(picref->data,     pic->data,     sizeof(picref->data));
00653     memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
00654 
00655     if(pts != MP_NOPTS_VALUE)
00656         picref->pts= pts * av_q2d(outlink->time_base);
00657 
00658     avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
00659     avfilter_draw_slice(outlink, 0, picref->video->h, 1);
00660     avfilter_end_frame(outlink);
00661     avfilter_unref_buffer(picref);
00662     m->frame_returned++;
00663 
00664     return 1;
00665 fail:
00666     if (picref && picref->video)
00667         av_free(picref->video);
00668     av_free(picref);
00669     av_free(pic);
00670     return 0;
00671 }
00672 
00673 int vf_next_config(struct vf_instance *vf,
00674         int width, int height, int d_width, int d_height,
00675         unsigned int voflags, unsigned int outfmt){
00676 
00677     av_assert0(width>0 && height>0);
00678     vf->next->w = width; vf->next->h = height;
00679 
00680     return 1;
00681 #if 0
00682     int flags=vf->next->query_format(vf->next,outfmt);
00683     if(!flags){
00684         // hmm. colorspace mismatch!!!
00685         //this is fatal for us ATM
00686         return 0;
00687     }
00688     mp_msg(MSGT_VFILTER,MSGL_V,"REQ: flags=0x%X  req=0x%X  \n",flags,vf->default_reqs);
00689     miss=vf->default_reqs - (flags&vf->default_reqs);
00690     if(miss&VFCAP_ACCEPT_STRIDE){
00691         // vf requires stride support but vf->next doesn't support it!
00692         // let's insert the 'expand' filter, it does the job for us:
00693         vf_instance_t* vf2=vf_open_filter(vf->next,"expand",NULL);
00694         if(!vf2) return 0; // shouldn't happen!
00695         vf->next=vf2;
00696     }
00697     vf->next->w = width; vf->next->h = height;
00698 #endif
00699     return 1;
00700 }
00701 
00702 int vf_next_control(struct vf_instance *vf, int request, void* data){
00703     MPContext *m= (void*)vf;
00704     av_log(m->avfctx, AV_LOG_DEBUG, "Received control %d\n", request);
00705     return 0;
00706 }
00707 
00708 static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt){
00709     MPContext *m= (void*)vf;
00710     int i;
00711     av_log(m->avfctx, AV_LOG_DEBUG, "query %X\n", fmt);
00712 
00713     for(i=0; conversion_map[i].fmt; i++){
00714         if(fmt==conversion_map[i].fmt)
00715             return 1; //we suport all
00716     }
00717     return 0;
00718 }
00719 
00720 
00721 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
00722 {
00723     MPContext *m = ctx->priv;
00724     char name[256];
00725     int i;
00726 
00727     av_log(ctx, AV_LOG_WARNING,
00728 "This is a unholy filter, it will be purified by the ffmpeg exorcist team\n"
00729 "which will change its syntax from dark -vf mp to light -vf.\n"
00730 "Thou shalst not make spells or scripts that depend on it\n");
00731 
00732     m->avfctx= ctx;
00733 
00734     if(!args || 1!=sscanf(args, "%255[^:=]", name)){
00735         av_log(ctx, AV_LOG_ERROR, "Invalid parameter.\n");
00736         return AVERROR(EINVAL);
00737     }
00738     args+= strlen(name)+1;
00739 
00740     for(i=0; ;i++){
00741         if(!filters[i] || !strcmp(name, filters[i]->name))
00742             break;
00743     }
00744 
00745     if(!filters[i]){
00746         av_log(ctx, AV_LOG_ERROR, "Unknown filter %s\n", name);
00747         return AVERROR(EINVAL);
00748     }
00749 
00750     memset(&m->vf,0,sizeof(m->vf));
00751     m->vf.info= filters[i];
00752 
00753     m->vf.next        = &m->next_vf;
00754     m->vf.put_image   = vf_next_put_image;
00755     m->vf.config      = vf_next_config;
00756     m->vf.query_format= vf_default_query_format;
00757     m->vf.control     = vf_next_control;
00758     m->vf.default_caps=VFCAP_ACCEPT_STRIDE;
00759     m->vf.default_reqs=0;
00760     if(m->vf.info->opts)
00761         av_log(ctx, AV_LOG_ERROR, "opts / m_struct_set is unsupported\n");
00762 #if 0
00763     if(vf->info->opts) { // vf_vo get some special argument
00764       const m_struct_t* st = vf->info->opts;
00765       void* vf_priv = m_struct_alloc(st);
00766       int n;
00767       for(n = 0 ; args && args[2*n] ; n++)
00768         m_struct_set(st,vf_priv,args[2*n],args[2*n+1]);
00769       vf->priv = vf_priv;
00770       args = NULL;
00771     } else // Otherwise we should have the '_oldargs_'
00772       if(args && !strcmp(args[0],"_oldargs_"))
00773         args = (char**)args[1];
00774       else
00775         args = NULL;
00776 #endif
00777     if(m->vf.info->vf_open(&m->vf, args)<=0){
00778         av_log(ctx, AV_LOG_ERROR, "vf_open() of %s with arg=%s failed\n", name, args);
00779         return -1;
00780     }
00781 
00782     return 0;
00783 }
00784 
00785 static int query_formats(AVFilterContext *ctx)
00786 {
00787     AVFilterFormats *avfmts=NULL;
00788     MPContext *m = ctx->priv;
00789     enum PixelFormat lastpixfmt = PIX_FMT_NONE;
00790     int i;
00791 
00792     for(i=0; conversion_map[i].fmt; i++){
00793         av_log(ctx, AV_LOG_DEBUG, "query: %X\n", conversion_map[i].fmt);
00794         if(m->vf.query_format(&m->vf, conversion_map[i].fmt)){
00795             av_log(ctx, AV_LOG_DEBUG, "supported,adding\n");
00796             if (conversion_map[i].pix_fmt != lastpixfmt) {
00797                 avfilter_add_format(&avfmts, conversion_map[i].pix_fmt);
00798                 lastpixfmt = conversion_map[i].pix_fmt;
00799             }
00800         }
00801     }
00802 
00803     //We assume all allowed input formats are also allowed output formats
00804     avfilter_set_common_pixel_formats(ctx, avfmts);
00805     return 0;
00806 }
00807 
00808 static int config_inprops(AVFilterLink *inlink)
00809 {
00810     MPContext *m = inlink->dst->priv;
00811     int i;
00812     for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
00813 
00814     av_assert0(conversion_map[i].fmt && inlink->w && inlink->h);
00815 
00816     m->vf.fmt.have_configured = 1;
00817     m->vf.fmt.orig_height     = inlink->h;
00818     m->vf.fmt.orig_width      = inlink->w;
00819     m->vf.fmt.orig_fmt        = conversion_map[i].fmt;
00820 
00821     if(m->vf.config(&m->vf, inlink->w, inlink->h, inlink->w, inlink->h, 0, conversion_map[i].fmt)<=0)
00822         return -1;
00823 
00824     return 0;
00825 }
00826 
00827 static int config_outprops(AVFilterLink *outlink)
00828 {
00829     MPContext *m = outlink->src->priv;
00830 
00831     outlink->w = m->next_vf.w;
00832     outlink->h = m->next_vf.h;
00833 
00834     return 0;
00835 }
00836 
00837 static int request_frame(AVFilterLink *outlink)
00838 {
00839     MPContext *m = outlink->src->priv;
00840     int ret;
00841 
00842     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame\n");
00843 
00844     for(m->frame_returned=0; !m->frame_returned;){
00845         ret=avfilter_request_frame(outlink->src->inputs[0]);
00846         if(ret<0)
00847             break;
00848     }
00849 
00850     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame ret=%d\n", ret);
00851     return ret;
00852 }
00853 
00854 static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
00855 {
00856 }
00857 
00858 static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
00859 {
00860 }
00861 
00862 static void end_frame(AVFilterLink *inlink)
00863 {
00864     MPContext *m = inlink->dst->priv;
00865     AVFilterBufferRef *inpic  = inlink->cur_buf;
00866     int i;
00867     double pts= MP_NOPTS_VALUE;
00868     mp_image_t* mpi = new_mp_image(inpic->video->w, inpic->video->h);
00869 
00870     if(inpic->pts != AV_NOPTS_VALUE)
00871         pts= inpic->pts / av_q2d(inlink->time_base);
00872 
00873     for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
00874     mp_image_setfmt(mpi,conversion_map[i].fmt);
00875 
00876     memcpy(mpi->planes, inpic->data,     FFMIN(sizeof(inpic->data)    , sizeof(mpi->planes)));
00877     memcpy(mpi->stride, inpic->linesize, FFMIN(sizeof(inpic->linesize), sizeof(mpi->stride)));
00878 
00879     //FIXME pass interleced & tff flags around
00880 
00881     // mpi->flags|=MP_IMGFLAG_ALLOCATED; ?
00882     mpi->flags |= MP_IMGFLAG_READABLE;
00883     if(!(inpic->perms & AV_PERM_WRITE))
00884         mpi->flags |= MP_IMGFLAG_PRESERVE;
00885     if(m->vf.put_image(&m->vf, mpi, pts) == 0){
00886         av_log(m->avfctx, AV_LOG_DEBUG, "put_image() says skip\n");
00887     }
00888     free_mp_image(mpi);
00889 
00890     avfilter_unref_buffer(inpic);
00891 }
00892 
00893 AVFilter avfilter_vf_mp = {
00894     .name      = "mp",
00895     .description = NULL_IF_CONFIG_SMALL("libmpcodecs wrapper."),
00896     .init = init,
00897     .priv_size = sizeof(MPContext),
00898     .query_formats = query_formats,
00899 
00900     .inputs    = (AVFilterPad[]) {{ .name            = "default",
00901                                     .type            = AVMEDIA_TYPE_VIDEO,
00902                                     .start_frame     = start_frame,
00903                                     .draw_slice      = null_draw_slice,
00904                                     .end_frame       = end_frame,
00905                                     .config_props    = config_inprops,
00906                                     .min_perms       = AV_PERM_READ, },
00907                                   { .name = NULL}},
00908     .outputs   = (AVFilterPad[]) {{ .name            = "default",
00909                                     .type            = AVMEDIA_TYPE_VIDEO,
00910                                     .request_frame   = request_frame,
00911                                     .config_props    = config_outprops, },
00912                                   { .name = NULL}},
00913 };

Generated on Fri Feb 22 2013 07:24:31 for FFmpeg by  doxygen 1.7.1