mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 00:06:36 +00:00
rtsp-server: Add new ensure-keyunit-on-start property
While the suspend modes NONE and PAUSED provided a low startup latency for connecting clients they did not ensure that streams started on fresh data. With this property we can maintain the low startup latency of those suspend modes while also ensuring that a stream starts on a key unit. Furthermore, by modifying the value of a new property, ensure-keyunit-on-start-timeout, it is possible to accept a keyunit of a certain age but discard it if too much time has passed and instead force a new keyunit. Fixes #2443 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4334>
This commit is contained in:
parent
acccc91005
commit
eb0272e210
11 changed files with 837 additions and 10 deletions
|
@ -3767,6 +3767,34 @@ g_object_unref() after usage.</doc>
|
|||
</instance-parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="get_ensure_keyunit_on_start" c:identifier="gst_rtsp_media_get_ensure_keyunit_on_start" version="1.24">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">Get ensure-keyunit-on-start flag.</doc>
|
||||
<source-position filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">The ensure-keyunit-on-start flag.</doc>
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<instance-parameter name="media" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">a #GstRTSPMedia</doc>
|
||||
<type name="RTSPMedia" c:type="GstRTSPMedia*"/>
|
||||
</instance-parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="get_ensure_keyunit_on_start_timeout" c:identifier="gst_rtsp_media_get_ensure_keyunit_on_start_timeout" version="1.24">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">Get ensure-keyunit-on-start-timeout time.</doc>
|
||||
<source-position filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">The ensure-keyunit-on-start-timeout time.</doc>
|
||||
<type name="guint" c:type="guint"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<instance-parameter name="media" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">a #GstRTSPMedia</doc>
|
||||
<type name="RTSPMedia" c:type="GstRTSPMedia*"/>
|
||||
</instance-parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="get_latency" c:identifier="gst_rtsp_media_get_latency">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">Get the latency that is used for receiving media.</doc>
|
||||
<source-position filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.h"/>
|
||||
|
@ -4415,6 +4443,48 @@ INADDR_ANY.</doc>
|
|||
</parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="set_ensure_keyunit_on_start" c:identifier="gst_rtsp_media_set_ensure_keyunit_on_start" version="1.24">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">Set whether or not a keyunit should be ensured when a client connects. It
|
||||
will also configure the streams to drop delta units to ensure that they start
|
||||
on a keyunit.
|
||||
|
||||
Note that this will only affect non-shared medias for now.</doc>
|
||||
<source-position filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<type name="none" c:type="void"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<instance-parameter name="media" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">a #GstRTSPMedia</doc>
|
||||
<type name="RTSPMedia" c:type="GstRTSPMedia*"/>
|
||||
</instance-parameter>
|
||||
<parameter name="ensure_keyunit_on_start" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">the new value</doc>
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="set_ensure_keyunit_on_start_timeout" c:identifier="gst_rtsp_media_set_ensure_keyunit_on_start_timeout" version="1.24">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">Sets the maximum allowed time before the first keyunit is considered
|
||||
expired.
|
||||
|
||||
Note that this will only have an effect when ensure-keyunit-on-start is
|
||||
enabled.</doc>
|
||||
<source-position filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<type name="none" c:type="void"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<instance-parameter name="media" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">a #GstRTSPMedia</doc>
|
||||
<type name="RTSPMedia" c:type="GstRTSPMedia*"/>
|
||||
</instance-parameter>
|
||||
<parameter name="timeout" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">the new value</doc>
|
||||
<type name="guint" c:type="guint"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="set_eos_shutdown" c:identifier="gst_rtsp_media_set_eos_shutdown">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">Set or unset if an EOS event will be sent to the pipeline for @media before
|
||||
it is unprepared.</doc>
|
||||
|
@ -4857,6 +4927,22 @@ when the media was not in the suspended state.</doc>
|
|||
<property name="element" writable="1" construct-only="1" transfer-ownership="none">
|
||||
<type name="Gst.Element"/>
|
||||
</property>
|
||||
<property name="ensure-keyunit-on-start" version="1.24" writable="1" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">Whether or not a keyunit should be ensured when a client connects. It
|
||||
will also configure the streams to drop delta units to ensure that they start
|
||||
on a keyunit.
|
||||
|
||||
Note that this will only affect non-shared medias for now.</doc>
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</property>
|
||||
<property name="ensure-keyunit-on-start-timeout" version="1.24" writable="1" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media.c">The maximum allowed time before the first keyunit is considered
|
||||
expired.
|
||||
|
||||
Note that this will only have an effect when ensure-keyunit-on-start is
|
||||
enabled.</doc>
|
||||
<type name="guint" c:type="guint"/>
|
||||
</property>
|
||||
<property name="eos-shutdown" writable="1" transfer-ownership="none">
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</property>
|
||||
|
@ -5568,6 +5654,34 @@ of all medias created from this factory.</doc>
|
|||
</instance-parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="get_ensure_keyunit_on_start" c:identifier="gst_rtsp_media_factory_get_ensure_keyunit_on_start" version="1.24">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">Get ensure-keyunit-on-start flag.</doc>
|
||||
<source-position filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">The ensure-keyunit-on-start flag.</doc>
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<instance-parameter name="factory" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">a #GstRTSPMediaFactory</doc>
|
||||
<type name="RTSPMediaFactory" c:type="GstRTSPMediaFactory*"/>
|
||||
</instance-parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="get_ensure_keyunit_on_start_timeout" c:identifier="gst_rtsp_media_factory_get_ensure_keyunit_on_start_timeout" version="1.24">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">Get ensure-keyunit-on-start-timeout time.</doc>
|
||||
<source-position filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">The ensure-keyunit-on-start-timeout time.</doc>
|
||||
<type name="guint" c:type="guint"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<instance-parameter name="factory" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">a #GstRTSPMediaFactory</doc>
|
||||
<type name="RTSPMediaFactory" c:type="GstRTSPMediaFactory*"/>
|
||||
</instance-parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="get_latency" c:identifier="gst_rtsp_media_factory_get_latency">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">Get the latency that is used for receiving media</doc>
|
||||
<source-position filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.h"/>
|
||||
|
@ -5928,6 +6042,41 @@ receiving media</doc>
|
|||
</parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="set_ensure_keyunit_on_start" c:identifier="gst_rtsp_media_factory_set_ensure_keyunit_on_start" version="1.24">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">If media from this factory should ensure a key unit when a client connects.</doc>
|
||||
<source-position filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<type name="none" c:type="void"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<instance-parameter name="factory" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">a #GstRTSPMediaFactory</doc>
|
||||
<type name="RTSPMediaFactory" c:type="GstRTSPMediaFactory*"/>
|
||||
</instance-parameter>
|
||||
<parameter name="ensure_keyunit_on_start" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">the new value</doc>
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="set_ensure_keyunit_on_start_timeout" c:identifier="gst_rtsp_media_factory_set_ensure_keyunit_on_start_timeout" version="1.24">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">Configures medias from this factory to consider keyunits older than timeout
|
||||
to be expired. Expired keyunits will be discarded.</doc>
|
||||
<source-position filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<type name="none" c:type="void"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<instance-parameter name="factory" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">a #GstRTSPMediaFactory</doc>
|
||||
<type name="RTSPMediaFactory" c:type="GstRTSPMediaFactory*"/>
|
||||
</instance-parameter>
|
||||
<parameter name="timeout" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">the new value</doc>
|
||||
<type name="guint" c:type="guint"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="set_eos_shutdown" c:identifier="gst_rtsp_media_factory_set_eos_shutdown">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">Configure if media created from this factory will have an EOS sent to the
|
||||
pipeline before shutdown.</doc>
|
||||
|
@ -6212,6 +6361,25 @@ when a client disconnects without sending TEARDOWN.</doc>
|
|||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">Whether the created media should send and receive RTCP</doc>
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</property>
|
||||
<property name="ensure-keyunit-on-start" version="1.24" writable="1" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">If media from this factory should ensure a key unit when a client connects.
|
||||
|
||||
This property will ensure that the stream always starts on a key unit
|
||||
instead of a delta unit which the client would not be able to decode.
|
||||
|
||||
Note that this will only affect non-shared medias for now.</doc>
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</property>
|
||||
<property name="ensure-keyunit-on-start-timeout" version="1.24" writable="1" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-media-factory.c">Timeout in milliseconds used to determine if a keyunit should be discarded
|
||||
when a client connects.
|
||||
|
||||
If the timeout has been reached a new keyframe will be forced, otherwise
|
||||
the currently blocking keyframe will be used.
|
||||
|
||||
This options is only relevant when ensure-keyunit-on-start is enabled.</doc>
|
||||
<type name="guint" c:type="guint"/>
|
||||
</property>
|
||||
<property name="eos-shutdown" writable="1" transfer-ownership="none">
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</property>
|
||||
|
|
|
@ -55,7 +55,7 @@ rtsp_server_headers = files(
|
|||
|
||||
install_headers(rtsp_server_headers, subdir : 'gstreamer-1.0/gst/rtsp-server')
|
||||
|
||||
gst_rtsp_server_deps = [gstrtsp_dep, gstrtp_dep, gstsdp_dep, gstnet_dep, gstapp_dep, gst_dep]
|
||||
gst_rtsp_server_deps = [gstrtsp_dep, gstrtp_dep, gstsdp_dep, gstnet_dep, gstapp_dep, gst_dep, gstvideo_dep]
|
||||
gst_rtsp_server = library('gstrtspserver-@0@'.format(api_version),
|
||||
rtsp_server_sources,
|
||||
include_directories : rtspserver_incs,
|
||||
|
@ -104,6 +104,6 @@ gst_libraries += [[pkg_name, library_def]]
|
|||
gst_rtsp_server_dep = declare_dependency(link_with : gst_rtsp_server,
|
||||
include_directories : rtspserver_incs,
|
||||
sources : rtsp_server_gen_sources,
|
||||
dependencies : [gstrtsp_dep, gstrtp_dep, gstsdp_dep, gstnet_dep, gstapp_dep])
|
||||
dependencies : [gstrtsp_dep, gstrtp_dep, gstsdp_dep, gstnet_dep, gstapp_dep, gstvideo_dep])
|
||||
|
||||
meson.override_dependency(pkg_name, gst_rtsp_server_dep)
|
||||
|
|
|
@ -59,6 +59,8 @@ struct _GstRTSPMediaFactoryPrivate
|
|||
GstRTSPProfile profiles;
|
||||
GstRTSPLowerTrans protocols;
|
||||
guint buffer_size;
|
||||
gboolean ensure_keyunit_on_start;
|
||||
guint ensure_keyunit_on_start_timeout;
|
||||
gint dscp_qos;
|
||||
GstRTSPAddressPool *pool;
|
||||
GstRTSPTransportMode transport_mode;
|
||||
|
@ -90,6 +92,8 @@ struct _GstRTSPMediaFactoryPrivate
|
|||
#define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
|
||||
GST_RTSP_LOWER_TRANS_TCP
|
||||
#define DEFAULT_BUFFER_SIZE 0x80000
|
||||
#define DEFAULT_ENSURE_KEYUNIT_ON_START FALSE
|
||||
#define DEFAULT_ENSURE_KEYUNIT_ON_START_TIMEOUT 100
|
||||
#define DEFAULT_LATENCY 200
|
||||
#define DEFAULT_MAX_MCAST_TTL 255
|
||||
#define DEFAULT_BIND_MCAST_ADDRESS FALSE
|
||||
|
@ -109,6 +113,8 @@ enum
|
|||
PROP_PROFILES,
|
||||
PROP_PROTOCOLS,
|
||||
PROP_BUFFER_SIZE,
|
||||
PROP_ENSURE_KEYUNIT_ON_START,
|
||||
PROP_ENSURE_KEYUNIT_ON_START_TIMEOUT,
|
||||
PROP_LATENCY,
|
||||
PROP_TRANSPORT_MODE,
|
||||
PROP_STOP_ON_DISCONNECT,
|
||||
|
@ -214,6 +220,48 @@ gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
|
|||
"The kernel UDP buffer size to use", 0, G_MAXUINT,
|
||||
DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstRTSPMediaFactory:ensure-keyunit-on-start:
|
||||
*
|
||||
* If media from this factory should ensure a key unit when a client connects.
|
||||
*
|
||||
* This property will ensure that the stream always starts on a key unit
|
||||
* instead of a delta unit which the client would not be able to decode.
|
||||
*
|
||||
* Note that this will only affect non-shared medias for now.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_ENSURE_KEYUNIT_ON_START,
|
||||
g_param_spec_boolean ("ensure-keyunit-on-start",
|
||||
"Ensure keyunit on start",
|
||||
"If media from this factory should ensure a key unit when a client "
|
||||
"connects.",
|
||||
DEFAULT_ENSURE_KEYUNIT_ON_START,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstRTSPMediaFactory:ensure-keyunit-on-start-timeout:
|
||||
*
|
||||
* Timeout in milliseconds used to determine if a keyunit should be discarded
|
||||
* when a client connects.
|
||||
*
|
||||
* If the timeout has been reached a new keyframe will be forced, otherwise
|
||||
* the currently blocking keyframe will be used.
|
||||
*
|
||||
* This options is only relevant when ensure-keyunit-on-start is enabled.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_ENSURE_KEYUNIT_ON_START_TIMEOUT,
|
||||
g_param_spec_uint ("ensure-keyunit-on-start-timeout",
|
||||
"Timeout for discarding old keyunit on start",
|
||||
"Timeout in milliseconds used to determine if a keyunit should be "
|
||||
"discarded when a client connects.", 0, G_MAXUINT,
|
||||
DEFAULT_ENSURE_KEYUNIT_ON_START_TIMEOUT,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_LATENCY,
|
||||
g_param_spec_uint ("latency", "Latency",
|
||||
"Latency used for receiving media in milliseconds", 0, G_MAXUINT,
|
||||
|
@ -304,6 +352,9 @@ gst_rtsp_media_factory_init (GstRTSPMediaFactory * factory)
|
|||
priv->profiles = DEFAULT_PROFILES;
|
||||
priv->protocols = DEFAULT_PROTOCOLS;
|
||||
priv->buffer_size = DEFAULT_BUFFER_SIZE;
|
||||
priv->ensure_keyunit_on_start = DEFAULT_ENSURE_KEYUNIT_ON_START;
|
||||
priv->ensure_keyunit_on_start_timeout =
|
||||
DEFAULT_ENSURE_KEYUNIT_ON_START_TIMEOUT;
|
||||
priv->latency = DEFAULT_LATENCY;
|
||||
priv->transport_mode = DEFAULT_TRANSPORT_MODE;
|
||||
priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
|
||||
|
@ -373,6 +424,14 @@ gst_rtsp_media_factory_get_property (GObject * object, guint propid,
|
|||
g_value_set_uint (value,
|
||||
gst_rtsp_media_factory_get_buffer_size (factory));
|
||||
break;
|
||||
case PROP_ENSURE_KEYUNIT_ON_START:
|
||||
g_value_set_boolean (value,
|
||||
gst_rtsp_media_factory_get_ensure_keyunit_on_start (factory));
|
||||
break;
|
||||
case PROP_ENSURE_KEYUNIT_ON_START_TIMEOUT:
|
||||
g_value_set_uint (value,
|
||||
gst_rtsp_media_factory_get_ensure_keyunit_on_start_timeout (factory));
|
||||
break;
|
||||
case PROP_LATENCY:
|
||||
g_value_set_uint (value, gst_rtsp_media_factory_get_latency (factory));
|
||||
break;
|
||||
|
@ -438,6 +497,14 @@ gst_rtsp_media_factory_set_property (GObject * object, guint propid,
|
|||
gst_rtsp_media_factory_set_buffer_size (factory,
|
||||
g_value_get_uint (value));
|
||||
break;
|
||||
case PROP_ENSURE_KEYUNIT_ON_START:
|
||||
gst_rtsp_media_factory_set_ensure_keyunit_on_start (factory,
|
||||
g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_ENSURE_KEYUNIT_ON_START_TIMEOUT:
|
||||
gst_rtsp_media_factory_set_ensure_keyunit_on_start_timeout (factory,
|
||||
g_value_get_uint (value));
|
||||
break;
|
||||
case PROP_LATENCY:
|
||||
gst_rtsp_media_factory_set_latency (factory, g_value_get_uint (value));
|
||||
break;
|
||||
|
@ -853,6 +920,111 @@ gst_rtsp_media_factory_get_buffer_size (GstRTSPMediaFactory * factory)
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_factory_set_ensure_keyunit_on_start:
|
||||
* @factory: a #GstRTSPMediaFactory
|
||||
* @ensure_keyunit_on_start: the new value
|
||||
*
|
||||
* If media from this factory should ensure a key unit when a client connects.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
void
|
||||
gst_rtsp_media_factory_set_ensure_keyunit_on_start (GstRTSPMediaFactory *
|
||||
factory, gboolean ensure_keyunit_on_start)
|
||||
{
|
||||
GstRTSPMediaFactoryPrivate *priv;
|
||||
|
||||
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
|
||||
|
||||
priv = factory->priv;
|
||||
|
||||
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
|
||||
priv->ensure_keyunit_on_start = ensure_keyunit_on_start;
|
||||
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_factory_get_ensure_keyunit_on_start:
|
||||
* @factory: a #GstRTSPMediaFactory
|
||||
*
|
||||
* Get ensure-keyunit-on-start flag.
|
||||
*
|
||||
* Returns: The ensure-keyunit-on-start flag.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
gboolean
|
||||
gst_rtsp_media_factory_get_ensure_keyunit_on_start (GstRTSPMediaFactory *
|
||||
factory)
|
||||
{
|
||||
GstRTSPMediaFactoryPrivate *priv;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
|
||||
|
||||
priv = factory->priv;
|
||||
|
||||
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
|
||||
result = priv->ensure_keyunit_on_start;
|
||||
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_factory_set_ensure_keyunit_on_start_timeout:
|
||||
* @factory: a #GstRTSPMediaFactory
|
||||
* @timeout: the new value
|
||||
*
|
||||
* Configures medias from this factory to consider keyunits older than timeout
|
||||
* to be expired. Expired keyunits will be discarded.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
void
|
||||
gst_rtsp_media_factory_set_ensure_keyunit_on_start_timeout (GstRTSPMediaFactory
|
||||
* factory, guint timeout)
|
||||
{
|
||||
GstRTSPMediaFactoryPrivate *priv;
|
||||
|
||||
g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
|
||||
|
||||
priv = factory->priv;
|
||||
|
||||
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
|
||||
priv->ensure_keyunit_on_start_timeout = timeout;
|
||||
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_factory_get_ensure_keyunit_on_start_timeout:
|
||||
* @factory: a #GstRTSPMediaFactory
|
||||
*
|
||||
* Get ensure-keyunit-on-start-timeout time.
|
||||
*
|
||||
* Returns: The ensure-keyunit-on-start-timeout time.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
guint
|
||||
gst_rtsp_media_factory_get_ensure_keyunit_on_start_timeout (GstRTSPMediaFactory
|
||||
* factory)
|
||||
{
|
||||
GstRTSPMediaFactoryPrivate *priv;
|
||||
guint result;
|
||||
|
||||
g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
|
||||
|
||||
priv = factory->priv;
|
||||
|
||||
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
|
||||
result = priv->ensure_keyunit_on_start_timeout;
|
||||
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_factory_set_dscp_qos:
|
||||
* @factory: a #GstRTSPMediaFactory
|
||||
|
@ -1878,6 +2050,8 @@ default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
|
|||
|
||||
/* We need to call this prior to collecting streams */
|
||||
gst_rtsp_media_set_enable_rtcp (media, enable_rtcp);
|
||||
gst_rtsp_media_set_ensure_keyunit_on_start (media,
|
||||
gst_rtsp_media_factory_get_ensure_keyunit_on_start (factory));
|
||||
|
||||
gst_rtsp_media_collect_streams (media);
|
||||
|
||||
|
@ -1928,6 +2102,8 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
|
|||
GstRTSPMediaFactoryPrivate *priv = factory->priv;
|
||||
gboolean shared, eos_shutdown, stop_on_disconnect;
|
||||
guint size;
|
||||
gboolean ensure_keyunit_on_start;
|
||||
guint ensure_keyunit_on_start_timeout;
|
||||
gint dscp_qos;
|
||||
GstRTSPSuspendMode suspend_mode;
|
||||
GstRTSPProfile profiles;
|
||||
|
@ -1949,6 +2125,8 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
|
|||
shared = priv->shared;
|
||||
eos_shutdown = priv->eos_shutdown;
|
||||
size = priv->buffer_size;
|
||||
ensure_keyunit_on_start = priv->ensure_keyunit_on_start;
|
||||
ensure_keyunit_on_start_timeout = priv->ensure_keyunit_on_start_timeout;
|
||||
dscp_qos = priv->dscp_qos;
|
||||
profiles = priv->profiles;
|
||||
protocols = priv->protocols;
|
||||
|
@ -1966,6 +2144,9 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
|
|||
gst_rtsp_media_set_shared (media, shared);
|
||||
gst_rtsp_media_set_eos_shutdown (media, eos_shutdown);
|
||||
gst_rtsp_media_set_buffer_size (media, size);
|
||||
gst_rtsp_media_set_ensure_keyunit_on_start (media, ensure_keyunit_on_start);
|
||||
gst_rtsp_media_set_ensure_keyunit_on_start_timeout (media,
|
||||
ensure_keyunit_on_start_timeout);
|
||||
gst_rtsp_media_set_dscp_qos (media, dscp_qos);
|
||||
gst_rtsp_media_set_profiles (media, profiles);
|
||||
gst_rtsp_media_set_protocols (media, protocols);
|
||||
|
|
|
@ -191,6 +191,21 @@ void gst_rtsp_media_factory_set_buffer_size (GstRTSPMediaFacto
|
|||
GST_RTSP_SERVER_API
|
||||
guint gst_rtsp_media_factory_get_buffer_size (GstRTSPMediaFactory * factory);
|
||||
|
||||
GST_RTSP_SERVER_API
|
||||
void gst_rtsp_media_factory_set_ensure_keyunit_on_start (GstRTSPMediaFactory * factory,
|
||||
gboolean ensure_keyunit_on_start);
|
||||
|
||||
GST_RTSP_SERVER_API
|
||||
gboolean gst_rtsp_media_factory_get_ensure_keyunit_on_start (GstRTSPMediaFactory * factory);
|
||||
|
||||
GST_RTSP_SERVER_API
|
||||
void gst_rtsp_media_factory_set_ensure_keyunit_on_start_timeout (GstRTSPMediaFactory * factory,
|
||||
guint timeout);
|
||||
|
||||
GST_RTSP_SERVER_API
|
||||
guint gst_rtsp_media_factory_get_ensure_keyunit_on_start_timeout (GstRTSPMediaFactory * factory);
|
||||
|
||||
|
||||
GST_RTSP_SERVER_API
|
||||
void gst_rtsp_media_factory_set_retransmission_time (GstRTSPMediaFactory * factory,
|
||||
GstClockTime time);
|
||||
|
|
|
@ -77,6 +77,8 @@
|
|||
#include <gst/sdp/gstmikey.h>
|
||||
#include <gst/rtp/gstrtppayloads.h>
|
||||
|
||||
#include <gst/video/video-event.h>
|
||||
|
||||
#define AES_128_KEY_LEN 16
|
||||
#define AES_256_KEY_LEN 32
|
||||
|
||||
|
@ -107,6 +109,10 @@ struct _GstRTSPMediaPrivate
|
|||
gboolean reused;
|
||||
gboolean eos_shutdown;
|
||||
guint buffer_size;
|
||||
gboolean ensure_keyunit_on_start;
|
||||
guint ensure_keyunit_on_start_timeout;
|
||||
gboolean keyunit_is_expired; /* if the blocking keyunit has expired */
|
||||
GSource *keyunit_expiration_source;
|
||||
gint dscp_qos;
|
||||
GstRTSPAddressPool *pool;
|
||||
gchar *multicast_iface;
|
||||
|
@ -172,6 +178,8 @@ struct _GstRTSPMediaPrivate
|
|||
GST_RTSP_LOWER_TRANS_TCP
|
||||
#define DEFAULT_EOS_SHUTDOWN FALSE
|
||||
#define DEFAULT_BUFFER_SIZE 0x80000
|
||||
#define DEFAULT_ENSURE_KEYUNIT_ON_START FALSE
|
||||
#define DEFAULT_ENSURE_KEYUNIT_ON_START_TIMEOUT 100
|
||||
#define DEFAULT_DSCP_QOS (-1)
|
||||
#define DEFAULT_TIME_PROVIDER FALSE
|
||||
#define DEFAULT_LATENCY 200
|
||||
|
@ -197,6 +205,8 @@ enum
|
|||
PROP_PROTOCOLS,
|
||||
PROP_EOS_SHUTDOWN,
|
||||
PROP_BUFFER_SIZE,
|
||||
PROP_ENSURE_KEYUNIT_ON_START,
|
||||
PROP_ENSURE_KEYUNIT_ON_START_TIMEOUT,
|
||||
PROP_ELEMENT,
|
||||
PROP_TIME_PROVIDER,
|
||||
PROP_LATENCY,
|
||||
|
@ -371,6 +381,44 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
|
|||
"The kernel UDP buffer size to use", 0, G_MAXUINT,
|
||||
DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstRTSPMedia:ensure-keyunit-on-start:
|
||||
*
|
||||
* Whether or not a keyunit should be ensured when a client connects. It
|
||||
* will also configure the streams to drop delta units to ensure that they start
|
||||
* on a keyunit.
|
||||
*
|
||||
* Note that this will only affect non-shared medias for now.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_ENSURE_KEYUNIT_ON_START,
|
||||
g_param_spec_boolean ("ensure-keyunit-on-start",
|
||||
"Ensure keyunit on start",
|
||||
"Whether the stream will ensure a keyunit when a client connects.",
|
||||
DEFAULT_ENSURE_KEYUNIT_ON_START,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstRTSPMedia:ensure-keyunit-on-start-timeout:
|
||||
*
|
||||
* The maximum allowed time before the first keyunit is considered
|
||||
* expired.
|
||||
*
|
||||
* Note that this will only have an effect when ensure-keyunit-on-start is
|
||||
* enabled.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_ENSURE_KEYUNIT_ON_START_TIMEOUT,
|
||||
g_param_spec_uint ("ensure-keyunit-on-start-timeout",
|
||||
"Timeout for discarding old keyunit on start",
|
||||
"Timeout in milliseconds used to determine if a keyunit should be "
|
||||
"discarded when a client connects.", 0, G_MAXUINT,
|
||||
DEFAULT_ENSURE_KEYUNIT_ON_START_TIMEOUT,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_ELEMENT,
|
||||
g_param_spec_object ("element", "The Element",
|
||||
"The GstBin to use for streaming the media", GST_TYPE_ELEMENT,
|
||||
|
@ -504,6 +552,11 @@ gst_rtsp_media_init (GstRTSPMedia * media)
|
|||
priv->protocols = DEFAULT_PROTOCOLS;
|
||||
priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
|
||||
priv->buffer_size = DEFAULT_BUFFER_SIZE;
|
||||
priv->ensure_keyunit_on_start = DEFAULT_ENSURE_KEYUNIT_ON_START;
|
||||
priv->ensure_keyunit_on_start_timeout =
|
||||
DEFAULT_ENSURE_KEYUNIT_ON_START_TIMEOUT;
|
||||
priv->keyunit_is_expired = FALSE;
|
||||
priv->keyunit_expiration_source = NULL;
|
||||
priv->time_provider = DEFAULT_TIME_PROVIDER;
|
||||
priv->transport_mode = DEFAULT_TRANSPORT_MODE;
|
||||
priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
|
||||
|
@ -554,6 +607,12 @@ gst_rtsp_media_finalize (GObject * obj)
|
|||
g_cond_clear (&priv->cond);
|
||||
g_rec_mutex_clear (&priv->state_lock);
|
||||
|
||||
if (priv->keyunit_expiration_source != NULL) {
|
||||
g_source_destroy (priv->keyunit_expiration_source);
|
||||
g_source_unref (priv->keyunit_expiration_source);
|
||||
priv->keyunit_expiration_source = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
|
||||
}
|
||||
|
||||
|
@ -588,6 +647,14 @@ gst_rtsp_media_get_property (GObject * object, guint propid,
|
|||
case PROP_BUFFER_SIZE:
|
||||
g_value_set_uint (value, gst_rtsp_media_get_buffer_size (media));
|
||||
break;
|
||||
case PROP_ENSURE_KEYUNIT_ON_START:
|
||||
g_value_set_boolean (value,
|
||||
gst_rtsp_media_get_ensure_keyunit_on_start (media));
|
||||
break;
|
||||
case PROP_ENSURE_KEYUNIT_ON_START_TIMEOUT:
|
||||
g_value_set_uint (value,
|
||||
gst_rtsp_media_get_ensure_keyunit_on_start_timeout (media));
|
||||
break;
|
||||
case PROP_TIME_PROVIDER:
|
||||
g_value_set_boolean (value, gst_rtsp_media_is_time_provider (media));
|
||||
break;
|
||||
|
@ -649,6 +716,14 @@ gst_rtsp_media_set_property (GObject * object, guint propid,
|
|||
case PROP_BUFFER_SIZE:
|
||||
gst_rtsp_media_set_buffer_size (media, g_value_get_uint (value));
|
||||
break;
|
||||
case PROP_ENSURE_KEYUNIT_ON_START:
|
||||
gst_rtsp_media_set_ensure_keyunit_on_start (media,
|
||||
g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_ENSURE_KEYUNIT_ON_START_TIMEOUT:
|
||||
gst_rtsp_media_set_ensure_keyunit_on_start_timeout (media,
|
||||
g_value_get_uint (value));
|
||||
break;
|
||||
case PROP_TIME_PROVIDER:
|
||||
gst_rtsp_media_use_time_provider (media, g_value_get_boolean (value));
|
||||
break;
|
||||
|
@ -1487,6 +1562,116 @@ gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_set_ensure_keyunit_on_start:
|
||||
* @media: a #GstRTSPMedia
|
||||
* @ensure_keyunit_on_start: the new value
|
||||
*
|
||||
* Set whether or not a keyunit should be ensured when a client connects. It
|
||||
* will also configure the streams to drop delta units to ensure that they start
|
||||
* on a keyunit.
|
||||
*
|
||||
* Note that this will only affect non-shared medias for now.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
void
|
||||
gst_rtsp_media_set_ensure_keyunit_on_start (GstRTSPMedia * media,
|
||||
gboolean ensure_keyunit_on_start)
|
||||
{
|
||||
GstRTSPMediaPrivate *priv;
|
||||
|
||||
g_return_if_fail (GST_IS_RTSP_MEDIA (media));
|
||||
|
||||
priv = media->priv;
|
||||
|
||||
g_mutex_lock (&priv->lock);
|
||||
priv->ensure_keyunit_on_start = ensure_keyunit_on_start;
|
||||
g_mutex_unlock (&priv->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_get_ensure_keyunit_on_start:
|
||||
* @media: a #GstRTSPMedia
|
||||
*
|
||||
* Get ensure-keyunit-on-start flag.
|
||||
*
|
||||
* Returns: The ensure-keyunit-on-start flag.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
gboolean
|
||||
gst_rtsp_media_get_ensure_keyunit_on_start (GstRTSPMedia * media)
|
||||
{
|
||||
GstRTSPMediaPrivate *priv;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
|
||||
|
||||
priv = media->priv;
|
||||
|
||||
g_mutex_lock (&priv->lock);
|
||||
result = priv->ensure_keyunit_on_start;
|
||||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_set_ensure_keyunit_on_start_timeout:
|
||||
* @media: a #GstRTSPMedia
|
||||
* @timeout: the new value
|
||||
*
|
||||
* Sets the maximum allowed time before the first keyunit is considered
|
||||
* expired.
|
||||
*
|
||||
* Note that this will only have an effect when ensure-keyunit-on-start is
|
||||
* enabled.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
void
|
||||
gst_rtsp_media_set_ensure_keyunit_on_start_timeout (GstRTSPMedia * media,
|
||||
guint timeout)
|
||||
{
|
||||
GstRTSPMediaPrivate *priv;
|
||||
|
||||
g_return_if_fail (GST_IS_RTSP_MEDIA (media));
|
||||
|
||||
priv = media->priv;
|
||||
|
||||
g_mutex_lock (&priv->lock);
|
||||
priv->ensure_keyunit_on_start_timeout = timeout;
|
||||
g_mutex_unlock (&priv->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_get_ensure_keyunit_on_start_timeout
|
||||
* @media: a #GstRTSPMedia
|
||||
*
|
||||
* Get ensure-keyunit-on-start-timeout time.
|
||||
*
|
||||
* Returns: The ensure-keyunit-on-start-timeout time.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
guint
|
||||
gst_rtsp_media_get_ensure_keyunit_on_start_timeout (GstRTSPMedia * media)
|
||||
{
|
||||
GstRTSPMediaPrivate *priv;
|
||||
guint result;
|
||||
|
||||
g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
|
||||
|
||||
priv = media->priv;
|
||||
|
||||
g_mutex_lock (&priv->lock);
|
||||
result = priv->ensure_keyunit_on_start_timeout;
|
||||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
do_set_dscp_qos (GstRTSPStream * stream, gint * dscp_qos)
|
||||
{
|
||||
|
@ -2502,6 +2687,7 @@ gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader,
|
|||
gst_rtsp_stream_set_protocols (stream, priv->protocols);
|
||||
gst_rtsp_stream_set_retransmission_time (stream, priv->rtx_time);
|
||||
gst_rtsp_stream_set_buffer_size (stream, priv->buffer_size);
|
||||
gst_rtsp_stream_set_drop_delta_units (stream, priv->ensure_keyunit_on_start);
|
||||
gst_rtsp_stream_set_publish_clock_mode (stream, priv->publish_clock_mode);
|
||||
gst_rtsp_stream_set_rate_control (stream, priv->do_rate_control);
|
||||
|
||||
|
@ -2837,6 +3023,23 @@ media_streams_set_blocked (GstRTSPMedia * media, gboolean blocked)
|
|||
priv->blocking_msg_received = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
stream_install_drop_probe (GstRTSPStream * stream, gpointer user_data)
|
||||
{
|
||||
if (!gst_rtsp_stream_is_complete (stream))
|
||||
return;
|
||||
|
||||
gst_rtsp_stream_install_drop_probe (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
media_streams_install_drop_probe (GstRTSPMedia * media)
|
||||
{
|
||||
GstRTSPMediaPrivate *priv = media->priv;
|
||||
|
||||
g_ptr_array_foreach (priv->streams, (GFunc) stream_install_drop_probe, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status)
|
||||
{
|
||||
|
@ -4590,6 +4793,15 @@ do_set_seqnum (GstRTSPStream * stream)
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
enable_keyunit_expired (GstRTSPMedia * media)
|
||||
{
|
||||
GST_DEBUG_OBJECT (media, "keyunit has expired");
|
||||
media->priv->keyunit_is_expired = TRUE;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
/* call with state_lock */
|
||||
static gboolean
|
||||
default_suspend (GstRTSPMedia * media)
|
||||
|
@ -4629,6 +4841,20 @@ default_suspend (GstRTSPMedia * media)
|
|||
if (ret != GST_STATE_CHANGE_FAILURE && ret != GST_STATE_CHANGE_ASYNC)
|
||||
priv->expected_async_done = FALSE;
|
||||
|
||||
/* set expiration date on buffer in case of delayed PLAY request */
|
||||
if (priv->ensure_keyunit_on_start) {
|
||||
/* no need to install the timer if configured to trigger immediately */
|
||||
if (priv->ensure_keyunit_on_start_timeout == 0) {
|
||||
enable_keyunit_expired (media);
|
||||
} else {
|
||||
priv->keyunit_expiration_source =
|
||||
g_timeout_source_new (priv->ensure_keyunit_on_start_timeout);
|
||||
g_source_set_callback (priv->keyunit_expiration_source,
|
||||
G_SOURCE_FUNC (enable_keyunit_expired), (gpointer) media, NULL);
|
||||
g_source_attach (priv->keyunit_expiration_source, priv->thread->context);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
|
@ -4684,6 +4910,7 @@ gst_rtsp_media_suspend (GstRTSPMedia * media)
|
|||
}
|
||||
|
||||
gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_SUSPENDED);
|
||||
|
||||
done:
|
||||
g_rec_mutex_unlock (&priv->state_lock);
|
||||
|
||||
|
@ -4710,6 +4937,79 @@ suspend_failed:
|
|||
}
|
||||
}
|
||||
|
||||
/* Call with state_lock */
|
||||
static gboolean
|
||||
ensure_new_keyunit (GstRTSPMedia * media)
|
||||
{
|
||||
GstRTSPMediaPrivate *priv = media->priv;
|
||||
gboolean preroll_ok;
|
||||
gboolean is_blocking = FALSE;
|
||||
|
||||
/* nothing to be done without complete senders */
|
||||
if (get_num_complete_sender_streams (media) == 0) {
|
||||
GST_DEBUG_OBJECT (media, "no complete senders, skipping force keyunit");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
is_blocking = media_streams_blocking (media);
|
||||
|
||||
/* if we unsuspend before the keyunit is expired remove the timer so that
|
||||
* no future buffer is marked as expired */
|
||||
if (is_blocking && !priv->keyunit_is_expired) {
|
||||
GST_DEBUG_OBJECT (media, "using currently blocking keyunit");
|
||||
g_source_destroy (priv->keyunit_expiration_source);
|
||||
g_source_unref (priv->keyunit_expiration_source);
|
||||
priv->keyunit_expiration_source = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* set the media to preparing, thus requiring a successful preroll before
|
||||
* completing unsuspend. */
|
||||
gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
|
||||
GST_DEBUG_OBJECT (media, "ensuring new keyunit, doing preroll");
|
||||
if (!start_preroll (media))
|
||||
goto start_failed;
|
||||
|
||||
if (is_blocking) {
|
||||
/* if we end up here then the keyunit has expired and the timer callback
|
||||
* has been removed so reset the flag */
|
||||
priv->keyunit_is_expired = FALSE;
|
||||
|
||||
/* install a probe that will drop the currently blocking keyunit on all
|
||||
* complete streams. */
|
||||
GST_DEBUG_OBJECT (media, "media is blocking. Installing drop probe");
|
||||
media_streams_install_drop_probe (media);
|
||||
}
|
||||
|
||||
/* force the keyunit from src */
|
||||
GST_DEBUG_OBJECT (media, "sending force keyunit event");
|
||||
gst_element_send_event (priv->element,
|
||||
gst_video_event_new_upstream_force_key_unit (GST_CLOCK_TIME_NONE,
|
||||
TRUE, 0));
|
||||
|
||||
/* wait preroll */
|
||||
g_rec_mutex_unlock (&priv->state_lock);
|
||||
preroll_ok = wait_preroll (media);
|
||||
g_rec_mutex_lock (&priv->state_lock);
|
||||
|
||||
if (!preroll_ok)
|
||||
goto preroll_failed;
|
||||
|
||||
return TRUE;
|
||||
|
||||
start_failed:
|
||||
{
|
||||
GST_WARNING ("failed to preroll pipeline");
|
||||
return FALSE;
|
||||
}
|
||||
preroll_failed:
|
||||
{
|
||||
GST_WARNING ("failed while waiting to preroll pipeline");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* call with state_lock */
|
||||
static gboolean
|
||||
default_unsuspend (GstRTSPMedia * media)
|
||||
|
@ -4749,14 +5049,19 @@ default_unsuspend (GstRTSPMedia * media)
|
|||
|
||||
if (!preroll_ok)
|
||||
goto preroll_failed;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (gst_rtsp_media_get_ensure_keyunit_on_start (media)) {
|
||||
return ensure_new_keyunit (media);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
/* ERRORS */
|
||||
start_failed:
|
||||
{
|
||||
GST_WARNING ("failed to preroll pipeline");
|
||||
|
@ -4764,7 +5069,7 @@ start_failed:
|
|||
}
|
||||
preroll_failed:
|
||||
{
|
||||
GST_WARNING ("failed to preroll pipeline");
|
||||
GST_WARNING ("failed while waiting to preroll pipeline");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -278,6 +278,20 @@ void gst_rtsp_media_set_buffer_size (GstRTSPMedia *media, guin
|
|||
GST_RTSP_SERVER_API
|
||||
guint gst_rtsp_media_get_buffer_size (GstRTSPMedia *media);
|
||||
|
||||
GST_RTSP_SERVER_API
|
||||
void gst_rtsp_media_set_ensure_keyunit_on_start (GstRTSPMedia* media,
|
||||
gboolean ensure_keyunit_on_start);
|
||||
|
||||
GST_RTSP_SERVER_API
|
||||
gboolean gst_rtsp_media_get_ensure_keyunit_on_start (GstRTSPMedia* media);
|
||||
|
||||
GST_RTSP_SERVER_API
|
||||
void gst_rtsp_media_set_ensure_keyunit_on_start_timeout (GstRTSPMedia* media,
|
||||
guint timeout);
|
||||
|
||||
GST_RTSP_SERVER_API
|
||||
guint gst_rtsp_media_get_ensure_keyunit_on_start_timeout (GstRTSPMedia* media);
|
||||
|
||||
GST_RTSP_SERVER_API
|
||||
void gst_rtsp_media_set_retransmission_time (GstRTSPMedia *media, GstClockTime time);
|
||||
|
||||
|
|
|
@ -146,6 +146,10 @@ gst_rtsp_onvif_media_factory_construct (GstRTSPMediaFactory * factory,
|
|||
g_object_new (media_gtype, "element", element,
|
||||
"transport-mode", GST_RTSP_TRANSPORT_MODE_PLAY, NULL);
|
||||
|
||||
/* we need to call this prior to collecting streams */
|
||||
gst_rtsp_media_set_ensure_keyunit_on_start (media,
|
||||
gst_rtsp_media_factory_get_ensure_keyunit_on_start (factory));
|
||||
|
||||
/* this adds the non-backchannel streams */
|
||||
gst_rtsp_media_collect_streams (media);
|
||||
|
||||
|
|
|
@ -63,6 +63,10 @@ gboolean gst_rtsp_stream_is_tcp_receiver (GstRTSPStream * stream
|
|||
void gst_rtsp_media_set_enable_rtcp (GstRTSPMedia *media, gboolean enable);
|
||||
void gst_rtsp_stream_set_enable_rtcp (GstRTSPStream *stream, gboolean enable);
|
||||
|
||||
void gst_rtsp_stream_set_drop_delta_units (GstRTSPStream * stream, gboolean drop);
|
||||
|
||||
gboolean gst_rtsp_stream_install_drop_probe (GstRTSPStream * stream);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_RTSP_SERVER_INTERNAL_H__ */
|
||||
|
|
|
@ -230,6 +230,14 @@ struct _GstRTSPStreamPrivate
|
|||
gulong block_early_rtcp_probe;
|
||||
GstPad *block_early_rtcp_pad_ipv6;
|
||||
gulong block_early_rtcp_probe_ipv6;
|
||||
|
||||
/* set to drop delta units in blocking pad */
|
||||
gboolean drop_delta_units;
|
||||
|
||||
/* used to indicate that the drop probe has dropped a buffer and should be
|
||||
* removed */
|
||||
gboolean remove_drop_probe;
|
||||
|
||||
};
|
||||
|
||||
#define DEFAULT_CONTROL NULL
|
||||
|
@ -357,6 +365,8 @@ gst_rtsp_stream_init (GstRTSPStream * stream)
|
|||
priv->block_early_rtcp_probe = 0;
|
||||
priv->block_early_rtcp_pad_ipv6 = NULL;
|
||||
priv->block_early_rtcp_probe_ipv6 = 0;
|
||||
priv->drop_delta_units = FALSE;
|
||||
priv->remove_drop_probe = FALSE;
|
||||
}
|
||||
|
||||
typedef struct _UdpClientAddrInfo UdpClientAddrInfo;
|
||||
|
@ -4317,7 +4327,7 @@ gst_rtsp_stream_get_rtpinfo (GstRTSPStream * stream,
|
|||
else
|
||||
g_object_get (priv->appsink[0], "last-sample", &last_sample, NULL);
|
||||
|
||||
if (last_sample) {
|
||||
if (last_sample && !priv->blocking) {
|
||||
GstCaps *caps;
|
||||
GstBuffer *buffer;
|
||||
GstSegment *segment;
|
||||
|
@ -4373,6 +4383,8 @@ gst_rtsp_stream_get_rtpinfo (GstRTSPStream * stream,
|
|||
gst_sample_unref (last_sample);
|
||||
}
|
||||
} else if (priv->blocking) {
|
||||
if (last_sample != NULL)
|
||||
gst_sample_unref (last_sample);
|
||||
if (seq) {
|
||||
if (!priv->blocked_buffer)
|
||||
goto stats;
|
||||
|
@ -5326,6 +5338,14 @@ rtp_pad_blocking (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
|||
gst_rtp_buffer_unmap (&rtp);
|
||||
}
|
||||
priv->position = GST_BUFFER_TIMESTAMP (buffer);
|
||||
if (priv->drop_delta_units) {
|
||||
if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
|
||||
g_assert (!priv->blocking);
|
||||
GST_DEBUG_OBJECT (pad, "dropping delta-unit buffer");
|
||||
ret = GST_PAD_PROBE_DROP;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
} else if ((info->type & GST_PAD_PROBE_TYPE_BUFFER_LIST)) {
|
||||
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
|
||||
|
||||
|
@ -5338,12 +5358,20 @@ rtp_pad_blocking (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
|||
gst_rtp_buffer_unmap (&rtp);
|
||||
}
|
||||
priv->position = GST_BUFFER_TIMESTAMP (buffer);
|
||||
if (priv->drop_delta_units) {
|
||||
if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
|
||||
g_assert (!priv->blocking);
|
||||
GST_DEBUG_OBJECT (pad, "dropping delta-unit buffer");
|
||||
ret = GST_PAD_PROBE_DROP;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
} else if ((info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM)) {
|
||||
if (GST_EVENT_TYPE (info->data) == GST_EVENT_GAP) {
|
||||
gst_event_parse_gap (info->data, &priv->position, NULL);
|
||||
} else {
|
||||
ret = GST_PAD_PROBE_PASS;
|
||||
g_mutex_unlock (&priv->lock);
|
||||
GST_WARNING ("Passing event.");
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
|
@ -5371,6 +5399,11 @@ rtp_pad_blocking (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
|||
gst_event_unref (event);
|
||||
}
|
||||
|
||||
/* make sure to block on the correct frame type */
|
||||
if (priv->drop_delta_units) {
|
||||
g_assert (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT));
|
||||
}
|
||||
|
||||
priv->blocking = TRUE;
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "Now blocking");
|
||||
|
@ -5378,14 +5411,44 @@ rtp_pad_blocking (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
|||
GST_DEBUG_OBJECT (stream, "position: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (priv->position));
|
||||
|
||||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
gst_element_post_message (priv->payloader,
|
||||
gst_message_new_element (GST_OBJECT_CAST (priv->payloader),
|
||||
gst_structure_new ("GstRTSPStreamBlocking", "is_complete",
|
||||
G_TYPE_BOOLEAN, priv->is_complete, NULL)));
|
||||
|
||||
done:
|
||||
g_mutex_unlock (&priv->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* this probe will drop a single buffer. It is used when an old buffer is
|
||||
* blocking the pipeline, such as between a DESCRIBE and a PLAY request. */
|
||||
static GstPadProbeReturn
|
||||
drop_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
||||
{
|
||||
GstRTSPStreamPrivate *priv;
|
||||
GstRTSPStream *stream;
|
||||
/* drop an old buffer stuck in a blocked pipeline */
|
||||
GstPadProbeReturn ret = GST_PAD_PROBE_DROP;
|
||||
|
||||
stream = user_data;
|
||||
priv = stream->priv;
|
||||
|
||||
g_mutex_lock (&priv->lock);
|
||||
|
||||
if ((info->type & GST_PAD_PROBE_TYPE_BUFFER ||
|
||||
info->type & GST_PAD_PROBE_TYPE_BUFFER_LIST)) {
|
||||
/* if a buffer has been dropped then remove this probe */
|
||||
if (priv->remove_drop_probe) {
|
||||
priv->remove_drop_probe = FALSE;
|
||||
ret = GST_PAD_PROBE_REMOVE;
|
||||
} else {
|
||||
priv->blocking = FALSE;
|
||||
priv->remove_drop_probe = TRUE;
|
||||
}
|
||||
} else {
|
||||
ret = GST_PAD_PROBE_PASS;
|
||||
}
|
||||
g_mutex_unlock (&priv->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -5423,6 +5486,26 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
install_drop_probe (GstRTSPStream * stream)
|
||||
{
|
||||
GstRTSPStreamPrivate *priv;
|
||||
|
||||
priv = stream->priv;
|
||||
|
||||
/* if receiver */
|
||||
if (priv->sinkpad)
|
||||
return;
|
||||
|
||||
/* install for data channel only */
|
||||
if (priv->send_src[0]) {
|
||||
gst_pad_add_probe (priv->send_src[0],
|
||||
GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER |
|
||||
GST_PAD_PROBE_TYPE_BUFFER_LIST |
|
||||
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, drop_probe,
|
||||
g_object_ref (stream), g_object_unref);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_blocked (GstRTSPStream * stream, gboolean blocked)
|
||||
|
@ -5499,6 +5582,34 @@ gst_rtsp_stream_set_blocked (GstRTSPStream * stream, gboolean blocked)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_stream_install_drop_probe:
|
||||
* @stream: a #GstRTSPStream
|
||||
*
|
||||
* This probe can be installed when the currently blocking buffer should be
|
||||
* dropped. When it has successfully dropped the buffer, it will remove itself.
|
||||
* The goal is to avoid sending old data, typically when there has been a delay
|
||||
* between a DESCRIBE and a PLAY request.
|
||||
*
|
||||
* Returns: %TRUE on success
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
gboolean
|
||||
gst_rtsp_stream_install_drop_probe (GstRTSPStream * stream)
|
||||
{
|
||||
GstRTSPStreamPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
|
||||
|
||||
priv = stream->priv;
|
||||
g_mutex_lock (&priv->lock);
|
||||
install_drop_probe (stream);
|
||||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_stream_ublock_linked:
|
||||
* @stream: a #GstRTSPStream
|
||||
|
@ -6415,3 +6526,25 @@ gst_rtsp_stream_unblock_rtcp (GstRTSPStream * stream)
|
|||
}
|
||||
g_mutex_unlock (&priv->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_stream_set_drop_delta_units:
|
||||
* @stream: a #GstRTSPStream
|
||||
* @drop: TRUE if delta unit frames are supposed to be dropped.
|
||||
*
|
||||
* Decide whether the blocking probe is supposed to drop delta units at the
|
||||
* beginning of a stream.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
void
|
||||
gst_rtsp_stream_set_drop_delta_units (GstRTSPStream * stream, gboolean drop)
|
||||
{
|
||||
GstRTSPStreamPrivate *priv;
|
||||
|
||||
g_return_if_fail (GST_IS_RTSP_STREAM (stream));
|
||||
priv = stream->priv;
|
||||
g_mutex_lock (&priv->lock);
|
||||
priv->drop_delta_units = drop;
|
||||
g_mutex_unlock (&priv->lock);
|
||||
}
|
||||
|
|
|
@ -146,6 +146,8 @@ gstsdp_dep = dependency('gstreamer-sdp-1.0', version : gst_req,
|
|||
fallback : ['gst-plugins-base', 'sdp_dep'])
|
||||
gstapp_dep = dependency('gstreamer-app-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'app_dep'])
|
||||
gstvideo_dep = dependency('gstreamer-video-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'video_dep'])
|
||||
gstnet_dep = dependency('gstreamer-net-1.0', version : gst_req,
|
||||
fallback : ['gstreamer', 'gst_net_dep'])
|
||||
if host_machine.system() != 'windows'
|
||||
|
|
|
@ -57,7 +57,8 @@ foreach test_name : rtsp_server_tests
|
|||
exe = executable(test_name, fname,
|
||||
include_directories : rtspserver_incs,
|
||||
c_args : rtspserver_args + test_c_args,
|
||||
dependencies : [gstcheck_dep, gstrtsp_dep, gstrtp_dep, gst_rtsp_server_dep]
|
||||
dependencies : [gstcheck_dep, gstrtsp_dep, gstrtp_dep, gst_rtsp_server_dep,
|
||||
gstvideo_dep]
|
||||
)
|
||||
test(test_name, exe,
|
||||
env : env,
|
||||
|
|
Loading…
Reference in a new issue