summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim@centricular.com>2018-01-31 20:19:47 +0000
committerTim-Philipp Müller <tim@centricular.com>2018-02-19 16:03:39 +0000
commit0846ceef598e8a23da193d41efec3854952bd761 (patch)
tree142638d91b93428e1c954ad964368f857afdfad7
parent8b22d470575931e7e115602d5bf2a8342e686f46 (diff)
appsink: don't signal the GCond if no one is waiting on it
Performance optimisation: Keep track whenever the streaming thread or the application thread are waiting on the GCond for more space or new data, and only signal on the GCond if someone is actually waiting. Avoids unnecessary syscalls and thus context switches.
-rw-r--r--gst-libs/gst/app/gstappsink.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/gst-libs/gst/app/gstappsink.c b/gst-libs/gst/app/gstappsink.c
index b3c110ec8..87ae643e2 100644
--- a/gst-libs/gst/app/gstappsink.c
+++ b/gst-libs/gst/app/gstappsink.c
@@ -73,6 +73,13 @@
#include "gstappsink.h"
+typedef enum
+{
+ NOONE_WAITING,
+ STREAM_WAITING, /* streaming thread is waiting for application thread */
+ APP_WAITING, /* application thread is waiting for streaming thread */
+} GstAppSinkWaitStatus;
+
struct _GstAppSinkPrivate
{
GstCaps *caps;
@@ -81,6 +88,7 @@ struct _GstAppSinkPrivate
guint max_buffers;
gboolean drop;
gboolean wait_on_eos;
+ GstAppSinkWaitStatus wait_status;
GCond cond;
GMutex mutex;
@@ -459,6 +467,7 @@ gst_app_sink_init (GstAppSink * appsink)
priv->drop = DEFAULT_PROP_DROP;
priv->wait_on_eos = DEFAULT_PROP_WAIT_ON_EOS;
priv->buffer_lists_supported = DEFAULT_PROP_BUFFER_LIST;
+ priv->wait_status = NOONE_WAITING;
}
static void
@@ -632,6 +641,7 @@ gst_app_sink_start (GstBaseSink * psink)
g_mutex_lock (&priv->mutex);
GST_DEBUG_OBJECT (appsink, "starting");
+ priv->wait_status = NOONE_WAITING;
priv->flushing = FALSE;
priv->started = TRUE;
gst_segment_init (&priv->preroll_segment, GST_FORMAT_TIME);
@@ -651,6 +661,7 @@ gst_app_sink_stop (GstBaseSink * psink)
GST_DEBUG_OBJECT (appsink, "stopping");
priv->flushing = TRUE;
priv->started = FALSE;
+ priv->wait_status = NOONE_WAITING;
gst_app_sink_flush_unlocked (appsink);
gst_buffer_replace (&priv->preroll_buffer, NULL);
gst_caps_replace (&priv->preroll_caps, NULL);
@@ -707,8 +718,11 @@ gst_app_sink_event (GstBaseSink * sink, GstEvent * event)
* Otherwise we might signal EOS before all buffers are
* consumed, which is a bit confusing for the application
*/
- while (priv->num_buffers > 0 && !priv->flushing && priv->wait_on_eos)
+ while (priv->num_buffers > 0 && !priv->flushing && priv->wait_on_eos) {
+ priv->wait_status = STREAM_WAITING;
g_cond_wait (&priv->cond, &priv->mutex);
+ priv->wait_status = NOONE_WAITING;
+ }
if (priv->flushing)
emit = FALSE;
g_mutex_unlock (&priv->mutex);
@@ -755,7 +769,9 @@ gst_app_sink_preroll (GstBaseSink * psink, GstBuffer * buffer)
GST_DEBUG_OBJECT (appsink, "setting preroll buffer %p", buffer);
gst_buffer_replace (&priv->preroll_buffer, buffer);
- g_cond_signal (&priv->cond);
+ if (priv->wait_status == APP_WAITING)
+ g_cond_signal (&priv->cond);
+
emit = priv->emit_signals;
g_mutex_unlock (&priv->mutex);
@@ -869,7 +885,10 @@ restart:
}
/* wait for a buffer to be removed or flush */
+ priv->wait_status = STREAM_WAITING;
g_cond_wait (&priv->cond, &priv->mutex);
+ priv->wait_status = NOONE_WAITING;
+
if (priv->flushing)
goto flushing;
}
@@ -877,7 +896,10 @@ restart:
/* we need to ref the buffer/list when pushing it in the queue */
gst_queue_array_push_tail (priv->queue, gst_mini_object_ref (data));
priv->num_buffers++;
- g_cond_signal (&priv->cond);
+
+ if (priv->wait_status == APP_WAITING)
+ g_cond_signal (&priv->cond);
+
emit = priv->emit_signals;
g_mutex_unlock (&priv->mutex);
@@ -972,8 +994,11 @@ gst_app_sink_query (GstBaseSink * bsink, GstQuery * query)
{
g_mutex_lock (&priv->mutex);
GST_DEBUG_OBJECT (appsink, "waiting buffers to be consumed");
- while (priv->num_buffers > 0 || priv->preroll_buffer)
+ while (priv->num_buffers > 0 || priv->preroll_buffer) {
+ priv->wait_status = STREAM_WAITING;
g_cond_wait (&priv->cond, &priv->mutex);
+ priv->wait_status = NOONE_WAITING;
+ }
g_mutex_unlock (&priv->mutex);
ret = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query);
break;
@@ -1486,12 +1511,14 @@ gst_app_sink_try_pull_preroll (GstAppSink * appsink, GstClockTime timeout)
/* nothing to return, wait */
GST_DEBUG_OBJECT (appsink, "waiting for the preroll buffer");
+ priv->wait_status = APP_WAITING;
if (timeout_valid) {
if (!g_cond_wait_until (&priv->cond, &priv->mutex, end_time))
goto expired;
} else {
g_cond_wait (&priv->cond, &priv->mutex);
}
+ priv->wait_status = NOONE_WAITING;
}
sample =
gst_sample_new (priv->preroll_buffer, priv->preroll_caps,
@@ -1506,6 +1533,7 @@ gst_app_sink_try_pull_preroll (GstAppSink * appsink, GstClockTime timeout)
expired:
{
GST_DEBUG_OBJECT (appsink, "timeout expired, return NULL");
+ priv->wait_status = NOONE_WAITING;
g_mutex_unlock (&priv->mutex);
return NULL;
}
@@ -1581,12 +1609,14 @@ gst_app_sink_try_pull_sample (GstAppSink * appsink, GstClockTime timeout)
/* nothing to return, wait */
GST_DEBUG_OBJECT (appsink, "waiting for a buffer");
+ priv->wait_status = APP_WAITING;
if (timeout_valid) {
if (!g_cond_wait_until (&priv->cond, &priv->mutex, end_time))
goto expired;
} else {
g_cond_wait (&priv->cond, &priv->mutex);
}
+ priv->wait_status = NOONE_WAITING;
}
obj = dequeue_buffer (appsink);
@@ -1601,7 +1631,9 @@ gst_app_sink_try_pull_sample (GstAppSink * appsink, GstClockTime timeout)
}
gst_mini_object_unref (obj);
- g_cond_signal (&priv->cond);
+ if (priv->wait_status == STREAM_WAITING)
+ g_cond_signal (&priv->cond);
+
g_mutex_unlock (&priv->mutex);
return sample;
@@ -1610,6 +1642,7 @@ gst_app_sink_try_pull_sample (GstAppSink * appsink, GstClockTime timeout)
expired:
{
GST_DEBUG_OBJECT (appsink, "timeout expired, return NULL");
+ priv->wait_status = NOONE_WAITING;
g_mutex_unlock (&priv->mutex);
return NULL;
}