appsink: Add new leaky-type property

For symmetry with appsrc. As part of this, also deprecated the drop property.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8824>
This commit is contained in:
Sebastian Dröge 2025-04-11 15:29:13 +03:00 committed by GStreamer Marge Bot
parent ed75968ff5
commit 3450050b1a
4 changed files with 206 additions and 20 deletions

View File

@ -7,6 +7,20 @@ and/or use gtk-doc annotations. -->
<package name="gstreamer-app-1.0"/>
<c:include name="gst/app/app.h"/>
<namespace name="GstApp" version="1.0" shared-library="libgstapp-1.0.so.0" c:identifier-prefixes="Gst" c:symbol-prefixes="gst">
<function-macro name="APP_DEPRECATED_FOR" c:identifier="GST_APP_DEPRECATED_FOR" introspectable="0">
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/app-prelude.h"/>
<parameters>
<parameter name="f">
</parameter>
</parameters>
</function-macro>
<function-macro name="APP_DEPRECATED_TYPE_FOR" c:identifier="GST_APP_DEPRECATED_TYPE_FOR" introspectable="0">
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/app-prelude.h"/>
<parameters>
<parameter name="f">
</parameter>
</parameters>
</function-macro>
<function-macro name="APP_SINK" c:identifier="GST_APP_SINK" introspectable="0">
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
<parameters>
@ -80,7 +94,7 @@ which accept a timeout parameter to limit the amount of time to wait.
Appsink will internally use a queue to collect buffers from the streaming
thread. If the application is not pulling samples fast enough, this queue
will consume a lot of memory over time. The "max-buffers", "max-time" and "max-bytes"
properties can be used to limit the queue size. The "drop" property controls whether the
properties can be used to limit the queue size. The "leaky-type" property controls whether the
streaming thread blocks or if older buffers are dropped when the maximum
queue size is reached. Note that blocking the streaming thread can negatively
affect real-time performance and should be avoided.
@ -365,9 +379,10 @@ condition.</doc>
</instance-parameter>
</parameters>
</method>
<method name="get_drop" c:identifier="gst_app_sink_get_drop" glib:get-property="drop">
<method name="get_drop" c:identifier="gst_app_sink_get_drop" glib:get-property="drop" deprecated="1" deprecated-version="1.28">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Check if @appsink will drop old buffers when the maximum amount of queued
data is reached (meaning max buffers, time or bytes limit, whichever is hit first).</doc>
<doc-deprecated xml:space="preserve">Use gst_app_src_get_leaky_type() instead.</doc-deprecated>
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">%TRUE if @appsink is dropping old buffers when the queue is
@ -396,6 +411,21 @@ signals.</doc>
</instance-parameter>
</parameters>
</method>
<method name="get_leaky_type" c:identifier="gst_app_sink_get_leaky_type" glib:get-property="leaky-type" version="1.28">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Returns the currently set #GstAppLeakyType. See gst_app_sink_set_leaky_type()
for more details.</doc>
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">The currently set #GstAppLeakyType.</doc>
<type name="AppLeakyType" c:type="GstAppLeakyType"/>
</return-value>
<parameters>
<instance-parameter name="appsink" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">a #GstAppSink</doc>
<type name="AppSink" c:type="GstAppSink*"/>
</instance-parameter>
</parameters>
</method>
<method name="get_max_buffers" c:identifier="gst_app_sink_get_max_buffers" glib:get-property="max-buffers">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Get the maximum amount of buffers that can be queued in @appsink.</doc>
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
@ -635,9 +665,10 @@ you must check the caps on the samples to get the actual used caps.</doc>
</parameter>
</parameters>
</method>
<method name="set_drop" c:identifier="gst_app_sink_set_drop" glib:set-property="drop">
<method name="set_drop" c:identifier="gst_app_sink_set_drop" glib:set-property="drop" deprecated="1" deprecated-version="1.28">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Instruct @appsink to drop old buffers when the maximum amount of queued
data is reached, that is, when any configured limit is hit (max-buffers, max-time or max-bytes).</doc>
<doc-deprecated xml:space="preserve">Use gst_app_src_get_leaky_type() instead.</doc-deprecated>
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
@ -672,6 +703,26 @@ the application prefers to operate in pull mode.</doc>
</parameter>
</parameters>
</method>
<method name="set_leaky_type" c:identifier="gst_app_sink_set_leaky_type" glib:set-property="leaky-type" version="1.28">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">When set to any other value than GST_APP_LEAKY_TYPE_NONE then the appsink
will drop any buffers that are pushed into it once its internal queue is
full. The selected type defines whether to drop the oldest or new
buffers.</doc>
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<instance-parameter name="appsink" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">a #GstAppSink</doc>
<type name="AppSink" c:type="GstAppSink*"/>
</instance-parameter>
<parameter name="leaky" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">the #GstAppLeakyType</doc>
<type name="AppLeakyType" c:type="GstAppLeakyType"/>
</parameter>
</parameters>
</method>
<method name="set_max_buffers" c:identifier="gst_app_sink_set_max_buffers" glib:set-property="max-buffers">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">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
@ -871,7 +922,9 @@ condition.</doc>
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">The amount of currently queued time inside appsink.</doc>
<type name="guint64" c:type="guint64"/>
</property>
<property name="drop" writable="1" transfer-ownership="none" setter="set_drop" getter="get_drop" default-value="FALSE">
<property name="drop" deprecated="1" deprecated-version="1.28" writable="1" transfer-ownership="none" setter="set_drop" getter="get_drop" default-value="FALSE">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Drop old buffers when the buffer queue is filled.</doc>
<doc-deprecated xml:space="preserve">Use "leaky-type" property instead.</doc-deprecated>
<type name="gboolean" c:type="gboolean"/>
</property>
<property name="emit-signals" writable="1" transfer-ownership="none" setter="set_emit_signals" getter="get_emit_signals" default-value="FALSE">
@ -880,6 +933,13 @@ condition.</doc>
<property name="eos" transfer-ownership="none" default-value="TRUE">
<type name="gboolean" c:type="gboolean"/>
</property>
<property name="leaky-type" version="1.28" writable="1" transfer-ownership="none" setter="set_leaky_type" getter="get_leaky_type" default-value="GST_APP_LEAKY_TYPE_NONE">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">When set to any other value than GST_APP_LEAKY_TYPE_NONE then the appsink
will drop any buffers that are pushed into it once its internal queue is
full. The selected type defines whether to drop the oldest or new
buffers.</doc>
<type name="AppLeakyType"/>
</property>
<property name="max-buffers" writable="1" transfer-ownership="none" setter="set_max_buffers" getter="get_max_buffers" default-value="0">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Maximum amount of buffers in the queue (0 = unlimited).</doc>
<type name="guint" c:type="guint"/>
@ -1021,7 +1081,7 @@ can pull samples at its own rate.
Note that when the application does not pull samples fast enough, the
queued samples could consume a lot of memory, especially when dealing with
raw video frames. It's possible to control the behaviour of the queue with
the "drop" and "max-buffers" / "max-bytes" / "max-time" set of properties.
the "leaky-type" and "max-buffers" / "max-bytes" / "max-time" set of properties.
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.</doc>
@ -1042,7 +1102,7 @@ Events can be pulled when the appsink is in the READY, PAUSED or PLAYING state.
Note that when the application does not pull samples fast enough, the
queued samples could consume a lot of memory, especially when dealing with
raw video frames. It's possible to control the behaviour of the queue with
the "drop" and "max-buffers" / "max-bytes" / "max-time" set of properties.
the "leaky-type" and "max-buffers" / "max-bytes" / "max-time" set of properties.
This function will only pull serialized events, excluding
the EOS event for which this functions returns
@ -1107,7 +1167,7 @@ can pull samples at its own rate.
Note that when the application does not pull samples fast enough, the
queued samples could consume a lot of memory, especially when dealing with
raw video frames. It's possible to control the behaviour of the queue with
the "drop" and "max-buffers" / "max-bytes" / "max-time" set of properties.
the "leaky-type" and "max-buffers" / "max-bytes" / "max-time" set of properties.
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

