summaryrefslogtreecommitdiff
path: root/src/xine-engine/xine.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xine-engine/xine.c')
-rw-r--r--src/xine-engine/xine.c230
1 files changed, 174 insertions, 56 deletions
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;