diff options
Diffstat (limited to 'src/video_out/video_out_xxmc.c')
-rw-r--r-- | src/video_out/video_out_xxmc.c | 232 |
1 files changed, 133 insertions, 99 deletions
diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c index 28679e95d..61e0139e3 100644 --- a/src/video_out/video_out_xxmc.c +++ b/src/video_out/video_out_xxmc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2004 the xine project + * Copyright (C) 2000-2004, 2008 the xine project * Copyright (C) 2004 the Unichrome project * * This file is part of xine, a free video player. @@ -34,9 +34,9 @@ */ - #include "xxmc.h" #include <unistd.h> +#include "xv_common.h" static int gX11Fail; @@ -45,6 +45,8 @@ static void xxmc_frame_updates(xxmc_driver_t *driver, xxmc_frame_t *frame, static void dispose_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo, XvImage *myimage); +VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES; +VIDEO_DEVICE_XV_DECL_PREFER_TYPES; /* * Acceleration level priority. Static for now. It may well turn out that IDCT @@ -158,18 +160,13 @@ static void xxmc_xvmc_dump_subpictures(xxmc_driver_t *this) static void xxmc_xvmc_surface_handler_construct(xxmc_driver_t *this) { - int i; xvmc_surface_handler_t *handler = &this->xvmc_surf_handler; pthread_mutex_init(&handler->mutex,NULL); - for (i=0; i<XVMC_MAX_SURFACES; ++i) { - handler->surfInUse[i] = 0; - handler->surfValid[i] = 0; - } - for (i=0; i<XVMC_MAX_SUBPICTURES; ++i) { - handler->subInUse[i] = 0; - handler->subValid[i] = 0; - } + memset(handler->surfInUse, 0, sizeof(handler->surfInUse)); + memset(handler->surfValid, 0, sizeof(handler->surfValid)); + memset(handler->subInUse, 0, sizeof(handler->subInUse)); + memset(handler->subValid, 0, sizeof(handler->subValid)); } static void xxmc_xvmc_destroy_surfaces(xxmc_driver_t *this) @@ -550,7 +547,7 @@ static vo_frame_t *xxmc_alloc_frame (vo_driver_t *this_gen) { xxmc_driver_t *this = (xxmc_driver_t *) this_gen; xxmc_frame_t *frame ; - frame = (xxmc_frame_t *) xine_xmalloc (sizeof (xxmc_frame_t)); + frame = calloc(1, sizeof (xxmc_frame_t)); if (!frame) return NULL; @@ -1611,8 +1608,8 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) * other than 100 %, so let's disable deinterlacing at all for this frame */ if (this->deinterlace_enabled && this->bob) { - disable_deinterlace = this->disable_bob_for_progressive_frames && frame->vo_frame.progressive_frame - || this->disable_bob_for_scaled_osd && this->scaled_osd_active + disable_deinterlace = (this->disable_bob_for_progressive_frames && frame->vo_frame.progressive_frame) + || (this->disable_bob_for_scaled_osd && this->scaled_osd_active) || !frame->vo_frame.stream || xine_get_param(frame->vo_frame.stream, XINE_PARAM_FINE_SPEED) != XINE_FINE_SPEED_NORMAL; if (!disable_deinterlace) { @@ -2065,13 +2062,13 @@ static int xxmc_check_yv12 (Display *display, XvPortID port) { /* called xlocked */ static void xxmc_check_capability (xxmc_driver_t *this, - int property, XvAttribute attr, - int base_id, char *str_prop, - char *config_name, - char *config_desc, - char *config_help) { + int property, XvAttribute attr, int base_id, + const char *config_name, + const char *config_desc, + const char *config_help) { int int_default; cfg_entry_t *entry; + const char *str_prop = attr.name; if (VO_PROP_COLORKEY && (attr.max_value == ~0)) attr.max_value = 2147483615; @@ -2133,36 +2130,32 @@ static void xxmc_check_capability (xxmc_driver_t *this, this->props[property].value = int_default; } -static void xxmc_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { +static void xxmc_update_attr (void *this_gen, xine_cfg_entry_t *entry, + const char *atomstr, const char *debugstr) +{ xxmc_driver_t *this = (xxmc_driver_t *) this_gen; Atom atom; - int xv_filter; - - xv_filter = entry->num_value; XLockDisplay(this->display); - atom = XInternAtom (this->display, "XV_FILTER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_filter); + atom = XInternAtom (this->display, atomstr, False); + XvSetPortAttribute (this->display, this->xv_port, atom, entry->num_value); XUnlockDisplay(this->display); xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xxmc: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter); + LOG_MODULE ": %s = %d\n", debugstr, entry->num_value); } -static void xxmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { - xxmc_driver_t *this = (xxmc_driver_t *) this_gen; - Atom atom; - int xv_double_buffer; - - xv_double_buffer = entry->num_value; +static void xxmc_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { + xxmc_update_attr (this_gen, entry, "XV_FILTER", "bilinear scaling mode"); +} - XLockDisplay(this->display); - atom = XInternAtom (this->display, "XV_DOUBLE_BUFFER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_double_buffer); - XUnlockDisplay(this->display); +static void xxmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { + xxmc_update_attr (this_gen, entry, "XV_DOUBLE_BUFFER", "double buffering mode"); +} - xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xxmc: double buffering mode = %d\n", xv_double_buffer); +static void xxmc_update_XV_BICUBIC(void *this_gen, xine_cfg_entry_t *entry) +{ + xxmc_update_attr (this_gen, entry, "XV_BICUBIC", "bicubic filtering mode"); } static void xxmc_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) { @@ -2201,6 +2194,52 @@ static void xxmc_update_disable_bob_for_scaled_osd(void *this_gen, xine_cfg_entr this->disable_bob_for_scaled_osd = entry->num_value; } +static int xxmc_open_port (xxmc_driver_t *this, XvPortID port) { + int ret; + x11_InstallXErrorHandler (this); + ret = ! xxmc_check_yv12(this->display, port) + && XvGrabPort(this->display, port, 0) == Success; + x11_DeInstallXErrorHandler (this); + return ret; +} + +static unsigned int +xxmc_find_adaptor_by_port (int port, unsigned int adaptors, + XvAdaptorInfo *adaptor_info) +{ + unsigned int an; + for (an = 0; an < adaptors; an++) + if (adaptor_info[an].type & XvImageMask) + if (port >= adaptor_info[an].base_id && + port < adaptor_info[an].base_id + adaptor_info[an].num_ports) + return an; + return 0; /* shouldn't happen */ +} + +static XvPortID xxmc_autodetect_port(xxmc_driver_t *this, + unsigned int adaptors, + XvAdaptorInfo *adaptor_info, + unsigned int *adaptor_num, + XvPortID base, + xv_prefertype prefer_type) +{ + unsigned int an, j; + + for (an = 0; an < adaptors; an++) + if (adaptor_info[an].type & XvImageMask && + (prefer_type == xv_prefer_none || + strcasestr (adaptor_info[an].name, prefer_substrings[prefer_type]))) + for (j = 0; j < adaptor_info[an].num_ports; j++) { + XvPortID port = adaptor_info[an].base_id + j; + if (port >= base && xxmc_open_port(this, port)) { + *adaptor_num = an; + return port; + } + } + + return 0; +} + static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) { @@ -2363,17 +2402,18 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi x11_visual_t *visual = (x11_visual_t *) visual_gen; XColor dummy; XvImage *myimage; - unsigned int adaptors, j; + unsigned int adaptors; unsigned int ver,rel,req,ev,err; XShmSegmentInfo myshminfo; XvPortID xv_port; XvAdaptorInfo *adaptor_info; unsigned int adaptor_num; + xv_prefertype prefer_type; cfg_entry_t *entry; int use_more_frames; int use_unscaled; - this = (xxmc_driver_t *) xine_xmalloc (sizeof (xxmc_driver_t)); + this = calloc(1, sizeof (xxmc_driver_t)); if (!this) return NULL; @@ -2404,24 +2444,31 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi return NULL; } - xv_port = 0; - - for ( adaptor_num = 0; (adaptor_num < adaptors) && !xv_port; adaptor_num++ ) { - - if (adaptor_info[adaptor_num].type & XvImageMask) { - - for (j = 0; j < adaptor_info[adaptor_num].num_ports && !xv_port; j++) - if (( !(xxmc_check_yv12 (this->display, - adaptor_info[adaptor_num].base_id + j))) - && (XvGrabPort (this->display, - adaptor_info[adaptor_num].base_id + j, - 0) == Success)) { - xv_port = adaptor_info[adaptor_num].base_id + j; - } - - if( xv_port ) - break; - } + xv_port = config->register_num (config, "video.device.xv_port", 0, + VIDEO_DEVICE_XV_PORT_HELP, + 20, NULL, NULL); + prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0, + prefer_labels, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, + 10, NULL, NULL); + + if (xv_port != 0) { + if (! xxmc_open_port(this, xv_port)) { + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: could not open Xv port %d - autodetecting\n"), + LOG_MODULE, xv_port); + xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, xv_port, prefer_type); + } else + adaptor_num = xxmc_find_adaptor_by_port (xv_port, adaptors, adaptor_info); + } + if (!xv_port) + xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, prefer_type); + if (!xv_port) + { + if (prefer_type) + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: no available ports of type \"%s\", defaulting...\n"), + LOG_MODULE, prefer_labels[prefer_type]); + xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, xv_prefer_none); } if (!xv_port) { @@ -2510,72 +2557,60 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi for(k = 0; k < nattr; k++) { if((attr[k].flags & XvSettable) && (attr[k].flags & XvGettable)) { - if(!strcmp(attr[k].name, "XV_HUE")) { + const char *const name = attr[k].name; + if(!strcmp(name, "XV_HUE")) { if (!strncmp(adaptor_info[adaptor_num].name, "NV", 2)) { xprintf (this->xine, XINE_VERBOSITY_NONE, "video_out_xxmc: ignoring broken XV_HUE settings on NVidia cards\n"); } else { xxmc_check_capability (this, VO_PROP_HUE, attr[k], - adaptor_info[adaptor_num].base_id, "XV_HUE", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); } - } else if(!strcmp(attr[k].name, "XV_SATURATION")) { + } else if(!strcmp(name, "XV_SATURATION")) { xxmc_check_capability (this, VO_PROP_SATURATION, attr[k], - adaptor_info[adaptor_num].base_id, "XV_SATURATION", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - } else if(!strcmp(attr[k].name, "XV_BRIGHTNESS")) { + } else if(!strcmp(name, "XV_BRIGHTNESS")) { xxmc_check_capability (this, VO_PROP_BRIGHTNESS, attr[k], - adaptor_info[adaptor_num].base_id, "XV_BRIGHTNESS", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - } else if(!strcmp(attr[k].name, "XV_CONTRAST")) { + } else if(!strcmp(name, "XV_CONTRAST")) { xxmc_check_capability (this, VO_PROP_CONTRAST, attr[k], - adaptor_info[adaptor_num].base_id, "XV_CONTRAST", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - } else if(!strcmp(attr[k].name, "XV_COLORKEY")) { + } else if(!strcmp(name, "XV_COLORKEY")) { xxmc_check_capability (this, VO_PROP_COLORKEY, attr[k], - adaptor_info[adaptor_num].base_id, "XV_COLORKEY", + adaptor_info[adaptor_num].base_id, "video.device.xv_colorkey", - _("video overlay colour key"), - _("The colour key is used to tell the graphics card where to " - "overlay the video image. Try different values, if you experience " - "windows becoming transparent.")); - - } else if(!strcmp(attr[k].name, "XV_AUTOPAINT_COLORKEY")) { + VIDEO_DEVICE_XV_COLORKEY_HELP); + } else if(!strcmp(name, "XV_AUTOPAINT_COLORKEY")) { xxmc_check_capability (this, VO_PROP_AUTOPAINT_COLORKEY, attr[k], - adaptor_info[adaptor_num].base_id, "XV_AUTOPAINT_COLORKEY", + adaptor_info[adaptor_num].base_id, "video.device.xv_autopaint_colorkey", - _("autopaint colour key"), - _("Make Xv autopaint its colour key.")); - - } else if(!strcmp(attr[k].name, "XV_FILTER")) { + VIDEO_DEVICE_XV_AUTOPAINT_COLORKEY_HELP); + } else if(!strcmp(name, "XV_FILTER")) { int xv_filter; /* This setting is specific to Permedia 2/3 cards. */ xv_filter = config->register_range (config, "video.device.xv_filter", 0, attr[k].min_value, attr[k].max_value, - _("bilinear scaling mode"), - _("Selects the bilinear scaling mode for Permedia cards. " - "The individual values are:\n\n" - "Permedia 2\n" - "0 - disable bilinear filtering\n" - "1 - enable bilinear filtering\n\n" - "Permedia 3\n" - "0 - disable bilinear filtering\n" - "1 - horizontal linear filtering\n" - "2 - enable full bilinear filtering"), + VIDEO_DEVICE_XV_FILTER_HELP, 20, xxmc_update_XV_FILTER, this); config->update_num(config,"video.device.xv_filter",xv_filter); - } else if(!strcmp(attr[k].name, "XV_DOUBLE_BUFFER")) { - int xv_double_buffer; - xv_double_buffer = + } else if(!strcmp(name, "XV_DOUBLE_BUFFER")) { + int xv_double_buffer = config->register_bool (config, "video.device.xv_double_buffer", 1, - _("enable double buffering"), - _("Double buffering will synchronize the update of the video image to the " - "repainting of the entire screen (\"vertical retrace\"). This eliminates " - "flickering and tearing artifacts, but will use more graphics memory."), + VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP, 20, xxmc_update_XV_DOUBLE_BUFFER, this); config->update_num(config,"video.device.xv_double_buffer",xv_double_buffer); + } else if(!strcmp(name, "XV_BICUBIC")) { + int xv_bicubic = + config->register_enum (config, "video.device.xv_bicubic", 2, + bicubic_types, VIDEO_DEVICE_XV_BICUBIC_HELP, + 20, xxmc_update_XV_BICUBIC, this); + config->update_num(config,"video.device.xv_bicubic",xv_bicubic); } } } @@ -2639,8 +2674,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi this->use_pitch_alignment = config->register_bool (config, "video.device.xv_pitch_alignment", 0, - _("pitch alignment workaround"), - _("Some buggy video drivers need a workaround to function properly."), + VIDEO_DEVICE_XV_PITCH_ALIGNMENT_HELP, 10, xxmc_update_xv_pitch_alignment, this); use_more_frames= @@ -2744,7 +2778,7 @@ static void dispose_class (video_driver_class_t *this_gen) { } static void *init_class (xine_t *xine, void *visual_gen) { - xxmc_class_t *this = (xxmc_class_t *) xine_xmalloc (sizeof (xxmc_class_t)); + xxmc_class_t *this = calloc(1, sizeof (xxmc_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; |