• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • 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_1bpp;
00124 extern const vf_info_t vf_info_2xsai;
00125 extern const vf_info_t vf_info_ass;
00126 extern const vf_info_t vf_info_bmovl;
00127 extern const vf_info_t vf_info_crop;
00128 extern const vf_info_t vf_info_decimate;
00129 extern const vf_info_t vf_info_denoise3d;
00130 extern const vf_info_t vf_info_detc;
00131 extern const vf_info_t vf_info_dint;
00132 extern const vf_info_t vf_info_divtc;
00133 extern const vf_info_t vf_info_down3dright;
00134 extern const vf_info_t vf_info_dsize;
00135 extern const vf_info_t vf_info_dvbscale;
00136 extern const vf_info_t vf_info_eq2;
00137 extern const vf_info_t vf_info_eq;
00138 extern const vf_info_t vf_info_expand;
00139 extern const vf_info_t vf_info_field;
00140 extern const vf_info_t vf_info_fil;
00141 extern const vf_info_t vf_info_filmdint;
00142 extern const vf_info_t vf_info_fixpts;
00143 extern const vf_info_t vf_info_flip;
00144 extern const vf_info_t vf_info_format;
00145 extern const vf_info_t vf_info_framestep;
00146 extern const vf_info_t vf_info_fspp;
00147 extern const vf_info_t vf_info_geq;
00148 extern const vf_info_t vf_info_halfpack;
00149 extern const vf_info_t vf_info_harddup;
00150 extern const vf_info_t vf_info_hqdn3d;
00151 extern const vf_info_t vf_info_hue;
00152 extern const vf_info_t vf_info_il;
00153 extern const vf_info_t vf_info_ilpack;
00154 extern const vf_info_t vf_info_ivtc;
00155 extern const vf_info_t vf_info_kerndeint;
00156 extern const vf_info_t vf_info_lavc;
00157 extern const vf_info_t vf_info_lavcdeint;
00158 extern const vf_info_t vf_info_mcdeint;
00159 extern const vf_info_t vf_info_mirror;
00160 extern const vf_info_t vf_info_noformat;
00161 extern const vf_info_t vf_info_noise;
00162 extern const vf_info_t vf_info_ow;
00163 extern const vf_info_t vf_info_palette;
00164 extern const vf_info_t vf_info_perspective;
00165 extern const vf_info_t vf_info_phase;
00166 extern const vf_info_t vf_info_pp7;
00167 extern const vf_info_t vf_info_pp;
00168 extern const vf_info_t vf_info_pullup;
00169 extern const vf_info_t vf_info_qp;
00170 extern const vf_info_t vf_info_rectangle;
00171 extern const vf_info_t vf_info_remove_logo;
00172 extern const vf_info_t vf_info_rotate;
00173 extern const vf_info_t vf_info_sab;
00174 extern const vf_info_t vf_info_scale;
00175 extern const vf_info_t vf_info_screenshot;
00176 extern const vf_info_t vf_info_smartblur;
00177 extern const vf_info_t vf_info_softpulldown;
00178 extern const vf_info_t vf_info_softskip;
00179 extern const vf_info_t vf_info_spp;
00180 extern const vf_info_t vf_info_stereo3d;
00181 extern const vf_info_t vf_info_swapuv;
00182 extern const vf_info_t vf_info_telecine;
00183 extern const vf_info_t vf_info_test;
00184 extern const vf_info_t vf_info_tfields;
00185 extern const vf_info_t vf_info_tile;
00186 extern const vf_info_t vf_info_tinterlace;
00187 extern const vf_info_t vf_info_unsharp;
00188 extern const vf_info_t vf_info_uspp;
00189 extern const vf_info_t vf_info_vo;
00190 extern const vf_info_t vf_info_yadif;
00191 extern const vf_info_t vf_info_yuvcsp;
00192 extern const vf_info_t vf_info_yvu9;
00193 extern const vf_info_t vf_info_zrmjpeg;
00194 
00195 
00196 static const vf_info_t* const filters[]={
00197     &vf_info_2xsai,
00198     &vf_info_decimate,
00199     &vf_info_denoise3d,
00200     &vf_info_detc,
00201     &vf_info_dint,
00202     &vf_info_divtc,
00203     &vf_info_down3dright,
00204     &vf_info_dsize,
00205     &vf_info_eq2,
00206     &vf_info_eq,
00207     &vf_info_field,
00208     &vf_info_fil,
00209 //    &vf_info_filmdint, cmmx.h vd.h ‘opt_screen_size_x’
00210     &vf_info_fixpts,
00211     &vf_info_framestep,
00212     &vf_info_fspp,
00213     &vf_info_geq,
00214     &vf_info_harddup,
00215     &vf_info_hqdn3d,
00216     &vf_info_hue,
00217     &vf_info_il,
00218     &vf_info_ilpack,
00219     &vf_info_ivtc,
00220     &vf_info_kerndeint,
00221     &vf_info_mcdeint,
00222     &vf_info_mirror,
00223     &vf_info_noise,
00224     &vf_info_ow,
00225     &vf_info_palette,
00226     &vf_info_perspective,
00227     &vf_info_phase,
00228     &vf_info_pp7,
00229     &vf_info_pullup,
00230     &vf_info_qp,
00231     &vf_info_rectangle,
00232     &vf_info_remove_logo,
00233     &vf_info_rotate,
00234     &vf_info_sab,
00235     &vf_info_screenshot,
00236     &vf_info_smartblur,
00237     &vf_info_softpulldown,
00238     &vf_info_softskip,
00239     &vf_info_spp,
00240     &vf_info_stereo3d,
00241     &vf_info_swapuv,
00242     &vf_info_telecine,
00243     &vf_info_tile,
00244     &vf_info_tinterlace,
00245     &vf_info_unsharp,
00246     &vf_info_uspp,
00247     &vf_info_yuvcsp,
00248     &vf_info_yvu9,
00249 
00250     NULL
00251 };
00252 
00253 /*
00254 Unsupported filters
00255 1bpp
00256 ass
00257 bmovl
00258 crop
00259 dvbscale
00260 flip
00261 expand
00262 format
00263 halfpack
00264 lavc
00265 lavcdeint
00266 noformat
00267 pp
00268 scale
00269 tfields
00270 vo
00271 yadif
00272 zrmjpeg
00273 */
00274 
00275 CpuCaps gCpuCaps; //FIXME initialize this so optims work
00276 
00277 
00278 static void sws_getFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, SwsFilter **dstFilterParam)
00279 {
00280         static int firstTime=1;
00281         *flags=0;
00282 
00283 #if ARCH_X86
00284         if(gCpuCaps.hasMMX)
00285                 __asm__ volatile("emms\n\t"::: "memory"); //FIXME this should not be required but it IS (even for non-MMX versions)
00286 #endif
00287         if(firstTime)
00288         {
00289                 firstTime=0;
00290                 *flags= SWS_PRINT_INFO;
00291         }
00292         else if( mp_msg_test(MSGT_VFILTER,MSGL_DBG2) ) *flags= SWS_PRINT_INFO;
00293 
00294         switch(SWS_BILINEAR)
00295         {
00296                 case 0: *flags|= SWS_FAST_BILINEAR; break;
00297                 case 1: *flags|= SWS_BILINEAR; break;
00298                 case 2: *flags|= SWS_BICUBIC; break;
00299                 case 3: *flags|= SWS_X; break;
00300                 case 4: *flags|= SWS_POINT; break;
00301                 case 5: *flags|= SWS_AREA; break;
00302                 case 6: *flags|= SWS_BICUBLIN; break;
00303                 case 7: *flags|= SWS_GAUSS; break;
00304                 case 8: *flags|= SWS_SINC; break;
00305                 case 9: *flags|= SWS_LANCZOS; break;
00306                 case 10:*flags|= SWS_SPLINE; break;
00307                 default:*flags|= SWS_BILINEAR; break;
00308         }
00309 
00310         *srcFilterParam= NULL;
00311         *dstFilterParam= NULL;
00312 }
00313 
00314 //exact copy from vf_scale.c
00315 // will use sws_flags & src_filter (from cmd line)
00316 struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat)
00317 {
00318         int flags, i;
00319         SwsFilter *dstFilterParam, *srcFilterParam;
00320         enum PixelFormat dfmt, sfmt;
00321 
00322         for(i=0; conversion_map[i].fmt && dstFormat != conversion_map[i].fmt; i++);
00323         dfmt= conversion_map[i].pix_fmt;
00324         for(i=0; conversion_map[i].fmt && srcFormat != conversion_map[i].fmt; i++);
00325         sfmt= conversion_map[i].pix_fmt;
00326 
00327         if (srcFormat == IMGFMT_RGB8 || srcFormat == IMGFMT_BGR8) sfmt = PIX_FMT_PAL8;
00328         sws_getFlagsAndFilterFromCmdLine(&flags, &srcFilterParam, &dstFilterParam);
00329 
00330         return sws_getContext(srcW, srcH, sfmt, dstW, dstH, dfmt, flags , srcFilterParam, dstFilterParam, NULL);
00331 }
00332 
00333 typedef struct {
00334     vf_instance_t vf;
00335     vf_instance_t next_vf;
00336     AVFilterContext *avfctx;
00337     int frame_returned;
00338 } MPContext;
00339 
00340 void mp_msg(int mod, int lev, const char *format, ... ){
00341     va_list va;
00342     va_start(va, format);
00343     //FIXME convert lev/mod
00344     av_vlog(NULL, AV_LOG_DEBUG, format, va);
00345     va_end(va);
00346 }
00347 
00348 int mp_msg_test(int mod, int lev){
00349     return 123;
00350 }
00351 
00352 void init_avcodec(void)
00353 {
00354     //we maybe should init but its kinda 1. unneeded 2. a bit inpolite from here
00355 }
00356 
00357 //Exact copy of vf.c
00358 void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src){
00359     dst->pict_type= src->pict_type;
00360     dst->fields = src->fields;
00361     dst->qscale_type= src->qscale_type;
00362     if(dst->width == src->width && dst->height == src->height){
00363         dst->qstride= src->qstride;
00364         dst->qscale= src->qscale;
00365     }
00366 }
00367 
00368 //Exact copy of vf.c
00369 void vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){
00370     if (vf->next->draw_slice) {
00371         vf->next->draw_slice(vf->next,src,stride,w,h,x,y);
00372         return;
00373     }
00374     if (!vf->dmpi) {
00375         mp_msg(MSGT_VFILTER,MSGL_ERR,"draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
00376         return;
00377     }
00378     if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) {
00379         memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+vf->dmpi->bpp/8*x,
00380             src[0], vf->dmpi->bpp/8*w, h, vf->dmpi->stride[0], stride[0]);
00381         return;
00382     }
00383     memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+x, src[0],
00384         w, h, vf->dmpi->stride[0], stride[0]);
00385     memcpy_pic(vf->dmpi->planes[1]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[1]+(x>>vf->dmpi->chroma_x_shift),
00386         src[1], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]);
00387     memcpy_pic(vf->dmpi->planes[2]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[2]+(x>>vf->dmpi->chroma_x_shift),
00388         src[2], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]);
00389 }
00390 
00391 //Exact copy of vf.c
00392 void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h){
00393     int y;
00394     if(mpi->flags&MP_IMGFLAG_PLANAR){
00395         y0&=~1;h+=h&1;
00396         if(x0==0 && w==mpi->width){
00397             // full width clear:
00398             memset(mpi->planes[0]+mpi->stride[0]*y0,0,mpi->stride[0]*h);
00399             memset(mpi->planes[1]+mpi->stride[1]*(y0>>mpi->chroma_y_shift),128,mpi->stride[1]*(h>>mpi->chroma_y_shift));
00400             memset(mpi->planes[2]+mpi->stride[2]*(y0>>mpi->chroma_y_shift),128,mpi->stride[2]*(h>>mpi->chroma_y_shift));
00401         } else
00402         for(y=y0;y<y0+h;y+=2){
00403             memset(mpi->planes[0]+x0+mpi->stride[0]*y,0,w);
00404             memset(mpi->planes[0]+x0+mpi->stride[0]*(y+1),0,w);
00405             memset(mpi->planes[1]+(x0>>mpi->chroma_x_shift)+mpi->stride[1]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
00406             memset(mpi->planes[2]+(x0>>mpi->chroma_x_shift)+mpi->stride[2]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
00407         }
00408         return;
00409     }
00410     // packed:
00411     for(y=y0;y<y0+h;y++){
00412         unsigned char* dst=mpi->planes[0]+mpi->stride[0]*y+(mpi->bpp>>3)*x0;
00413         if(mpi->flags&MP_IMGFLAG_YUV){
00414             unsigned int* p=(unsigned int*) dst;
00415             int size=(mpi->bpp>>3)*w/4;
00416             int i;
00417 #if HAVE_BIGENDIAN
00418 #define CLEAR_PACKEDYUV_PATTERN 0x00800080
00419 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x80008000
00420 #else
00421 #define CLEAR_PACKEDYUV_PATTERN 0x80008000
00422 #define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x00800080
00423 #endif
00424             if(mpi->flags&MP_IMGFLAG_SWAPPED){
00425                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
00426                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
00427             } else {
00428                 for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN;
00429                 for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN;
00430             }
00431         } else
00432             memset(dst,0,(mpi->bpp>>3)*w);
00433     }
00434 }
00435 
00436 int vf_next_query_format(struct vf_instance *vf, unsigned int fmt){
00437     return 1;
00438 }
00439 
00440 //used by delogo
00441 unsigned int vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred){
00442     return preferred;
00443 }
00444 
00445 mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h){
00446     MPContext *m= (MPContext*)(((uint8_t*)vf) - offsetof(MPContext, next_vf));
00447   mp_image_t* mpi=NULL;
00448   int w2;
00449   int number = mp_imgtype >> 16;
00450 
00451   av_assert0(vf->next == NULL); // all existing filters call this just on next
00452 
00453   //vf_dint needs these as it calls vf_get_image() before configuring the output
00454   if(vf->w==0 && w>0) vf->w=w;
00455   if(vf->h==0 && h>0) vf->h=h;
00456 
00457   av_assert0(w == -1 || w >= vf->w);
00458   av_assert0(h == -1 || h >= vf->h);
00459   av_assert0(vf->w > 0);
00460   av_assert0(vf->h > 0);
00461 
00462   av_log(m->avfctx, AV_LOG_DEBUG, "get_image: %d:%d, vf: %d:%d\n", w,h,vf->w,vf->h);
00463 
00464   if (w == -1) w = vf->w;
00465   if (h == -1) h = vf->h;
00466 
00467   w2=(mp_imgflag&MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE)?((w+15)&(~15)):w;
00468 
00469   // Note: we should call libvo first to check if it supports direct rendering
00470   // and if not, then fallback to software buffers:
00471   switch(mp_imgtype & 0xff){
00472   case MP_IMGTYPE_EXPORT:
00473     if(!vf->imgctx.export_images[0]) vf->imgctx.export_images[0]=new_mp_image(w2,h);
00474     mpi=vf->imgctx.export_images[0];
00475     break;
00476   case MP_IMGTYPE_STATIC:
00477     if(!vf->imgctx.static_images[0]) vf->imgctx.static_images[0]=new_mp_image(w2,h);
00478     mpi=vf->imgctx.static_images[0];
00479     break;
00480   case MP_IMGTYPE_TEMP:
00481     if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
00482     mpi=vf->imgctx.temp_images[0];
00483     break;
00484   case MP_IMGTYPE_IPB:
00485     if(!(mp_imgflag&MP_IMGFLAG_READABLE)){ // B frame:
00486       if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
00487       mpi=vf->imgctx.temp_images[0];
00488       break;
00489     }
00490   case MP_IMGTYPE_IP:
00491     if(!vf->imgctx.static_images[vf->imgctx.static_idx]) vf->imgctx.static_images[vf->imgctx.static_idx]=new_mp_image(w2,h);
00492     mpi=vf->imgctx.static_images[vf->imgctx.static_idx];
00493     vf->imgctx.static_idx^=1;
00494     break;
00495   case MP_IMGTYPE_NUMBERED:
00496     if (number == -1) {
00497       int i;
00498       for (i = 0; i < NUM_NUMBERED_MPI; i++)
00499         if (!vf->imgctx.numbered_images[i] || !vf->imgctx.numbered_images[i]->usage_count)
00500           break;
00501       number = i;
00502     }
00503     if (number < 0 || number >= NUM_NUMBERED_MPI) return NULL;
00504     if (!vf->imgctx.numbered_images[number]) vf->imgctx.numbered_images[number] = new_mp_image(w2,h);
00505     mpi = vf->imgctx.numbered_images[number];
00506     mpi->number = number;
00507     break;
00508   }
00509   if(mpi){
00510     mpi->type=mp_imgtype;
00511     mpi->w=vf->w; mpi->h=vf->h;
00512     // keep buffer allocation status & color flags only:
00513 //    mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE|MP_IMGFLAG_DIRECT);
00514     mpi->flags&=MP_IMGFLAG_ALLOCATED|MP_IMGFLAG_TYPE_DISPLAYED|MP_IMGFLAGMASK_COLORS;
00515     // accept restrictions, draw_slice and palette flags only:
00516     mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK|MP_IMGFLAG_RGB_PALETTE);
00517     if(!vf->draw_slice) mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK;
00518     if(mpi->width!=w2 || mpi->height!=h){
00519 //      printf("vf.c: MPI parameters changed!  %dx%d -> %dx%d   \n", mpi->width,mpi->height,w2,h);
00520         if(mpi->flags&MP_IMGFLAG_ALLOCATED){
00521             if(mpi->width<w2 || mpi->height<h){
00522                 // need to re-allocate buffer memory:
00523                 av_free(mpi->planes[0]);
00524                 mpi->flags&=~MP_IMGFLAG_ALLOCATED;
00525                 mp_msg(MSGT_VFILTER,MSGL_V,"vf.c: have to REALLOCATE buffer memory :(\n");
00526             }
00527 //      } else {
00528         } {
00529             mpi->width=w2; mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
00530             mpi->height=h; mpi->chroma_height=(h + (1<<mpi->chroma_y_shift) - 1)>>mpi->chroma_y_shift;
00531         }
00532     }
00533     if(!mpi->bpp) mp_image_setfmt(mpi,outfmt);
00534     if(!(mpi->flags&MP_IMGFLAG_ALLOCATED) && mpi->type>MP_IMGTYPE_EXPORT){
00535 
00536         av_assert0(!vf->get_image);
00537         // check libvo first!
00538         if(vf->get_image) vf->get_image(vf,mpi);
00539 
00540         if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
00541           // non-direct and not yet allocated image. allocate it!
00542           if (!mpi->bpp) { // no way we can allocate this
00543               mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
00544                      "vf_get_image: Tried to allocate a format that can not be allocated!\n");
00545               return NULL;
00546           }
00547 
00548           // check if codec prefer aligned stride:
00549           if(mp_imgflag&MP_IMGFLAG_PREFER_ALIGNED_STRIDE){
00550               int align=(mpi->flags&MP_IMGFLAG_PLANAR &&
00551                          mpi->flags&MP_IMGFLAG_YUV) ?
00552                          (8<<mpi->chroma_x_shift)-1 : 15; // -- maybe FIXME
00553               w2=((w+align)&(~align));
00554               if(mpi->width!=w2){
00555 #if 0
00556                   // we have to change width... check if we CAN co it:
00557                   int flags=vf->query_format(vf,outfmt); // should not fail
00558                   if(!(flags&3)) mp_msg(MSGT_DECVIDEO,MSGL_WARN,"??? vf_get_image{vf->query_format(outfmt)} failed!\n");
00559 //                printf("query -> 0x%X    \n",flags);
00560                   if(flags&VFCAP_ACCEPT_STRIDE){
00561 #endif
00562                       mpi->width=w2;
00563                       mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
00564 //                  }
00565               }
00566           }
00567 
00568           mp_image_alloc_planes(mpi);
00569 //        printf("clearing img!\n");
00570           vf_mpi_clear(mpi,0,0,mpi->width,mpi->height);
00571         }
00572     }
00573     av_assert0(!vf->start_slice);
00574     if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)
00575         if(vf->start_slice) vf->start_slice(vf,mpi);
00576     if(!(mpi->flags&MP_IMGFLAG_TYPE_DISPLAYED)){
00577             mp_msg(MSGT_DECVIDEO,MSGL_V,"*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
00578                   "NULL"/*vf->info->name*/,
00579                   (mpi->type==MP_IMGTYPE_EXPORT)?"Exporting":
00580                   ((mpi->flags&MP_IMGFLAG_DIRECT)?"Direct Rendering":"Allocating"),
00581                   (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)?" (slices)":"",
00582                   mpi->width,mpi->height,mpi->bpp,
00583                   (mpi->flags&MP_IMGFLAG_YUV)?"YUV":((mpi->flags&MP_IMGFLAG_SWAPPED)?"BGR":"RGB"),
00584                   (mpi->flags&MP_IMGFLAG_PLANAR)?"planar":"packed",
00585                   mpi->bpp*mpi->width*mpi->height/8);
00586             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",
00587                 mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
00588                 mpi->stride[0], mpi->stride[1], mpi->stride[2],
00589                 mpi->chroma_width, mpi->chroma_height, mpi->chroma_x_shift, mpi->chroma_y_shift);
00590             mpi->flags|=MP_IMGFLAG_TYPE_DISPLAYED;
00591     }
00592 
00593   mpi->qscale = NULL;
00594   }
00595   mpi->usage_count++;
00596 //    printf("\rVF_MPI: %p %p %p %d %d %d    \n",
00597 //      mpi->planes[0],mpi->planes[1],mpi->planes[2],
00598 //      mpi->stride[0],mpi->stride[1],mpi->stride[2]);
00599   return mpi;
00600 }
00601 
00602 
00603 int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){
00604     MPContext *m= (void*)vf;
00605     AVFilterLink *outlink     = m->avfctx->outputs[0];
00606     AVFilterBuffer    *pic    = av_mallocz(sizeof(AVFilterBuffer));
00607     AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef));
00608     int i;
00609 
00610     av_assert0(vf->next);
00611 
00612     av_log(m->avfctx, AV_LOG_DEBUG, "vf_next_put_image\n");
00613 
00614     if (!pic || !picref)
00615         goto fail;
00616 
00617     picref->buf = pic;
00618     picref->buf->please_use_av_free= (void*)av_free;
00619     if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps))))
00620         goto fail;
00621 
00622     pic->w = picref->video->w = mpi->w;
00623     pic->h = picref->video->h = mpi->h;
00624 
00625     /* make sure the buffer gets read permission or it's useless for output */
00626     picref->perms = AV_PERM_READ | AV_PERM_REUSE2;
00627 //    av_assert0(mpi->flags&MP_IMGFLAG_READABLE);
00628     if(!(mpi->flags&MP_IMGFLAG_PRESERVE))
00629         picref->perms |= AV_PERM_WRITE;
00630 
00631     pic->refcount = 1;
00632     picref->type = AVMEDIA_TYPE_VIDEO;
00633 
00634     for(i=0; conversion_map[i].fmt && mpi->imgfmt != conversion_map[i].fmt; i++);
00635     pic->format = picref->format = conversion_map[i].pix_fmt;
00636 
00637     memcpy(pic->data,        mpi->planes,   FFMIN(sizeof(pic->data)    , sizeof(mpi->planes)));
00638     memcpy(pic->linesize,    mpi->stride,   FFMIN(sizeof(pic->linesize), sizeof(mpi->stride)));
00639     memcpy(picref->data,     pic->data,     sizeof(picref->data));
00640     memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
00641 
00642     if(pts != MP_NOPTS_VALUE)
00643         picref->pts= pts * av_q2d(outlink->time_base);
00644 
00645     avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
00646     avfilter_draw_slice(outlink, 0, picref->video->h, 1);
00647     avfilter_end_frame(outlink);
00648     avfilter_unref_buffer(picref);
00649     m->frame_returned++;
00650 
00651     return 1;
00652 fail:
00653     if (picref && picref->video)
00654         av_free(picref->video);
00655     av_free(picref);
00656     av_free(pic);
00657     return 0;
00658 }
00659 
00660 int vf_next_config(struct vf_instance *vf,
00661         int width, int height, int d_width, int d_height,
00662         unsigned int voflags, unsigned int outfmt){
00663 
00664     av_assert0(width>0 && height>0);
00665     vf->next->w = width; vf->next->h = height;
00666 
00667     return 1;
00668 #if 0
00669     int flags=vf->next->query_format(vf->next,outfmt);
00670     if(!flags){
00671         // hmm. colorspace mismatch!!!
00672         //this is fatal for us ATM
00673         return 0;
00674     }
00675     mp_msg(MSGT_VFILTER,MSGL_V,"REQ: flags=0x%X  req=0x%X  \n",flags,vf->default_reqs);
00676     miss=vf->default_reqs - (flags&vf->default_reqs);
00677     if(miss&VFCAP_ACCEPT_STRIDE){
00678         // vf requires stride support but vf->next doesn't support it!
00679         // let's insert the 'expand' filter, it does the job for us:
00680         vf_instance_t* vf2=vf_open_filter(vf->next,"expand",NULL);
00681         if(!vf2) return 0; // shouldn't happen!
00682         vf->next=vf2;
00683     }
00684     vf->next->w = width; vf->next->h = height;
00685 #endif
00686     return 1;
00687 }
00688 
00689 int vf_next_control(struct vf_instance *vf, int request, void* data){
00690     MPContext *m= (void*)vf;
00691     av_log(m->avfctx, AV_LOG_DEBUG, "Received control %d\n", request);
00692     return 0;
00693 }
00694 
00695 static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt){
00696     MPContext *m= (void*)vf;
00697     int i;
00698     av_log(m->avfctx, AV_LOG_DEBUG, "query %X\n", fmt);
00699 
00700     for(i=0; conversion_map[i].fmt; i++){
00701         if(fmt==conversion_map[i].fmt)
00702             return 1; //we suport all
00703     }
00704     return 0;
00705 }
00706 
00707 
00708 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
00709 {
00710     MPContext *m = ctx->priv;
00711     char name[256];
00712     int i;
00713 
00714     m->avfctx= ctx;
00715 
00716     if(!args || 1!=sscanf(args, "%255[^:=]", name)){
00717         av_log(ctx, AV_LOG_ERROR, "Invalid parameter.\n");
00718         return AVERROR(EINVAL);
00719     }
00720     args+= strlen(name)+1;
00721 
00722     for(i=0; ;i++){
00723         if(!filters[i] || !strcmp(name, filters[i]->name))
00724             break;
00725     }
00726 
00727     if(!filters[i]){
00728         av_log(ctx, AV_LOG_ERROR, "Unknown filter %s\n", name);
00729         return AVERROR(EINVAL);
00730     }
00731 
00732     av_log(ctx, AV_LOG_WARNING,
00733            "'%s' is a wrapped MPlayer filter (libmpcodecs). This filter may be removed\n"
00734            "once it has been ported to a native libavfilter.\n", name);
00735 
00736     memset(&m->vf,0,sizeof(m->vf));
00737     m->vf.info= filters[i];
00738 
00739     m->vf.next        = &m->next_vf;
00740     m->vf.put_image   = vf_next_put_image;
00741     m->vf.config      = vf_next_config;
00742     m->vf.query_format= vf_default_query_format;
00743     m->vf.control     = vf_next_control;
00744     m->vf.default_caps=VFCAP_ACCEPT_STRIDE;
00745     m->vf.default_reqs=0;
00746     if(m->vf.info->opts)
00747         av_log(ctx, AV_LOG_ERROR, "opts / m_struct_set is unsupported\n");
00748 #if 0
00749     if(vf->info->opts) { // vf_vo get some special argument
00750       const m_struct_t* st = vf->info->opts;
00751       void* vf_priv = m_struct_alloc(st);
00752       int n;
00753       for(n = 0 ; args && args[2*n] ; n++)
00754         m_struct_set(st,vf_priv,args[2*n],args[2*n+1]);
00755       vf->priv = vf_priv;
00756       args = NULL;
00757     } else // Otherwise we should have the '_oldargs_'
00758       if(args && !strcmp(args[0],"_oldargs_"))
00759         args = (char**)args[1];
00760       else
00761         args = NULL;
00762 #endif
00763     if(m->vf.info->vf_open(&m->vf, args)<=0){
00764         av_log(ctx, AV_LOG_ERROR, "vf_open() of %s with arg=%s failed\n", name, args);
00765         return -1;
00766     }
00767 
00768     return 0;
00769 }
00770 
00771 static int query_formats(AVFilterContext *ctx)
00772 {
00773     AVFilterFormats *avfmts=NULL;
00774     MPContext *m = ctx->priv;
00775     enum PixelFormat lastpixfmt = PIX_FMT_NONE;
00776     int i;
00777 
00778     for(i=0; conversion_map[i].fmt; i++){
00779         av_log(ctx, AV_LOG_DEBUG, "query: %X\n", conversion_map[i].fmt);
00780         if(m->vf.query_format(&m->vf, conversion_map[i].fmt)){
00781             av_log(ctx, AV_LOG_DEBUG, "supported,adding\n");
00782             if (conversion_map[i].pix_fmt != lastpixfmt) {
00783                 avfilter_add_format(&avfmts, conversion_map[i].pix_fmt);
00784                 lastpixfmt = conversion_map[i].pix_fmt;
00785             }
00786         }
00787     }
00788 
00789     //We assume all allowed input formats are also allowed output formats
00790     avfilter_set_common_pixel_formats(ctx, avfmts);
00791     return 0;
00792 }
00793 
00794 static int config_inprops(AVFilterLink *inlink)
00795 {
00796     MPContext *m = inlink->dst->priv;
00797     int i;
00798     for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
00799 
00800     av_assert0(conversion_map[i].fmt && inlink->w && inlink->h);
00801 
00802     m->vf.fmt.have_configured = 1;
00803     m->vf.fmt.orig_height     = inlink->h;
00804     m->vf.fmt.orig_width      = inlink->w;
00805     m->vf.fmt.orig_fmt        = conversion_map[i].fmt;
00806 
00807     if(m->vf.config(&m->vf, inlink->w, inlink->h, inlink->w, inlink->h, 0, conversion_map[i].fmt)<=0)
00808         return -1;
00809 
00810     return 0;
00811 }
00812 
00813 static int config_outprops(AVFilterLink *outlink)
00814 {
00815     MPContext *m = outlink->src->priv;
00816 
00817     outlink->w = m->next_vf.w;
00818     outlink->h = m->next_vf.h;
00819 
00820     return 0;
00821 }
00822 
00823 static int request_frame(AVFilterLink *outlink)
00824 {
00825     MPContext *m = outlink->src->priv;
00826     int ret;
00827 
00828     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame\n");
00829 
00830     for(m->frame_returned=0; !m->frame_returned;){
00831         ret=avfilter_request_frame(outlink->src->inputs[0]);
00832         if(ret<0)
00833             break;
00834     }
00835 
00836     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame ret=%d\n", ret);
00837     return ret;
00838 }
00839 
00840 static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
00841 {
00842 }
00843 
00844 static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
00845 {
00846 }
00847 
00848 static void end_frame(AVFilterLink *inlink)
00849 {
00850     MPContext *m = inlink->dst->priv;
00851     AVFilterBufferRef *inpic  = inlink->cur_buf;
00852     int i;
00853     double pts= MP_NOPTS_VALUE;
00854     mp_image_t* mpi = new_mp_image(inpic->video->w, inpic->video->h);
00855 
00856     if(inpic->pts != AV_NOPTS_VALUE)
00857         pts= inpic->pts / av_q2d(inlink->time_base);
00858 
00859     for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++);
00860     mp_image_setfmt(mpi,conversion_map[i].fmt);
00861 
00862     memcpy(mpi->planes, inpic->data,     FFMIN(sizeof(inpic->data)    , sizeof(mpi->planes)));
00863     memcpy(mpi->stride, inpic->linesize, FFMIN(sizeof(inpic->linesize), sizeof(mpi->stride)));
00864 
00865     //FIXME pass interleced & tff flags around
00866 
00867     // mpi->flags|=MP_IMGFLAG_ALLOCATED; ?
00868     mpi->flags |= MP_IMGFLAG_READABLE;
00869     if(!(inpic->perms & AV_PERM_WRITE))
00870         mpi->flags |= MP_IMGFLAG_PRESERVE;
00871     if(m->vf.put_image(&m->vf, mpi, pts) == 0){
00872         av_log(m->avfctx, AV_LOG_DEBUG, "put_image() says skip\n");
00873     }
00874     free_mp_image(mpi);
00875 
00876     avfilter_unref_buffer(inpic);
00877 }
00878 
00879 AVFilter avfilter_vf_mp = {
00880     .name      = "mp",
00881     .description = NULL_IF_CONFIG_SMALL("Apply a libmpcodecs filter to the input video."),
00882     .init = init,
00883     .priv_size = sizeof(MPContext),
00884     .query_formats = query_formats,
00885 
00886     .inputs    = (const AVFilterPad[]) {{ .name      = "default",
00887                                     .type            = AVMEDIA_TYPE_VIDEO,
00888                                     .start_frame     = start_frame,
00889                                     .draw_slice      = null_draw_slice,
00890                                     .end_frame       = end_frame,
00891                                     .config_props    = config_inprops,
00892                                     .min_perms       = AV_PERM_READ, },
00893                                   { .name = NULL}},
00894     .outputs   = (const AVFilterPad[]) {{ .name      = "default",
00895                                     .type            = AVMEDIA_TYPE_VIDEO,
00896                                     .request_frame   = request_frame,
00897                                     .config_props    = config_outprops, },
00898                                   { .name = NULL}},
00899 };
Generated on Fri Feb 1 2013 14:34:50 for FFmpeg by doxygen 1.7.1