Skip to content

Instantly share code, notes, and snippets.

@joanpau
Last active July 14, 2016 17:58
Show Gist options
  • Save joanpau/f979dc11fd792ca43a3f9f1fd7fe687f to your computer and use it in GitHub Desktop.
Save joanpau/f979dc11fd792ca43a3f9f1fd7fe687f to your computer and use it in GitHub Desktop.
Add timeout sample pull to GstAppSink
/* inside gst_app_sink_class_init */
static void
gst_app_sink_class_init (GstAppSinkClass * klass)
{
/* ... */
gst_app_sink_signals[SIGNAL_TRY_PULL_SAMPLE] =
g_signal_new ("try-pull-sample", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
try_pull_sample), NULL, NULL, NULL, GST_TYPE_SAMPLE, 1, /* WE WANT GstClockTime HERE */);
/* ... */
}
/**
* gst_app_sink_try_pull_sample:
* @appsink: a #GstAppSink
* @timeout: the maximum amount of time to wait for a sample
*
* This function blocks until a sample or EOS becomes available or the appsink
* element is set to the READY/NULL state or the timeout expires.
*
* This function will only return samples when the appsink is in the PLAYING
* state. All rendered buffers will be put in a queue so that the application
* can pull samples at its own rate. Note that when the application does not
* pull samples fast enough, the queued buffers could consume a lot of memory,
* especially when dealing with raw video frames.
*
* If an EOS event was received before any buffers or the timeout expires,
* this function returns %NULL. Use gst_app_sink_is_eos () to check for the EOS
* condition.
*
* Returns: (transfer full): a #GstSample or NULL when the appsink is stopped or EOS or the timeout expires.
* Call gst_sample_unref() after usage.
*/
GstSample *
gst_app_sink_try_pull_sample (GstAppSink * appsink, GstClockTime timeout)
{
GstSample *sample = NULL;
GstBuffer *buffer;
GstAppSinkPrivate *priv;
gint64 end_time;
const gboolean timeout_valid = timeout != GST_CLOCK_TIME_NONE;
g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
if (timeout_valid)
end_time =
g_get_monotonic_time () + timeout / (GST_SECOND / G_TIME_SPAN_SECOND);
priv = appsink->priv;
g_mutex_lock (&priv->mutex);
while (TRUE) {
GST_DEBUG_OBJECT (appsink, "trying to grab a buffer");
if (!priv->started)
goto not_started;
if (priv->num_buffers > 0)
break;
if (priv->is_eos)
goto eos;
/* nothing to return, wait */
GST_DEBUG_OBJECT (appsink, "waiting for a buffer");
if (timeout_valid) {
if (!g_cond_wait_until (&priv->cond, &priv->mutex, end_time))
goto expired;
} else {
g_cond_wait (&priv->cond, &priv->mutex);
}
}
buffer = dequeue_buffer (appsink);
GST_DEBUG_OBJECT (appsink, "we have a buffer %p", buffer);
sample = gst_sample_new (buffer, priv->last_caps, &priv->last_segment, NULL);
gst_buffer_unref (buffer);
g_cond_signal (&priv->cond);
g_mutex_unlock (&priv->mutex);
return sample;
/* special conditions */
expired:
{
GST_DEBUG_OBJECT (appsink, "timeout expired, return NULL");
g_mutex_unlock (&priv->mutex);
return NULL;
}
eos:
{
GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
g_mutex_unlock (&priv->mutex);
return NULL;
}
not_started:
{
GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
g_mutex_unlock (&priv->mutex);
return NULL;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment