From 7fc8916e6231e4cd7ed55c0fc7423f1ff705e497 Mon Sep 17 00:00:00 2001 From: Matthias Kretz Date: Mon, 4 Jun 2007 23:30:16 +0200 Subject: handle unplugged devices in audio_alsa_out (return -1) and in audio_out close the driver on a return value <0 --- src/audio_out/audio_alsa_out.c | 12 +++++++++--- src/xine-engine/audio_out.c | 16 +++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/audio_out/audio_alsa_out.c b/src/audio_out/audio_alsa_out.c index 6ad78da2a..ce3e7fb2b 100644 --- a/src/audio_out/audio_alsa_out.c +++ b/src/audio_out/audio_alsa_out.c @@ -752,6 +752,9 @@ static int ao_alsa_write(ao_driver_t *this_gen, int16_t *data, uint32_t count) { if (res < 0) return 0; state = snd_pcm_state(this->audio_fd); + } else if (state == SND_PCM_STATE_DISCONNECTED) { + /* the device is gone. audio_out.c handles it if we return something < 0 */ + return -1; } if (state == SND_PCM_STATE_XRUN) { #ifdef LOG_DEBUG @@ -784,11 +787,11 @@ static int ao_alsa_write(ao_driver_t *this_gen, int16_t *data, uint32_t count) { #endif snd_pcm_status(this->audio_fd, pcm_stat); if ( snd_pcm_status_get_avail(pcm_stat) < number_of_frames) { - wait_result = snd_pcm_wait(this->audio_fd, 1000000); + wait_result = snd_pcm_wait(this->audio_fd, 1000); #ifdef LOG_DEBUG printf("audio_alsa_out:write:loop:wait_result=%d\n",wait_result); #endif - if (wait_result < 0) return 0; + if (wait_result <= 0) return 0; } } if (this->mmap != 0) { @@ -808,7 +811,10 @@ static int ao_alsa_write(ao_driver_t *this_gen, int16_t *data, uint32_t count) { return 0; continue; } - if ( (state != SND_PCM_STATE_PREPARED) && + if (state == SND_PCM_STATE_DISCONNECTED) { + /* the device is gone. audio_out.c handles it if we return something < 0 */ + return -1; + } else if ( (state != SND_PCM_STATE_PREPARED) && (state != SND_PCM_STATE_RUNNING) && (state != SND_PCM_STATE_DRAINING) ) { xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index d39c99aba..fddae2dfe 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -1211,13 +1211,15 @@ static void *ao_loop (void *this_gen) { } if( result < 0 ) { - /* FIXME: USB device unplugged. - * We should get the card into a closed state here, that involves closing - * the PCM as well as the MIXER. - * Maybe we should pause the stream until the USB device is plugged in again. - * Return values 0 happen even if usb not unplugged, so needs further investigation. - */ - xprintf(this->xine, XINE_VERBOSITY_LOG, _("write to sound card failed. Was a USB device unplugged ?\n")); + /* device unplugged. */ + xprintf(this->xine, XINE_VERBOSITY_LOG, _("write to sound card failed. Assuming the device was unplugged.\n")); + + pthread_mutex_lock( &this->driver_lock ); + if(this->driver_open) + this->driver->close(this->driver); + this->driver_open = 0; + pthread_mutex_unlock( &this->driver_lock ); + /* closing the driver will result in XINE_MSG_AUDIO_OUT_UNAVAILABLE to be emitted */ } lprintf ("loop: next buf from fifo\n"); -- cgit v1.2.3 From d121d898bd4a4061cb95162ecb886bd4d8d2e79b Mon Sep 17 00:00:00 2001 From: Matthias Kretz Date: Mon, 4 Jun 2007 23:30:47 +0200 Subject: fallback to none output when the device is unplugged --- src/xine-engine/audio_out.c | 18 +++++++++++++++--- src/xine-engine/load_plugins.c | 32 ++++++++++++++++++++++++++++++++ src/xine-engine/xine_internal.h | 2 +- 3 files changed, 48 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index fddae2dfe..6f5351986 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -1213,11 +1213,23 @@ static void *ao_loop (void *this_gen) { if( result < 0 ) { /* device unplugged. */ xprintf(this->xine, XINE_VERBOSITY_LOG, _("write to sound card failed. Assuming the device was unplugged.\n")); + _x_message (in_buf->stream, XINE_MSG_AUDIO_OUT_UNAVAILABLE, NULL); pthread_mutex_lock( &this->driver_lock ); - if(this->driver_open) - this->driver->close(this->driver); - this->driver_open = 0; + if(this->driver_open) { + this->driver->close(this->driver); + this->driver_open = 0; + this->driver->exit(this->driver); + this->driver = _x_load_audio_output_plugin (this->xine, "none"); + if (this->driver && !in_buf->stream->emergency_brake && + ao_change_settings(this, + in_buf->format.bits, + in_buf->format.rate, + in_buf->format.mode) == 0) { + in_buf->stream->emergency_brake = 1; + _x_message (in_buf->stream, XINE_MSG_AUDIO_OUT_UNAVAILABLE, NULL); + } + } pthread_mutex_unlock( &this->driver_lock ); /* closing the driver will result in XINE_MSG_AUDIO_OUT_UNAVAILABLE to be emitted */ } diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index c72241487..912455b18 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -1681,6 +1681,38 @@ static ao_driver_t *_load_audio_driver (xine_t *this, plugin_node_t *node, return driver; } +ao_driver_t *_x_load_audio_output_plugin (xine_t *this, const char *id) +{ + plugin_node_t *node; + ao_driver_t *driver = NULL; + ao_info_t *ao_info; + plugin_catalog_t *catalog = this->plugin_catalog; + int list_id, list_size; + + pthread_mutex_lock (&catalog->lock); + + list_size = xine_sarray_size (this->plugin_catalog->plugin_lists[PLUGIN_AUDIO_OUT - 1]); + for (list_id = 0; list_id < list_size; list_id++) { + + node = xine_sarray_get (this->plugin_catalog->plugin_lists[PLUGIN_AUDIO_OUT - 1], list_id); + + ao_info = (ao_info_t *)node->info->special_info; + + if (!strcasecmp(node->info->id, id)) { + driver = _load_audio_driver (this, node, NULL); + break; + } + } + + pthread_mutex_unlock (&catalog->lock); + + if (!driver) { + xprintf (this, XINE_VERBOSITY_LOG, + _("load_plugins: failed to load audio output plugin <%s>\n"), id); + } + return driver; +} + xine_audio_port_t *xine_open_audio_driver (xine_t *this, const char *id, void *data) { diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h index c88bcc904..8230dfb13 100644 --- a/src/xine-engine/xine_internal.h +++ b/src/xine-engine/xine_internal.h @@ -484,7 +484,7 @@ vo_driver_t *_x_load_video_output_plugin(xine_t *this, * load a specific audio output plugin */ -ao_driver_t *_x_load_audio_output_plugin (xine_t *self, char *id) XINE_PROTECTED; +ao_driver_t *_x_load_audio_output_plugin (xine_t *self, const char *id) XINE_PROTECTED; void _x_set_speed (xine_stream_t *stream, int speed) XINE_PROTECTED; -- cgit v1.2.3 From 6f430a25e9cd653fdb6995ae4e427ea6be0d8c3a Mon Sep 17 00:00:00 2001 From: Steve Freeland Date: Wed, 6 Jun 2007 00:39:12 +0100 Subject: [PATCH] video_out_fb crash I discovered some problems with the framebuffer output driver. The first problem I had was a segfault when trying to play a 480x360 clip on a 640x480 display. I traced it to the yuv420_rgb16() color conversion function, which was overrunning the input buffer (the "y" part of the image). The reason was that it was being called downstack from fb_frame_proc_slice(), multiple times for each 16-pixel high horizontal slice of the image. When it got to the last slice, only 8 pixels were left to the bottom but it still tried to process a 16-pixel high slice. Nosing around a bit, I compared the configuration of the color converter as used by the fb driver to the xshm driver and found some oddities: 1) The color converter was configured with a "source height" of 16 pixels no matter what the size of the image, and a "dest height" based on what was referred to within video_out_fb.c as a "stripe" -- essentially an input slice scaled up or down as required by the output size. 2) Apparently to prevent the above from causing problems, the position in the output buffer was managed by special code -- see the "stripe_incr" variable. 3) The xshm driver calls yuv2rgb_next_slice() with a NULL argument at the beginning of each frame to allow the color converter to reset its tracking of the slice-by-slice progress through the image; the fb driver does not. I'm not sure exactly why it was done that way, but my best guess would be that whoever coded it didn't know about the need to call yuv2rgb_next_slice() with a NULL argument, and the rest was built up to get it to mostly work without that. The attached patch changes the behaviour to match that of the xshm driver, and also removes the reset_dest_pointers() function, replacing its single invocation with one to fb_frame_field(), which is identical after removing the "stripe" management. It fixed my crash. Can anyone see if I've misunderstood what was going on? If not, it should probably be applied to the official version. --- src/video_out/video_out_fb.c | 44 ++++++-------------------------------------- 1 file changed, 6 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/video_out/video_out_fb.c b/src/video_out/video_out_fb.c index e88def112..3c53adf4d 100644 --- a/src/video_out/video_out_fb.c +++ b/src/video_out/video_out_fb.c @@ -99,7 +99,6 @@ typedef struct fb_frame_s yuv2rgb_t *yuv2rgb; /* yuv2rgb converter for this frame */ uint8_t *rgb_dst; int yuv_stride; - int stripe_height, stripe_inc; int bytes_per_line; @@ -182,7 +181,6 @@ static void fb_frame_proc_slice(vo_frame_t *vo_img, uint8_t **src) else frame->yuv2rgb->yuy22rgb_fun(frame->yuv2rgb, frame->rgb_dst, src[0]); - frame->rgb_dst += frame->stripe_inc; } static void fb_frame_field(vo_frame_t *vo_img, int which_field) @@ -193,21 +191,18 @@ static void fb_frame_field(vo_frame_t *vo_img, int which_field) { case VO_TOP_FIELD: frame->rgb_dst = frame->data; - frame->stripe_inc = 2*frame->stripe_height * - frame->bytes_per_line; break; case VO_BOTTOM_FIELD: frame->rgb_dst = frame->data + frame->bytes_per_line ; - frame->stripe_inc = 2*frame->stripe_height * - frame->bytes_per_line; break; case VO_BOTH_FIELDS: frame->rgb_dst = frame->data; break; } + frame->yuv2rgb->next_slice (frame->yuv2rgb, NULL); } static void fb_frame_dispose(vo_frame_t *vo_img) @@ -304,11 +299,11 @@ static void setup_colorspace_converter(fb_frame_t *frame, int flags) frame->yuv2rgb-> configure(frame->yuv2rgb, frame->sc.delivered_width, - 16, + frame->sc.delivered_height, 2 * frame->vo_frame.pitches[0], 2 * frame->vo_frame.pitches[1], frame->sc.output_width, - frame->stripe_height, + frame->sc.output_height, frame->bytes_per_line * 2); frame->yuv_stride = frame->bytes_per_line * 2; break; @@ -317,42 +312,17 @@ static void setup_colorspace_converter(fb_frame_t *frame, int flags) frame->yuv2rgb-> configure(frame->yuv2rgb, frame->sc.delivered_width, - 16, + frame->sc.delivered_height, frame->vo_frame.pitches[0], frame->vo_frame.pitches[1], frame->sc.output_width, - frame->stripe_height, + frame->sc.output_height, frame->bytes_per_line); frame->yuv_stride = frame->bytes_per_line; break; } } -static void reset_dest_pointers(fb_frame_t *frame, int flags) -{ - switch(flags) - { - case VO_TOP_FIELD: - frame->rgb_dst = frame->data; - frame->stripe_inc = 2 * frame->stripe_height * - frame->bytes_per_line; - break; - - case VO_BOTTOM_FIELD: - frame->rgb_dst = frame->data + - frame->bytes_per_line ; - frame->stripe_inc = 2 * frame->stripe_height * - frame->bytes_per_line; - break; - - case VO_BOTH_FIELDS: - frame->rgb_dst = frame->data; - frame->stripe_inc = frame->stripe_height * - frame->bytes_per_line; - break; - } -} - static void frame_reallocate(fb_driver_t *this, fb_frame_t *frame, uint32_t width, uint32_t height, int format) { @@ -457,8 +427,6 @@ static void fb_update_frame_format(vo_driver_t *this_gen, frame_reallocate(this, frame, width, height, format); - frame->stripe_height = 16 * frame->sc.output_height / - frame->sc.delivered_height; if(this->use_zero_copy) frame->bytes_per_line = this->fb_bytes_per_line; else @@ -468,7 +436,7 @@ static void fb_update_frame_format(vo_driver_t *this_gen, setup_colorspace_converter(frame, flags); } - reset_dest_pointers(frame, flags); + fb_frame_field(frame_gen, flags); } static void fb_overlay_clut_yuv2rgb(fb_driver_t *this, -- cgit v1.2.3 From e026dc188cfa93f778e7f1db9ef58d115d91417e Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Wed, 6 Jun 2007 23:48:52 +0100 Subject: Fix RealPlayer codec detection and a nearby logging build failure. Both typos. --- src/libreal/real_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/libreal/real_common.c b/src/libreal/real_common.c index 22c33aa03..e2a4ee3d6 100644 --- a/src/libreal/real_common.c +++ b/src/libreal/real_common.c @@ -79,7 +79,7 @@ void _x_real_codecs_init(xine_t *const xine) { struct stat s; #define try_real_path(path) \ - if (!stat (path "/dvrc.so", &s)) \ + if (!stat (path "/drvc.so", &s)) \ default_real_codecs_path = path; #define try_real_subpath(path) \ try_real_path("/usr/" path) \ @@ -114,7 +114,7 @@ void _x_real_codecs_init(xine_t *const xine) { "how to install the codecs."), 10, NULL, NULL); - lprintf ("real codecs path : %s\n", real_codec_path); + lprintf ("real codecs path : %s\n", real_codecs_path); } void *_x_real_codec_open(xine_stream_t *const stream, const char *const path, -- cgit v1.2.3 From 9043d0680a6e15ab0058e8cabc48610de50cc29a Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Fri, 8 Jun 2007 00:40:11 +0100 Subject: Fix build issues on systems which need our internal asprintf. config.h is now include/configure.h and no longer #includes os_internals.h. A new file, include/config.h, #includes both; this breaks a #include loop. Other files are updated accordingly. --- src/libfaad/common.h | 2 +- src/xine-utils/attributes.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/libfaad/common.h b/src/libfaad/common.h index 47832e648..31f07708a 100644 --- a/src/libfaad/common.h +++ b/src/libfaad/common.h @@ -36,7 +36,7 @@ extern "C" { #define __STRICT_ANSI__ #endif -#include "../config.h" +#include "config.h" #define INLINE __inline #if 0 //defined(_WIN32) && !defined(_WIN32_WCE) diff --git a/src/xine-utils/attributes.h b/src/xine-utils/attributes.h index 13c787925..2a7029522 100644 --- a/src/xine-utils/attributes.h +++ b/src/xine-utils/attributes.h @@ -45,7 +45,7 @@ #endif #ifdef XINE_COMPILE -# include "config.h" +# include "configure.h" #endif /* Export protected only for libxine functions */ -- cgit v1.2.3