mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
appsink: add max-time and max-buffers properties
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5321>
This commit is contained in:
parent
4c13ccec16
commit
60591960c3
5 changed files with 426 additions and 65 deletions
|
@ -79,8 +79,8 @@ 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
|
Appsink will internally use a queue to collect buffers from the streaming
|
||||||
thread. If the application is not pulling samples fast enough, this queue
|
thread. If the application is not pulling samples fast enough, this queue
|
||||||
will consume a lot of memory over time. The "max-buffers" property can be
|
will consume a lot of memory over time. The "max-buffers", "max-time" and "max-bytes"
|
||||||
used to limit the queue size. The "drop" property controls whether the
|
properties can be used to limit the queue size. The "drop" property controls whether the
|
||||||
streaming thread blocks or if older buffers are dropped when the maximum
|
streaming thread blocks or if older buffers are dropped when the maximum
|
||||||
queue size is reached. Note that blocking the streaming thread can negatively
|
queue size is reached. Note that blocking the streaming thread can negatively
|
||||||
affect real-time performance and should be avoided.
|
affect real-time performance and should be avoided.
|
||||||
|
@ -325,7 +325,7 @@ condition.</doc>
|
||||||
</method>
|
</method>
|
||||||
<method name="get_drop" c:identifier="gst_app_sink_get_drop">
|
<method name="get_drop" c:identifier="gst_app_sink_get_drop">
|
||||||
<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
|
<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
|
||||||
buffers is reached.</doc>
|
data is reached (meaning max buffers, time or bytes limit, whichever is hit first).</doc>
|
||||||
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
|
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
|
||||||
<return-value transfer-ownership="none">
|
<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
|
<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
|
||||||
|
@ -368,6 +368,34 @@ signals.</doc>
|
||||||
</instance-parameter>
|
</instance-parameter>
|
||||||
</parameters>
|
</parameters>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="get_max_bytes" c:identifier="gst_app_sink_get_max_bytes" version="1.24">
|
||||||
|
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Get the maximum total size, in bytes, that can be queued in @appsink.</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 maximum amount of bytes that can be queued</doc>
|
||||||
|
<type name="guint64" c:type="guint64"/>
|
||||||
|
</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_time" c:identifier="gst_app_sink_get_max_time" version="1.24">
|
||||||
|
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Get the maximum total duration that can be queued in @appsink.</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 maximum total duration that can be queued.</doc>
|
||||||
|
<type name="Gst.ClockTime" c:type="GstClockTime"/>
|
||||||
|
</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_wait_on_eos" c:identifier="gst_app_sink_get_wait_on_eos">
|
<method name="get_wait_on_eos" c:identifier="gst_app_sink_get_wait_on_eos">
|
||||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Check if @appsink will wait for all buffers to be consumed when an EOS is
|
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Check if @appsink will wait for all buffers to be consumed when an EOS is
|
||||||
received.</doc>
|
received.</doc>
|
||||||
|
@ -567,7 +595,7 @@ you must check the caps on the samples to get the actual used caps.</doc>
|
||||||
</method>
|
</method>
|
||||||
<method name="set_drop" c:identifier="gst_app_sink_set_drop">
|
<method name="set_drop" c:identifier="gst_app_sink_set_drop">
|
||||||
<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
|
<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
|
||||||
buffers is reached.</doc>
|
data is reached, that is, when any configured limit is hit (max-buffers, max-time or max-bytes).</doc>
|
||||||
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
|
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
|
||||||
<return-value transfer-ownership="none">
|
<return-value transfer-ownership="none">
|
||||||
<type name="none" c:type="void"/>
|
<type name="none" c:type="void"/>
|
||||||
|
@ -605,7 +633,8 @@ the application prefers to operate in pull mode.</doc>
|
||||||
<method name="set_max_buffers" c:identifier="gst_app_sink_set_max_buffers">
|
<method name="set_max_buffers" c:identifier="gst_app_sink_set_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
|
<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
|
amount of buffers are queued in appsink, any more buffers will block upstream
|
||||||
elements until a sample is pulled from @appsink.</doc>
|
elements until a sample is pulled from @appsink, unless 'drop' is set, in which
|
||||||
|
case new buffers will be discarded.</doc>
|
||||||
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
|
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
|
||||||
<return-value transfer-ownership="none">
|
<return-value transfer-ownership="none">
|
||||||
<type name="none" c:type="void"/>
|
<type name="none" c:type="void"/>
|
||||||
|
@ -621,6 +650,46 @@ elements until a sample is pulled from @appsink.</doc>
|
||||||
</parameter>
|
</parameter>
|
||||||
</parameters>
|
</parameters>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="set_max_bytes" c:identifier="gst_app_sink_set_max_bytes" version="1.24">
|
||||||
|
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Set the maximum total size that can be queued in @appsink. After this
|
||||||
|
amount of buffers are queued in appsink, any more buffers will block upstream
|
||||||
|
elements until a sample is pulled from @appsink, unless 'drop' is set, in which
|
||||||
|
case new buffers will be discarded.</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="max" transfer-ownership="none">
|
||||||
|
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">the maximum total size of buffers to queue, in bytes</doc>
|
||||||
|
<type name="guint64" c:type="guint64"/>
|
||||||
|
</parameter>
|
||||||
|
</parameters>
|
||||||
|
</method>
|
||||||
|
<method name="set_max_time" c:identifier="gst_app_sink_set_max_time" version="1.24">
|
||||||
|
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Set the maximum total duration that can be queued in @appsink. After this
|
||||||
|
amount of buffers are queued in appsink, any more buffers will block upstream
|
||||||
|
elements until a sample is pulled from @appsink, unless 'drop' is set, in which
|
||||||
|
case new buffers will be discarded.</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="max" transfer-ownership="none">
|
||||||
|
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">the maximum total duration to queue</doc>
|
||||||
|
<type name="Gst.ClockTime" c:type="GstClockTime"/>
|
||||||
|
</parameter>
|
||||||
|
</parameters>
|
||||||
|
</method>
|
||||||
<method name="set_wait_on_eos" c:identifier="gst_app_sink_set_wait_on_eos">
|
<method name="set_wait_on_eos" c:identifier="gst_app_sink_set_wait_on_eos">
|
||||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Instruct @appsink to wait for all buffers to be consumed when an EOS is received.</doc>
|
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Instruct @appsink to wait for all buffers to be consumed when an EOS is received.</doc>
|
||||||
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
|
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.h"/>
|
||||||
|
@ -758,9 +827,22 @@ condition.</doc>
|
||||||
<type name="gboolean" c:type="gboolean"/>
|
<type name="gboolean" c:type="gboolean"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="max-buffers" writable="1" transfer-ownership="none">
|
<property name="max-buffers" writable="1" transfer-ownership="none">
|
||||||
|
<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"/>
|
<type name="guint" c:type="guint"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="wait-on-eos" writable="1" transfer-ownership="none">
|
<property name="max-bytes" version="1.24" writable="1" transfer-ownership="none">
|
||||||
|
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Maximum amount of bytes in the queue (0 = unlimited)</doc>
|
||||||
|
<type name="guint64" c:type="guint64"/>
|
||||||
|
</property>
|
||||||
|
<property name="max-time" version="1.24" writable="1" transfer-ownership="none">
|
||||||
|
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Maximum total duration of data in the queue (0 = unlimited)</doc>
|
||||||
|
<type name="guint64" c:type="guint64"/>
|
||||||
|
</property>
|
||||||
|
<property name="wait-on-eos" version="1.8" writable="1" transfer-ownership="none">
|
||||||
|
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c">Wait for all buffers to be processed after receiving an EOS.
|
||||||
|
|
||||||
|
In cases where it is uncertain if an @appsink will have a consumer for its buffers
|
||||||
|
when it receives an EOS, set to %FALSE to ensure that the @appsink will not hang.</doc>
|
||||||
<type name="gboolean" c:type="gboolean"/>
|
<type name="gboolean" c:type="gboolean"/>
|
||||||
</property>
|
</property>
|
||||||
<field name="basesink">
|
<field name="basesink">
|
||||||
|
@ -885,7 +967,7 @@ can pull samples at its own rate.
|
||||||
Note that when the application does not pull samples fast enough, the
|
Note that when the application does not pull samples fast enough, the
|
||||||
queued samples could consume a lot of memory, especially when dealing with
|
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
|
raw video frames. It's possible to control the behaviour of the queue with
|
||||||
the "drop" and "max-buffers" properties.
|
the "drop" and "max-buffers" / "max-bytes" / "max-time" set of properties.
|
||||||
|
|
||||||
If an EOS event was received before any buffers, this function returns
|
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>
|
%NULL. Use gst_app_sink_is_eos () to check for the EOS condition.</doc>
|
||||||
|
@ -906,7 +988,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
|
Note that when the application does not pull samples fast enough, the
|
||||||
queued samples could consume a lot of memory, especially when dealing with
|
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
|
raw video frames. It's possible to control the behaviour of the queue with
|
||||||
the "drop" and "max-buffers" properties.
|
the "drop" and "max-buffers" / "max-bytes" / "max-time" set of properties.
|
||||||
|
|
||||||
This function will only pull serialized events, excluding
|
This function will only pull serialized events, excluding
|
||||||
the EOS event for which this functions returns
|
the EOS event for which this functions returns
|
||||||
|
@ -971,7 +1053,7 @@ can pull samples at its own rate.
|
||||||
Note that when the application does not pull samples fast enough, the
|
Note that when the application does not pull samples fast enough, the
|
||||||
queued samples could consume a lot of memory, especially when dealing with
|
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
|
raw video frames. It's possible to control the behaviour of the queue with
|
||||||
the "drop" and "max-buffers" properties.
|
the "drop" and "max-buffers" / "max-bytes" / "max-time" set of properties.
|
||||||
|
|
||||||
If an EOS event was received before any buffers or the timeout expires,
|
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
|
this function returns %NULL. Use gst_app_sink_is_eos () to check
|
||||||
|
|
|
@ -339,6 +339,34 @@
|
||||||
"type": "guint",
|
"type": "guint",
|
||||||
"writable": true
|
"writable": true
|
||||||
},
|
},
|
||||||
|
"max-bytes": {
|
||||||
|
"blurb": "The maximum amount of bytes to queue internally (0 = unlimited)",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "0",
|
||||||
|
"max": "18446744073709551615",
|
||||||
|
"min": "0",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint64",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
"max-time": {
|
||||||
|
"blurb": "The maximum total duration to queue internally (in ns, 0 = unlimited)",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "0",
|
||||||
|
"max": "18446744073709551615",
|
||||||
|
"min": "0",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "guint64",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
"wait-on-eos": {
|
"wait-on-eos": {
|
||||||
"blurb": "Wait for all buffers to be processed after receiving an EOS",
|
"blurb": "Wait for all buffers to be processed after receiving an EOS",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
|
|
@ -40,8 +40,8 @@
|
||||||
*
|
*
|
||||||
* Appsink will internally use a queue to collect buffers from the streaming
|
* Appsink will internally use a queue to collect buffers from the streaming
|
||||||
* thread. If the application is not pulling samples fast enough, this queue
|
* thread. If the application is not pulling samples fast enough, this queue
|
||||||
* will consume a lot of memory over time. The "max-buffers" property can be
|
* will consume a lot of memory over time. The "max-buffers", "max-time" and "max-bytes"
|
||||||
* used to limit the queue size. The "drop" property controls whether the
|
* properties can be used to limit the queue size. The "drop" property controls whether the
|
||||||
* streaming thread blocks or if older buffers are dropped when the maximum
|
* streaming thread blocks or if older buffers are dropped when the maximum
|
||||||
* queue size is reached. Note that blocking the streaming thread can negatively
|
* queue size is reached. Note that blocking the streaming thread can negatively
|
||||||
* affect real-time performance and should be avoided.
|
* affect real-time performance and should be avoided.
|
||||||
|
@ -72,6 +72,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "gstappsink.h"
|
#include "gstappsink.h"
|
||||||
|
#include "gstapputils.h"
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -112,12 +113,13 @@ struct _GstAppSinkPrivate
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
gboolean emit_signals;
|
gboolean emit_signals;
|
||||||
guint num_buffers;
|
guint64 max_buffers;
|
||||||
guint num_events;
|
GstClockTime max_time;
|
||||||
guint max_buffers;
|
guint64 max_bytes;
|
||||||
gboolean drop;
|
gboolean drop;
|
||||||
gboolean wait_on_eos;
|
gboolean wait_on_eos;
|
||||||
GstAppSinkWaitStatus wait_status;
|
GstAppSinkWaitStatus wait_status;
|
||||||
|
GstQueueStatusInfo queue_status_info;
|
||||||
|
|
||||||
GCond cond;
|
GCond cond;
|
||||||
GMutex mutex;
|
GMutex mutex;
|
||||||
|
@ -163,6 +165,8 @@ enum
|
||||||
#define DEFAULT_PROP_EOS TRUE
|
#define DEFAULT_PROP_EOS TRUE
|
||||||
#define DEFAULT_PROP_EMIT_SIGNALS FALSE
|
#define DEFAULT_PROP_EMIT_SIGNALS FALSE
|
||||||
#define DEFAULT_PROP_MAX_BUFFERS 0
|
#define DEFAULT_PROP_MAX_BUFFERS 0
|
||||||
|
#define DEFAULT_PROP_MAX_TIME 0
|
||||||
|
#define DEFAULT_PROP_MAX_BYTES 0
|
||||||
#define DEFAULT_PROP_DROP FALSE
|
#define DEFAULT_PROP_DROP FALSE
|
||||||
#define DEFAULT_PROP_WAIT_ON_EOS TRUE
|
#define DEFAULT_PROP_WAIT_ON_EOS TRUE
|
||||||
#define DEFAULT_PROP_BUFFER_LIST FALSE
|
#define DEFAULT_PROP_BUFFER_LIST FALSE
|
||||||
|
@ -177,6 +181,8 @@ enum
|
||||||
PROP_DROP,
|
PROP_DROP,
|
||||||
PROP_WAIT_ON_EOS,
|
PROP_WAIT_ON_EOS,
|
||||||
PROP_BUFFER_LIST,
|
PROP_BUFFER_LIST,
|
||||||
|
PROP_MAX_TIME,
|
||||||
|
PROP_MAX_BYTES,
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -255,12 +261,43 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
|
||||||
DEFAULT_PROP_EMIT_SIGNALS,
|
DEFAULT_PROP_EMIT_SIGNALS,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAppSink:max-buffers:
|
||||||
|
*
|
||||||
|
* Maximum amount of buffers in the queue (0 = unlimited).
|
||||||
|
*/
|
||||||
g_object_class_install_property (gobject_class, PROP_MAX_BUFFERS,
|
g_object_class_install_property (gobject_class, PROP_MAX_BUFFERS,
|
||||||
g_param_spec_uint ("max-buffers", "Max Buffers",
|
g_param_spec_uint ("max-buffers", "Max Buffers",
|
||||||
"The maximum number of buffers to queue internally (0 = unlimited)",
|
"The maximum number of buffers to queue internally (0 = unlimited)",
|
||||||
0, G_MAXUINT, DEFAULT_PROP_MAX_BUFFERS,
|
0, G_MAXUINT, DEFAULT_PROP_MAX_BUFFERS,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAppSink:max-time:
|
||||||
|
*
|
||||||
|
* Maximum total duration of data in the queue (0 = unlimited)
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_MAX_TIME,
|
||||||
|
g_param_spec_uint64 ("max-time", "Max time",
|
||||||
|
"The maximum total duration to queue internally (in ns, 0 = unlimited)",
|
||||||
|
0, G_MAXUINT64, DEFAULT_PROP_MAX_TIME,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAppSink:max-bytes:
|
||||||
|
*
|
||||||
|
* Maximum amount of bytes in the queue (0 = unlimited)
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_MAX_BYTES,
|
||||||
|
g_param_spec_uint64 ("max-bytes", "Max bytes",
|
||||||
|
"The maximum amount of bytes to queue internally (0 = unlimited)",
|
||||||
|
0, G_MAXUINT64, DEFAULT_PROP_MAX_BYTES,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_DROP,
|
g_object_class_install_property (gobject_class, PROP_DROP,
|
||||||
g_param_spec_boolean ("drop", "Drop",
|
g_param_spec_boolean ("drop", "Drop",
|
||||||
"Drop old buffers when the buffer queue is filled", DEFAULT_PROP_DROP,
|
"Drop old buffers when the buffer queue is filled", DEFAULT_PROP_DROP,
|
||||||
|
@ -270,8 +307,9 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
|
||||||
g_param_spec_boolean ("buffer-list", "Buffer List",
|
g_param_spec_boolean ("buffer-list", "Buffer List",
|
||||||
"Use buffer lists", DEFAULT_PROP_BUFFER_LIST,
|
"Use buffer lists", DEFAULT_PROP_BUFFER_LIST,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstAppSink::wait-on-eos:
|
* GstAppSink:wait-on-eos:
|
||||||
*
|
*
|
||||||
* Wait for all buffers to be processed after receiving an EOS.
|
* Wait for all buffers to be processed after receiving an EOS.
|
||||||
*
|
*
|
||||||
|
@ -425,7 +463,7 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
|
||||||
* Note that when the application does not pull samples fast enough, the
|
* Note that when the application does not pull samples fast enough, the
|
||||||
* queued samples could consume a lot of memory, especially when dealing with
|
* 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
|
* raw video frames. It's possible to control the behaviour of the queue with
|
||||||
* the "drop" and "max-buffers" properties.
|
* the "drop" and "max-buffers" / "max-bytes" / "max-time" set of properties.
|
||||||
*
|
*
|
||||||
* If an EOS event was received before any buffers, this function returns
|
* 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.
|
* %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
|
||||||
|
@ -487,7 +525,7 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
|
||||||
* Note that when the application does not pull samples fast enough, the
|
* Note that when the application does not pull samples fast enough, the
|
||||||
* queued samples could consume a lot of memory, especially when dealing with
|
* 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
|
* raw video frames. It's possible to control the behaviour of the queue with
|
||||||
* the "drop" and "max-buffers" properties.
|
* the "drop" and "max-buffers" / "max-bytes" / "max-time" set of properties.
|
||||||
*
|
*
|
||||||
* If an EOS event was received before any buffers or the timeout expires,
|
* 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
|
* this function returns %NULL. Use gst_app_sink_is_eos () to check
|
||||||
|
@ -519,7 +557,7 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
|
||||||
* Note that when the application does not pull samples fast enough, the
|
* Note that when the application does not pull samples fast enough, the
|
||||||
* queued samples could consume a lot of memory, especially when dealing with
|
* 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
|
* raw video frames. It's possible to control the behaviour of the queue with
|
||||||
* the "drop" and "max-buffers" properties.
|
* the "drop" and "max-buffers" / "max-bytes" / "max-time" set of properties.
|
||||||
*
|
*
|
||||||
* This function will only pull serialized events, excluding
|
* This function will only pull serialized events, excluding
|
||||||
* the EOS event for which this functions returns
|
* the EOS event for which this functions returns
|
||||||
|
@ -582,6 +620,8 @@ gst_app_sink_init (GstAppSink * appsink)
|
||||||
|
|
||||||
priv->emit_signals = DEFAULT_PROP_EMIT_SIGNALS;
|
priv->emit_signals = DEFAULT_PROP_EMIT_SIGNALS;
|
||||||
priv->max_buffers = DEFAULT_PROP_MAX_BUFFERS;
|
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->drop = DEFAULT_PROP_DROP;
|
||||||
priv->wait_on_eos = DEFAULT_PROP_WAIT_ON_EOS;
|
priv->wait_on_eos = DEFAULT_PROP_WAIT_ON_EOS;
|
||||||
priv->buffer_lists_supported = DEFAULT_PROP_BUFFER_LIST;
|
priv->buffer_lists_supported = DEFAULT_PROP_BUFFER_LIST;
|
||||||
|
@ -651,6 +691,12 @@ gst_app_sink_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_MAX_BUFFERS:
|
case PROP_MAX_BUFFERS:
|
||||||
gst_app_sink_set_max_buffers (appsink, g_value_get_uint (value));
|
gst_app_sink_set_max_buffers (appsink, g_value_get_uint (value));
|
||||||
break;
|
break;
|
||||||
|
case PROP_MAX_TIME:
|
||||||
|
gst_app_sink_set_max_time (appsink, g_value_get_uint64 (value));
|
||||||
|
break;
|
||||||
|
case PROP_MAX_BYTES:
|
||||||
|
gst_app_sink_set_max_bytes (appsink, g_value_get_uint64 (value));
|
||||||
|
break;
|
||||||
case PROP_DROP:
|
case PROP_DROP:
|
||||||
gst_app_sink_set_drop (appsink, g_value_get_boolean (value));
|
gst_app_sink_set_drop (appsink, g_value_get_boolean (value));
|
||||||
break;
|
break;
|
||||||
|
@ -693,6 +739,12 @@ gst_app_sink_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_MAX_BUFFERS:
|
case PROP_MAX_BUFFERS:
|
||||||
g_value_set_uint (value, gst_app_sink_get_max_buffers (appsink));
|
g_value_set_uint (value, gst_app_sink_get_max_buffers (appsink));
|
||||||
break;
|
break;
|
||||||
|
case PROP_MAX_TIME:
|
||||||
|
g_value_set_uint64 (value, gst_app_sink_get_max_time (appsink));
|
||||||
|
break;
|
||||||
|
case PROP_MAX_BYTES:
|
||||||
|
g_value_set_uint64 (value, gst_app_sink_get_max_bytes (appsink));
|
||||||
|
break;
|
||||||
case PROP_DROP:
|
case PROP_DROP:
|
||||||
g_value_set_boolean (value, gst_app_sink_get_drop (appsink));
|
g_value_set_boolean (value, gst_app_sink_get_drop (appsink));
|
||||||
break;
|
break;
|
||||||
|
@ -750,8 +802,9 @@ gst_app_sink_flush_unlocked (GstAppSink * appsink)
|
||||||
gst_buffer_replace (&priv->preroll_buffer, NULL);
|
gst_buffer_replace (&priv->preroll_buffer, NULL);
|
||||||
while ((obj = gst_queue_array_pop_head (priv->queue)))
|
while ((obj = gst_queue_array_pop_head (priv->queue)))
|
||||||
gst_mini_object_unref (obj);
|
gst_mini_object_unref (obj);
|
||||||
priv->num_buffers = 0;
|
|
||||||
priv->num_events = 0;
|
gst_queue_status_info_reset (&priv->queue_status_info);
|
||||||
|
|
||||||
gst_caps_replace (&priv->last_caps, NULL);
|
gst_caps_replace (&priv->last_caps, NULL);
|
||||||
g_cond_signal (&priv->cond);
|
g_cond_signal (&priv->cond);
|
||||||
}
|
}
|
||||||
|
@ -814,8 +867,10 @@ gst_app_sink_setcaps (GstBaseSink * sink, GstCaps * caps)
|
||||||
|
|
||||||
g_mutex_lock (&priv->mutex);
|
g_mutex_lock (&priv->mutex);
|
||||||
GST_DEBUG_OBJECT (appsink, "receiving CAPS");
|
GST_DEBUG_OBJECT (appsink, "receiving CAPS");
|
||||||
|
|
||||||
gst_queue_array_push_tail (priv->queue, gst_event_new_caps (caps));
|
gst_queue_array_push_tail (priv->queue, gst_event_new_caps (caps));
|
||||||
priv->num_events++;
|
gst_queue_status_info_push_event (&priv->queue_status_info);
|
||||||
|
|
||||||
if (!priv->preroll_buffer)
|
if (!priv->preroll_buffer)
|
||||||
gst_caps_replace (&priv->preroll_caps, caps);
|
gst_caps_replace (&priv->preroll_caps, caps);
|
||||||
g_mutex_unlock (&priv->mutex);
|
g_mutex_unlock (&priv->mutex);
|
||||||
|
@ -850,11 +905,13 @@ gst_app_sink_event (GstBaseSink * sink, GstEvent * event)
|
||||||
g_mutex_unlock (&priv->mutex);
|
g_mutex_unlock (&priv->mutex);
|
||||||
|
|
||||||
g_mutex_lock (&priv->mutex);
|
g_mutex_lock (&priv->mutex);
|
||||||
/* wait until all buffers are consumed or we're flushing.
|
|
||||||
* Otherwise we might signal EOS before all buffers are
|
/* Wait until all buffers are consumed, or we're flushing.
|
||||||
|
* Otherwise, we might signal EOS before all buffers are
|
||||||
* consumed, which is a bit confusing for the application
|
* consumed, which is a bit confusing for the application
|
||||||
*/
|
*/
|
||||||
while (priv->num_buffers > 0 && !priv->flushing && priv->wait_on_eos) {
|
while (priv->queue_status_info.queued_buffers > 0 && !priv->flushing
|
||||||
|
&& priv->wait_on_eos) {
|
||||||
if (priv->unlock) {
|
if (priv->unlock) {
|
||||||
/* we are asked to unlock, call the wait_preroll method */
|
/* we are asked to unlock, call the wait_preroll method */
|
||||||
g_mutex_unlock (&priv->mutex);
|
g_mutex_unlock (&priv->mutex);
|
||||||
|
@ -920,7 +977,7 @@ gst_app_sink_event (GstBaseSink * sink, GstEvent * event)
|
||||||
callbacks = callbacks_ref (priv->callbacks);
|
callbacks = callbacks_ref (priv->callbacks);
|
||||||
|
|
||||||
gst_queue_array_push_tail (priv->queue, gst_event_ref (event));
|
gst_queue_array_push_tail (priv->queue, gst_event_ref (event));
|
||||||
priv->num_events++;
|
gst_queue_status_info_push_event (&priv->queue_status_info);
|
||||||
|
|
||||||
g_mutex_unlock (&priv->mutex);
|
g_mutex_unlock (&priv->mutex);
|
||||||
|
|
||||||
|
@ -998,12 +1055,9 @@ dequeue_object (GstAppSink * appsink)
|
||||||
|
|
||||||
if (GST_IS_BUFFER (obj) || GST_IS_BUFFER_LIST (obj)) {
|
if (GST_IS_BUFFER (obj) || GST_IS_BUFFER_LIST (obj)) {
|
||||||
GST_DEBUG_OBJECT (appsink, "dequeued buffer/list %p", obj);
|
GST_DEBUG_OBJECT (appsink, "dequeued buffer/list %p", obj);
|
||||||
priv->num_buffers--;
|
|
||||||
} else if (GST_IS_EVENT (obj)) {
|
} else if (GST_IS_EVENT (obj)) {
|
||||||
GstEvent *event = GST_EVENT_CAST (obj);
|
GstEvent *event = GST_EVENT_CAST (obj);
|
||||||
|
|
||||||
priv->num_events--;
|
|
||||||
|
|
||||||
switch (GST_EVENT_TYPE (obj)) {
|
switch (GST_EVENT_TYPE (obj)) {
|
||||||
case GST_EVENT_CAPS:
|
case GST_EVENT_CAPS:
|
||||||
{
|
{
|
||||||
|
@ -1028,6 +1082,10 @@ dequeue_object (GstAppSink * appsink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We don't have last/current segment differentiation in appsink, so pass last_segment twice */
|
||||||
|
gst_queue_status_info_pop (&priv->queue_status_info, obj,
|
||||||
|
&priv->last_segment, &priv->last_segment, GST_OBJECT_CAST (appsink));
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1075,10 +1133,12 @@ restart:
|
||||||
priv->last_caps);
|
priv->last_caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (appsink, "pushing render buffer/list %p on queue (%d)",
|
GST_DEBUG_OBJECT (appsink,
|
||||||
data, priv->num_buffers);
|
"pushing render buffer/list %p on queue (%" G_GUINT64_FORMAT ")", data,
|
||||||
|
priv->queue_status_info.queued_buffers);
|
||||||
|
|
||||||
while (priv->max_buffers > 0 && priv->num_buffers >= priv->max_buffers) {
|
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->drop) {
|
||||||
GstMiniObject *old;
|
GstMiniObject *old;
|
||||||
|
|
||||||
|
@ -1088,8 +1148,13 @@ restart:
|
||||||
gst_mini_object_unref (old);
|
gst_mini_object_unref (old);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (appsink, "waiting for free space, length %d >= %d",
|
GST_DEBUG_OBJECT (appsink,
|
||||||
priv->num_buffers, priv->max_buffers);
|
"waiting for free space: have %" G_GUINT64_FORMAT " buffers (max %"
|
||||||
|
G_GUINT64_FORMAT "), %" G_GUINT64_FORMAT " bytes (max %"
|
||||||
|
G_GUINT64_FORMAT "), %" G_GUINT64_FORMAT " time (max %"
|
||||||
|
G_GUINT64_FORMAT ")", priv->queue_status_info.queued_buffers,
|
||||||
|
priv->max_buffers, priv->queue_status_info.queued_bytes,
|
||||||
|
priv->max_bytes, priv->queue_status_info.queued_time, priv->max_time);
|
||||||
|
|
||||||
if (priv->unlock) {
|
if (priv->unlock) {
|
||||||
/* we are asked to unlock, call the wait_preroll method */
|
/* we are asked to unlock, call the wait_preroll method */
|
||||||
|
@ -1112,7 +1177,8 @@ restart:
|
||||||
}
|
}
|
||||||
/* we need to ref the buffer/list when pushing it in the queue */
|
/* we need to ref the buffer/list when pushing it in the queue */
|
||||||
gst_queue_array_push_tail (priv->queue, gst_mini_object_ref (data));
|
gst_queue_array_push_tail (priv->queue, gst_mini_object_ref (data));
|
||||||
priv->num_buffers++;
|
gst_queue_status_info_push (&priv->queue_status_info, data,
|
||||||
|
&priv->last_segment, GST_OBJECT_CAST (appsink));
|
||||||
|
|
||||||
if ((priv->wait_status & APP_WAITING))
|
if ((priv->wait_status & APP_WAITING))
|
||||||
g_cond_signal (&priv->cond);
|
g_cond_signal (&priv->cond);
|
||||||
|
@ -1215,7 +1281,7 @@ gst_app_sink_query (GstBaseSink * bsink, GstQuery * query)
|
||||||
{
|
{
|
||||||
g_mutex_lock (&priv->mutex);
|
g_mutex_lock (&priv->mutex);
|
||||||
GST_DEBUG_OBJECT (appsink, "waiting buffers to be consumed");
|
GST_DEBUG_OBJECT (appsink, "waiting buffers to be consumed");
|
||||||
while (priv->num_buffers > 0 || priv->preroll_buffer) {
|
while (priv->queue_status_info.queued_buffers > 0 || priv->preroll_buffer) {
|
||||||
if (priv->unlock) {
|
if (priv->unlock) {
|
||||||
/* we are asked to unlock, call the wait_preroll method */
|
/* we are asked to unlock, call the wait_preroll method */
|
||||||
g_mutex_unlock (&priv->mutex);
|
g_mutex_unlock (&priv->mutex);
|
||||||
|
@ -1346,7 +1412,7 @@ gst_app_sink_is_eos (GstAppSink * appsink)
|
||||||
if (!priv->started)
|
if (!priv->started)
|
||||||
goto not_started;
|
goto not_started;
|
||||||
|
|
||||||
if (priv->is_eos && priv->num_buffers == 0) {
|
if (priv->is_eos && priv->queue_status_info.queued_buffers == 0) {
|
||||||
GST_DEBUG_OBJECT (appsink, "we are EOS and the queue is empty");
|
GST_DEBUG_OBJECT (appsink, "we are EOS and the queue is empty");
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1414,6 +1480,41 @@ gst_app_sink_get_emit_signals (GstAppSink * appsink)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GST_APP_SINK_GET_PROPERTY(prop_name) \
|
||||||
|
G_STMT_START { \
|
||||||
|
GstAppSinkPrivate *priv; \
|
||||||
|
guint result; \
|
||||||
|
\
|
||||||
|
g_return_val_if_fail (GST_IS_APP_SINK (appsink), 0); \
|
||||||
|
\
|
||||||
|
priv = appsink->priv; \
|
||||||
|
\
|
||||||
|
g_mutex_lock (&priv->mutex); \
|
||||||
|
result = priv->prop_name; \
|
||||||
|
g_mutex_unlock (&priv->mutex); \
|
||||||
|
\
|
||||||
|
return result; \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define GST_APP_SINK_SET_PROPERTY(prop_name, value) \
|
||||||
|
G_STMT_START { \
|
||||||
|
GstAppSinkPrivate *priv; \
|
||||||
|
\
|
||||||
|
g_return_if_fail (GST_IS_APP_SINK (appsink)); \
|
||||||
|
\
|
||||||
|
priv = appsink->priv; \
|
||||||
|
\
|
||||||
|
g_mutex_lock (&priv->mutex); \
|
||||||
|
\
|
||||||
|
if (value != priv->prop_name) { \
|
||||||
|
priv->prop_name = value; \
|
||||||
|
/* signal the change */ \
|
||||||
|
g_cond_signal (&priv->cond); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
g_mutex_unlock (&priv->mutex); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_app_sink_set_max_buffers:
|
* gst_app_sink_set_max_buffers:
|
||||||
* @appsink: a #GstAppSink
|
* @appsink: a #GstAppSink
|
||||||
|
@ -1421,24 +1522,49 @@ gst_app_sink_get_emit_signals (GstAppSink * appsink)
|
||||||
*
|
*
|
||||||
* Set the maximum amount of buffers that can be queued in @appsink. After this
|
* 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
|
* amount of buffers are queued in appsink, any more buffers will block upstream
|
||||||
* elements until a sample is pulled from @appsink.
|
* elements until a sample is pulled from @appsink, unless 'drop' is set, in which
|
||||||
|
* case new buffers will be discarded.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_app_sink_set_max_buffers (GstAppSink * appsink, guint max)
|
gst_app_sink_set_max_buffers (GstAppSink * appsink, guint max)
|
||||||
{
|
{
|
||||||
GstAppSinkPrivate *priv;
|
GST_APP_SINK_SET_PROPERTY (max_buffers, max);
|
||||||
|
}
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_APP_SINK (appsink));
|
/**
|
||||||
|
* gst_app_sink_set_max_time:
|
||||||
|
* @appsink: a #GstAppSink
|
||||||
|
* @max: the maximum total duration to queue
|
||||||
|
*
|
||||||
|
* Set the maximum total duration that can be queued in @appsink. After this
|
||||||
|
* amount of buffers are queued in appsink, any more buffers will block upstream
|
||||||
|
* elements until a sample is pulled from @appsink, unless 'drop' is set, in which
|
||||||
|
* case new buffers will be discarded.
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_app_sink_set_max_time (GstAppSink * appsink, GstClockTime max)
|
||||||
|
{
|
||||||
|
GST_APP_SINK_SET_PROPERTY (max_time, max);
|
||||||
|
}
|
||||||
|
|
||||||
priv = appsink->priv;
|
/**
|
||||||
|
* gst_app_sink_set_max_bytes:
|
||||||
g_mutex_lock (&priv->mutex);
|
* @appsink: a #GstAppSink
|
||||||
if (max != priv->max_buffers) {
|
* @max: the maximum total size of buffers to queue, in bytes
|
||||||
priv->max_buffers = max;
|
*
|
||||||
/* signal the change */
|
* Set the maximum total size that can be queued in @appsink. After this
|
||||||
g_cond_signal (&priv->cond);
|
* amount of buffers are queued in appsink, any more buffers will block upstream
|
||||||
}
|
* elements until a sample is pulled from @appsink, unless 'drop' is set, in which
|
||||||
g_mutex_unlock (&priv->mutex);
|
* case new buffers will be discarded.
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_app_sink_set_max_bytes (GstAppSink * appsink, guint64 max)
|
||||||
|
{
|
||||||
|
GST_APP_SINK_SET_PROPERTY (max_bytes, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1452,27 +1578,51 @@ gst_app_sink_set_max_buffers (GstAppSink * appsink, guint max)
|
||||||
guint
|
guint
|
||||||
gst_app_sink_get_max_buffers (GstAppSink * appsink)
|
gst_app_sink_get_max_buffers (GstAppSink * appsink)
|
||||||
{
|
{
|
||||||
guint result;
|
GST_APP_SINK_GET_PROPERTY (max_buffers);
|
||||||
GstAppSinkPrivate *priv;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_APP_SINK (appsink), 0);
|
|
||||||
|
|
||||||
priv = appsink->priv;
|
|
||||||
|
|
||||||
g_mutex_lock (&priv->mutex);
|
|
||||||
result = priv->max_buffers;
|
|
||||||
g_mutex_unlock (&priv->mutex);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_app_sink_get_max_time:
|
||||||
|
* @appsink: a #GstAppSink
|
||||||
|
*
|
||||||
|
* Get the maximum total duration that can be queued in @appsink.
|
||||||
|
*
|
||||||
|
* Returns: The maximum total duration that can be queued.
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
GstClockTime
|
||||||
|
gst_app_sink_get_max_time (GstAppSink * appsink)
|
||||||
|
{
|
||||||
|
GST_APP_SINK_GET_PROPERTY (max_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_app_sink_get_max_bytes:
|
||||||
|
* @appsink: a #GstAppSink
|
||||||
|
*
|
||||||
|
* Get the maximum total size, in bytes, that can be queued in @appsink.
|
||||||
|
*
|
||||||
|
* Returns: The maximum amount of bytes that can be queued
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
guint64
|
||||||
|
gst_app_sink_get_max_bytes (GstAppSink * appsink)
|
||||||
|
{
|
||||||
|
GST_APP_SINK_GET_PROPERTY (max_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef GST_APP_SINK_GET_PROPERTY
|
||||||
|
#undef GST_APP_SINK_SET_PROPERTY
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_app_sink_set_drop:
|
* gst_app_sink_set_drop:
|
||||||
* @appsink: a #GstAppSink
|
* @appsink: a #GstAppSink
|
||||||
* @drop: the new state
|
* @drop: the new state
|
||||||
*
|
*
|
||||||
* Instruct @appsink to drop old buffers when the maximum amount of queued
|
* Instruct @appsink to drop old buffers when the maximum amount of queued
|
||||||
* buffers is reached.
|
* data is reached, that is, when any configured limit is hit (max-buffers, max-time or max-bytes).
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_app_sink_set_drop (GstAppSink * appsink, gboolean drop)
|
gst_app_sink_set_drop (GstAppSink * appsink, gboolean drop)
|
||||||
|
@ -1497,7 +1647,7 @@ gst_app_sink_set_drop (GstAppSink * appsink, gboolean drop)
|
||||||
* @appsink: a #GstAppSink
|
* @appsink: a #GstAppSink
|
||||||
*
|
*
|
||||||
* Check if @appsink will drop old buffers when the maximum amount of queued
|
* Check if @appsink will drop old buffers when the maximum amount of queued
|
||||||
* buffers is reached.
|
* data is reached (meaning max buffers, time or bytes limit, whichever is hit first).
|
||||||
*
|
*
|
||||||
* Returns: %TRUE if @appsink is dropping old buffers when the queue is
|
* Returns: %TRUE if @appsink is dropping old buffers when the queue is
|
||||||
* filled.
|
* filled.
|
||||||
|
@ -1920,7 +2070,8 @@ gst_app_sink_try_pull_object (GstAppSink * appsink, GstClockTime timeout)
|
||||||
if (!priv->started)
|
if (!priv->started)
|
||||||
goto not_started;
|
goto not_started;
|
||||||
|
|
||||||
if (priv->num_buffers > 0 || priv->num_events > 0)
|
if (priv->queue_status_info.queued_buffers > 0
|
||||||
|
|| priv->queue_status_info.num_events > 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (priv->is_eos)
|
if (priv->is_eos)
|
||||||
|
|
|
@ -151,6 +151,18 @@ void gst_app_sink_set_max_buffers (GstAppSink *appsink, guint max);
|
||||||
GST_APP_API
|
GST_APP_API
|
||||||
guint gst_app_sink_get_max_buffers (GstAppSink *appsink);
|
guint gst_app_sink_get_max_buffers (GstAppSink *appsink);
|
||||||
|
|
||||||
|
GST_APP_API
|
||||||
|
void gst_app_sink_set_max_time (GstAppSink *appsink, GstClockTime max);
|
||||||
|
|
||||||
|
GST_APP_API
|
||||||
|
GstClockTime gst_app_sink_get_max_time (GstAppSink *appsink);
|
||||||
|
|
||||||
|
GST_APP_API
|
||||||
|
void gst_app_sink_set_max_bytes (GstAppSink *appsink, guint64 max);
|
||||||
|
|
||||||
|
GST_APP_API
|
||||||
|
guint64 gst_app_sink_get_max_bytes (GstAppSink *appsink);
|
||||||
|
|
||||||
GST_APP_API
|
GST_APP_API
|
||||||
void gst_app_sink_set_drop (GstAppSink *appsink, gboolean drop);
|
void gst_app_sink_set_drop (GstAppSink *appsink, gboolean drop);
|
||||||
|
|
||||||
|
@ -198,4 +210,3 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAppSink, gst_object_unref)
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,7 @@ GST_END_TEST;
|
||||||
static const gint values[] = { 1, 2, 4 };
|
static const gint values[] = { 1, 2, 4 };
|
||||||
|
|
||||||
static GstBufferList *
|
static GstBufferList *
|
||||||
create_buffer_list (void)
|
create_buffer_list_with_buffer_duration (GstClockTime duration)
|
||||||
{
|
{
|
||||||
guint len;
|
guint len;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
|
@ -224,9 +224,27 @@ create_buffer_list (void)
|
||||||
gst_buffer_fill (buffer, 0, &values[2], sizeof (gint));
|
gst_buffer_fill (buffer, 0, &values[2], sizeof (gint));
|
||||||
gst_buffer_list_add (mylist, buffer);
|
gst_buffer_list_add (mylist, buffer);
|
||||||
|
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (duration)) {
|
||||||
|
guint i;
|
||||||
|
GstClockTime dts = 0;
|
||||||
|
GstBuffer *current;
|
||||||
|
|
||||||
|
for (i = 0; i < gst_buffer_list_length (mylist); ++i) {
|
||||||
|
current = gst_buffer_list_get (mylist, i);
|
||||||
|
GST_BUFFER_DTS (current) = dts;
|
||||||
|
dts += duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return mylist;
|
return mylist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstBufferList *
|
||||||
|
create_buffer_list (void)
|
||||||
|
{
|
||||||
|
return create_buffer_list_with_buffer_duration (GST_CLOCK_TIME_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
callback_function_sample_fallback (GstAppSink * appsink, gpointer p_counter)
|
callback_function_sample_fallback (GstAppSink * appsink, gpointer p_counter)
|
||||||
{
|
{
|
||||||
|
@ -1155,6 +1173,75 @@ GST_START_TEST (test_query_allocation_signals)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
struct TestBufferingLimitsParams
|
||||||
|
{
|
||||||
|
guint64 max_time;
|
||||||
|
guint max_buffers;
|
||||||
|
guint max_bytes;
|
||||||
|
guint expected_num_samples;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct TestBufferingLimitsParams test_buffering_limit_params[] = {
|
||||||
|
/* no limits */
|
||||||
|
{0, 0, 0, 3},
|
||||||
|
/* exceeded time limit and max-time is not a multiple of buffer duration:
|
||||||
|
* this effectively means the queue will have to pass one additional buffer before blocking/dropping */
|
||||||
|
{50 * GST_MSECOND, 0, 0, 3},
|
||||||
|
/* exceeded buffers limit */
|
||||||
|
{0, 2, 0, 2},
|
||||||
|
/* exceeded bytes limit */
|
||||||
|
{0, 0, 2 * sizeof (guint), 2},
|
||||||
|
/* time and bytes; time is exceeded first */
|
||||||
|
{20 * GST_MSECOND, 0, 2 * sizeof (guint), 1},
|
||||||
|
/* time, buffers and bytes; bytes are exceeded first */
|
||||||
|
{60 * GST_MSECOND, 2, 1 * sizeof (guint), 1},
|
||||||
|
};
|
||||||
|
|
||||||
|
GST_START_TEST (test_buffering_limits)
|
||||||
|
{
|
||||||
|
const gboolean use_lists = __i__ % 2;
|
||||||
|
struct TestBufferingLimitsParams *param =
|
||||||
|
&test_buffering_limit_params[__i__ / 2];
|
||||||
|
GstAppSink *app_sink = GST_APP_SINK (setup_appsink ());
|
||||||
|
guint num_samples = 0;
|
||||||
|
GstSample *queued_sample;
|
||||||
|
GstBufferList *list;
|
||||||
|
gint j;
|
||||||
|
|
||||||
|
ASSERT_SET_STATE (app_sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
|
||||||
|
|
||||||
|
gst_app_sink_set_max_time (app_sink, param->max_time);
|
||||||
|
gst_app_sink_set_max_bytes (app_sink, param->max_bytes);
|
||||||
|
gst_app_sink_set_max_buffers (app_sink, param->max_buffers);
|
||||||
|
gst_app_sink_set_drop (app_sink, TRUE);
|
||||||
|
|
||||||
|
list = create_buffer_list_with_buffer_duration (20 * GST_MSECOND);
|
||||||
|
|
||||||
|
if (use_lists) {
|
||||||
|
gst_buffer_list_ref (list);
|
||||||
|
gst_pad_push_list (mysrcpad, list);
|
||||||
|
} else {
|
||||||
|
for (j = 0; j < gst_buffer_list_length (list); j++) {
|
||||||
|
GstBuffer *buf = gst_buffer_list_get (list, j);
|
||||||
|
gst_buffer_ref (buf);
|
||||||
|
gst_pad_push (mysrcpad, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((queued_sample = gst_app_sink_try_pull_sample (app_sink, 0))) {
|
||||||
|
num_samples++;
|
||||||
|
gst_sample_unref (queued_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
fail_unless_equals_int (num_samples, param->expected_num_samples);
|
||||||
|
|
||||||
|
ASSERT_SET_STATE (app_sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
|
||||||
|
cleanup_appsink (GST_ELEMENT_CAST (app_sink));
|
||||||
|
gst_buffer_list_unref (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
appsink_suite (void)
|
appsink_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -1183,6 +1270,8 @@ appsink_suite (void)
|
||||||
tcase_add_test (tc_chain, test_caps_before_flush_race_condition);
|
tcase_add_test (tc_chain, test_caps_before_flush_race_condition);
|
||||||
tcase_add_test (tc_chain, test_query_allocation_callback);
|
tcase_add_test (tc_chain, test_query_allocation_callback);
|
||||||
tcase_add_test (tc_chain, test_query_allocation_signals);
|
tcase_add_test (tc_chain, test_query_allocation_signals);
|
||||||
|
tcase_add_loop_test (tc_chain, test_buffering_limits, 0,
|
||||||
|
G_N_ELEMENTS (test_buffering_limit_params) * 2);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue