vo_xvmc.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,427 行 · 第 1/3 页
C
1,427 行
#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include "config.h"#include "mp_msg.h"#include "video_out.h"#include "video_out_internal.h"#include "osdep/timer.h"#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/Xatom.h>#ifdef HAVE_SHM#include <sys/ipc.h>#include <sys/shm.h>#include <X11/extensions/XShm.h>#endif#include <X11/extensions/Xv.h>#include <X11/extensions/Xvlib.h>#include <X11/extensions/XvMClib.h>#include "x11_common.h"#include "xvmc_render.h"#include "sub.h"#include "aspect.h"#include "subopt-helper.h"#ifdef HAVE_NEW_GUI#include "gui/interface.h"#endif#include "libavutil/common.h"//no chance for xinerama to be supported in the near future#undef HAVE_XINERAMA#undef NDEBUG #include <assert.h>#define UNUSED(x) ((void)(x))#include "libavcodec/avcodec.h"#if LIBAVCODEC_BUILD < ((51<<16)+(40<<8)+2)#error You need at least libavcodecs v51.40.2#endifstatic int benchmark;static int use_sleep;static int first_frame;//draw colorkey on first framestatic int use_queue;static int xv_port_request = 0;static int bob_deinterlace;static int top_field_first;static int image_width,image_height;static int image_format;static uint32_t drwX,drwY;#define NO_SUBPICTURE 0#define OVERLAY_SUBPICTURE 1#define BLEND_SUBPICTURE 2#define BACKEND_SUBPICTURE 3static int subpicture_mode;static int subpicture_alloc;static XvMCSubpicture subpicture;static XvImageFormatValues subpicture_info;static int subpicture_clear_color;//transparent color for the subpicture or color key for overlaystatic XvMCSurfaceInfo surface_info;static XvMCContext ctx;static XvMCBlockArray data_blocks;static XvMCMacroBlockArray mv_blocks;#define MAX_SURFACES 8static int number_of_surfaces=0;static XvMCSurface surface_array[MAX_SURFACES];static xvmc_render_state_t * surface_render;static xvmc_render_state_t * p_render_surface_to_show=NULL;static xvmc_render_state_t * p_render_surface_visible=NULL;//display queue, kinda render aheadstatic xvmc_render_state_t * show_queue[MAX_SURFACES];static int free_element;static void (*draw_osd_fnc)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);static void (*clear_osd_fnc)(int x0,int y0, int w,int h);static void (*init_osd_fnc)(void);static void draw_osd_AI44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);static void draw_osd_IA44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);static void clear_osd_subpic(int x0,int y0, int w,int h);static void init_osd_yuv_pal(void);static const struct{ int id;//id as xvimages or as mplayer RGB|{8,15,16,24,32} void (* init_func_ptr)(); void (* draw_func_ptr)(); void (* clear_func_ptr)(); } osd_render[]={ {0x34344149,init_osd_yuv_pal,draw_osd_AI44,clear_osd_subpic}, {0x34344941,init_osd_yuv_pal,draw_osd_IA44,clear_osd_subpic}, {0,NULL,NULL,NULL} };static void xvmc_free(void);static void xvmc_clean_surfaces(void);static int count_free_surfaces();static xvmc_render_state_t * find_free_surface();static vo_info_t info = { "XVideo Motion Compensation", "xvmc", "Ivan Kalvachev <iive@users.sf.net>", ""};LIBVO_EXTERN(xvmc);//shm stuff from vo_xv#ifdef HAVE_SHM/* since it doesn't seem to be defined on some platforms */int XShmGetEventBase(Display*);static XShmSegmentInfo Shminfo;static int Shmem_Flag;#endifXvImage * xvimage;static void allocate_xvimage(int xvimage_width,int xvimage_height,int xv_format){ /* * allocate XvImages. FIXME: no error checking, without * mit-shm this will bomb... trzing to fix ::atmos */#ifdef HAVE_SHM if ( mLocalDisplay && XShmQueryExtension( mDisplay ) ) Shmem_Flag = 1; else { Shmem_Flag = 0; mp_msg(MSGT_VO,MSGL_INFO, "Shared memory not supported\nReverting to normal Xv\n" ); } if ( Shmem_Flag ) { xvimage = (XvImage *) XvShmCreateImage(mDisplay, xv_port, xv_format, NULL, xvimage_width, xvimage_height, &Shminfo); Shminfo.shmid = shmget(IPC_PRIVATE, xvimage->data_size, IPC_CREAT | 0777); Shminfo.shmaddr = (char *) shmat(Shminfo.shmid, 0, 0); Shminfo.readOnly = False; xvimage->data = Shminfo.shmaddr; XShmAttach(mDisplay, &Shminfo); XSync(mDisplay, False); shmctl(Shminfo.shmid, IPC_RMID, 0); } else#endif { xvimage = (XvImage *) XvCreateImage(mDisplay, xv_port, xv_format, NULL, xvimage_width, xvimage_height); xvimage->data = malloc(xvimage->data_size); XSync(mDisplay,False); }// memset(xvimage->data,128,xvimage->data_size); return;}static void deallocate_xvimage(){#ifdef HAVE_SHM if ( Shmem_Flag ) { XShmDetach( mDisplay,&Shminfo ); shmdt( Shminfo.shmaddr ); } else#endif { free(xvimage->data); } XFree(xvimage); XSync(mDisplay, False); return;}//end of vo_xv shm/xvimage codestatic int xvmc_check_surface_format(uint32_t format, XvMCSurfaceInfo * surf_info){ 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; return 0; } if ( format == IMGFMT_XVMC_MOCO_MPEG2 ){ if(surf_info->mc_type != XVMC_MPEG_2) return -1; if(surf_info->chroma_format != XVMC_CHROMA_FORMAT_420) return -1; return 0; } return -1;//fail}//print all info needed to add new formatstatic void print_xvimage_format_values(XvImageFormatValues *xifv){int i; printf("Format_ID = 0x%X\n",xifv->id); printf(" type = "); if(xifv->type == XvRGB) printf("RGB\n"); else if(xifv->type == XvYUV) printf("YUV\n"); else printf("Unknown\n"); printf(" byte_order = "); if(xifv->byte_order == LSBFirst) printf("LSB First\n"); else if(xifv->type == MSBFirst) printf("MSB First\n"); else printf("Unknown\n");//yes Linux support other types too printf(" guid = "); for(i=0;i<16;i++) printf("%02X ",(unsigned char)xifv->guid[i]); printf("\n"); printf(" bits_per_pixel = %d\n",xifv->bits_per_pixel); printf(" format = "); if(xifv->format == XvPacked) printf("XvPacked\n"); else if(xifv->format == XvPlanar) printf("XvPlanar\n"); else printf("Unknown\n"); printf(" num_planes = %d\n",xifv->num_planes); if(xifv->type == XvRGB){ printf(" red_mask = %0X\n", xifv->red_mask); printf(" green_mask = %0X\n",xifv->green_mask); printf(" blue_mask = %0X\n", xifv->blue_mask); } if(xifv->type == XvYUV){ printf(" y_sample_bits = %d\n u_sample_bits = %d\n v_sample_bits = %d\n", xifv->y_sample_bits,xifv->u_sample_bits,xifv->v_sample_bits); printf(" horz_y_period = %d\n horz_u_period = %d\n horz_v_period = %d\n", xifv->horz_y_period,xifv->horz_u_period,xifv->horz_v_period); printf(" vert_y_period = %d\n vert_u_period = %d\n vert_v_period = %d\n", xifv->vert_y_period,xifv->vert_u_period,xifv->vert_v_period); printf(" component_order = "); for(i=0;i<32;i++) if(xifv->component_order[i]>=32) printf("%c",xifv->component_order[i]); printf("\n"); printf(" scanline = "); if(xifv->scanline_order == XvTopToBottom) printf("XvTopToBottom\n"); else if(xifv->scanline_order == XvBottomToTop) printf("XvBottomToTop\n"); else printf("Unknown\n"); } printf("\n");}// WARNING This function may changes xv_port and surface_info!static int xvmc_find_surface_by_format(int format,int width,int height, XvMCSurfaceInfo * surf_info,int query){int rez;XvAdaptorInfo * ai;int num_adaptors,i;unsigned long p;int s,mc_surf_num;XvMCSurfaceInfo * mc_surf_list; rez = XvQueryAdaptors(mDisplay,DefaultRootWindow(mDisplay),&num_adaptors,&ai); if( rez != Success ) return -1; if( mp_msg_test(MSGT_VO,MSGL_DBG3) ) { printf("vo_xvmc: Querying %d adaptors\n",num_adaptors); } for(i=0; i<num_adaptors; i++) { if( mp_msg_test(MSGT_VO,MSGL_DBG3) ) { printf("vo_xvmc: Quering adaptor #%d\n",i); } if( ai[i].type == 0 ) continue;// we need at least dummy type!//probing ports for(p=ai[i].base_id; p<ai[i].base_id+ai[i].num_ports; p++) { if( mp_msg_test(MSGT_VO,MSGL_DBG3) ) { printf("vo_xvmc: probing port #%ld\n",p); } mc_surf_list = XvMCListSurfaceTypes(mDisplay,p,&mc_surf_num); if( mc_surf_list == NULL || mc_surf_num == 0){ if( mp_msg_test(MSGT_VO,MSGL_DBG3) ) { printf("vo_xvmc: No XvMC supported. \n"); } continue; } if( mp_msg_test(MSGT_VO,MSGL_DBG3) ) { printf("vo_xvmc: XvMC list have %d surfaces\n",mc_surf_num); }//we have XvMC list! for(s=0; s<mc_surf_num; s++) { if( width > mc_surf_list[s].max_width ) continue; if( height > mc_surf_list[s].max_height ) continue; if( xvmc_check_surface_format(format,&mc_surf_list[s])<0 ) continue;//we have match! /* respect the users wish */ if ( xv_port_request != 0 && xv_port_request != p ) { continue; } if(!query){ rez = XvGrabPort(mDisplay,p,CurrentTime); if(rez != Success){ if ( mp_msg_test(MSGT_VO,MSGL_DBG3) ) { printf("vo_xvmc: Fail to grab port %ld\n",p); } continue; } printf("vo_xvmc: Port %ld grabed\n",p); xv_port = p; } goto surface_found; }//for mc surf XFree(mc_surf_list);//if mc_surf_num==0 is list==NULL ? }//for ports }//for adaptors XvFreeAdaptorInfo(ai); if(!query) printf("vo_xvmc: Could not find free matching surface. Sorry.\n"); return 0;// somebody know cleaner way to escape from 3 internal loops?surface_found: XvFreeAdaptorInfo(ai); memcpy(surf_info,&mc_surf_list[s],sizeof(XvMCSurfaceInfo)); if( mp_msg_test(MSGT_VO,MSGL_DBG3) || !query) printf("vo_xvmc: Found matching surface with id=%X on %ld port at %d adapter\n", mc_surf_list[s].surface_type_id,p,i); return mc_surf_list[s].surface_type_id;}static uint32_t xvmc_draw_image(mp_image_t *mpi){xvmc_render_state_t * rndr; assert(mpi!=NULL); assert(mpi->flags &MP_IMGFLAG_DIRECT);// assert(mpi->flags &MP_IMGFLAGS_DRAWBACK); rndr = (xvmc_render_state_t*)mpi->priv;//there is copy in plane[2] assert( rndr != NULL ); assert( rndr->magic == MP_XVMC_RENDER_MAGIC ); if( mp_msg_test(MSGT_VO,MSGL_DBG4) ) printf("vo_xvmc: draw_image(show rndr=%p)\n",rndr);// the surface have passed vf system without been skiped, it will be displayed rndr->state |= MP_XVMC_STATE_DISPLAY_PENDING; p_render_surface_to_show = rndr; top_field_first = mpi->fields & MP_IMGFIELD_TOP_FIRST; return VO_TRUE;}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;int mc_ver,mc_rev;strarg_t ck_src_arg = { 0, NULL };strarg_t ck_method_arg = { 0, NULL };opt_t subopts [] ={ /* name arg type arg var test */ { "port", OPT_ARG_INT, &xv_port_request, (opt_test_f)int_pos }, { "ck", OPT_ARG_STR, &ck_src_arg, xv_test_ck }, { "ck-method", OPT_ARG_STR, &ck_method_arg, xv_test_ckm }, { "benchmark", OPT_ARG_BOOL, &benchmark, NULL }, { "sleep", OPT_ARG_BOOL, &use_sleep, NULL }, { "queue", OPT_ARG_BOOL, &use_queue, NULL }, { "bobdeint", OPT_ARG_BOOL, &bob_deinterlace, NULL }, { NULL }}; //Obtain display handler if (!vo_init()) return -1;//vo_xv //XvMC is subdivision of XVideo if (Success != XvQueryExtension(mDisplay,&xv_version,&xv_release,&xv_request_base, &xv_event_base,&xv_error_base) ){ mp_msg(MSGT_VO,MSGL_ERR,"Sorry, Xv(MC) not supported by this X11 version/driver\n"); mp_msg(MSGT_VO,MSGL_ERR,"********** Try with -vo x11 or -vo sdl ***********\n"); return -1; } printf("vo_xvmc: X-Video extension %d.%d\n",xv_version,xv_release); if( True != XvMCQueryExtension(mDisplay,&mc_eventBase,&mc_errorBase) ){ printf("vo_xvmc: No X-Video MotionCompensation Extension on %s\n", XDisplayName(NULL)); return -1; } if(Success == XvMCQueryVersion(mDisplay, &mc_ver, &mc_rev) ){ printf("vo_xvmc: X-Video MotionCompensation Extension version %i.%i\n", mc_ver,mc_rev); } else{ printf("vo_xvmc: Error querying version info!\n"); return -1; } surface_render = NULL; xv_port = 0; number_of_surfaces = 0; subpicture_alloc = 0; benchmark = 0; //disable PutImageto allow faster display than screen refresh use_sleep = 0; use_queue = 0; bob_deinterlace = 0; /* parse suboptions */ if ( subopt_parse( arg, subopts ) != 0 ) { return -1; } xv_setup_colorkeyhandling( ck_method_arg.str, ck_src_arg.str ); return 0;}static void calc_drwXY(uint32_t *drwX, uint32_t *drwY) { *drwX = *drwY = 0; if (vo_fs) { aspect(&vo_dwidth, &vo_dheight, A_ZOOM); vo_dwidth = FFMIN(vo_dwidth, vo_screenwidth); vo_dheight = FFMIN(vo_dheight, vo_screenheight); *drwX = (vo_screenwidth - vo_dwidth) / 2; *drwY = (vo_screenheight - vo_dheight) / 2; mp_msg(MSGT_VO, MSGL_V, "[xvmc-fs] dx: %d dy: %d dw: %d dh: %d\n", *drwX, *drwY, vo_dwidth, vo_dheight); } else if (WinID == 0) { *drwX = vo_dx; *drwY = vo_dy; }}static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format){int i,mode_id,rez;int numblocks,blocks_per_macroblock;//bpmb we have 6,8,12//from vo_xvXSizeHints hint;XVisualInfo vinfo;XGCValues xgcv;XSetWindowAttributes xswa;XWindowAttributes attribs;unsigned long xswamask;int depth;#ifdef HAVE_XF86VMint vm=0;unsigned int modeline_width, modeline_height;static uint32_t vm_width;static uint32_t vm_height;#endif//end of vo_xv if( !IMGFMT_IS_XVMC(format) ) { assert(0);//should never happen, abort on debug or return 1;//return error on relese }// Find free port that supports MC, by querying adaptors if( xv_port != 0 || number_of_surfaces != 0 ){ if( height==image_height && width==image_width && image_format==format){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?