|
From: Torsten J. <t....@gm...> - 2018-01-19 17:42:41
|
# HG changeset patch
# User Torsten Jager <t....@gm...>
# Date 1516383740 -3600
# Node ID 77a743daee62f5cf4ad8f01530cbd5c910c87e1f
# Branch default
# Parent 18755f89e01de0f56c68d1978473179f9fe5f774
Optimize tickets 5.
- Faster revoke response.
- Fix port rewire during pause.
- Use rewire ticket revoke mode.
- (Un)ref post ports fed by a stream.
diff --git a/include/xine/post.h b/include/xine/post.h
--- a/include/xine/post.h
+++ b/include/xine/post.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2017 the xine project
+ * Copyright (C) 2000-2018 the xine project
*
* This file is part of xine, a free video player.
*
@@ -340,9 +340,41 @@
post_in_t **input, post_out_t **output) XINE_PROTECTED;
-/* 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) */
+/* If you do intercept these decoder-called functions
+ * (that is, you do not use post defaults), please
+ * open ():
+ * _x_post_inc_usage (port);
+ * _x_post_rewire (port->post);
+ * ...
+ * close ():
+ * ...
+ * _x_post_dec_usage (port);
+ * get_buffer ():
+ * _x_post_inc_usage (port);
+ * ...
+ * port->original_port->get_buffer (port->original_port); and/or
+ * while (not_done_yet) {
+ * _x_post_rewire (port->post);
+ * timed_wait (done);
+ * }
+ * ...
+ * _x_post_dec_usage (port);
+ * get_frame ():
+ * _x_post_inc_usage (port);
+ * ...
+ * port->original_port->get_frame (port->original_port, ...); and/or
+ * while (not_done_yet) {
+ * _x_post_rewire (port->post);
+ * timed_wait (done);
+ * }
+ * ...
+ * if (this_frame_is_not_intercepted)
+ * _x_post_dec_usage (port);
+ * frame.free ():
+ * ...
+ * _x_post_dec_usage (port);
+ * this will allow pending rewire operations, while preventing your port from getting
+ * pulled from under your feet by the possible rewire. */
static inline void _x_post_rewire(post_plugin_t *post) {
if (post->running_ticket->ticket_revoked)
post->running_ticket->renew(post->running_ticket, 1);
@@ -390,6 +422,14 @@
pthread_mutex_unlock(&(port)->usage_lock); \
} while(0)
+#ifdef POST_INTERNAL
+/* try to recognize post ports, do the above, return new use count.
+ * otherwise, return -1. */
+int _x_post_video_port_ref (xine_video_port_t *port_gen);
+int _x_post_video_port_unref (xine_video_port_t *port_gen);
+int _x_post_audio_port_ref (xine_audio_port_t *port_gen);
+int _x_post_audio_port_unref (xine_audio_port_t *port_gen);
+#endif
/* macros to create parameter descriptors */
--git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
--- a/src/xine-engine/audio_out.c
+++ b/src/xine-engine/audio_out.c
@@ -580,33 +580,61 @@
}
}
-static audio_buffer_t *ao_fifo_get_nonblock (audio_fifo_t *fifo) {
+static void ao_ticket_revoked (void *user_data, int flags) {
+ aos_t *this = (aos_t *)user_data;
+ const char *s1 = (flags & XINE_TICKET_FLAG_ATOMIC) ? " atomic" : "";
+ const char *s2 = (flags & XINE_TICKET_FLAG_REWIRE) ? " port_rewire" : "";
+ pthread_cond_signal (&this->free_fifo.not_empty);
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_out: port ticket revoked%s%s.\n", s1, s2);
+}
+
+static audio_buffer_t *ao_free_fifo_get (aos_t *this) {
audio_buffer_t *buf;
- pthread_mutex_lock (&fifo->mutex);
- while (!(buf = fifo->first)) {
- struct timeval tv;
- struct timespec ts;
- gettimeofday (&tv, NULL);
- ts.tv_sec = tv.tv_sec + 1;
- ts.tv_nsec = tv.tv_usec * 1000;
- fifo->num_waiters++;
- if (pthread_cond_timedwait (&fifo->not_empty, &fifo->mutex, &ts) != 0) {
- fifo->num_waiters--;
- pthread_mutex_unlock (&fifo->mutex);
- return NULL;
+
+ pthread_mutex_lock (&this->free_fifo.mutex);
+ while (!(buf = this->free_fifo.first)) {
+ if (this->xine->port_ticket->ticket_revoked) {
+ pthread_mutex_unlock (&this->free_fifo.mutex);
+ this->xine->port_ticket->renew (this->xine->port_ticket, 1);
+ if (!(this->xine->port_ticket->ticket_revoked & XINE_TICKET_FLAG_REWIRE)) {
+ pthread_mutex_lock (&this->free_fifo.mutex);
+ continue;
+ }
+ /* O dear. Port rewiring ahead. Try unblock. */
+ if (this->clock->speed == XINE_SPEED_PAUSE) {
+ pthread_mutex_lock (&this->out_fifo.mutex);
+ if (this->out_fifo.first) {
+ buf = ao_fifo_pop_int (&this->out_fifo);
+ pthread_mutex_unlock (&this->out_fifo.mutex);
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_out: try unblocking decoder.\n");
+ return buf;
+ }
+ pthread_mutex_unlock (&this->out_fifo.mutex);
+ }
+ pthread_mutex_lock (&this->free_fifo.mutex);
}
- fifo->num_waiters--;
+ {
+ struct timeval tv;
+ struct timespec ts;
+ gettimeofday (&tv, NULL);
+ ts.tv_sec = tv.tv_sec + 1;
+ ts.tv_nsec = tv.tv_usec * 1000;
+ this->free_fifo.num_waiters++;
+ pthread_cond_timedwait (&this->free_fifo.not_empty, &this->free_fifo.mutex, &ts);
+ this->free_fifo.num_waiters--;
+ }
}
+
if (buf->next) {
- fifo->first = buf->next;
+ this->free_fifo.first = buf->next;
buf->next = NULL;
- fifo->num_buffers--;
+ this->free_fifo.num_buffers--;
} else {
- fifo->first = NULL;
- fifo->last = NULL;
- fifo->num_buffers = 0;
+ this->free_fifo.first = NULL;
+ this->free_fifo.last = NULL;
+ this->free_fifo.num_buffers = 0;
}
- pthread_mutex_unlock (&fifo->mutex);
+ pthread_mutex_unlock (&this->free_fifo.mutex);
return buf;
}
@@ -1796,9 +1824,7 @@
aos_t *this = (aos_t *) this_gen;
audio_buffer_t *buf;
- while (!(buf = ao_fifo_get_nonblock (&this->free_fifo)))
- if (this->xine->port_ticket->ticket_revoked)
- this->xine->port_ticket->renew(this->xine->port_ticket, 1);
+ buf = ao_free_fifo_get (this);
_x_extra_info_reset( buf->extra_info );
buf->stream = NULL;
@@ -1884,6 +1910,8 @@
int vol;
int prop = 0;
+ this->xine->port_ticket->revoke_cb_unregister (this->xine->port_ticket, ao_ticket_revoked, this);
+
if (this->audio_loop_running) {
void *p;
@@ -2493,6 +2521,8 @@
this->frame_buf[1] = buf;
}
+ this->xine->port_ticket->revoke_cb_register (this->xine->port_ticket, ao_ticket_revoked, this);
+
/*
* Set audio volume to latest used one ?
*/
--git a/src/xine-engine/post.c b/src/xine-engine/post.c
--- a/src/xine-engine/post.c
+++ b/src/xine-engine/post.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2017 the xine project
+ * Copyright (C) 2000-2018 the xine project
*
* This file is part of xine, a free video player.
*
@@ -63,11 +63,8 @@
static void post_frame_free (vo_frame_t *vo_img);
static void post_frame_dispose (vo_frame_t *vo_img);
-static vo_frame_t *post_intercept_video_frame (vo_frame_t *frame, post_video_port_t *port, int usage) {
+static vf_alias_t *post_new_video_alias (post_video_port_t *port, int usage) {
vf_alias_t *new_frame;
-
- if (usage && port->frame_lock)
- pthread_mutex_lock (port->frame_lock);
/* get a free frame slot */
pthread_mutex_lock (&port->usage_lock);
if (port->free_frame_slots) {
@@ -79,6 +76,27 @@
if (usage)
port->usage_count++;
pthread_mutex_unlock (&port->usage_lock);
+ return new_frame;
+}
+
+static void post_free_unused_video_alias (post_video_port_t *port, vf_alias_t *f) {
+ /* put the now free slot into the free frames list */
+ pthread_mutex_lock (&port->usage_lock);
+ f->frame.next = port->free_frame_slots;
+ port->free_frame_slots = &f->frame;
+ port->usage_count--;
+ if (port->usage_count || !port->post->dispose_pending) {
+ pthread_mutex_unlock (&port->usage_lock);
+ } else {
+ pthread_mutex_unlock (&port->usage_lock);
+ port->post->dispose (port->post);
+ }
+}
+
+static vo_frame_t *post_intercept_video_frame (post_video_port_t *port, vo_frame_t *frame, vf_alias_t *new_frame, int usage) {
+
+ if (usage && port->frame_lock)
+ pthread_mutex_lock (port->frame_lock);
/* make a copy and attach the original */
xine_fast_memcpy (&new_frame->frame, frame, sizeof (vo_frame_t));
@@ -164,30 +182,37 @@
static void post_video_enable_ovl (xine_video_port_t *port_gen, int ovl_enable);
static video_overlay_manager_t *post_video_get_overlay_manager (xine_video_port_t *port_gen);
-static void post_video_port_ref (xine_video_port_t *port_gen) {
+static int post_video_port_ref (xine_video_port_t *port_gen) {
post_video_port_t *port = (post_video_port_t *)port_gen;
+ int n = -1;
if (!port)
- return;
+ return n;
if ((port->new_port.get_capabilities == post_video_get_capabilities)
|| (port->new_port.get_frame == post_video_get_frame)
|| (port->new_port.enable_ovl == post_video_enable_ovl)
|| (port->new_port.get_overlay_manager == post_video_get_overlay_manager)) {
pthread_mutex_lock (&port->usage_lock);
- port->usage_count++;
+ n = (++port->usage_count);
pthread_mutex_unlock (&port->usage_lock);
}
+ return n;
}
-static void post_video_port_unref (xine_video_port_t *port_gen) {
+int _x_post_video_port_ref (xine_video_port_t *port_gen) {
+ return post_video_port_ref (port_gen);
+}
+
+static int post_video_port_unref (xine_video_port_t *port_gen) {
post_video_port_t *port = (post_video_port_t *)port_gen;
+ int n = -1;
if (!port)
- return;
+ return n;
if ((port->new_port.get_capabilities == post_video_get_capabilities)
|| (port->new_port.get_frame == post_video_get_frame)
|| (port->new_port.enable_ovl == post_video_enable_ovl)
|| (port->new_port.get_overlay_manager == post_video_get_overlay_manager)) {
pthread_mutex_lock (&port->usage_lock);
- port->usage_count--;
+ n = (--port->usage_count);
if (port->usage_count || !port->post->dispose_pending) {
pthread_mutex_unlock (&port->usage_lock);
} else {
@@ -195,6 +220,11 @@
port->post->dispose (port->post);
}
}
+ return n;
+}
+
+int _x_post_video_port_unref (xine_video_port_t *port_gen) {
+ return post_video_port_unref (port_gen);
}
static uint32_t post_audio_get_capabilities (xine_audio_port_t *port_gen);
@@ -203,30 +233,37 @@
static void post_audio_put_buffer (xine_audio_port_t *port_gen, audio_buffer_t *buf,
xine_stream_t *stream);
-static void post_audio_port_ref (xine_audio_port_t *port_gen) {
+static int post_audio_port_ref (xine_audio_port_t *port_gen) {
post_audio_port_t *port = (post_audio_port_t *)port_gen;
+ int n = -1;
if (!port)
- return;
+ return n;
if ((port->new_port.get_capabilities == post_audio_get_capabilities)
|| (port->new_port.get_buffer == post_audio_get_buffer)
|| (port->new_port.control == post_audio_control)
|| (port->new_port.put_buffer == post_audio_put_buffer)) {
pthread_mutex_lock (&port->usage_lock);
- port->usage_count++;
+ n = (++port->usage_count);
pthread_mutex_unlock (&port->usage_lock);
}
+ return n;
[... 27 lines omitted ...]
+ return n;
}
+int _x_post_audio_port_unref (xine_audio_port_t *port_gen) {
+ return post_audio_port_unref (port_gen);
+}
+
+
void _x_post_init(post_plugin_t *post, int num_audio_inputs, int num_video_inputs) {
post->input = xine_list_new();
post->output = xine_list_new();
@@ -257,8 +300,8 @@
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(port->post);
- _x_post_inc_usage(port);
+ _x_post_inc_usage (port);
+ _x_post_rewire (port->post);
if (port->port_lock) pthread_mutex_lock(port->port_lock);
(port->original_port->open) (port->original_port, stream);
if (port->port_lock) pthread_mutex_unlock(port->port_lock);
@@ -270,15 +313,20 @@
uint32_t height, double ratio, int format, int flags) {
post_video_port_t *port = (post_video_port_t *)port_gen;
vo_frame_t *frame;
+ /* We always need to ref this port here to protect it from
+ * possible port rewiring inside get_frame ().
+ * In the intercept case, we save an extra unref. */
+ vf_alias_t *alias = post_new_video_alias (port, 1);
- _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);
if (port->port_lock) pthread_mutex_unlock(port->port_lock);
if (frame && (!port->intercept_frame || port->intercept_frame(port, frame))) {
- frame = post_intercept_video_frame (frame, port, 1);
+ frame = post_intercept_video_frame (port, frame, alias, 1);
+ } else {
+ post_free_unused_video_alias (port, alias);
}
return frame;
@@ -423,8 +471,7 @@
if (!new_port)
return 0;
- this->running_ticket->lock_port_rewiring(this->running_ticket, -1);
- this->running_ticket->revoke(this->running_ticket, 1);
+ this->running_ticket->revoke (this->running_ticket, XINE_TICKET_FLAG_REWIRE);
if (new_port) {
/* The wiring itself. */
@@ -442,8 +489,7 @@
}
input_port->original_port = new_port;
- this->running_ticket->issue(this->running_ticket, 1);
- this->running_ticket->unlock_port_rewiring(this->running_ticket);
+ this->running_ticket->issue (this->running_ticket, XINE_TICKET_FLAG_REWIRE);
return 1;
}
@@ -592,7 +638,8 @@
vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port) {
- return post_intercept_video_frame (frame, port, 0);
+ vf_alias_t *alias = post_new_video_alias (port, 0);
+ return post_intercept_video_frame (port, frame, alias, 0);
}
vo_frame_t *_x_post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port) {
@@ -801,8 +848,8 @@
post_audio_port_t *port = (post_audio_port_t *)port_gen;
int result;
- _x_post_rewire(port->post);
- _x_post_inc_usage(port);
+ _x_post_inc_usage (port);
+ _x_post_rewire (port->post);
if (port->port_lock) pthread_mutex_lock(port->port_lock);
result = (port->original_port->open) (port->original_port, stream, bits, rate, mode);
if (port->port_lock) pthread_mutex_unlock(port->port_lock);
@@ -816,11 +863,13 @@
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(port->post);
+ /* Ugly: we always need to ref this port here to protect it from
+ * possible port rewiring inside get_buffer (). */
+ _x_post_inc_usage (port);
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);
+ _x_post_dec_usage (port);
return buf;
}
@@ -901,8 +950,7 @@
if (!new_port)
return 0;
- this->running_ticket->lock_port_rewiring(this->running_ticket, -1);
- this->running_ticket->revoke(this->running_ticket, 1);
+ this->running_ticket->revoke (this->running_ticket, XINE_TICKET_FLAG_REWIRE);
post_audio_port_ref (new_port);
if (input_port->original_port->status(input_port->original_port, input_port->stream,
@@ -913,8 +961,7 @@
post_audio_port_unref (input_port->original_port);
input_port->original_port = new_port;
- this->running_ticket->issue(this->running_ticket, 1);
- this->running_ticket->unlock_port_rewiring(this->running_ticket);
+ this->running_ticket->issue (this->running_ticket, XINE_TICKET_FLAG_REWIRE);
return 1;
}
@@ -1101,3 +1148,5 @@
return 0;
}
+
+
--git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.c
@@ -412,6 +412,14 @@
pthread_mutex_unlock (&queue->mutex);
}
+static void vo_ticket_revoked (void *user_data, int flags) {
+ vos_t *this = (vos_t *)user_data;
+ const char *s1 = (flags & XINE_TICKET_FLAG_ATOMIC) ? " atomic" : "";
+ const char *s2 = (flags & XINE_TICKET_FLAG_REWIRE) ? " port_rewire" : "";
+ pthread_cond_signal (&this->free_img_buf_queue.not_empty);
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out: port ticket revoked%s%s.\n", s1, s2);
+}
+
static void vo_queue_append_int (img_buf_fifo_t *queue, vo_frame_t *img) {
int n;
@@ -478,16 +486,85 @@
pthread_mutex_unlock (&queue->mutex);
}
-static vo_frame_t *vo_queue_get_nonblock (img_buf_fifo_t *queue,
+static vo_frame_t *vo_queue_pop_int (img_buf_fifo_t *queue) {
+ vo_frame_t *img;
+
+ img = queue->first;
+ queue->first = img->next;
+ img->next = NULL;
+ if (!queue->first) {
+ queue->last = NULL;
+ queue->num_buffers = 0;
+ } else {
+ queue->num_buffers--;
+ }
+
+ return img;
+}
+
+static int vo_frame_dec2_lock_int (vos_t *this, vo_frame_t *img);
+
+static vo_frame_t *vo_get_unblock_frame (vos_t *this) {
+ vo_frame_t *f, *prev;
+ /* Try 1: free queue reserve. */
+ pthread_mutex_lock (&this->free_img_buf_queue.mutex);
+ if (this->free_img_buf_queue.first) {
+ f = vo_queue_pop_int (&this->free_img_buf_queue);
+ pthread_mutex_unlock (&this->free_img_buf_queue.mutex);
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out: got unblock frame from free queue.\n");
+ return f;
+ }
+ pthread_mutex_unlock (&this->free_img_buf_queue.mutex);
+ /* Try 2: shared display queue. */
+ pthread_mutex_lock (&this->display_img_buf_queue.mutex);
+ prev = NULL;
+ f = this->display_img_buf_queue.first;
+ while (f) {
+ if (f->lock_counter <= 2)
+ break;
+ prev = f;
+ f = f->next;
+ }
+ if (f) {
+ if (!prev) {
+ if (!f->next) { /* only */
+ this->display_img_buf_queue.first =
+ this->display_img_buf_queue.last = NULL;
+ this->display_img_buf_queue.num_buffers = 0;
+ } else { /* first */
+ this->display_img_buf_queue.first = f->next;
+ f->next = NULL;
+ this->display_img_buf_queue.num_buffers--;
+ }
+ } else {
+ this->display_img_buf_queue.num_buffers--;
+ if (f->next) { /* middle */
+ prev->next = f->next;
+ f->next = NULL;
+ } else { /* last */
+ prev->next = NULL;
+ this->display_img_buf_queue.last = prev;
+ }
+ }
+ vo_frame_dec2_lock_int (this, f);
+ pthread_mutex_unlock (&this->display_img_buf_queue.mutex);
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out: got unblock frame from display queue.\n");
+ return f;
+ }
+ pthread_mutex_unlock (&this->display_img_buf_queue.mutex);
+ return NULL;
+}
+
+static vo_frame_t *vo_free_queue_get (vos_t *this,
uint32_t width, uint32_t height, double ratio, int format, int flags) {
vo_frame_t *img, *prev;
- pthread_mutex_lock (&queue->mutex);
+ pthread_mutex_lock (&this->free_img_buf_queue.mutex);
do {
prev = NULL;
- if (queue->num_buffers > queue->locked_for_read) {
- img = queue->first;
+ if (this->free_img_buf_queue.num_buffers > this->free_img_buf_queue.locked_for_read) {
+ img = this->free_img_buf_queue.first;
#if EXPERIMENTAL_FRAME_QUEUE_OPTIMIZATION
if (width && height) {
/* try to obtain a frame with the same format first.
@@ -505,7 +582,7 @@
}
if (!img) {
- if ((queue->num_buffers == 1) && (queue->num_buffers_max > 8)) {
+ if ((this->free_img_buf_queue.num_buffers == 1) && (this->free_img_buf_queue.num_buffers_max > 8)) {
/* only a single frame on fifo with different
* format -> ignore it (give another chance of a frame format hit)
* only if we have a lot of buffers at all.
@@ -516,12 +593,12 @@
* on fifo but they don't match -> give up. return whatever we got.
*/
prev = NULL;
- img = queue->first;
- lprintf("frame format miss (%d/%d)\n", i, queue->num_buffers);
+ img = this->free_img_buf_queue.first;
+ lprintf("frame format miss (%d/%d)\n", i, this->free_img_buf_queue.num_buffers);
}
} else {
/* good: format match! */
[... 9 lines omitted ...]
- struct timeval tv;
- struct timespec ts;
- gettimeofday (&tv, NULL);
- ts.tv_sec = tv.tv_sec + 1;
- ts.tv_nsec = tv.tv_usec * 1000;
- if (pthread_cond_timedwait (&queue->not_empty, &queue->mutex, &ts) != 0)
- break;
+ if (this->xine->port_ticket->ticket_revoked) {
+ pthread_mutex_unlock (&this->free_img_buf_queue.mutex);
+ this->xine->port_ticket->renew (this->xine->port_ticket, 1);
+ if (!(this->xine->port_ticket->ticket_revoked & XINE_TICKET_FLAG_REWIRE)) {
+ pthread_mutex_lock (&this->free_img_buf_queue.mutex);
+ continue;
+ }
+ /* O dear. Port rewire ahaed. Try unblocking with regular or emergency frame. */
+ if (this->clock->speed == XINE_SPEED_PAUSE) {
+ img = vo_get_unblock_frame (this);
+ if (img)
+ return img;
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out: allow port rewire.\n");
+ this->xine->port_ticket->renew (this->xine->port_ticket, XINE_TICKET_FLAG_REWIRE);
+ pthread_mutex_lock (&this->free_img_buf_queue.mutex);
+ continue;
+ }
+ pthread_mutex_lock (&this->free_img_buf_queue.mutex);
+ }
+ {
+ struct timeval tv;
+ struct timespec ts;
+ gettimeofday (&tv, NULL);
+ ts.tv_sec = tv.tv_sec + 1;
+ ts.tv_nsec = tv.tv_usec * 1000;
+ pthread_cond_timedwait (&this->free_img_buf_queue.not_empty, &this->free_img_buf_queue.mutex, &ts);
+ }
}
} while (!img);
if (img) {
if (!prev) {
if (!img->next) { /* only */
- queue->first = queue->last = NULL;
- queue->num_buffers = 0;
+ this->free_img_buf_queue.first = this->free_img_buf_queue.last = NULL;
+ this->free_img_buf_queue.num_buffers = 0;
} else { /* first */
- queue->first = img->next;
+ this->free_img_buf_queue.first = img->next;
img->next = NULL;
- queue->num_buffers--;
+ this->free_img_buf_queue.num_buffers--;
}
} else {
- queue->num_buffers--;
+ this->free_img_buf_queue.num_buffers--;
if (img->next) { /* middle */
prev->next = img->next;
img->next = NULL;
} else { /* last */
prev->next = NULL;
- queue->last = prev;
+ this->free_img_buf_queue.last = prev;
}
}
}
- pthread_mutex_unlock (&queue->mutex);
-
- return img;
-}
-
-static vo_frame_t *vo_queue_pop_int (img_buf_fifo_t *queue) {
- vo_frame_t *img;
-
- img = queue->first;
- queue->first = img->next;
- img->next = NULL;
- if (!queue->first) {
- queue->last = NULL;
- queue->num_buffers = 0;
- } else {
- queue->num_buffers--;
- }
-
+ pthread_mutex_unlock (&this->free_img_buf_queue.mutex);
return img;
}
@@ -1235,10 +1315,7 @@
while (1) {
- while (!(img = vo_queue_get_nonblock (&this->free_img_buf_queue,
- width, height, ratio, format, flags)))
- if (this->xine->port_ticket->ticket_revoked)
- this->xine->port_ticket->renew(this->xine->port_ticket, 1);
+ img = vo_free_queue_get (this, width, height, ratio, format, flags);
lprintf ("got a frame -> pthread_mutex_lock (&img->mutex)\n");
@@ -1620,8 +1697,8 @@
*
* frame allocation inside vo loop is dangerous:
* we must never wait for a free frame -> deadlock condition.
- * to avoid deadlocks we don't use vo_queue_get_nonblock ()
- * but vo_queue_get_dupl () instead.
+ * to avoid deadlocks we don't use vo_free_queue_get ()
+ * but vo_*_get_dupl () instead.
*/
static vo_frame_t *duplicate_frame (vos_t *this, vo_frame_t *img) {
vo_frame_t *dupl;
@@ -2671,6 +2748,8 @@
xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out: exit.\n");
+ this->xine->port_ticket->revoke_cb_unregister (this->xine->port_ticket, vo_ticket_revoked, this);
+
if (this->video_loop_running) {
void *p;
@@ -3015,6 +3094,8 @@
}
this->free_img_buf_queue.locked_for_read = 0;
+ this->xine->port_ticket->revoke_cb_register (this->xine->port_ticket, vo_ticket_revoked, this);
+
this->warn_skipped_threshold =
xine->config->register_num (xine->config, "engine.performance.warn_skipped_threshold", 10,
_("percentage of skipped frames to tolerate"),
--git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.c
@@ -59,11 +59,13 @@
#define XINE_ENABLE_EXPERIMENTAL_FEATURES
#define METRONOM_INTERNAL
#define METRONOM_CLOCK_INTERNAL
+#define POST_INTERNAL
#include <xine/xine_internal.h>
#include <xine/plugin_catalog.h>
#include <xine/audio_out.h>
#include <xine/video_out.h>
+#include <xine/post.h>
#include <xine/demux.h>
#include <xine/buffer.h>
#include <xine/spu_decoder.h>
@@ -748,7 +750,7 @@
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;
+ xine_audio_port_t *new_port = (xine_audio_port_t *)data, *old_port;
uint32_t bits, rate;
int mode;
@@ -758,18 +760,19 @@
/* just an optimization */
set_speed_internal (stream, XINE_LIVE_PAUSE_OFF);
- stream->xine->port_ticket->lock_port_rewiring(stream->xine->port_ticket, -1);
- stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1);
-
- if (stream->audio_out->status(stream->audio_out, stream, &bits, &rate, &mode)) {
+ stream->xine->port_ticket->revoke (stream->xine->port_ticket, XINE_TICKET_FLAG_REWIRE);
+
+ old_port = stream->audio_out;
+ _x_post_audio_port_ref (new_port);
+ if (old_port->status (old_port, 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);
+ old_port->close (old_port, stream);
}
stream->audio_out = new_port;
-
- stream->xine->port_ticket->issue(stream->xine->port_ticket, 1);
- stream->xine->port_ticket->unlock_port_rewiring(stream->xine->port_ticket);
+ _x_post_audio_port_unref (old_port);
+
+ stream->xine->port_ticket->issue (stream->xine->port_ticket, XINE_TICKET_FLAG_REWIRE);
return 1;
}
@@ -777,7 +780,7 @@
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;
+ xine_video_port_t *new_port = (xine_video_port_t *)data, *old_port;
int64_t img_duration;
int width, height;
@@ -787,18 +790,19 @@
/* just an optimization */
set_speed_internal (stream, XINE_LIVE_PAUSE_OFF);
- stream->xine->port_ticket->lock_port_rewiring(stream->xine->port_ticket, -1);
- stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1);
-
- if (stream->video_out->status(stream->video_out, stream, &width, &height, &img_duration)) {
+ stream->xine->port_ticket->revoke (stream->xine->port_ticket, XINE_TICKET_FLAG_REWIRE);
+
+ old_port = stream->video_out;
+ _x_post_video_port_ref (new_port);
+ if (old_port->status (old_port, 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);
+ old_port->close (old_port, stream);
}
stream->video_out = new_port;
-
- stream->xine->port_ticket->issue(stream->xine->port_ticket, 1);
- stream->xine->port_ticket->unlock_port_rewiring(stream->xine->port_ticket);
+ _x_post_video_port_unref (old_port);
+
+ stream->xine->port_ticket->issue (stream->xine->port_ticket, XINE_TICKET_FLAG_REWIRE);
return 1;
}
|