View File

@ -30,4 +30,16 @@
#define GST_APP_API GST_API_IMPORT
#endif
#ifndef GST_DISABLE_DEPRECATED
#define GST_APP_DEPRECATED GST_APP_API
#define GST_APP_DEPRECATED_FOR(f) GST_APP_API
#define GST_APP_DEPRECATED_TYPE
#define GST_APP_DEPRECATED_TYPE_FOR(f)
#else
#define GST_APP_DEPRECATED G_DEPRECATED GST_APP_API
#define GST_APP_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) GST_APP_API
#define GST_APP_DEPRECATED_TYPE G_DEPRECATED
#define GST_APP_DEPRECATED_TYPE_FOR(f) G_DEPRECATED_FOR(f)
#endif
#endif /* __GST_APP_PRELUDE_H__ */

View File

@ -41,7 +41,7 @@
* Appsink will internally use a queue to collect buffers from the streaming
* thread. If the application is not pulling samples fast enough, this queue
* will consume a lot of memory over time. The "max-buffers", "max-time" and "max-bytes"
* properties can be used to limit the queue size. The "drop" property controls whether the
* properties can be used to limit the queue size. The "leaky-type" property controls whether the
* streaming thread blocks or if older buffers are dropped when the maximum
* queue size is reached. Note that blocking the streaming thread can negatively
* affect real-time performance and should be avoided.
@ -71,6 +71,7 @@
#include <string.h>
#include "gstappsrc.h" /* for GstAppLeakyType */
#include "gstappsink.h"
#include "gstapputils.h"
@ -116,10 +117,10 @@ struct _GstAppSinkPrivate
guint64 max_buffers;
GstClockTime max_time;
guint64 max_bytes;
gboolean drop;
gboolean wait_on_eos;
GstAppSinkWaitStatus wait_status;
GstQueueStatusInfo queue_status_info;
GstAppLeakyType leaky_type;
GCond cond;
GMutex mutex;
@ -173,6 +174,7 @@ enum
#define DEFAULT_PROP_CURRENT_LEVEL_BYTES 0
#define DEFAULT_PROP_CURRENT_LEVEL_BUFFERS 0
#define DEFAULT_PROP_CURRENT_LEVEL_TIME 0
#define DEFAULT_PROP_LEAKY_TYPE GST_APP_LEAKY_TYPE_NONE
enum
{
@ -189,6 +191,7 @@ enum
PROP_CURRENT_LEVEL_BYTES,
PROP_CURRENT_LEVEL_BUFFERS,
PROP_CURRENT_LEVEL_TIME,
PROP_LEAKY_TYPE,
PROP_LAST
};
@ -304,10 +307,17 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
0, G_MAXUINT64, DEFAULT_PROP_MAX_BYTES,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstAppSink:drop:
*
* Drop old buffers when the buffer queue is filled.
*
* Deprecated: 1.28: Use "leaky-type" property instead.
*/
g_object_class_install_property (gobject_class, PROP_DROP,
g_param_spec_boolean ("drop", "Drop",
"Drop old buffers when the buffer queue is filled", DEFAULT_PROP_DROP,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
G_PARAM_DEPRECATED | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_BUFFER_LIST,
g_param_spec_boolean ("buffer-list", "Buffer List",
@ -369,6 +379,24 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
0, G_MAXUINT64, DEFAULT_PROP_CURRENT_LEVEL_TIME,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
/**
* GstAppSink:leaky-type:
*
* When set to any other value than GST_APP_LEAKY_TYPE_NONE then the appsink
* will drop any buffers that are pushed into it once its internal queue is
* full. The selected type defines whether to drop the oldest or new
* buffers.
*
* Since: 1.28
*/
g_object_class_install_property (gobject_class, PROP_LEAKY_TYPE,
g_param_spec_enum ("leaky-type", "Leaky Type",
"Whether to drop buffers once the internal queue is full",
GST_TYPE_APP_LEAKY_TYPE,
DEFAULT_PROP_LEAKY_TYPE,
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
G_PARAM_STATIC_STRINGS));
/**
* GstAppSink::eos:
* @appsink: the appsink element that emitted the signal
@ -508,7 +536,7 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
* Note that when the application does not pull samples fast enough, the
* queued samples could consume a lot of memory, especially when dealing with
* raw video frames. It's possible to control the behaviour of the queue with
* the "drop" and "max-buffers" / "max-bytes" / "max-time" set of properties.
* the "leaky-type" and "max-buffers" / "max-bytes" / "max-time" set of properties.
*
* 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.
@ -570,7 +598,7 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
* Note that when the application does not pull samples fast enough, the
* queued samples could consume a lot of memory, especially when dealing with
* raw video frames. It's possible to control the behaviour of the queue with
* the "drop" and "max-buffers" / "max-bytes" / "max-time" set of properties.
* the "leaky-type" and "max-buffers" / "max-bytes" / "max-time" set of properties.
*
* 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
@ -602,7 +630,7 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
* Note that when the application does not pull samples fast enough, the
* queued samples could consume a lot of memory, especially when dealing with
* raw video frames. It's possible to control the behaviour of the queue with
* the "drop" and "max-buffers" / "max-bytes" / "max-time" set of properties.
* the "leaky-type" and "max-buffers" / "max-bytes" / "max-time" set of properties.
*
* This function will only pull serialized events, excluding
* the EOS event for which this functions returns
@ -667,10 +695,10 @@ gst_app_sink_init (GstAppSink * appsink)
priv->max_buffers = DEFAULT_PROP_MAX_BUFFERS;
priv->max_bytes = DEFAULT_PROP_MAX_BYTES;
priv->max_time = DEFAULT_PROP_MAX_TIME;
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;
priv->leaky_type = DEFAULT_PROP_LEAKY_TYPE;
}
static void
@ -752,6 +780,9 @@ gst_app_sink_set_property (GObject * object, guint prop_id,
case PROP_WAIT_ON_EOS:
gst_app_sink_set_wait_on_eos (appsink, g_value_get_boolean (value));
break;
case PROP_LEAKY_TYPE:
gst_app_sink_set_leaky_type (appsink, g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -811,6 +842,9 @@ gst_app_sink_get_property (GObject * object, guint prop_id, GValue * value,
case PROP_CURRENT_LEVEL_TIME:
g_value_set_uint64 (value, gst_app_sink_get_current_level_time (appsink));
break;
case PROP_LEAKY_TYPE:
g_value_set_enum (value, gst_app_sink_get_leaky_type (appsink));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -1195,7 +1229,7 @@ restart:
while (gst_queue_status_info_is_full (&priv->queue_status_info,
priv->max_buffers, priv->max_bytes, priv->max_time)) {
if (priv->drop) {
if (priv->leaky_type == GST_APP_LEAKY_TYPE_DOWNSTREAM) {
GstMiniObject *old;
/* we need to drop the oldest buffer/list and try again */
@ -1203,6 +1237,8 @@ restart:
GST_DEBUG_OBJECT (appsink, "dropping old buffer/list %p", old);
gst_mini_object_unref (old);
}
} else if (priv->leaky_type == GST_APP_LEAKY_TYPE_UPSTREAM) {
goto dropped;
} else {
GST_DEBUG_OBJECT (appsink,
"waiting for free space: have %" G_GUINT64_FORMAT " buffers (max %"
@ -1266,6 +1302,12 @@ stopping:
GST_DEBUG_OBJECT (appsink, "we are stopping");
return ret;
}
dropped:
{
GST_DEBUG_OBJECT (appsink, "dropped new buffer/list %p, we are full", data);
g_mutex_unlock (&priv->mutex);
return ret;
}
}
static GstFlowReturn
@ -1727,19 +1769,24 @@ gst_app_sink_get_current_level_time (GstAppSink * appsink)
*
* Instruct @appsink to drop old buffers when the maximum amount of queued
* data is reached, that is, when any configured limit is hit (max-buffers, max-time or max-bytes).
*
* Deprecated: 1.28: Use gst_app_src_get_leaky_type() instead.
*/
void
gst_app_sink_set_drop (GstAppSink * appsink, gboolean drop)
{
GstAppSinkPrivate *priv;
GstAppLeakyType leaky_type;
g_return_if_fail (GST_IS_APP_SINK (appsink));
priv = appsink->priv;
leaky_type = drop ? GST_APP_LEAKY_TYPE_DOWNSTREAM : GST_APP_LEAKY_TYPE_NONE;
g_mutex_lock (&priv->mutex);
if (priv->drop != drop) {
priv->drop = drop;
if (priv->leaky_type != leaky_type) {
priv->leaky_type = leaky_type;
/* signal the change */
g_cond_signal (&priv->cond);
}
@ -1755,6 +1802,8 @@ gst_app_sink_set_drop (GstAppSink * appsink, gboolean drop)
*
* Returns: %TRUE if @appsink is dropping old buffers when the queue is
* filled.
*
* Deprecated: 1.28: Use gst_app_src_get_leaky_type() instead.
*/
gboolean
gst_app_sink_get_drop (GstAppSink * appsink)
@ -1767,12 +1816,70 @@ gst_app_sink_get_drop (GstAppSink * appsink)
priv = appsink->priv;
g_mutex_lock (&priv->mutex);
result = priv->drop;
result = priv->leaky_type != GST_APP_LEAKY_TYPE_NONE;
g_mutex_unlock (&priv->mutex);
return result;
}
/**
* gst_app_sink_set_leaky_type:
* @appsink: a #GstAppSink
* @leaky: the #GstAppLeakyType
*
* When set to any other value than GST_APP_LEAKY_TYPE_NONE then the appsink
* will drop any buffers that are pushed into it once its internal queue is
* full. The selected type defines whether to drop the oldest or new
* buffers.
*
* Since: 1.28
*/
void
gst_app_sink_set_leaky_type (GstAppSink * appsink, GstAppLeakyType leaky)
{
GstAppSinkPrivate *priv;
g_return_if_fail (GST_IS_APP_SINK (appsink));
priv = appsink->priv;
g_mutex_lock (&priv->mutex);
if (priv->leaky_type != leaky) {
priv->leaky_type = leaky;
/* signal the change */
g_cond_signal (&priv->cond);
}
g_mutex_unlock (&priv->mutex);
}
/**
* gst_app_sink_get_leaky_type:
* @appsink: a #GstAppSink
*
* Returns the currently set #GstAppLeakyType. See gst_app_sink_set_leaky_type()
* for more details.
*
* Returns: The currently set #GstAppLeakyType.
*
* Since: 1.28
*/
GstAppLeakyType
gst_app_sink_get_leaky_type (GstAppSink * appsink)
{
GstAppSinkPrivate *priv;
GstAppLeakyType leaky_type;
g_return_val_if_fail (GST_IS_APP_SINK (appsink), GST_APP_LEAKY_TYPE_NONE);
priv = appsink->priv;
g_mutex_lock (&priv->mutex);
leaky_type = appsink->priv->leaky_type;
g_mutex_unlock (&priv->mutex);
return leaky_type;
}
/**
* gst_app_sink_set_buffer_list_support:
* @appsink: a #GstAppSink

View File

@ -23,6 +23,7 @@
#include <gst/gst.h>
#include <gst/base/gstbasesink.h>
#include <gst/app/app-prelude.h>
#include <gst/app/gstappsrc.h>
G_BEGIN_DECLS
@ -172,12 +173,18 @@ guint64 gst_app_sink_get_current_level_buffers (GstAppSink * appsink);
GST_APP_API
GstClockTime gst_app_sink_get_current_level_time (GstAppSink * appsink);
GST_APP_API
GST_APP_DEPRECATED_FOR(gst_app_sink_set_leaky_type)
void gst_app_sink_set_drop (GstAppSink *appsink, gboolean drop);
GST_APP_API
GST_APP_DEPRECATED_FOR(gst_app_sink_get_leaky_type)
gboolean gst_app_sink_get_drop (GstAppSink *appsink);
GST_APP_API
void gst_app_sink_set_leaky_type (GstAppSink * appsink, GstAppLeakyType leaky);
GST_APP_API
GstAppLeakyType gst_app_sink_get_leaky_type (GstAppSink * appsink);
GST_APP_API
void gst_app_sink_set_buffer_list_support (GstAppSink *appsink, gboolean enable_lists);