diff --git a/libvo/vo_xv.c b/libvo/vo_xv.c index 1b1c7746b8..a5a97133c1 100644 --- a/libvo/vo_xv.c +++ b/libvo/vo_xv.c @@ -36,6 +36,8 @@ Buffer allocation: #include "sub.h" #include "aspect.h" +#include "subopt-helper.h" + #ifdef HAVE_NEW_GUI #include "Gui/interface.h" #endif @@ -66,7 +68,7 @@ static int Shmem_Flag; // FIXME: dynamically allocate this stuff static void allocate_xvimage(int); static unsigned int ver, rel, req, ev, err; -static unsigned int formats, adaptors, xv_port, xv_format; +static unsigned int formats, adaptors, xv_format; static XvAdaptorInfo *ai = NULL; static XvImageFormatValues *fo=NULL; @@ -270,6 +272,10 @@ static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width, XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo); xswa.background_pixel = 0; + if (xv_ck_info.method == CK_METHOD_BACKGROUND) + { + xswa.background_pixel = xv_colorkey; + } xswa.border_pixel = 0; xswamask = CWBackPixel | CWBorderPixel; @@ -302,6 +308,7 @@ static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width, vinfo.visual, hint.x, hint.y, hint.width, hint.height, depth, CopyFromParent); + XChangeWindowAttributes(mDisplay, vo_window, xswamask, &xswa); vo_x11_classhint(mDisplay, vo_window, "xv"); vo_hidecursor(mDisplay, vo_window); @@ -519,18 +526,8 @@ static void check_events(void) { int e = vo_x11_check_events(mDisplay); - if (e & VO_EVENT_EXPOSE && vo_fs) - vo_x11_clearwindow(mDisplay, vo_window); - if (e & VO_EVENT_RESIZE) { - if (vo_fs) - { - e |= VO_EVENT_EXPOSE; - XClearWindow(mDisplay, vo_window); - XFlush(mDisplay); - } - XGetGeometry(mDisplay, vo_window, &mRoot, &drwX, &drwY, &vo_dwidth, &vo_dheight, &drwBorderWidth, &drwDepth); drwX = drwY = 0; @@ -558,6 +555,11 @@ static void check_events(void) } } + if (e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE) + { + vo_xv_draw_colorkey(drwX,drwY,vo_dwidth,vo_dheight); + } + if ((e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE) && int_pause) flip_page(); } @@ -778,21 +780,29 @@ static uint32_t preinit(const char *arg) XvPortID xv_p; int busy_ports = 0; unsigned int i; + 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, (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 }, + { NULL } + }; xv_port = 0; - if (arg) + /* parse suboptions */ + if ( subopt_parse( arg, subopts ) != 0 ) { - if ((strlen(arg) >= 6) && !strncmp(arg, "port=", 5)) - { - xv_port = atoi(arg + 5); - } else - { - mp_msg(MSGT_VO, MSGL_ERR, "vo_xv: Unknown subdevice: %s\n", - arg); - return ENOSYS; - } + return -1; } + + /* modify colorkey settings according to the given options */ + xv_setup_colorkeyhandling( ck_method_arg.str, ck_src_arg.str ); + if (!vo_init()) return -1; @@ -880,20 +890,9 @@ static uint32_t preinit(const char *arg) return -1; } + if ( !vo_xv_init_colorkey() ) { - int howmany, i; - XvAttribute * const attributes = - XvQueryPortAttributes(mDisplay, xv_port, &howmany); - - for (i = 0; i < howmany && attributes; i++) - if (!strcmp(attributes[i].name, "XV_AUTOPAINT_COLORKEY")) - { - const Atom autopaint = - XInternAtom(mDisplay, "XV_AUTOPAINT_COLORKEY", False); - XvSetPortAttribute(mDisplay, xv_port, autopaint, 1); - break; - } - XFree(attributes); + return -1; // bail out, colorkey setup failed } fo = XvListImageFormats(mDisplay, xv_port, (int *) &formats); diff --git a/libvo/vo_xvmc.c b/libvo/vo_xvmc.c index 1075c93041..99c0ec4a31 100644 --- a/libvo/vo_xvmc.c +++ b/libvo/vo_xvmc.c @@ -30,6 +30,8 @@ #include "sub.h" #include "aspect.h" +#include "subopt-helper.h" + #ifdef HAVE_NEW_GUI #include "Gui/interface.h" #endif @@ -48,21 +50,13 @@ extern int vo_directrendering; extern int vo_verbose; static int benchmark; -static int busy_wait; +static int use_sleep; static int use_queue; +static int xv_port_request = 0; static int image_width,image_height; static uint32_t drwX,drwY; -static XvPortID xv_port; - -#define AUTO_COLORKEY 0 -#define BACKGROUND_COLORKEY 1 -#define AUTOPAINT_COLORKEY 2 -#define MANUALFILL_COLORKEY 3 -static int keycolor_handling; -static unsigned long keycolor; - #define NO_SUBPICTURE 0 #define OVERLAY_SUBPICTURE 1 #define BLEND_SUBPICTURE 2 @@ -194,58 +188,6 @@ static void deallocate_xvimage() } //end of vo_xv shm/xvimage code - -static void init_keycolor(){ -Atom xv_atom; -XvAttribute * attributes; -int colorkey; -int rez; -int attrib_count,i; - - keycolor=2110; - - if(keycolor_handling == AUTO_COLORKEY){ - //XV_AUTOPING_COLORKEY doesn't work for XvMC yet(NVidia 43.63) - attributes = XvQueryPortAttributes(mDisplay, xv_port, &attrib_count); - if(attributes!=NULL){ - for (i = 0; i < attrib_count; i++){ - if (!strcmp(attributes[i].name, "XV_COLORKEY")) - { - xv_atom = XInternAtom(mDisplay, "XV_COLORKEY", False); - if(xv_atom!=None) - { - rez=XvGetPortAttribute(mDisplay,xv_port, xv_atom, &colorkey); - if(rez == Success){ - keycolor = colorkey; - keycolor_handling = MANUALFILL_COLORKEY; - } - } - break; - } - } - XFree(attributes); - } - } -} - -//from vo_xmga -static void mDrawColorKey(uint32_t x,uint32_t y, uint32_t w, uint32_t h) -{ - if( (keycolor_handling != AUTOPAINT_COLORKEY) && - (keycolor_handling != MANUALFILL_COLORKEY) ) - return; - - XSetBackground( mDisplay,vo_gc,0 ); - XClearWindow( mDisplay,vo_window ); - - if(keycolor_handling == MANUALFILL_COLORKEY){ - XSetForeground( mDisplay,vo_gc,keycolor ); - XFillRectangle( mDisplay,vo_window,vo_gc,x,y,w,h); - } - XFlush( mDisplay ); -} - - static 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; @@ -350,6 +292,11 @@ XvMCSurfaceInfo * mc_surf_list; 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); @@ -401,6 +348,19 @@ static uint32_t 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 }, + { NULL } +}; //Obtain display handler if (!vo_init()) return -1;//vo_xv @@ -431,40 +391,19 @@ int mc_ver,mc_rev; surface_render = NULL; xv_port = 0; number_of_surfaces = 0; - keycolor_handling = AUTO_COLORKEY; subpicture_alloc = 0; benchmark = 0; //disable PutImageto allow faster display than screen refresh - busy_wait = 1; + use_sleep = 0; use_queue = 0; - if(arg) - while(*arg){ - if(strncmp(arg,"benchmark",9) == 0){ - arg+=9; - if(*arg == ':') arg++; - benchmark = 1;//disable PutImageto allow faster display than screen refresh - continue; - } - if(strncmp(arg,"wait",4) == 0){ - arg+=4; - if(*arg == ':') arg++; - busy_wait = 1; - continue; - } - if(strncmp(arg,"sleep",5) == 0){ - arg+=5; - if(*arg == ':') arg++; - busy_wait = 0; - continue; - } - if(strncmp(arg,"queue",5) == 0){ - arg+=5; - if(*arg == ':') arg++; - use_queue = 1; - continue; - } - break; - } + + /* parse suboptions */ + if ( subopt_parse( arg, subopts ) != 0 ) + { + return -1; + } + + xv_setup_colorkeyhandling( ck_method_arg.str, ck_src_arg.str ); return 0; } @@ -505,6 +444,10 @@ static uint32_t vm_height; numblocks=((width+15)/16)*((height+15)/16); // Find Supported Surface Type mode_id = xvmc_find_surface_by_format(format,width,height,&surface_info,0);//false=1 to grab port, not query + if ( mode_id == 0 ) + { + return -1; + } rez = XvMCCreateContext(mDisplay, xv_port,mode_id,width,height,XVMC_DIRECT,&ctx); if( rez != Success ) return -1; @@ -635,7 +578,12 @@ found_subpic: break; } - init_keycolor();// take keycolor value and choose method for handling it +//take keycolor value and choose method for handling it + if ( !vo_xv_init_colorkey() ) + { + return -1; // bail out, colorkey setup failed + } + //taken from vo_xv panscan_init(); @@ -708,8 +656,8 @@ found_subpic: XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo); xswa.background_pixel = 0; - if (keycolor_handling == BACKGROUND_COLORKEY) - xswa.background_pixel = keycolor;// 2110; + if (xv_ck_info.method == CK_METHOD_BACKGROUND) + xswa.background_pixel = xv_colorkey; xswa.border_pixel = 0; xswamask = CWBackPixel | CWBorderPixel; @@ -1034,7 +982,7 @@ int status,rez; assert(rez==Success); if((status & XVMC_RENDERING) == 0) return;//surface is already complete - if(!busy_wait){ + if(use_sleep){ rez = XvMCFlushSurface(mDisplay, srf); assert(rez==Success); @@ -1140,7 +1088,7 @@ int e=vo_x11_check_events(mDisplay); } if ( e & VO_EVENT_EXPOSE ) { - mDrawColorKey(drwX,drwY,vo_dwidth,vo_dheight); + vo_xv_draw_colorkey(drwX,drwY,vo_dwidth,vo_dheight); if(p_render_surface_visible != NULL) XvMCPutSurface(mDisplay, p_render_surface_visible->p_surface,vo_window, 0, 0, image_width, image_height, diff --git a/libvo/x11_common.c b/libvo/x11_common.c index bae6c647a0..e0f0a74282 100644 --- a/libvo/x11_common.c +++ b/libvo/x11_common.c @@ -46,6 +46,8 @@ #ifdef HAVE_XV #include #include + +#include "subopt-helper.h" #endif #include "input/input.h" @@ -2242,4 +2244,313 @@ int vo_xv_get_eq(uint32_t xv_port, char *name, int *value) return (VO_FALSE); } +/** \brief contains flags changing the execution of the colorkeying code */ +xv_ck_info_t xv_ck_info = { CK_METHOD_MANUALFILL, CK_SRC_CUR }; +unsigned long xv_colorkey; ///< The color used for manual colorkeying. +unsigned int xv_port; ///< The selected Xv port. + +/** + * \brief Interns the requested atom if it is available. + * + * \param atom_name String containing the name of the requested atom. + * + * \return Returns the atom if available, else None is returned. + * + */ +static Atom xv_intern_atom_if_exists( char const * atom_name ) +{ + XvAttribute * attributes; + int attrib_count,i; + Atom xv_atom = None; + + attributes = XvQueryPortAttributes( mDisplay, xv_port, &attrib_count ); + if( attributes!=NULL ) + { + for ( i = 0; i < attrib_count; ++i ) + { + if ( strcmp(attributes[i].name, atom_name ) == 0 ) + { + xv_atom = XInternAtom( mDisplay, atom_name, False ); + break; // found what we want, break out + } + } + XFree( attributes ); + } + + return xv_atom; +} +/** + * \brief Print information about the colorkey method and source. + * + * \param ck_handling Integer value containing the information about + * colorkey handling (see x11_common.h). + * + * Outputs the content of |ck_handling| as a readable message. + * + */ +void vo_xv_print_ck_info() +{ + mp_msg( MSGT_VO, MSGL_V, "[xv common] " ); + + switch ( xv_ck_info.method ) + { + case CK_METHOD_NONE: + mp_msg( MSGT_VO, MSGL_V, "Drawing no colorkey.\n" ); return; + case CK_METHOD_AUTOPAINT: + mp_msg( MSGT_VO, MSGL_V, "Colorkey is drawn by Xv." ); break; + case CK_METHOD_MANUALFILL: + mp_msg( MSGT_VO, MSGL_V, "Drawing colorkey manually." ); break; + case CK_METHOD_BACKGROUND: + mp_msg( MSGT_VO, MSGL_V, "Colorkey is drawn as window background." ); break; + } + + mp_msg( MSGT_VO, MSGL_V, "\n[xv common] " ); + + switch ( xv_ck_info.source ) + { + case CK_SRC_CUR: + mp_msg( MSGT_VO, MSGL_V, "Using colorkey from Xv (0x%06x).\n", + xv_colorkey ); + break; + case CK_SRC_USE: + if ( xv_ck_info.method == CK_METHOD_AUTOPAINT ) + { + mp_msg( MSGT_VO, MSGL_V, + "Ignoring colorkey from MPlayer (0x%06x).\n", + xv_colorkey ); + } + else + { + mp_msg( MSGT_VO, MSGL_V, + "Using colorkey from MPlayer (0x%06x)." + " Use -colorkey to change.\n", + xv_colorkey ); + } + break; + case CK_SRC_SET: + mp_msg( MSGT_VO, MSGL_V, + "Setting and using colorkey from MPlayer (0x%06x)." + " Use -colorkey to change.\n", + xv_colorkey ); + break; + } +} +/** + * \brief Init colorkey depending on the settings in xv_ck_info. + * + * \return Returns 0 on failure and 1 on success. + * + * Sets the colorkey variable according to the CK_SRC_* and CK_METHOD_* + * flags in xv_ck_info. + * + * Possiblilities: + * * Methods + * - manual colorkey drawing ( CK_METHOD_MANUALFILL ) + * - set colorkey as window background ( CK_METHOD_BACKGROUND ) + * - let Xv paint the colorkey ( CK_METHOD_AUTOPAINT ) + * * Sources + * - use currently set colorkey ( CK_SRC_CUR ) + * - use colorkey in vo_colorkey ( CK_SRC_USE ) + * - use and set colorkey in vo_colorkey ( CK_SRC_SET ) + * + * NOTE: If vo_colorkey has bits set after the first 3 low order bytes + * we don't draw anything as this means it was forced to off. + */ +int vo_xv_init_colorkey() +{ + Atom xv_atom; + int rez; + + /* check if colorkeying is needed */ + xv_atom = xv_intern_atom_if_exists( "XV_COLORKEY" ); + + /* if we have to deal with colorkeying ... */ + if( xv_atom != None && !(vo_colorkey & 0xFF000000) ) + { + /* check if we should use the colorkey specified in vo_colorkey */ + if ( xv_ck_info.source != CK_SRC_CUR ) + { + xv_colorkey = vo_colorkey; + + /* check if we have to set the colorkey too */ + if ( xv_ck_info.source == CK_SRC_SET ) + { + xv_atom = XInternAtom(mDisplay, "XV_COLORKEY",False); + + rez = XvSetPortAttribute( mDisplay, xv_port, xv_atom, vo_colorkey ); + if ( rez != Success ) + { + mp_msg( MSGT_VO, MSGL_FATAL, + "[xv common] Couldn't set colorkey!\n" ); + return 0; // error setting colorkey + } + } + } + else + { + int colorkey_ret; + + rez=XvGetPortAttribute(mDisplay,xv_port, xv_atom, &colorkey_ret); + if ( rez == Success ) + { + xv_colorkey = colorkey_ret; + } + else + { + mp_msg( MSGT_VO, MSGL_FATAL, + "[xv common] Couldn't get colorkey!" + "Maybe the selected Xv port has no overlay.\n" ); + return 0; // error getting colorkey + } + } + + /* should we draw the colorkey ourselves or activate autopainting? */ + if ( xv_ck_info.method == CK_METHOD_AUTOPAINT ) + { + rez = !Success; // reset rez to something different than Success + xv_atom = xv_intern_atom_if_exists( "XV_AUTOPAINT_COLORKEY" ); + + if ( xv_atom != None ) // autopaint is supported + { + rez = XvSetPortAttribute( mDisplay, xv_port, xv_atom, 1 ); + } + + if ( rez != Success ) + { + // fallback to manual colorkey drawing + xv_ck_info.method = CK_METHOD_MANUALFILL; + } + } + } + else // do no colorkey drawing at all + { + xv_ck_info.method = CK_METHOD_NONE; + } /* end: should we draw colorkey */ + + /* output information about the curren colorkey settings */ + vo_xv_print_ck_info(); + + return 1; // success +} + +/** + * \brief Draw the colorkey on the video window. + * + * Draws the colorkey depending on the set method ( colorkey_handling ). + * + * It also draws the black bars ( when the video doesn't fit to the + * display in full screen ) seperately, so they don't overlap with the + * video area. + * + */ +inline void vo_xv_draw_colorkey( uint32_t x, uint32_t y, + uint32_t w, uint32_t h ) +{ + if( xv_ck_info.method == CK_METHOD_MANUALFILL ) + { + XSetForeground( mDisplay, vo_gc, xv_colorkey ); + XFillRectangle( mDisplay, vo_window, vo_gc, + x, y, + w, h ); + } + + /* draw black bars if needed */ + if ( vo_fs ) + { + XSetForeground( mDisplay, vo_gc, 0 ); + if ( y > 0 ) + XFillRectangle( mDisplay, vo_window, vo_gc, + 0, 0, + vo_screenwidth, y); + if (x > 0) + XFillRectangle( mDisplay, vo_window, vo_gc, + 0, y, + x, h ); + if (x + w < vo_screenwidth) + XFillRectangle( mDisplay, vo_window, vo_gc, + x + w, y, + vo_screenwidth - (x + w), h ); + if (y + h < vo_screenheight) + XFillRectangle( mDisplay, vo_window, vo_gc, + 0, y + h, + vo_screenwidth, vo_screenheight - (y + h) ); + } + + XFlush( mDisplay ); +} + +/** \brief tests if a valid arg for the ck suboption was given */ +int xv_test_ck( void * arg ) +{ + strarg_t * strarg = (strarg_t *)arg; + + if ( strncmp( "use", strarg->str, 3 ) == 0 || + strncmp( "set", strarg->str, 3 ) == 0 || + strncmp( "cur", strarg->str, 3 ) == 0 ) + { + return 1; + } + + return 0; +} +/** \brief tests if a valid arg for the ck-method suboption was given */ +int xv_test_ckm( void * arg ) +{ + strarg_t * strarg = (strarg_t *)arg; + + if ( strncmp( "bg", strarg->str, 2 ) == 0 || + strncmp( "man", strarg->str, 3 ) == 0 || + strncmp( "auto", strarg->str, 4 ) == 0 ) + { + return 1; + } + + return 0; +} + +/** + * \brief Modify the colorkey_handling var according to str + * + * Checks if a valid pointer ( not NULL ) to the string + * was given. And in that case modifies the colorkey_handling + * var to reflect the requested behaviour. + * If nothing happens the content of colorkey_handling stays + * the same. + * + * \param str Pointer to the string or NULL + * + */ +void xv_setup_colorkeyhandling( char const * ck_method_str, + char const * ck_str ) +{ + /* check if a valid pointer to the string was passed */ + if ( ck_str ) + { + if ( strncmp( ck_str, "use", 3 ) == 0 ) + { + xv_ck_info.source = CK_SRC_USE; + } + else if ( strncmp( ck_str, "set", 3 ) == 0 ) + { + xv_ck_info.source = CK_SRC_SET; + } + } + /* check if a valid pointer to the string was passed */ + if ( ck_method_str ) + { + if ( strncmp( ck_method_str, "bg", 2 ) == 0 ) + { + xv_ck_info.method = CK_METHOD_BACKGROUND; + } + else if ( strncmp( ck_method_str, "man", 3 ) == 0 ) + { + xv_ck_info.method = CK_METHOD_MANUALFILL; + } + else if ( strncmp( ck_method_str, "auto", 4 ) == 0 ) + { + xv_ck_info.method = CK_METHOD_AUTOPAINT; + } + } +} + #endif diff --git a/libvo/x11_common.h b/libvo/x11_common.h index 2197a5a37f..583a49c881 100644 --- a/libvo/x11_common.h +++ b/libvo/x11_common.h @@ -79,8 +79,36 @@ extern GC vo_gc; extern XSizeHints vo_hint; #ifdef HAVE_XV +//XvPortID xv_port; +extern unsigned int xv_port; + extern int vo_xv_set_eq(uint32_t xv_port, char * name, int value); extern int vo_xv_get_eq(uint32_t xv_port, char * name, int *value); + +/*** colorkey handling ***/ +typedef struct xv_ck_info_s +{ + int method; ///< CK_METHOD_* constants + int source; ///< CK_SRC_* constants +} xv_ck_info_t; + +#define CK_METHOD_NONE 0 ///< no colorkey drawing +#define CK_METHOD_BACKGROUND 1 ///< set colorkey as window background +#define CK_METHOD_AUTOPAINT 2 ///< let xv draw the colorkey +#define CK_METHOD_MANUALFILL 3 ///< manually draw the colorkey +#define CK_SRC_USE 0 ///< use specified / default colorkey +#define CK_SRC_SET 1 ///< use and set specified / default colorkey +#define CK_SRC_CUR 2 ///< use current colorkey ( get it from xv ) + +extern xv_ck_info_t xv_ck_info; +extern unsigned long xv_colorkey; + +extern int vo_xv_init_colorkey(); +extern void vo_xv_colorkey(uint32_t x,uint32_t y, uint32_t w, uint32_t h); + +/*** test functions for common suboptions ***/ +int xv_test_ck( void * arg ); +int xv_test_ckm( void * arg ); #endif #ifdef HAVE_NEW_GUI