Last active
July 14, 2016 17:58
-
-
Save joanpau/f979dc11fd792ca43a3f9f1fd7fe687f to your computer and use it in GitHub Desktop.
Add timeout sample pull to GstAppSink
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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