Index: codec-cfg.c =================================================================== --- codec-cfg.c (revision 24967) +++ codec-cfg.c (working copy) @@ -179,6 +179,7 @@ {"ZRMJPEGIT", IMGFMT_ZRMJPEGIT}, {"ZRMJPEGIB", IMGFMT_ZRMJPEGIB}, + {"VLD_MPEG2",IMGFMT_XVMC_VLD_MPEG2}, {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2}, {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2}, Index: configure =================================================================== --- configure (revision 24967) +++ configure (working copy) @@ -527,6 +527,7 @@ _dga2=auto _xv=auto _xvmc=no #auto when complete +_xvmc_vld=auto _sdl=auto _directx=auto _win32waveout=auto @@ -3901,7 +3902,7 @@ _novomodules="x11 $_novomodules" _res_comment="check if the dev(el) packages are installed" # disable stuff that depends on X - _xv=no ; _xvmc=no ; _xinerama=no ; _vm=no ; _xf86keysym=no + _xv=no ; _xvmc=no ; _xvmc_vld=no ; _xinerama=no ; _vm=no ; _xf86keysym=no fi echores "$_x11" @@ -4001,6 +4002,31 @@ echores "$_xvmc" +echocheck "XvMC VLD" +if test "$_xvmc" = yes ; then + _xvmc_vld=no + cat > $TMPC < +#include +#include +#include +int main(void) { + (void) XvMCQueryExtension(0,0,0); + (void) XvMCCreateContext(0,0,0,0,0,0,0); + return 0; } +EOF + cc_check -lXvMC -l$_xvmclib && _xvmc_vld=yes + if test "$_xvmc_vld" = yes ; then + _def_xvmc_vld='#define HAVE_XVMC_VLD 1' + _libs_mencoder="$_libs_mencoder -l$_xvmclib" + else + _def_xvmc_vld='#undef HAVE_XVMC_VLD' + _libavdecoders=`echo $_libavdecoders | sed -e s/MPEG_XVMC_VLD_DECODER// ` + fi +fi +echores "$_xvmc_vld" + + echocheck "Xinerama" if test "$_xinerama" = auto ; then cat > $TMPC <pix_fmt==PIX_FMT_XVMC_MPEG2_IDCT) return CONTROL_TRUE; + case IMGFMT_XVMC_VLD_MPEG2: + if(avctx->pix_fmt==PIX_FMT_XVMC_MPEG2_VLD) return CONTROL_TRUE; #endif } return CONTROL_FALSE; @@ -225,6 +228,9 @@ vd_ffmpeg_ctx *ctx; AVCodec *lavc_codec; int lowres_w=0; +#ifdef HAVE_XVMC + char *voname = 0; +#endif int do_vis_debug= lavc_param_vismv || (lavc_param_debug&(FF_DEBUG_VIS_MB_TYPE|FF_DEBUG_VIS_QP)); if(!avcodec_inited){ @@ -260,11 +266,23 @@ #ifdef HAVE_XVMC + // Try and get the name of the selected vo system + // so that if its _not_ xvmc we can fail gracefully + // and mplayer can fall back to a sw decoder + if (sh->video_out) { + vo_info_t *voinfo; + vo_functions_t * shvoc=sh->video_out; + if (shvoc) { + voinfo = shvoc->info; + if (voinfo) voname=voinfo->short_name; + } + } #ifdef CODEC_CAP_HWACCEL - if(lavc_codec->capabilities & CODEC_CAP_HWACCEL){ + if((lavc_codec->capabilities & CODEC_CAP_HWACCEL) && #else - if(lavc_codec->id == CODEC_ID_MPEG2VIDEO_XVMC){ + if((lavc_codec->id == CODEC_ID_MPEG2VIDEO_XVMC) && #endif /* CODEC_CAP_HWACCEL */ + voname && !strcmp(voname,"xvmc") ) { mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_XVMCAcceleratedCodec); assert(ctx->do_dr1);//these are must to! assert(ctx->do_slices); //it is (vo_)ffmpeg bug if this fails @@ -535,6 +553,7 @@ #ifdef HAVE_XVMC case PIX_FMT_XVMC_MPEG2_MC:ctx->best_csp=IMGFMT_XVMC_MOCO_MPEG2;break; case PIX_FMT_XVMC_MPEG2_IDCT:ctx->best_csp=IMGFMT_XVMC_IDCT_MPEG2;break; + case PIX_FMT_XVMC_MPEG2_VLD:ctx->best_csp=IMGFMT_XVMC_VLD_MPEG2;break; #endif default: ctx->best_csp=0; @@ -919,7 +938,11 @@ avctx->get_buffer= mc_get_buffer; avctx->release_buffer= mc_release_buffer; avctx->draw_horiz_band = mc_render_slice; + if (avctx->xvmc_acceleration != 4) mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_XVMCAcceleratedMPEG2); + else + mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_XVMCVLDAcceleratedMPEG2); + assert(ctx->do_dr1);//these are must to! assert(ctx->do_slices); //it is (vo_)ffmpeg bug if this fails avctx->flags|= CODEC_FLAG_EMU_EDGE;//do i need that??!! Index: libmpcodecs/img_format.c =================================================================== --- libmpcodecs/img_format.c (revision 24967) +++ libmpcodecs/img_format.c (working copy) @@ -67,6 +67,7 @@ case IMGFMT_ZRMJPEGIB: return("Zoran MJPEG bottom field first"); case IMGFMT_XVMC_MOCO_MPEG2: return("MPEG1/2 Motion Compensation"); case IMGFMT_XVMC_IDCT_MPEG2: return("MPEG1/2 Motion Compensation and IDCT"); + case IMGFMT_XVMC_VLD_MPEG2: return("MPEG1/2 Motion Compensation and VLD"); } snprintf(unknow_format,20,"Unknown 0x%04x",format); return unknow_format; Index: libmpcodecs/img_format.h =================================================================== --- libmpcodecs/img_format.h (revision 24967) +++ libmpcodecs/img_format.h (working copy) @@ -107,6 +107,7 @@ //these are chroma420 #define IMGFMT_XVMC_MOCO_MPEG2 (IMGFMT_XVMC|0x02) #define IMGFMT_XVMC_IDCT_MPEG2 (IMGFMT_XVMC|0x82) +#define IMGFMT_XVMC_VLD_MPEG2 (IMGFMT_XVMC|0x42) typedef struct { void* data; Index: libmpdemux/stheader.h =================================================================== --- libmpdemux/stheader.h (revision 24967) +++ libmpdemux/stheader.h (working copy) @@ -78,6 +78,7 @@ int disp_w,disp_h; // display size (filled by fileformat parser) // output driver/filters: (set by libmpcodecs core) unsigned int outfmtidx; + void* video_out; // the video_out handle, used for this video stream struct vf_instance_s *vfilter; // the video filter chain, used for this video stream int vf_inited; #ifdef DYNAMIC_PLUGINS Index: libvo/vo_xvmc.c =================================================================== --- libvo/vo_xvmc.c (revision 24967) +++ libvo/vo_xvmc.c (working copy) @@ -23,6 +23,11 @@ #include #include +#ifdef HAVE_XVMC_VLD +#include +extern int has_xvmc_vld; +#endif + #include "x11_common.h" #include "xvmc_render.h" @@ -45,6 +50,7 @@ #define UNUSED(x) ((void)(x)) +extern unsigned int video_format; #include "libavcodec/avcodec.h" #if LIBAVCODEC_BUILD < ((51<<16)+(40<<8)+2) @@ -59,6 +65,8 @@ static int xv_port_request = 0; static int bob_deinterlace; static int top_field_first; +static int use_deint_one; +static int use_tv_clip; static int image_width,image_height; static int image_format; @@ -123,7 +131,7 @@ "XVideo Motion Compensation", "xvmc", "Ivan Kalvachev ", - "" + "Ivor Hewitt - VIA VLD support" }; LIBVO_EXTERN(xvmc); @@ -196,7 +204,23 @@ } //end of vo_xv shm/xvimage code +int hasVLDAcceleration() +{ +#ifdef HAVE_XVMC_VLD + return XVMC_VLD == (surface_info.mc_type & XVMC_VLD); +#else + return 0; +#endif +} + static int xvmc_check_surface_format(uint32_t format, XvMCSurfaceInfo * surf_info){ +#ifdef HAVE_XVMC_VLD + if (format == IMGFMT_XVMC_VLD_MPEG2 ){ + if( surf_info->mc_type != (XVMC_VLD|XVMC_MPEG_2) ) return -1; + if( surf_info->chroma_format != XVMC_CHROMA_FORMAT_420 ) return -1; + return 0; + } +#endif if ( format == IMGFMT_XVMC_IDCT_MPEG2 ){ if( surf_info->mc_type != (XVMC_IDCT|XVMC_MPEG_2) ) return -1; if( surf_info->chroma_format != XVMC_CHROMA_FORMAT_420 ) return -1; @@ -361,6 +385,59 @@ return VO_TRUE; } + +static int +check_xvmc_vld() +{ + int rez; + XvAdaptorInfo* ai; + XvMCSurfaceInfo* surf_info; + int max_adaptor; + int max_surf; + int i; + unsigned long p; + int s; + + rez = XvQueryAdaptors(mDisplay, DefaultRootWindow(mDisplay), + &max_adaptor,&ai); + if (rez != Success) return; + + if (mp_msg_test(MSGT_VO, MSGL_DBG3)) + printf("vo_xvmc: Querying %d adaptors for VLD\n", max_adaptor); + + for (i = 0; i < max_adaptor; i++) + { + if (mp_msg_test(MSGT_VO,MSGL_DBG3)) + printf("vo_xvmc: Quering adaptor #%d for VLD\n", i); + if (ai[i].type == 0) continue; + + // Probing every XV port + for (p = ai[i].base_id; p < ai[i].base_id + ai[i].num_ports; p++) + { + // Respect the users wish + if ((xv_port_request != 0) && (xv_port_request != p)) continue; + if (mp_msg_test(MSGT_VO,MSGL_DBG3)) + printf("vo_xvmc: Probing port #%ld for VLD\n", p); + surf_info = XvMCListSurfaceTypes(mDisplay, p, &max_surf); + if (surf_info == NULL || max_surf == 0) continue; + + // We have XvMC list! + for(s = 0; s < max_surf; s++) + { + // We have match! + if (XVMC_VLD == (surf_info[s].mc_type & XVMC_VLD)) + has_xvmc_vld = 1; + } + XFree(surf_info); + } + } + XvFreeAdaptorInfo(ai); + + if (mp_msg_test(MSGT_VO,MSGL_DBG3) && has_xvmc_vld) + printf("vo_xvmc: Found VLD support in XvMC\n"); +} + + static int preinit(const char *arg){ int xv_version,xv_release,xv_request_base,xv_event_base,xv_error_base; int mc_eventBase,mc_errorBase; @@ -377,9 +454,16 @@ { "sleep", OPT_ARG_BOOL, &use_sleep, NULL }, { "queue", OPT_ARG_BOOL, &use_queue, NULL }, { "bobdeint", OPT_ARG_BOOL, &bob_deinterlace, NULL }, + { "onedeint", OPT_ARG_BOOL, &use_deint_one, NULL }, + { "tv-clip", OPT_ARG_BOOL, &use_tv_clip, NULL }, { NULL } }; + // If the video is not MPEG1 or MPEG2, we can't decode it, so + // fail cleanly to allow mplayer to fallback to another vo system + if (video_format != 0x10000001 && video_format != 0x10000002) return -1; + + //Obtain display handler if (!vo_init()) return -1;//vo_xv @@ -415,6 +499,8 @@ use_sleep = 0; use_queue = 0; bob_deinterlace = 0; + use_deint_one = 0; + use_tv_clip = 0; /* parse suboptions */ if ( subopt_parse( arg, subopts ) != 0 ) @@ -424,6 +510,9 @@ xv_setup_colorkeyhandling( ck_method_arg.str, ck_src_arg.str ); + // Check whether XvMC supports VLD + check_xvmc_vld(); + return 0; } @@ -505,6 +594,8 @@ if(surface_info.chroma_format == XVMC_CHROMA_FORMAT_444) blocks_per_macroblock = 12; +if (!hasVLDAcceleration()) +{ rez = XvMCCreateBlocks(mDisplay,&ctx,numblocks*blocks_per_macroblock,&data_blocks); if( rez != Success ){ XvMCDestroyContext(mDisplay,&ctx); @@ -520,6 +611,8 @@ } printf("vo_xvmc: mv_blocks allocated\n"); +} + if(surface_render==NULL) surface_render=malloc(MAX_SURFACES*sizeof(xvmc_render_state_t));//easy mem debug memset(surface_render,0,MAX_SURFACES*sizeof(xvmc_render_state_t)); @@ -538,6 +631,11 @@ surface_render[i].chroma_format = surface_info.chroma_format; surface_render[i].unsigned_intra = (surface_info.flags & XVMC_INTRA_UNSIGNED) == XVMC_INTRA_UNSIGNED; surface_render[i].p_surface = &surface_array[i]; + + surface_render[i].state = 0; + surface_render[i].disp = mDisplay; + surface_render[i].ctx = &ctx; + if( mp_msg_test(MSGT_VO,MSGL_DBG4) ) printf("vo_xvmc: surface[%d] = %p .rndr=%p\n",i,&surface_array[i], &surface_render[i]); } @@ -993,6 +1091,8 @@ int rez; int clipX,clipY,clipW,clipH; int i; + int srcY=0, srcH=image_height; + int fieldnobob; if(p_render_surface == NULL) return; @@ -1002,22 +1102,38 @@ clipW = vo_dwidth+vo_panscan_x; clipH = vo_dheight+vo_panscan_y; + if (use_tv_clip) { + /* + * Clip top few lines off to get rid of annoying flicker + * when using bob de-interlacing on TV sourced video. + */ + srcY+=4; + srcH-=4; + } + if(draw_ck) vo_xv_draw_colorkey(clipX,clipY,clipW,clipH); if(benchmark) return; + fieldnobob = XVMC_FRAME_PICTURE; + + if (use_deint_one) + fieldnobob = (top_field_first) ? XVMC_TOP_FIELD : XVMC_BOTTOM_FIELD; + for (i = 1; i <= bob_deinterlace + 1; i++) { - int field = top_field_first ? i : i ^ 3; + int field = top_field_first ? i : i ^ XVMC_FRAME_PICTURE; rez = XvMCPutSurface(mDisplay, p_render_surface->p_surface, vo_window, - 0, 0, image_width, image_height, + 0, srcY, image_width, srcH, clipX, clipY, clipW, clipH, - bob_deinterlace ? field : 3); - //p_render_surface_to_show->display_flags); + bob_deinterlace ? field : fieldnobob); + if (i == 1 && bob_deinterlace) { + usleep(10*1000); + } if(rez != Success){ - printf("vo_xvmc: PutSurface failer, critical error %d!\n",rez); + printf("vo_xvmc: PutSurface failure, critical error %d!\n",rez); assert(0); } } @@ -1109,9 +1225,11 @@ if( number_of_surfaces ){ + if (!hasVLDAcceleration()) + { XvMCDestroyMacroBlocks(mDisplay,&mv_blocks); XvMCDestroyBlocks(mDisplay,&data_blocks); - + } for(i=0; imagic == MP_XVMC_RENDER_MAGIC ); + if (hasVLDAcceleration()) + { + rez = XvMCPutSlice2(mDisplay,&ctx,(char*)rndr->slice_data, + rndr->slice_datalen, + rndr->slice_code); + if (rez) + printf("vo_xxmc::slice Error %d\n",rez); + + } + else + { rez = XvMCRenderSurface(mDisplay,&ctx,rndr->picture_structure, rndr->p_surface, rndr->p_past_surface, @@ -1200,7 +1329,7 @@ if(rez != Success) { int i; - printf("vo_xvmc::slice: RenderSirface returned %d\n",rez); + printf("vo_xvmc::slice: RenderSurface returned %d\n",rez); printf("vo_xvmc::slice: pict=%d,flags=%x,start_blocks=%d,num_blocks=%d\n", rndr->picture_structure,rndr->flags,rndr->start_mv_blocks_num, @@ -1228,6 +1357,7 @@ rez = XvMCFlushSurface(mDisplay, rndr->p_surface); assert(rez==Success); +} // rndr->start_mv_blocks_num += rndr->filled_mv_blocks_num; rndr->start_mv_blocks_num = 0; rndr->filled_mv_blocks_num = 0; @@ -1337,8 +1467,16 @@ // these are shared!! so watch out // do call RenderSurface before overwriting +if (!hasVLDAcceleration()) +{ mpi->planes[0] = (char*)data_blocks.blocks; mpi->planes[1] = (char*)mv_blocks.macro_blocks; +} +else +{ + mpi->planes[0] = 1; + mpi->planes[1] = 0; +} mpi->priv = mpi->planes[2] = (char*)rndr; Index: mencoder.c =================================================================== --- mencoder.c (revision 24967) +++ mencoder.c (working copy) @@ -771,6 +771,7 @@ mux_v->bih=NULL; } sh_video->codec=NULL; +sh_video->video_out=NULL; sh_video->vfilter=NULL; // fixme! switch(mux_v->codec){ Index: mplayer.c =================================================================== --- mplayer.c (revision 24967) +++ mplayer.c (working copy) @@ -85,6 +85,8 @@ int quiet=0; int enable_mouse_movements=0; +unsigned int video_format=0; + #ifdef WIN32 char * proc_priority=NULL; #endif @@ -1897,10 +1899,16 @@ //shouldn't we set dvideo->id=-2 when we fail? vo_config_count=0; //if((mpctx->video_out->preinit(vo_subdevice))!=0){ + + // let the video driver know what format the video is in so it can + // reject it if it wants - lets vo_xvmc fail if ffmpeg12mc codec not used + video_format=sh_video->format; + if(!(mpctx->video_out=init_best_video_out(video_driver_list))){ mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_ErrorInitializingVODevice); goto err_out; } + sh_video->video_out=mpctx->video_out; inited_flags|=INITED_VO; } Index: xvmc_render.h =================================================================== --- xvmc_render.h (revision 24967) +++ xvmc_render.h (working copy) @@ -5,6 +5,9 @@ #include #include +#ifdef HAVE_XVMC_VLD +#include +#endif //the surface should be shown, video driver manipulate this #define MP_XVMC_STATE_DISPLAY_PENDING 1 @@ -27,6 +30,15 @@ int idct;//does we use IDCT acceleration? int chroma_format;//420,422,444 int unsigned_intra;//+-128 for intra pictures after clip +#ifdef HAVE_XVMC_VLD + // These are for the XVMC VLD slice interface + int pict_type; //this is for skipping frames + int slice_code; + int slice_datalen; + unsigned char *slice_data; + Display *disp; + XvMCContext *ctx; +#endif XvMCSurface* p_surface;//pointer to rendered surface, never changed //these are changed by decoder