From 195b53839e170cc4efe059784b1ebb31ce7707af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 26 Aug 2007 21:49:44 +0200 Subject: Protect drawable from beeing changed while drawing. When xine-ui switches to fullscreen mode or back again, it will change the drawable by sending XINE_GUI_SEND_DRAWABLE_CHANGED. This may lead to BadDrawable X Errors when the video out thread is still using the old drawable for drawing. The changes below block XINE_GUI_SEND_DRAWABLE_CHANGED from changing the drawable while it is used for drawing. --- src/video_out/video_out_xxmc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c index 4b926a2f1..60bd694b2 100644 --- a/src/video_out/video_out_xxmc.c +++ b/src/video_out/video_out_xxmc.c @@ -1684,12 +1684,14 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if (frame->format == XINE_IMGFMT_XXMC) { XVMCLOCKDISPLAY( this->display ); XvMCSyncSurface( this->display, frame->xvmc_surf ); + XLockDisplay( this->display ); /* blocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ XvMCPutSurface( this->display, frame->xvmc_surf , this->drawable, this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width, this->sc.displayed_height, this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_width, this->sc.output_height, this->cur_field); + XUnlockDisplay( this->display ); /* unblocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ XVMCUNLOCKDISPLAY( this->display ); if (this->deinterlace_enabled && !disable_deinterlace && this->bob) { struct timeval tv_middle; @@ -1718,13 +1720,14 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) this->cur_field = (frame->vo_frame.top_field_first) ? XVMC_BOTTOM_FIELD : XVMC_TOP_FIELD; XVMCLOCKDISPLAY( this->display ); + XLockDisplay( this->display ); /* blocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ XvMCPutSurface( this->display, frame->xvmc_surf , this->drawable, this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width, this->sc.displayed_height, this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_width, this->sc.output_height, this->cur_field); - + XUnlockDisplay( this->display ); /* unblocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ XVMCUNLOCKDISPLAY( this->display ); } } -- cgit v1.2.3 From 62d7654ffd81daef9d1f38d43d30b1e97675e614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 26 Aug 2007 22:05:41 +0200 Subject: Provide options to control ondemand disabling of bob deinterlacing. While disabling for progressive frames was ment to improve DVD playback, it turned out that many TV broadcasters set this flag too, although their content is not progressive. Adding an option allows the user now to enable this feature when the watched streams make correct use of this flag. Another option allows to disable bob deinterlacing when a scaled OSD is on screen. As bobbing adds some noise to horizontal lines the OSD quality might be improved by enabling this option. --- src/video_out/video_out_xxmc.c | 38 ++++++++++++++++++++++++++++++++++++-- src/video_out/xxmc.h | 3 +++ 2 files changed, 39 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c index 60bd694b2..2cde18dac 100644 --- a/src/video_out/video_out_xxmc.c +++ b/src/video_out/video_out_xxmc.c @@ -1491,6 +1491,7 @@ static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen; if (overlay->rle) { + this->scaled_osd_active = !overlay->unscaled; if( overlay->unscaled ) { if( this->ovl_changed && this->xoverlay ) { XLockDisplay (this->display); @@ -1618,7 +1619,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 = frame->vo_frame.progressive_frame + 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) { @@ -1628,6 +1630,12 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } } + /* + * reset this flag now -- it will be set again before the next call to + * xxmc_display_frame() as long as there is a scaled OSD active on screen. + */ + this->scaled_osd_active = 0; + /* * queue frames (deinterlacing) * free old frames @@ -2182,6 +2190,18 @@ static void xxmc_update_bob(void *this_gen, xine_cfg_entry_t *entry) { this->bob = entry->num_value; } +static void xxmc_update_disable_bob_for_progressive_frames(void *this_gen, xine_cfg_entry_t *entry) { + xxmc_driver_t *this = (xxmc_driver_t *) this_gen; + + this->disable_bob_for_progressive_frames = entry->num_value; +} + +static void xxmc_update_disable_bob_for_scaled_osd(void *this_gen, xine_cfg_entry_t *entry) { + xxmc_driver_t *this = (xxmc_driver_t *) this_gen; + + this->disable_bob_for_scaled_osd = entry->num_value; +} + static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) { @@ -2648,9 +2668,23 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi config->register_bool (config, "video.device.xvmc_bob_deinterlacing", 0, _("Use bob as accelerated deinterlace method."), _("When interlacing is enabled for hardware accelerated frames,\n" - "Alternate between top and bottom field at double the frame rate.\n"), + "alternate between top and bottom field at double the frame rate.\n"), 10, xxmc_update_bob, this); + this->disable_bob_for_progressive_frames = + config->register_bool (config, "video.device.xvmc_disable_bob_deinterlacing_for_progressive_frames", 0, + _("Don't use bob deinterlacing for progressive frames."), + _("Progressive frames don't need deinterlacing, so disabling it on\n" + "demand should result in a better picture.\n"), + 10, xxmc_update_disable_bob_for_progressive_frames, this); + + this->disable_bob_for_scaled_osd = + config->register_bool (config, "video.device.xvmc_disable_bob_deinterlacing_for_scaled_osd", 0, + _("Don't use bob deinterlacing while a scaled OSD is active."), + _("Bob deinterlacing adds some noise to horizontal lines, so disabling it\n" + "on demand should result in a better OSD picture.\n"), + 10, xxmc_update_disable_bob_for_scaled_osd, this); + this->deinterlace_enabled = 0; this->cur_field = XVMC_FRAME_PICTURE; diff --git a/src/video_out/xxmc.h b/src/video_out/xxmc.h index d5c067d36..a25e651e4 100644 --- a/src/video_out/xxmc.h +++ b/src/video_out/xxmc.h @@ -205,6 +205,9 @@ struct xxmc_driver_s { xxmc_frame_t *cur_frame; int cur_field; int bob; + int disable_bob_for_progressive_frames; + int disable_bob_for_scaled_osd; + int scaled_osd_active; x11osd *xoverlay; int xv_xoverlay_type; int xoverlay_type; -- cgit v1.2.3 From c0619b8e4099395749c048af84b6ff9337f339ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 26 Aug 2007 22:19:06 +0200 Subject: Protect previously shown frame from immediate reuse by decoder. It happend that the previously shown frame was still on screen while the decoder reused it already and the result was a mixed picture on screen. Protection is easy: just keep a reference to previously shown frame and it cannot be reused by the decoder until a frame duration has passed which should be sufficient to see the current frame on screen. Such referencing has already been implemented although it was not used for deinterlacing. Therefore it had been disabled to get an additional frame for decoding in coping with dropped frames. The change reenables referencing the previously shown frame. --- src/video_out/video_out_xxmc.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c index 2cde18dac..0ba004127 100644 --- a/src/video_out/video_out_xxmc.c +++ b/src/video_out/video_out_xxmc.c @@ -1643,21 +1643,16 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) xvmc_context_reader_lock( &this->xvmc_lock ); - xxmc_add_recent_frame (this, frame); /* deinterlacing */ - /* * the current implementation doesn't need recent frames for deinterlacing, - * but as most of the time we only have a little number of frames available - * per device, we only hold references to the most recent frame by filling - * the whole buffer with the same frame + * but we need to hold references on the frame we are about to show and to + * the previous frame which is currently shown on screen. Otherwise, the + * frame on screen will be immediately reused for decoding which will then + * most often result in mixed images on screen, especially when decoding + * is faster than sending the image to the monitor, and/or when exchanging + * the overlay image is synced to retrace. */ - { - int i; - for (i = 1; i < VO_NUM_RECENT_FRAMES; i++) { - frame->vo_frame.lock(&frame->vo_frame); - xxmc_add_recent_frame (this, frame); /* deinterlacing */ - } - } + xxmc_add_recent_frame (this, frame); /* deinterlacing */ if ((frame->format == XINE_IMGFMT_XXMC) && (!xxmc->decoded || !xxmc_xvmc_surface_valid(this, frame->xvmc_surf))) { -- cgit v1.2.3