/** * gst_app_sink_is_eos: * @appsink: a #GstAppSink * * Check if @appsink is EOS, which is when no more samples can be pulled because * an EOS event was received. * * This function also returns %TRUE when the appsink is not in the PAUSED or * PLAYING state. * * Returns: %TRUE if no more samples can be pulled and the appsink is EOS. */ gboolean gst_app_sink_is_eos (GstAppSink * appsink) { gboolean ret; GstAppSinkPrivate *priv; g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE); priv = appsink->priv; g_mutex_lock (priv->mutex); if (!priv->started) goto not_started; if (priv->is_eos && priv->num_buffers == 0) { GST_DEBUG_OBJECT (appsink, "we are EOS and the queue is empty"); ret = TRUE; } else { GST_DEBUG_OBJECT (appsink, "we are not yet EOS"); ret = FALSE; } g_mutex_unlock (priv->mutex); return ret; not_started: { GST_DEBUG_OBJECT (appsink, "we are stopped, return TRUE"); g_mutex_unlock (priv->mutex); return TRUE; } }
/** * gst_app_sink_is_eos: * @appsink: a #GstAppSink * * Check if @appsink is EOS, which is when no more buffers can be pulled because * an EOS event was received. * * This function also returns %TRUE when the appsink is not in the PAUSED or * PLAYING state. * * Returns: %TRUE if no more buffers can be pulled and the appsink is EOS. * * Since: 0.10.22 */ EXPORT_C gboolean gst_app_sink_is_eos (GstAppSink * appsink) { gboolean ret; g_return_val_if_fail (appsink != NULL, FALSE); g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE); g_mutex_lock (appsink->priv->mutex); if (!appsink->priv->started) goto not_started; if (appsink->priv->is_eos && g_queue_is_empty (appsink->priv->queue)) { GST_DEBUG_OBJECT (appsink, "we are EOS and the queue is empty"); ret = TRUE; } else { GST_DEBUG_OBJECT (appsink, "we are not yet EOS"); ret = FALSE; } g_mutex_unlock (appsink->priv->mutex); return ret; not_started: { GST_DEBUG_OBJECT (appsink, "we are stopped, return TRUE"); g_mutex_unlock (appsink->priv->mutex); return TRUE; } }
/** * gst_app_sink_set_callbacks: * @appsink: a #GstAppSink * @callbacks: the callbacks * @user_data: a user_data argument for the callbacks * @notify: a destroy notify function * * Set callbacks which will be executed for each new preroll, new buffer and eos. * This is an alternative to using the signals, it has lower overhead and is thus * less expensive, but also less flexible. * * If callbacks are installed, no signals will be emited for performance * reasons. * * Since: 0.10.23 */ EXPORT_C void gst_app_sink_set_callbacks (GstAppSink * appsink, GstAppSinkCallbacks * callbacks, gpointer user_data, GDestroyNotify notify) { GDestroyNotify old_notify; g_return_if_fail (appsink != NULL); g_return_if_fail (GST_IS_APP_SINK (appsink)); g_return_if_fail (callbacks != NULL); GST_OBJECT_LOCK (appsink); old_notify = appsink->priv->notify; if (old_notify) { gpointer old_data; old_data = appsink->priv->user_data; appsink->priv->user_data = NULL; appsink->priv->notify = NULL; GST_OBJECT_UNLOCK (appsink); old_notify (old_data); GST_OBJECT_LOCK (appsink); } appsink->priv->callbacks = *callbacks; appsink->priv->user_data = user_data; appsink->priv->notify = notify; GST_OBJECT_UNLOCK (appsink); }
/** * gst_app_sink_set_emit_signals: * @appsink: a #GstAppSink * @emit: the new state * * Make appsink emit the "new-preroll" and "new-buffer" signals. This option is * by default disabled because signal emission is expensive and unneeded when * the application prefers to operate in pull mode. * * Since: 0.10.22 */ void gst_app_sink_set_emit_signals (GstAppSink * appsink, gboolean emit) { g_return_if_fail (GST_IS_APP_SINK (appsink)); g_mutex_lock (appsink->priv->mutex); appsink->priv->emit_signals = emit; g_mutex_unlock (appsink->priv->mutex); }
GstSample * gst_app_sink_pull_sample (GstAppSink * appsink) { GstSample *sample = NULL; GstBuffer *buffer; GstAppSinkPrivate *priv; g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL); 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"); 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 */ 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; } }
/** * gst_app_sink_get_drop: * @appsink: a #GstAppSink * * Check if @appsink will drop old buffers when the maximum amount of queued * buffers is reached. * * Returns: %TRUE if @appsink is dropping old buffers when the queue is * filled. * * Since: 0.10.22 */ gboolean gst_app_sink_get_drop (GstAppSink * appsink) { gboolean result; g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE); g_mutex_lock (appsink->priv->mutex); result = appsink->priv->drop; g_mutex_unlock (appsink->priv->mutex); return result; }
/** * gst_app_sink_set_drop: * @appsink: a #GstAppSink * @drop: the new state * * Instruct @appsink to drop old buffers when the maximum amount of queued * buffers is reached. * * Since: 0.10.22 */ void gst_app_sink_set_drop (GstAppSink * appsink, gboolean drop) { g_return_if_fail (GST_IS_APP_SINK (appsink)); g_mutex_lock (appsink->priv->mutex); if (appsink->priv->drop != drop) { appsink->priv->drop = drop; /* signal the change */ g_cond_signal (appsink->priv->cond); } g_mutex_unlock (appsink->priv->mutex); }
/** * gst_app_sink_get_max_buffers: * @appsink: a #GstAppSink * * Get the maximum amount of buffers that can be queued in @appsink. * * Returns: The maximum amount of buffers that can be queued. * * Since: 0.10.22 */ guint gst_app_sink_get_max_buffers (GstAppSink * appsink) { guint result; g_return_val_if_fail (GST_IS_APP_SINK (appsink), 0); g_mutex_lock (appsink->priv->mutex); result = appsink->priv->max_buffers; g_mutex_unlock (appsink->priv->mutex); return result; }
/** * gst_app_sink_set_max_buffers: * @appsink: a #GstAppSink * @max: the maximum number of buffers to queue * * Set the maximum amount of buffers that can be queued in @appsink. After this * amount of buffers are queued in appsink, any more buffers will block upstream * elements until a buffer is pulled from @appsink. * * Since: 0.10.22 */ void gst_app_sink_set_max_buffers (GstAppSink * appsink, guint max) { g_return_if_fail (GST_IS_APP_SINK (appsink)); g_mutex_lock (appsink->priv->mutex); if (max != appsink->priv->max_buffers) { appsink->priv->max_buffers = max; /* signal the change */ g_cond_signal (appsink->priv->cond); } g_mutex_unlock (appsink->priv->mutex); }
/** * gst_app_sink_get_emit_signals: * @appsink: a #GstAppSink * * Check if appsink will emit the "new-preroll" and "new-buffer" signals. * * Returns: %TRUE if @appsink is emiting the "new-preroll" and "new-buffer" * signals. * * Since: 0.10.22 */ EXPORT_C gboolean gst_app_sink_get_emit_signals (GstAppSink * appsink) { gboolean result; g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE); g_mutex_lock (appsink->priv->mutex); result = appsink->priv->emit_signals; g_mutex_unlock (appsink->priv->mutex); return result; }
/** * gst_app_sink_pull_preroll: * @appsink: a #GstAppSink * * Get the last preroll sample in @appsink. This was the sample that caused the * appsink to preroll in the PAUSED state. This sample can be pulled many times * and remains available to the application even after EOS. * * This function is typically used when dealing with a pipeline in the PAUSED * state. Calling this function after doing a seek will give the sample right * after the seek position. * * Note that the preroll sample will also be returned as the first sample * when calling gst_app_sink_pull_sample(). * * If an EOS event was received before any buffers, this function returns * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. * * This function blocks until a preroll sample or EOS is received or the appsink * element is set to the READY/NULL state. * * Returns: (transfer full): a #GstSample or NULL when the appsink is stopped or EOS. * Call gst_sample_unref() after usage. */ GstSample * gst_app_sink_pull_preroll (GstAppSink * appsink) { GstSample *sample = NULL; GstAppSinkPrivate *priv; g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL); 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->preroll != NULL) break; if (priv->is_eos) goto eos; /* nothing to return, wait */ GST_DEBUG_OBJECT (appsink, "waiting for the preroll buffer"); g_cond_wait (&priv->cond, &priv->mutex); } sample = gst_sample_new (priv->preroll, priv->preroll_caps, &priv->preroll_segment, NULL); GST_DEBUG_OBJECT (appsink, "we have the preroll sample %p", sample); g_mutex_unlock (&priv->mutex); return sample; /* special conditions */ 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; } }
/** * gst_app_sink_get_caps: * @appsink: a #GstAppSink * * Get the configured caps on @appsink. * * Returns: the #GstCaps accepted by the sink. gst_caps_unref() after usage. * * Since: 0.10.22 */ GstCaps * gst_app_sink_get_caps (GstAppSink * appsink) { GstCaps *caps; g_return_val_if_fail (appsink != NULL, NULL); g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL); GST_OBJECT_LOCK (appsink); if ((caps = appsink->priv->caps)) gst_caps_ref (caps); GST_DEBUG_OBJECT (appsink, "getting caps of %" GST_PTR_FORMAT, caps); GST_OBJECT_UNLOCK (appsink); return caps; }
/** * gst_app_sink_get_wait_on_eos: * @appsink: a #GstAppSink * * Check if @appsink will wait for all buffers to be consumed when an EOS is * received. * * Returns: %TRUE if @appsink will wait for all buffers to be consumed when an * EOS is received. */ gboolean gst_app_sink_get_wait_on_eos (GstAppSink * appsink) { gboolean result; GstAppSinkPrivate *priv; g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE); priv = appsink->priv; g_mutex_lock (&priv->mutex); result = priv->wait_on_eos; g_mutex_unlock (&priv->mutex); return result; }
/** * gst_app_sink_pull_buffer: * @appsink: a #GstAppSink * * This function blocks until a buffer or EOS becomes available or the appsink * element is set to the READY/NULL state. * * This function will only return buffers when the appsink is in the PLAYING * state. All rendered buffers will be put in a queue so that the application * can pull buffers at its own rate. Note that when the application does not * pull buffers 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, this function returns * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. * * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS. */ GstBuffer * gst_app_sink_pull_buffer (GstAppSink * appsink) { GstBuffer *buf = NULL; //printf("pull_buffer\n"); g_return_val_if_fail (appsink != NULL, NULL); g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL); g_mutex_lock (appsink->mutex); while (TRUE) { GST_DEBUG_OBJECT (appsink, "trying to grab a buffer"); if (!appsink->started) goto not_started; if (!g_queue_is_empty (appsink->queue)) break; if (appsink->is_eos) goto eos; /* nothing to return, wait */ GST_DEBUG_OBJECT (appsink, "waiting for a buffer"); g_cond_wait (appsink->cond, appsink->mutex); } buf = (GstBuffer*)g_queue_pop_head (appsink->queue); GST_DEBUG_OBJECT (appsink, "we have a buffer %p", buf); g_mutex_unlock (appsink->mutex); return buf; /* special conditions */ eos: { GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL"); g_mutex_unlock (appsink->mutex); return NULL; } not_started: { GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL"); g_mutex_unlock (appsink->mutex); return NULL; } }
static GstMiniObject * gst_app_sink_pull_object (GstAppSink * appsink) { GstMiniObject *obj = NULL; g_return_val_if_fail (appsink != NULL, NULL); g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL); g_mutex_lock (appsink->priv->mutex); while (TRUE) { GST_DEBUG_OBJECT (appsink, "trying to grab a buffer/list"); if (!appsink->priv->started) goto not_started; if (!g_queue_is_empty (appsink->priv->queue)) break; if (appsink->priv->is_eos) goto eos; /* nothing to return, wait */ GST_DEBUG_OBJECT (appsink, "waiting for a buffer/list"); g_cond_wait (appsink->priv->cond, appsink->priv->mutex); } obj = g_queue_pop_head (appsink->priv->queue); GST_DEBUG_OBJECT (appsink, "we have a buffer/list %p", obj); g_cond_signal (appsink->priv->cond); g_mutex_unlock (appsink->priv->mutex); return obj; /* special conditions */ eos: { GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL"); g_mutex_unlock (appsink->priv->mutex); return NULL; } not_started: { GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL"); g_mutex_unlock (appsink->priv->mutex); return NULL; } }
/** * gst_app_sink_set_wait_on_eos: * @appsink: a #GstAppSink * @wait: the new state * * Instruct @appsink to wait for all buffers to be consumed when an EOS is received. * */ void gst_app_sink_set_wait_on_eos (GstAppSink * appsink, gboolean wait) { GstAppSinkPrivate *priv; g_return_if_fail (GST_IS_APP_SINK (appsink)); priv = appsink->priv; g_mutex_lock (&priv->mutex); if (priv->wait_on_eos != wait) { priv->wait_on_eos = wait; /* signal the change */ g_cond_signal (&priv->cond); } g_mutex_unlock (&priv->mutex); }
/** * gst_app_sink_pull_preroll: * @appsink: a #GstAppSink * * Get the last preroll buffer in @appsink. This was the buffer that caused the * appsink to preroll in the PAUSED state. This buffer can be pulled many times * and remains available to the application even after EOS. * * This function is typically used when dealing with a pipeline in the PAUSED * state. Calling this function after doing a seek will give the buffer right * after the seek position. * * Note that the preroll buffer will also be returned as the first buffer * when calling gst_app_sink_pull_buffer(). * * If an EOS event was received before any buffers, this function returns * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. * * This function blocks until a preroll buffer or EOS is received or the appsink * element is set to the READY/NULL state. * * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS. * * Since: 0.10.22 */ GstBuffer * gst_app_sink_pull_preroll (GstAppSink * appsink) { GstBuffer *buf = NULL; g_return_val_if_fail (appsink != NULL, NULL); g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL); g_mutex_lock (appsink->priv->mutex); while (TRUE) { GST_DEBUG_OBJECT (appsink, "trying to grab a buffer"); if (!appsink->priv->started) goto not_started; if (appsink->priv->preroll != NULL) break; if (appsink->priv->is_eos) goto eos; /* nothing to return, wait */ GST_DEBUG_OBJECT (appsink, "waiting for the preroll buffer"); g_cond_wait (appsink->priv->cond, appsink->priv->mutex); } buf = gst_buffer_ref (appsink->priv->preroll); GST_DEBUG_OBJECT (appsink, "we have the preroll buffer %p", buf); g_mutex_unlock (appsink->priv->mutex); return buf; /* special conditions */ eos: { GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL"); g_mutex_unlock (appsink->priv->mutex); return NULL; } not_started: { GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL"); g_mutex_unlock (appsink->priv->mutex); return NULL; } }
/** * gst_app_sink_set_caps: * @appsink: a #GstAppSink * @caps: caps to set * * Set the capabilities on the appsink element. This function takes * a copy of the caps structure. After calling this method, the sink will only * accept caps that match @caps. If @caps is non-fixed, you must check the caps * on the buffers to get the actual used caps. */ void gst_app_sink_set_caps (GstAppSink * appsink, const GstCaps * caps) { GstCaps *old; g_return_if_fail (appsink != NULL); g_return_if_fail (GST_IS_APP_SINK (appsink)); GST_OBJECT_LOCK (appsink); GST_DEBUG_OBJECT (appsink, "setting caps to %" GST_PTR_FORMAT, caps); old = appsink->caps; if (caps) appsink->caps = gst_caps_copy (caps); else appsink->caps = NULL; if (old) gst_caps_unref (old); GST_OBJECT_UNLOCK (appsink); }
/** * gst_app_sink_set_caps: * @appsink: a #GstAppSink * @caps: caps to set * * Set the capabilities on the appsink element. This function takes * a copy of the caps structure. After calling this method, the sink will only * accept caps that match @caps. If @caps is non-fixed, or incomplete, * you must check the caps on the samples to get the actual used caps. */ void gst_app_sink_set_caps (GstAppSink * appsink, const GstCaps * caps) { GstCaps *old; GstAppSinkPrivate *priv; g_return_if_fail (GST_IS_APP_SINK (appsink)); priv = appsink->priv; GST_OBJECT_LOCK (appsink); GST_DEBUG_OBJECT (appsink, "setting caps to %" GST_PTR_FORMAT, caps); if ((old = priv->caps) != caps) { if (caps) priv->caps = gst_caps_copy (caps); else priv->caps = NULL; if (old) gst_caps_unref (old); } GST_OBJECT_UNLOCK (appsink); }