diff options
-rw-r--r-- | src/xine-engine/audio_decoder.c | 46 | ||||
-rw-r--r-- | src/xine-engine/osd.c | 35 | ||||
-rw-r--r-- | src/xine-engine/osd.h | 5 | ||||
-rw-r--r-- | src/xine-engine/post.c | 115 | ||||
-rw-r--r-- | src/xine-engine/post.h | 59 | ||||
-rw-r--r-- | src/xine-engine/video_decoder.c | 40 | ||||
-rw-r--r-- | src/xine-engine/xine.c | 230 | ||||
-rw-r--r-- | src/xine-engine/xine_interface.c | 116 | ||||
-rw-r--r-- | src/xine-engine/xine_internal.h | 67 |
9 files changed, 458 insertions, 255 deletions
diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index ffccf247e..e6c6411f3 100644 --- a/src/xine-engine/audio_decoder.c +++ b/src/xine-engine/audio_decoder.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: audio_decoder.c,v 1.119 2004/01/09 01:26:34 miguelfreitas Exp $ + * $Id: audio_decoder.c,v 1.120 2004/02/12 18:19:12 mroi Exp $ * * * functions that implement audio decoding @@ -51,6 +51,7 @@ static void *audio_decoder_loop (void *stream_gen) { buf_element_t *last_header = NULL; int replaying_headers = 0; xine_stream_t *stream = (xine_stream_t *) stream_gen; + xine_ticket_t *running_ticket = stream->xine->port_ticket; int running = 1; int prof_audio_decode = -1; uint32_t buftype_unknown = 0; @@ -59,36 +60,26 @@ static void *audio_decoder_loop (void *stream_gen) { if (prof_audio_decode == -1) prof_audio_decode = xine_profiler_allocate_slot ("audio decoder/output"); + running_ticket->acquire(running_ticket, 0); + while (running) { lprintf ("audio_loop: waiting for package...\n"); - if( !replaying_headers ) + if( !replaying_headers ) { + running_ticket->release(running_ticket, 0); buf = stream->audio_fifo->get (stream->audio_fifo); + running_ticket->acquire(running_ticket, 0); + } lprintf ("audio_loop: got package pts = %lld, type = %08x\n", buf->pts, buf->type); _x_extra_info_merge( stream->audio_decoder_extra_info, buf->extra_info ); stream->audio_decoder_extra_info->seek_count = stream->video_seek_count; - - /* check for a new port to use */ - if (stream->next_audio_port) { - uint32_t bits, rate; - int mode; - - /* noone is allowed to modify the next port from now on */ - pthread_mutex_lock(&stream->next_audio_port_lock); - if (stream->audio_out->status(stream->audio_out, stream, &bits, &rate, &mode)) { - /* register our stream at the new output port */ - stream->next_audio_port->open(stream->next_audio_port, stream, bits, rate, mode); - stream->audio_out->close(stream->audio_out, stream); - } - stream->audio_out = stream->next_audio_port; - stream->next_audio_port = NULL; - pthread_mutex_unlock(&stream->next_audio_port_lock); - pthread_cond_broadcast(&stream->next_audio_port_wired); - } - + + if (running_ticket->ticket_revoked) + running_ticket->renew(running_ticket, 0); + switch (buf->type) { case BUF_CONTROL_HEADERS_DONE: @@ -112,7 +103,9 @@ static void *audio_decoder_loop (void *stream_gen) { stream->audio_type = 0; } + running_ticket->release(running_ticket, 0); stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_STREAMSTART, 0); + running_ticket->acquire(running_ticket, 0); buftype_unknown = 0; break; @@ -186,17 +179,23 @@ static void *audio_decoder_loop (void *stream_gen) { case BUF_CONTROL_DISCONTINUITY: if (stream->audio_decoder_plugin) stream->audio_decoder_plugin->discontinuity (stream->audio_decoder_plugin); + + running_ticket->release(running_ticket, 0); stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_RELATIVE, buf->disc_off); + running_ticket->acquire(running_ticket, 0); break; case BUF_CONTROL_NEWPTS: if (stream->audio_decoder_plugin) stream->audio_decoder_plugin->discontinuity (stream->audio_decoder_plugin); + + running_ticket->release(running_ticket, 0); if (buf->decoder_flags & BUF_FLAG_SEEK) { stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_STREAMSEEK, buf->disc_off); } else { stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_ABSOLUTE, buf->disc_off); } + running_ticket->acquire(running_ticket, 0); break; case BUF_CONTROL_AUDIO_CHANNEL: @@ -396,6 +395,8 @@ static void *audio_decoder_loop (void *stream_gen) { } } + running_ticket->release(running_ticket, 0); + return NULL; } @@ -461,9 +462,6 @@ void _x_audio_decoder_shutdown (xine_stream_t *stream) { stream->audio_fifo->dispose (stream->audio_fifo); stream->audio_fifo = NULL; - - /* wakeup any rewire operations */ - pthread_cond_broadcast(&stream->next_audio_port_wired); } int _x_get_audio_channel (xine_stream_t *stream) { diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index 70213606a..4e16f06e6 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -48,6 +48,8 @@ #define LOG */ +#define XINE_ENGINE_INTERNAL + #include "xine_internal.h" #include "video_out/alphablend.h" #include "xine-engine/bswap.h" @@ -173,14 +175,20 @@ static osd_object_t *osd_new_object (osd_renderer_t *this, int width, int height static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { osd_renderer_t *this = osd->renderer; + video_overlay_manager_t *ovl_manager; rle_elem_t rle, *rle_p=0; int x, y, spare; uint8_t *c; lprintf("osd=%p vpts=%lld\n", osd, vpts); + + this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1); + + ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out); if( osd->handle < 0 ) { - if( (osd->handle = this->video_overlay->get_handle(this->video_overlay,0)) == -1 ) { + if( (osd->handle = ovl_manager->get_handle(ovl_manager, 0)) == -1 ) { + this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); return 0; } } @@ -258,10 +266,12 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { this->event.event_type = OVERLAY_EVENT_SHOW; this->event.vpts = vpts; - this->video_overlay->add_event(this->video_overlay,(void *)&this->event); + ovl_manager->add_event(ovl_manager, (void *)&this->event); } pthread_mutex_unlock (&this->osd_mutex); + this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); + return 1; } @@ -286,6 +296,7 @@ static int osd_show_unscaled (osd_object_t *osd, int64_t vpts) { static int osd_hide (osd_object_t *osd, int64_t vpts) { osd_renderer_t *this = osd->renderer; + video_overlay_manager_t *ovl_manager; lprintf("osd=%p vpts=%lld\n",osd, vpts); @@ -301,7 +312,11 @@ static int osd_hide (osd_object_t *osd, int64_t vpts) { this->event.event_type = OVERLAY_EVENT_HIDE; this->event.vpts = vpts; - this->video_overlay->add_event(this->video_overlay,(void *)&this->event); + + this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1); + ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out); + ovl_manager->add_event(ovl_manager, (void *)&this->event); + this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); pthread_mutex_unlock (&this->osd_mutex); @@ -1211,6 +1226,7 @@ static void osd_preload_fonts (osd_renderer_t *this, char *path) { static void osd_free_object (osd_object_t *osd_to_close) { osd_renderer_t *this = osd_to_close->renderer; + video_overlay_manager_t *ovl_manager; osd_object_t *osd, *last; if( osd_to_close->handle >= 0 ) { @@ -1222,8 +1238,12 @@ static void osd_free_object (osd_object_t *osd_to_close) { memset( this->event.object.overlay, 0, sizeof(this->event.object.overlay) ); this->event.event_type = OVERLAY_EVENT_FREE_HANDLE; this->event.vpts = 0; - this->video_overlay->add_event(this->video_overlay,(void *)&this->event); - + + this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1); + ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out); + ovl_manager->add_event(ovl_manager, (void *)&this->event); + this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); + osd_to_close->handle = -1; /* handle will be freed */ } @@ -1314,9 +1334,11 @@ static uint32_t osd_get_capabilities (osd_object_t *osd) { capabilities |= XINE_OSD_CAP_FREETYPE2; #endif + this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 0); if( this->stream->video_out->get_capabilities(this->stream->video_out) & VO_CAP_UNSCALED_OVERLAY) capabilities |= XINE_OSD_CAP_UNSCALED; + this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 0); return capabilities; } @@ -1326,13 +1348,12 @@ static uint32_t osd_get_capabilities (osd_object_t *osd) { * initialize the osd rendering engine */ -osd_renderer_t *_x_osd_renderer_init( video_overlay_manager_t *video_overlay, xine_stream_t *stream ) { +osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) { osd_renderer_t *this; char str[1024]; this = xine_xmalloc(sizeof(osd_renderer_t)); - this->video_overlay = video_overlay; this->stream = stream; this->event.object.overlay = xine_xmalloc( sizeof(vo_overlay_t) ); diff --git a/src/xine-engine/osd.h b/src/xine-engine/osd.h index f1b884550..fc1a31bca 100644 --- a/src/xine-engine/osd.h +++ b/src/xine-engine/osd.h @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * OSD stuff (text and graphic primitives) - * $Id: osd.h,v 1.23 2003/12/09 00:02:36 f1rmb Exp $ + * $Id: osd.h,v 1.24 2004/02/12 18:19:12 mroi Exp $ */ #ifndef HAVE_OSD_H @@ -215,7 +215,6 @@ struct osd_renderer_s { /* private stuff */ pthread_mutex_t osd_mutex; - video_overlay_manager_t *video_overlay; video_overlay_event_t event; osd_object_t *osds; /* instances of osd */ osd_font_t *fonts; /* loaded fonts */ @@ -228,7 +227,7 @@ struct osd_renderer_s { /* * initialize the osd rendering engine */ -osd_renderer_t *_x_osd_renderer_init( video_overlay_manager_t *video_overlay, xine_stream_t *stream ); +osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ); /* diff --git a/src/xine-engine/post.c b/src/xine-engine/post.c index 58771dbb9..ae9c9ab09 100644 --- a/src/xine-engine/post.c +++ b/src/xine-engine/post.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: post.c,v 1.21 2004/01/07 19:52:43 mroi Exp $ + * $Id: post.c,v 1.22 2004/02/12 18:19:12 mroi Exp $ */ /* @@ -56,7 +56,7 @@ static uint32_t post_video_get_capabilities(xine_video_port_t *port_gen) { static void post_video_open(xine_video_port_t *port_gen, xine_stream_t *stream) { post_video_port_t *port = (post_video_port_t *)port_gen; - _x_post_rewire_video(port); + _x_post_rewire(port->post); _x_post_inc_usage(port); if (port->port_lock) pthread_mutex_lock(port->port_lock); port->original_port->open(port->original_port, stream); @@ -72,7 +72,7 @@ static vo_frame_t *post_video_get_frame(xine_video_port_t *port_gen, uint32_t wi post_video_port_t *port = (post_video_port_t *)port_gen; vo_frame_t *frame; - _x_post_rewire_video(port); + _x_post_rewire(port->post); if (port->port_lock) pthread_mutex_lock(port->port_lock); frame = port->original_port->get_frame(port->original_port, width, height, ratio, format, flags); @@ -188,25 +188,20 @@ static int post_video_rewire(xine_post_out_t *output_gen, void *data) { post_out_t *output = (post_out_t *)output_gen; xine_video_port_t *new_port = (xine_video_port_t *)data; post_video_port_t *input_port = (post_video_port_t *)output->user_data; + post_plugin_t *this = output->post; if (!new_port) return 0; - pthread_mutex_lock(&input_port->next_port_lock); - pthread_mutex_lock(&input_port->usage_lock); - input_port->next_port = new_port; - while (input_port->next_port) { - if (input_port->usage_count == 0) { - /* we can safely rewire right here, the plugin is not in use */ - input_port->original_port = new_port; - input_port->next_port = NULL; - } - pthread_mutex_unlock(&input_port->usage_lock); - if (input_port->next_port) - pthread_cond_wait(&input_port->next_port_wire, &input_port->next_port_lock); - pthread_mutex_lock(&input_port->usage_lock); - } - pthread_mutex_unlock(&input_port->usage_lock); - pthread_mutex_unlock(&input_port->next_port_lock); + + this->running_ticket->revoke(this->running_ticket, 1); + + new_port->open(new_port, (input_port->stream == POST_NULL_STREAM) ? NULL : input_port->stream); + input_port->original_port->close(input_port->original_port, + (input_port->stream == POST_NULL_STREAM) ? NULL : input_port->stream); + input_port->original_port = new_port; + + this->running_ticket->issue(this->running_ticket, 1); + return 1; } @@ -237,8 +232,6 @@ post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_ port->new_manager = &port->manager_storage; port->post = post; - pthread_mutex_init(&port->next_port_lock, NULL); - pthread_cond_init(&port->next_port_wire, NULL); pthread_mutex_init(&port->usage_lock, NULL); pthread_mutex_init(&port->free_frames_lock, NULL); @@ -268,22 +261,6 @@ post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_ } -void _x_post_rewire_video(post_video_port_t *port) { - if (port->next_port) { - pthread_mutex_lock(&port->next_port_lock); - if (port->next_port) { - port->next_port->open(port->next_port, (port->stream == POST_NULL_STREAM) ? NULL : port->stream); - port->original_port->close(port->original_port, (port->stream == POST_NULL_STREAM) ? NULL : port->stream); - port->original_port = port->next_port; - port->next_port = NULL; - pthread_mutex_unlock(&port->next_port_lock); - pthread_cond_broadcast(&port->next_port_wire); - } else - pthread_mutex_unlock(&port->next_port_lock); - } -} - - /* dummy intercept functions for frames */ static void post_frame_free(vo_frame_t *vo_img) { post_video_port_t *port = _x_post_video_frame_to_port(vo_img); @@ -630,7 +607,7 @@ static int post_audio_open(xine_audio_port_t *port_gen, xine_stream_t *stream, post_audio_port_t *port = (post_audio_port_t *)port_gen; int result; - _x_post_rewire_audio(port); + _x_post_rewire(port->post); _x_post_inc_usage(port); if (port->port_lock) pthread_mutex_lock(port->port_lock); result = port->original_port->open(port->original_port, stream, bits, rate, mode); @@ -649,7 +626,7 @@ static audio_buffer_t *post_audio_get_buffer(xine_audio_port_t *port_gen) { post_audio_port_t *port = (post_audio_port_t *)port_gen; audio_buffer_t *buf; - _x_post_rewire_audio(port); + _x_post_rewire(port->post); if (port->port_lock) pthread_mutex_lock(port->port_lock); buf = port->original_port->get_buffer(port->original_port); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -723,25 +700,21 @@ static int post_audio_rewire(xine_post_out_t *output_gen, void *data) { post_out_t *output = (post_out_t *)output_gen; xine_audio_port_t *new_port = (xine_audio_port_t *)data; post_audio_port_t *input_port = (post_audio_port_t *)output->user_data; + post_plugin_t *this = output->post; if (!new_port) return 0; - pthread_mutex_lock(&input_port->next_port_lock); - pthread_mutex_lock(&input_port->usage_lock); - input_port->next_port = new_port; - while (input_port->next_port) { - if (input_port->usage_count == 0) { - /* we can safely rewire right here, the plugin is not in use */ - input_port->original_port = new_port; - input_port->next_port = NULL; - } - pthread_mutex_unlock(&input_port->usage_lock); - if (input_port->next_port) - pthread_cond_wait(&input_port->next_port_wire, &input_port->next_port_lock); - pthread_mutex_lock(&input_port->usage_lock); - } - pthread_mutex_unlock(&input_port->usage_lock); - pthread_mutex_unlock(&input_port->next_port_lock); + + this->running_ticket->revoke(this->running_ticket, 1); + + new_port->open(new_port, (input_port->stream == POST_NULL_STREAM) ? NULL : input_port->stream, + input_port->bits, input_port->rate, input_port->mode); + input_port->original_port->close(input_port->original_port, + (input_port->stream == POST_NULL_STREAM) ? NULL : input_port->stream); + input_port->original_port = new_port; + + this->running_ticket->issue(this->running_ticket, 1); + return 1; } @@ -767,8 +740,6 @@ post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_ port->original_port = original; port->post = post; - pthread_mutex_init(&port->next_port_lock, NULL); - pthread_cond_init(&port->next_port_wire, NULL); pthread_mutex_init(&port->usage_lock, NULL); if (input) { @@ -797,23 +768,6 @@ post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_ } -void _x_post_rewire_audio(post_audio_port_t *port) { - if (port->next_port) { - pthread_mutex_lock(&port->next_port_lock); - if (port->next_port) { - port->next_port->open(port->next_port, (port->stream == POST_NULL_STREAM) ? NULL : port->stream, - port->bits, port->rate, port->mode); - port->original_port->close(port->original_port, (port->stream == POST_NULL_STREAM) ? NULL : port->stream); - port->original_port = port->next_port; - port->next_port = NULL; - pthread_mutex_unlock(&port->next_port_lock); - pthread_cond_broadcast(&port->next_port_wire); - } else - pthread_mutex_unlock(&port->next_port_lock); - } -} - - int _x_post_dispose(post_plugin_t *this) { int i, in_use = 0; @@ -865,6 +819,9 @@ int _x_post_dispose(post_plugin_t *this) { free(this->xine_post.audio_input); free(this->xine_post.video_input); + /* these were allocated in the plugin loader */ + free(this->input_ids); + free(this->output_ids); for (input = xine_list_first_content(this->input); input; input = xine_list_next_content(this->input)) { @@ -874,8 +831,6 @@ int _x_post_dispose(post_plugin_t *this) { post_video_port_t *port = (post_video_port_t *)input->data; vo_frame_t *first, *second; - pthread_mutex_destroy(&port->next_port_lock); - pthread_cond_destroy(&port->next_port_wire); pthread_mutex_destroy(&port->usage_lock); pthread_mutex_destroy(&port->free_frames_lock); @@ -893,8 +848,6 @@ int _x_post_dispose(post_plugin_t *this) { { post_audio_port_t *port = (post_audio_port_t *)input->data; - pthread_mutex_destroy(&port->next_port_lock); - pthread_cond_destroy(&port->next_port_wire); pthread_mutex_destroy(&port->usage_lock); free(port); @@ -922,6 +875,12 @@ int _x_post_dispose(post_plugin_t *this) { xine_list_free(this->input); xine_list_free(this->output); + /* since the plugin loader does not know, when the plugin gets disposed, + * we have to handle the reference counter here */ + pthread_mutex_lock(&this->xine->plugin_catalog->lock); + ((plugin_node_t *)this->node)->ref--; + pthread_mutex_unlock(&this->xine->plugin_catalog->lock); + return 1; } diff --git a/src/xine-engine/post.h b/src/xine-engine/post.h index 1ddc1b580..8e61a1009 100644 --- a/src/xine-engine/post.h +++ b/src/xine-engine/post.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: post.h,v 1.17 2004/01/07 19:52:43 mroi Exp $ + * $Id: post.h,v 1.18 2004/02/12 18:19:12 mroi Exp $ * * post plugin definitions * @@ -97,14 +97,30 @@ struct post_plugin_s { /* has dispose been called */ int dispose_pending; - /* plugins don't have to care for the stuff below */ + /* plugins don't have to init the stuff below */ + + /* + * the running ticket + * + * the plugin must assure to check for ticket revocation in + * intervals of finite length; this means that you must release + * the ticket before any operation that might block; + * note that all port functions are safe in this respect + * + * the running ticket is assigned to you by the engine + */ + xine_ticket_t *running_ticket; + + /* this is needed by the engine to decrement the reference counter + * on disposal of the plugin, but since this is useful, we expose it */ + xine_t *xine; /* used when the user requests a list of all inputs/outputs */ const char **input_ids; const char **output_ids; /* used by plugin loader */ - void *node; + void *node; }; /* helper function to initialize a post_plugin_t */ @@ -157,13 +173,6 @@ struct post_video_port_s { /* the original port to call its functions from inside yours */ xine_video_port_t *original_port; - /* when we are rewiring, next port points to the new port */ - xine_video_port_t *next_port; - - /* rewiring synchronization */ - pthread_mutex_t next_port_lock; - pthread_cond_t next_port_wire; - /* if you want to decide yourself, whether a given frame should * be intercepted, fill in this function; get_frame() acts as * a template method and asks your function; return a boolean; @@ -232,11 +241,6 @@ struct post_video_port_s { post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_port_t *port, post_in_t **input, post_out_t **output); -/* this will execute pending rewire operations, calling this at the beginning - * of decoder-called functions like get_frame() and open() is a good idea - * (if you do not intercept get_frame() or open(), this will be done automatically) */ -void _x_post_rewire_video(post_video_port_t *port); - /* use this to decorate and to undecorate a frame so that its functions * can be replaced with own implementations, decoration is usually done in * get_frame(), undecoration in frame->free() */ @@ -288,13 +292,6 @@ struct post_audio_port_s { /* the original port to call its functions from inside yours */ xine_audio_port_t *original_port; - /* when we are rewiring, next port points to the new port */ - xine_audio_port_t *next_port; - - /* rewiring synchronization */ - pthread_mutex_t next_port_lock; - pthread_cond_t next_port_wire; - /* usage counter: how many objects are floating around that need * these pointers to exist */ int usage_count; @@ -325,11 +322,24 @@ struct post_audio_port_s { post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_port_t *port, post_in_t **input, post_out_t **output); -/* this will execute pending rewire operations, calling this at the beginning + +/* this will allow pending rewire operations, calling this at the beginning * of decoder-called functions like get_buffer() and open() is a good idea * (if you do not intercept get_buffer() or open(), this will be done automatically) */ -void _x_post_rewire_audio(post_audio_port_t *port); +static inline void _x_post_rewire(post_plugin_t *post) { + if (post->running_ticket->ticket_revoked) + post->running_ticket->renew(post->running_ticket, 1); +} +/* with these functions you can switch interruptions like rewiring or engine pausing + * off for a block of code; use this only when really necessary */ +static inline void _x_post_lock(post_plugin_t *post) { + post->running_ticket->acquire(post->running_ticket, 1); +} +static inline void _x_post_unlock(post_plugin_t *post) { + post->running_ticket->release(post->running_ticket, 1); + _x_post_rewire(post); +} /* the standard disposal operation; returns 1 if the plugin is really * disposed and you should free everything you malloc()ed yourself */ @@ -354,7 +364,6 @@ do { \ pthread_mutex_lock(&(port)->usage_lock); \ (port)->usage_count--; \ if ((port)->usage_count == 0) { \ - pthread_cond_broadcast(&(port)->next_port_wire); \ if ((port)->post->dispose_pending) { \ pthread_mutex_unlock(&(port)->usage_lock); \ (port)->post->dispose((port)->post); \ diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index 49c115869..e9fe388d5 100644 --- a/src/xine-engine/video_decoder.c +++ b/src/xine-engine/video_decoder.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_decoder.c,v 1.142 2003/12/05 15:55:05 f1rmb Exp $ + * $Id: video_decoder.c,v 1.143 2004/02/12 18:19:12 mroi Exp $ * */ @@ -62,6 +62,7 @@ static void *video_decoder_loop (void *stream_gen) { buf_element_t *buf; xine_stream_t *stream = (xine_stream_t *) stream_gen; + xine_ticket_t *running_ticket = stream->xine->port_ticket; int running = 1; int streamtype; int prof_video_decode = -1; @@ -73,34 +74,24 @@ static void *video_decoder_loop (void *stream_gen) { if (prof_spu_decode == -1) prof_spu_decode = xine_profiler_allocate_slot ("spu decoder"); + running_ticket->acquire(running_ticket, 0); + while (running) { lprintf ("getting buffer...\n"); + running_ticket->release(running_ticket, 0); buf = stream->video_fifo->get (stream->video_fifo); + running_ticket->acquire(running_ticket, 0); + _x_extra_info_merge( stream->video_decoder_extra_info, buf->extra_info ); stream->video_decoder_extra_info->seek_count = stream->video_seek_count; lprintf ("got buffer 0x%08x\n", buf->type); - /* check for a new port to use */ - if (stream->next_video_port) { - int64_t img_duration; - int width, height; - - /* noone is allowed to modify the next port from now on */ - pthread_mutex_lock(&stream->next_video_port_lock); - if (stream->video_out->status(stream->video_out, stream, &width, &height, &img_duration)) { - /* register our stream at the new output port */ - stream->next_video_port->open(stream->next_video_port, stream); - stream->video_out->close(stream->video_out, stream); - } - stream->video_out = stream->next_video_port; - stream->next_video_port = NULL; - pthread_mutex_unlock(&stream->next_video_port_lock); - pthread_cond_broadcast(&stream->next_video_port_wired); - } - + if (running_ticket->ticket_revoked) + running_ticket->renew(running_ticket, 0); + switch (buf->type & 0xffff0000) { case BUF_CONTROL_HEADERS_DONE: pthread_mutex_lock (&stream->counter_lock); @@ -122,8 +113,10 @@ static void *video_decoder_loop (void *stream_gen) { stream->spu_track_map_entries = 0; } + running_ticket->release(running_ticket, 0); stream->metronom->handle_video_discontinuity (stream->metronom, DISC_STREAMSTART, 0); + running_ticket->acquire(running_ticket, 0); buftype_unknown = 0; break; @@ -231,7 +224,9 @@ static void *video_decoder_loop (void *stream_gen) { stream->video_decoder_plugin->discontinuity (stream->video_decoder_plugin); } + running_ticket->release(running_ticket, 0); stream->metronom->handle_video_discontinuity (stream->metronom, DISC_RELATIVE, buf->disc_off); + running_ticket->acquire(running_ticket, 0); break; @@ -245,11 +240,13 @@ static void *video_decoder_loop (void *stream_gen) { stream->video_decoder_plugin->discontinuity (stream->video_decoder_plugin); } + running_ticket->release(running_ticket, 0); if (buf->decoder_flags & BUF_FLAG_SEEK) { stream->metronom->handle_video_discontinuity (stream->metronom, DISC_STREAMSEEK, buf->disc_off); } else { stream->metronom->handle_video_discontinuity (stream->metronom, DISC_ABSOLUTE, buf->disc_off); } + running_ticket->acquire(running_ticket, 0); break; @@ -378,6 +375,8 @@ static void *video_decoder_loop (void *stream_gen) { buf->free_buffer (buf); } + running_ticket->release(running_ticket, 0); + return NULL; } @@ -455,7 +454,4 @@ void _x_video_decoder_shutdown (xine_stream_t *stream) { stream->video_fifo->dispose (stream->video_fifo); stream->video_fifo = NULL; - - /* wakeup any rewire operations */ - pthread_cond_broadcast(&stream->next_video_port_wired); } diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 281cb0ac0..ec0de15d2 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine.c,v 1.280 2004/01/07 22:22:54 jstembridge Exp $ + * $Id: xine.c,v 1.281 2004/02/12 18:19:00 mroi Exp $ */ /* @@ -127,15 +127,118 @@ void _x_extra_info_merge( extra_info_t *dst, extra_info_t *src ) { } } +static void ticket_acquire(xine_ticket_t *this, int irrevocable) { + + pthread_mutex_lock(&this->lock); + + if (this->ticket_revoked && !this->irrevocable_tickets) + pthread_cond_wait(&this->issued, &this->lock); + else if (this->atomic_revoke && !pthread_equal(this->atomic_revoker_thread, pthread_self())) + pthread_cond_wait(&this->issued, &this->lock); + + this->tickets_granted++; + if (irrevocable) + this->irrevocable_tickets++; + + pthread_mutex_unlock(&this->lock); +} + +static void ticket_release(xine_ticket_t *this, int irrevocable) { + + pthread_mutex_lock(&this->lock); + + this->tickets_granted--; + if (irrevocable) + this->irrevocable_tickets--; + + if (this->ticket_revoked && !this->tickets_granted) + pthread_cond_broadcast(&this->revoked); + if (this->ticket_revoked && !this->irrevocable_tickets) + pthread_cond_wait(&this->issued, &this->lock); + + pthread_mutex_unlock(&this->lock); +} + +static void ticket_renew(xine_ticket_t *this, int irrevocable) { + + pthread_mutex_lock(&this->lock); + + this->tickets_granted--; + + _x_assert(this->ticket_revoked); + if (!this->tickets_granted) + pthread_cond_broadcast(&this->revoked); + if (!this->irrevocable_tickets || !irrevocable) + pthread_cond_wait(&this->issued, &this->lock); + + this->tickets_granted++; + + pthread_mutex_unlock(&this->lock); +} + +static void ticket_issue(xine_ticket_t *this, int atomic) { + + if (!atomic) + pthread_mutex_lock(&this->revoke_lock); + pthread_mutex_lock(&this->lock); + + this->pending_revocations--; + if (!this->pending_revocations) + pthread_cond_broadcast(&this->issued); + this->atomic_revoke = 0; + + pthread_mutex_unlock(&this->lock); + pthread_mutex_unlock(&this->revoke_lock); +} + +static void ticket_revoke(xine_ticket_t *this, int atomic) { + + pthread_mutex_lock(&this->revoke_lock); + pthread_mutex_lock(&this->lock); + + this->pending_revocations++; + this->ticket_revoked = 1; + if (this->tickets_granted) + pthread_cond_wait(&this->revoked, &this->lock); + _x_assert(!this->tickets_granted); + this->ticket_revoked = 0; + if (atomic) { + this->atomic_revoke = 1; + this->atomic_revoker_thread = pthread_self(); + } + + pthread_mutex_unlock(&this->lock); + if (!atomic) + pthread_mutex_unlock(&this->revoke_lock); +} + +static void ticket_dispose(xine_ticket_t *this) { + + pthread_mutex_destroy(&this->lock); + pthread_mutex_destroy(&this->revoke_lock); + pthread_cond_destroy(&this->issued); + pthread_cond_destroy(&this->revoked); + + free(this); +} + static void __set_speed_internal (xine_stream_t *stream, int speed) { + xine_t *xine = stream->xine; + if (xine->clock->speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) + /* get all decoder and post threads in a state where they agree to be blocked */ + xine->port_ticket->revoke(xine->port_ticket, 0); + + if (xine->clock->speed == XINE_SPEED_PAUSE && speed != XINE_SPEED_PAUSE) + /* all decoder and post threads may continue now */ + xine->port_ticket->issue(xine->port_ticket, 0); + stream->xine->clock->set_speed (stream->xine->clock, speed); /* see coment on audio_out loop about audio_paused */ if( stream->audio_out ) { - stream->audio_out->set_property( stream->audio_out, AO_PROP_PAUSED, - (speed != XINE_SPEED_NORMAL) + (speed == XINE_SPEED_PAUSE) ); - + xine->port_ticket->acquire(xine->port_ticket, 1); + /* * slow motion / fast forward does not play sound, drop buffered * samples from the sound driver @@ -145,6 +248,8 @@ static void __set_speed_internal (xine_stream_t *stream, int speed) { stream->audio_out->control(stream->audio_out, speed == XINE_SPEED_PAUSE ? AO_CTRL_PLAY_PAUSE : AO_CTRL_PLAY_RESUME, NULL); + + xine->port_ticket->release(xine->port_ticket, 1); } } @@ -223,9 +328,10 @@ void xine_stop (xine_stream_t *stream) { pthread_mutex_lock (&stream->frontend_lock); + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1); + if (stream->audio_out) stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 1); - if (stream->video_out) stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 1); @@ -235,11 +341,12 @@ void xine_stop (xine_stream_t *stream) { xine_stop(stream->slave); if (stream->video_out) - stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0); - + stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0); if (stream->audio_out) stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 0); + stream->xine->port_ticket->release(stream->xine->port_ticket, 1); + pthread_mutex_unlock (&stream->frontend_lock); } @@ -299,24 +406,22 @@ static int __stream_rewire_audio(xine_post_out_t *output, void *data) { xine_stream_t *stream = (xine_stream_t *)output->data; xine_audio_port_t *new_port = (xine_audio_port_t *)data; - buf_element_t *buf; - + uint32_t bits, rate; + int mode; + if (!data) return 0; - pthread_mutex_lock(&stream->next_audio_port_lock); - stream->next_audio_port = new_port; - if (stream->audio_thread) { - buf = stream->audio_fifo->buffer_pool_try_alloc(stream->audio_fifo); - if (buf) { - /* wake up audio decoder thread */ - buf->type = BUF_CONTROL_NOP; - stream->audio_fifo->insert(stream->audio_fifo, buf); - } - /* wait till rewiring is finished */ - pthread_cond_wait(&stream->next_audio_port_wired, &stream->next_audio_port_lock); + stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1); + + if (stream->audio_out->status(stream->audio_out, stream, &bits, &rate, &mode)) { + /* register our stream at the new output port */ + new_port->open(new_port, stream, bits, rate, mode); + stream->audio_out->close(stream->audio_out, stream); } - pthread_mutex_unlock(&stream->next_audio_port_lock); + stream->audio_out = new_port; + + stream->xine->port_ticket->issue(stream->xine->port_ticket, 1); return 1; } @@ -325,24 +430,22 @@ static int __stream_rewire_video(xine_post_out_t *output, void *data) { xine_stream_t *stream = (xine_stream_t *)output->data; xine_video_port_t *new_port = (xine_video_port_t *)data; - buf_element_t *buf; - + int64_t img_duration; + int width, height; + if (!data) return 0; - pthread_mutex_lock(&stream->next_video_port_lock); - stream->next_video_port = new_port; - if (stream->video_thread) { - buf = stream->video_fifo->buffer_pool_try_alloc(stream->video_fifo); - if (buf) { - /* wake up video decoder thread */ - buf->type = BUF_CONTROL_NOP; - stream->video_fifo->insert(stream->video_fifo, buf); - } - /* wait till rewiring is finished */ - pthread_cond_wait(&stream->next_video_port_wired, &stream->next_video_port_lock); + stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1); + + if (stream->video_out->status(stream->video_out, stream, &width, &height, &img_duration)) { + /* register our stream at the new output port */ + new_port->open(new_port, stream); + stream->video_out->close(stream->video_out, stream); } - pthread_mutex_unlock(&stream->next_video_port_lock); + stream->video_out = new_port; + + stream->xine->port_ticket->issue(stream->xine->port_ticket, 1); return 1; } @@ -400,8 +503,6 @@ xine_stream_t *xine_stream_new (xine_t *this, stream->finished_count_audio = 0; stream->finished_count_video = 0; stream->err = 0; - stream->next_audio_port = NULL; - stream->next_video_port = NULL; stream->broadcaster = NULL; /* @@ -426,10 +527,6 @@ xine_stream_t *xine_stream_new (xine_t *this, pthread_mutex_init (&stream->first_frame_lock, NULL); pthread_cond_init (&stream->first_frame_reached, NULL); pthread_mutex_init (&stream->current_extra_info_lock, NULL); - pthread_mutex_init (&stream->next_video_port_lock, NULL); - pthread_mutex_init (&stream->next_audio_port_lock, NULL); - pthread_cond_init (&stream->next_video_port_wired, NULL); - pthread_cond_init (&stream->next_audio_port_wired, NULL); /* * Clear meta/stream info @@ -465,8 +562,7 @@ xine_stream_t *xine_stream_new (xine_t *this, * osd */ if (vo) - stream->osd_renderer = _x_osd_renderer_init (stream->video_out->get_overlay_manager (stream->video_out), - stream ); + stream->osd_renderer = _x_osd_renderer_init(stream); else stream->osd_renderer = NULL; @@ -901,12 +997,6 @@ static int __open_internal (xine_stream_t *stream, const char *mrl) { stream->input_plugin = NULL; stream->err = XINE_ERROR_NO_DEMUX_PLUGIN; - /* remove buffered samples from the sound device driver */ - /* why? */ - /*if (stream->audio_out) - stream->audio_out->control (stream->audio_out, AO_CTRL_FLUSH_BUFFERS, NULL); - */ - stream->status = XINE_STATUS_STOP; xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "return from\n"); @@ -958,6 +1048,8 @@ static int __play_internal (xine_stream_t *stream, int start_pos, int start_time if (stream->xine->clock->speed != XINE_SPEED_NORMAL) __set_speed_internal (stream, XINE_SPEED_NORMAL); + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1); + /* discard audio/video buffers to get engine going and take the lock faster */ if (stream->audio_out) stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 1); @@ -999,6 +1091,8 @@ static int __play_internal (xine_stream_t *stream, int start_pos, int start_time if (stream->video_out) stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0); + stream->xine->port_ticket->release(stream->xine->port_ticket, 1); + /* before resuming the demuxer, set first_frame_flag */ pthread_mutex_lock (&stream->first_frame_lock); stream->first_frame_flag = 2; @@ -1123,10 +1217,6 @@ void xine_dispose (xine_stream_t *stream) { pthread_mutex_destroy (&stream->demux_lock); pthread_mutex_destroy (&stream->first_frame_lock); pthread_cond_destroy (&stream->first_frame_reached); - pthread_mutex_destroy (&stream->next_video_port_lock); - pthread_mutex_destroy (&stream->next_audio_port_lock); - pthread_cond_destroy (&stream->next_video_port_wired); - pthread_cond_destroy (&stream->next_audio_port_wired); stream->metronom->exit (stream->metronom); @@ -1155,6 +1245,9 @@ void xine_exit (xine_t *this) { if(this->config) this->config->dispose(this->config); + if(this->port_ticket) + this->port_ticket->dispose(this->port_ticket); + #if defined(WIN32) WSACleanup(); #endif @@ -1212,12 +1305,21 @@ xine_t *xine_new (void) { #endif /* WIN32 */ /* - * streams_lock + * streams lock */ pthread_mutex_init (&this->streams_lock, NULL); this->verbosity = XINE_VERBOSITY_NONE; + + /* + * tickets + */ + + this->port_ticket = xine_xmalloc(sizeof(xine_ticket_t)); + pthread_mutex_init(&this->port_ticket->lock, NULL); + pthread_mutex_init(&this->port_ticket->revoke_lock, NULL); + pthread_cond_init(&this->port_ticket->issued, NULL); return this; } @@ -1338,7 +1440,17 @@ void xine_init (xine_t *this) { this->clock = _x_metronom_clock_init(this); this->clock->start_clock (this->clock, 0); - + + /* + * tickets + */ + this->port_ticket->acquire = ticket_acquire; + this->port_ticket->release = ticket_release; + this->port_ticket->renew = ticket_renew; + this->port_ticket->issue = ticket_issue; + this->port_ticket->revoke = ticket_revoke; + this->port_ticket->dispose = ticket_dispose; + } void _x_select_spu_channel (xine_stream_t *stream, int channel) { @@ -1346,6 +1458,8 @@ void _x_select_spu_channel (xine_stream_t *stream, int channel) { pthread_mutex_lock (&stream->frontend_lock); stream->spu_channel_user = (channel >= -2 ? channel : -2); + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); + switch (stream->spu_channel_user) { case -2: stream->spu_channel = -1; @@ -1361,6 +1475,8 @@ void _x_select_spu_channel (xine_stream_t *stream, int channel) { } lprintf("set to %d\n",stream->spu_channel); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + pthread_mutex_unlock (&stream->frontend_lock); } @@ -1485,8 +1601,10 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, vo_frame_t *frame; + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); frame = stream->video_out->get_last_frame (stream->video_out); - + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + if (!frame) return 0; diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index fff706bd2..e1a8abcb0 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine_interface.c,v 1.77 2004/01/23 09:26:16 andruil Exp $ + * $Id: xine_interface.c,v 1.78 2004/02/12 18:19:12 mroi Exp $ * * convenience/abstraction layer, functions to implement * libxine's public interface @@ -361,33 +361,45 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { break; case XINE_PARAM_AUDIO_VOLUME: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (stream->audio_out) stream->audio_out->set_property (stream->audio_out, AO_PROP_MIXER_VOL, value); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_AUDIO_MUTE: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (stream->audio_out) stream->audio_out->set_property (stream->audio_out, AO_PROP_MUTE_VOL, value); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_AUDIO_COMPR_LEVEL: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (stream->audio_out) stream->audio_out->set_property (stream->audio_out, AO_PROP_COMPRESSOR, value); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_AUDIO_AMP_LEVEL: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (stream->audio_out) stream->audio_out->set_property (stream->audio_out, AO_PROP_AMP, value); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_AUDIO_AMP_MUTE: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (stream->audio_out) stream->audio_out->set_property (stream->audio_out, AO_PROP_AMP_MUTE, value); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_AUDIO_CLOSE_DEVICE: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (stream->audio_out) stream->audio_out->set_property (stream->audio_out, AO_PROP_CLOSE_DEVICE, value); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_EQ_30HZ: @@ -400,10 +412,12 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { case XINE_PARAM_EQ_4000HZ: case XINE_PARAM_EQ_8000HZ: case XINE_PARAM_EQ_16000HZ: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (stream->audio_out) stream->audio_out->set_property (stream->audio_out, param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ, value); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_VERBOSITY: @@ -419,7 +433,9 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { case XINE_PARAM_VO_ZOOM_Y: case XINE_PARAM_VO_PAN_SCAN: case XINE_PARAM_VO_TVMODE: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); stream->video_out->set_property(stream->video_out, param, value); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_IGNORE_VIDEO: @@ -449,54 +465,81 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { default: xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "xine_interface: unknown param %d\n", param); - } + } } int xine_get_param (xine_stream_t *stream, int param) { + int ret; switch (param) { case XINE_PARAM_SPEED: - return stream->xine->clock->speed; + ret = stream->xine->clock->speed; + break; case XINE_PARAM_AV_OFFSET: - return stream->metronom->get_option (stream->metronom, METRONOM_AV_OFFSET); + ret = stream->metronom->get_option (stream->metronom, METRONOM_AV_OFFSET); + break; case XINE_PARAM_SPU_OFFSET: - return stream->metronom->get_option (stream->metronom, METRONOM_SPU_OFFSET); + ret = stream->metronom->get_option (stream->metronom, METRONOM_SPU_OFFSET); + break; case XINE_PARAM_AUDIO_CHANNEL_LOGICAL: - return stream->audio_channel_user; + ret = stream->audio_channel_user; + break; case XINE_PARAM_SPU_CHANNEL: - return stream->spu_channel_user; + ret = stream->spu_channel_user; + break; case XINE_PARAM_VIDEO_CHANNEL: - return stream->video_channel; + ret = stream->video_channel; + break; case XINE_PARAM_AUDIO_VOLUME: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (!stream->audio_out) - return -1; - return stream->audio_out->get_property (stream->audio_out, AO_PROP_MIXER_VOL); + ret = -1; + else + ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_MIXER_VOL); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + break; case XINE_PARAM_AUDIO_MUTE: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (!stream->audio_out) - return -1; - return stream->audio_out->get_property (stream->audio_out, AO_PROP_MUTE_VOL); + ret = -1; + else + ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_MUTE_VOL); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + break; case XINE_PARAM_AUDIO_COMPR_LEVEL: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (!stream->audio_out) - return -1; - return stream->audio_out->get_property (stream->audio_out, AO_PROP_COMPRESSOR); + ret = -1; + else + ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_COMPRESSOR); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + break; case XINE_PARAM_AUDIO_AMP_LEVEL: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (!stream->audio_out) - return -1; - return stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP); + ret = -1; + else + ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + break; case XINE_PARAM_AUDIO_AMP_MUTE: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (!stream->audio_out) - return -1; - return stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP_MUTE); + ret = -1; + else + ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP_MUTE); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + break; case XINE_PARAM_EQ_30HZ: case XINE_PARAM_EQ_60HZ: @@ -508,15 +551,18 @@ int xine_get_param (xine_stream_t *stream, int param) { case XINE_PARAM_EQ_4000HZ: case XINE_PARAM_EQ_8000HZ: case XINE_PARAM_EQ_16000HZ: + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (!stream->audio_out) - return -1; - - return stream->audio_out->get_property (stream->audio_out, - param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ); + ret = -1; + else + ret= stream->audio_out->get_property (stream->audio_out, + param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_VERBOSITY: - return stream->xine->verbosity; + ret = stream->xine->verbosity; + break; case XINE_PARAM_VO_HUE: case XINE_PARAM_VO_SATURATION: @@ -528,32 +574,40 @@ int xine_get_param (xine_stream_t *stream, int param) { case XINE_PARAM_VO_ZOOM_Y: case XINE_PARAM_VO_PAN_SCAN: case XINE_PARAM_VO_TVMODE: - return stream->video_out->get_property(stream->video_out, param); + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); + ret = stream->video_out->get_property(stream->video_out, param); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + break; case XINE_PARAM_IGNORE_VIDEO: - return _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_VIDEO); + ret = _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_VIDEO); + break; case XINE_PARAM_IGNORE_AUDIO: - return _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_AUDIO); + ret = _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_AUDIO); + break; case XINE_PARAM_IGNORE_SPU: - return _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_SPU); + ret = _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_SPU); + break; case XINE_PARAM_METRONOM_PREBUFFER: - return stream->metronom->get_option(stream->metronom, METRONOM_PREBUFFER); + ret = stream->metronom->get_option(stream->metronom, METRONOM_PREBUFFER); + break; case XINE_PARAM_BROADCASTER_PORT: if( stream->broadcaster ) - return _x_get_broadcaster_port(stream->broadcaster); + ret = _x_get_broadcaster_port(stream->broadcaster); else - return 0; + ret = 0; break; default: xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "xine_interface: unknown param %d\n", param); + ret = 0; } - return 0; + return ret; } uint32_t xine_get_stream_info (xine_stream_t *stream, int info) { diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h index 3bd7c319c..7953fd8cf 100644 --- a/src/xine-engine/xine_internal.h +++ b/src/xine-engine/xine_internal.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine_internal.h,v 1.153 2004/01/11 15:54:23 jstembridge Exp $ + * $Id: xine_internal.h,v 1.154 2004/02/12 18:19:00 mroi Exp $ * */ @@ -89,6 +89,8 @@ extern "C" { #define XINE_STREAM_INFO_MAX 99 +typedef struct xine_ticket_s xine_ticket_t; + /* * the "big" xine struct, holding everything together */ @@ -111,6 +113,61 @@ struct xine_s { pthread_mutex_t streams_lock; metronom_clock_t *clock; + +#ifdef XINE_ENGINE_INTERNAL + xine_ticket_t *port_ticket; +#endif +}; + +/* + * xine thread tickets + */ + +struct xine_ticket_s { + + /* the ticket owner must assure to check for ticket revocation in + * intervals of finite length; this means that you must release + * the ticket before any operation that might block + * + * you must never write to this member directly + */ + int ticket_revoked; + + /* apply for a ticket; between acquire and relese of an irrevocable + * ticket (be sure to pair them properly!), it is guaranteed that you + * will never be blocked by ticket revocation */ + void (*acquire)(xine_ticket_t *self, int irrevocable); + + /* give a ticket back */ + void (*release)(xine_ticket_t *self, int irrevocable); + + /* renew a ticket, when it has been revoked, see ticket_revoked above; + * irrevocable must be set to one, if your thread might have acquired + * irrevocable tickets you don't know of; set it to zero only when + * you know that this is impossible */ + void (*renew)(xine_ticket_t *self, int irrevocable); + +#ifdef XINE_ENGINE_INTERNAL + /* allow handing out new tickets */ + void (*issue)(xine_ticket_t *self, int atomic); + + /* revoke all tickets and deny new ones; + * a pair of atomic revoke and issue cannot be interrupted by another + * revocation or by other threads acquiring tickets */ + void (*revoke)(xine_ticket_t *self, int atomic); + + void (*dispose)(xine_ticket_t *self); + + pthread_mutex_t lock; + pthread_mutex_t revoke_lock; + pthread_cond_t issued; + pthread_cond_t revoked; + int tickets_granted; + int irrevocable_tickets; + int pending_revocations; + int atomic_revoke; + pthread_t atomic_revoker_thread; +#endif }; /* @@ -264,14 +321,6 @@ struct xine_stream_s { int err; - /* on-the-fly port rewiring */ - xine_video_port_t *next_video_port; - xine_audio_port_t *next_audio_port; - pthread_mutex_t next_video_port_lock; - pthread_mutex_t next_audio_port_lock; - pthread_cond_t next_video_port_wired; - pthread_cond_t next_audio_port_wired; - broadcaster_t *broadcaster; #endif }; |