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 + -
显示快捷键?