/* 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; } }