mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-09 08:55:33 +00:00
rtsp-server: Implement clock signalling according to RFC7273
For NTP and PTP clocks we signal the actual clock that is used and signal the direct media clock offset. For all other clocks we at least signal that it's the local sender clock. This allows receivers to know which clock was used to generate the media and its RTP timestamps. Receivers can then implement network synchronization, either absolute or at least relative by getting the sender clock rate directly via NTP/PTP instead of estimating it from RTP timestamps and packet receive times. https://bugzilla.gnome.org/show_bug.cgi?id=760005
This commit is contained in:
parent
b63a6f029f
commit
9fab555cc5
8 changed files with 363 additions and 0 deletions
|
@ -1042,10 +1042,12 @@ handle_pause_request (GstRTSPClient * client, GstRTSPContext * ctx)
|
|||
GstRTSPSession *session;
|
||||
GstRTSPClientClass *klass;
|
||||
GstRTSPSessionMedia *sessmedia;
|
||||
GstRTSPMedia *media;
|
||||
GstRTSPStatusCode code;
|
||||
GstRTSPState rtspstate;
|
||||
gchar *path;
|
||||
gint matched;
|
||||
guint i, n;
|
||||
|
||||
if (!(session = ctx->session))
|
||||
goto no_session;
|
||||
|
@ -1066,6 +1068,16 @@ handle_pause_request (GstRTSPClient * client, GstRTSPContext * ctx)
|
|||
|
||||
g_free (path);
|
||||
|
||||
media = gst_rtsp_session_media_get_media (sessmedia);
|
||||
n = gst_rtsp_media_n_streams (media);
|
||||
for (i = 0; i < n; i++) {
|
||||
GstRTSPStream *stream = gst_rtsp_media_get_stream (media, i);
|
||||
|
||||
if (gst_rtsp_stream_get_publish_clock_mode (stream) ==
|
||||
GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET)
|
||||
goto not_supported;
|
||||
}
|
||||
|
||||
ctx->sessmedia = sessmedia;
|
||||
|
||||
rtspstate = gst_rtsp_session_media_get_rtsp_state (sessmedia);
|
||||
|
@ -1126,6 +1138,12 @@ invalid_state:
|
|||
ctx);
|
||||
return FALSE;
|
||||
}
|
||||
not_supported:
|
||||
{
|
||||
GST_ERROR ("client %p: pausing not supported", client);
|
||||
send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* convert @url and @path to a URL used as a content base for the factory
|
||||
|
|
|
@ -72,6 +72,8 @@ struct _GstRTSPMediaFactoryPrivate
|
|||
GType media_gtype;
|
||||
|
||||
GstClock *clock;
|
||||
|
||||
GstRTSPPublishClockMode publish_clock_mode;
|
||||
};
|
||||
|
||||
#define DEFAULT_LAUNCH NULL
|
||||
|
@ -261,6 +263,7 @@ gst_rtsp_media_factory_init (GstRTSPMediaFactory * factory)
|
|||
priv->latency = DEFAULT_LATENCY;
|
||||
priv->transport_mode = DEFAULT_TRANSPORT_MODE;
|
||||
priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
|
||||
priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
|
||||
|
||||
g_mutex_init (&priv->lock);
|
||||
g_mutex_init (&priv->medias_lock);
|
||||
|
@ -1335,6 +1338,51 @@ gst_rtsp_media_factory_get_clock (GstRTSPMediaFactory * factory)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_factory_set_publish_clock_mode:
|
||||
* @factory: a #GstRTSPMediaFactory
|
||||
* @mode: the clock publish mode
|
||||
*
|
||||
* Sets if and how the media clock should be published according to RFC7273.
|
||||
*
|
||||
* Since: 1.8
|
||||
*/
|
||||
void
|
||||
gst_rtsp_media_factory_set_publish_clock_mode (GstRTSPMediaFactory * factory,
|
||||
GstRTSPPublishClockMode mode)
|
||||
{
|
||||
GstRTSPMediaFactoryPrivate *priv;
|
||||
|
||||
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
|
||||
priv = factory->priv;
|
||||
priv->publish_clock_mode = mode;
|
||||
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_factory_get_publish_clock_mode:
|
||||
* @factory: a #GstRTSPMediaFactory
|
||||
*
|
||||
* Gets if and how the media clock should be published according to RFC7273.
|
||||
*
|
||||
* Returns: The GstRTSPPublishClockMode
|
||||
*
|
||||
* Since: 1.8
|
||||
*/
|
||||
GstRTSPPublishClockMode
|
||||
gst_rtsp_media_factory_get_publish_clock_mode (GstRTSPMediaFactory * factory)
|
||||
{
|
||||
GstRTSPMediaFactoryPrivate *priv;
|
||||
GstRTSPPublishClockMode ret;
|
||||
|
||||
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
|
||||
priv = factory->priv;
|
||||
ret = priv->publish_clock_mode;
|
||||
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
default_gen_key (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
|
||||
{
|
||||
|
@ -1480,6 +1528,7 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
|
|||
GstRTSPTransportMode transport_mode;
|
||||
GstClock *clock;
|
||||
gchar *multicast_iface;
|
||||
GstRTSPPublishClockMode publish_clock_mode;
|
||||
|
||||
/* configure the sharedness */
|
||||
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
|
||||
|
@ -1494,6 +1543,7 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
|
|||
transport_mode = priv->transport_mode;
|
||||
stop_on_disconnect = priv->stop_on_disconnect;
|
||||
clock = priv->clock ? gst_object_ref (priv->clock) : NULL;
|
||||
publish_clock_mode = priv->publish_clock_mode;
|
||||
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
|
||||
|
||||
gst_rtsp_media_set_suspend_mode (media, suspend_mode);
|
||||
|
@ -1506,6 +1556,7 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
|
|||
gst_rtsp_media_set_latency (media, latency);
|
||||
gst_rtsp_media_set_transport_mode (media, transport_mode);
|
||||
gst_rtsp_media_set_stop_on_disconnect (media, stop_on_disconnect);
|
||||
gst_rtsp_media_set_publish_clock_mode (media, publish_clock_mode);
|
||||
|
||||
if (clock) {
|
||||
gst_rtsp_media_set_clock (media, clock);
|
||||
|
|
|
@ -168,6 +168,9 @@ void gst_rtsp_media_factory_set_clock (GstRTSPMediaFacto
|
|||
GstClock * clock);
|
||||
GstClock * gst_rtsp_media_factory_get_clock (GstRTSPMediaFactory *factory);
|
||||
|
||||
void gst_rtsp_media_factory_set_publish_clock_mode (GstRTSPMediaFactory * factory, GstRTSPPublishClockMode mode);
|
||||
GstRTSPPublishClockMode gst_rtsp_media_factory_get_publish_clock_mode (GstRTSPMediaFactory * factory);
|
||||
|
||||
/* creating the media from the factory and a url */
|
||||
GstRTSPMedia * gst_rtsp_media_factory_construct (GstRTSPMediaFactory *factory,
|
||||
const GstRTSPUrl *url);
|
||||
|
|
|
@ -141,6 +141,7 @@ struct _GstRTSPMediaPrivate
|
|||
GstClockTime rtx_time; /* protected by lock */
|
||||
guint latency; /* protected by lock */
|
||||
GstClock *clock; /* protected by lock */
|
||||
GstRTSPPublishClockMode publish_clock_mode;
|
||||
};
|
||||
|
||||
#define DEFAULT_SHARED FALSE
|
||||
|
@ -264,6 +265,29 @@ gst_rtsp_transport_mode_get_type (void)
|
|||
return (GType) id;
|
||||
}
|
||||
|
||||
GType
|
||||
gst_rtsp_publish_clock_mode_get_type (void)
|
||||
{
|
||||
static gsize id = 0;
|
||||
static const GEnumValue values[] = {
|
||||
{C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_NONE),
|
||||
"GST_RTSP_PUBLISH_CLOCK_MODE_NONE", "none"},
|
||||
{C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK),
|
||||
"GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK",
|
||||
"clock"},
|
||||
{C_ENUM (GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET),
|
||||
"GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET",
|
||||
"clock-and-offset"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
if (g_once_init_enter (&id)) {
|
||||
GType tmp = g_enum_register_static ("GstRTSPPublishClockMode", values);
|
||||
g_once_init_leave (&id, tmp);
|
||||
}
|
||||
return (GType) id;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
|
@ -415,6 +439,7 @@ gst_rtsp_media_init (GstRTSPMedia * media)
|
|||
priv->time_provider = DEFAULT_TIME_PROVIDER;
|
||||
priv->transport_mode = DEFAULT_TRANSPORT_MODE;
|
||||
priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
|
||||
priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1438,6 +1463,59 @@ gst_rtsp_media_set_clock (GstRTSPMedia * media, GstClock * clock)
|
|||
g_mutex_unlock (&priv->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_set_publish_clock_mode:
|
||||
* @media: a #GstRTSPMedia
|
||||
* @mode: the clock publish mode
|
||||
*
|
||||
* Sets if and how the media clock should be published according to RFC7273.
|
||||
*
|
||||
* Since: 1.8
|
||||
*/
|
||||
void
|
||||
gst_rtsp_media_set_publish_clock_mode (GstRTSPMedia * media,
|
||||
GstRTSPPublishClockMode mode)
|
||||
{
|
||||
GstRTSPMediaPrivate *priv;
|
||||
guint i, n;
|
||||
|
||||
priv = media->priv;
|
||||
g_mutex_lock (&priv->lock);
|
||||
priv->publish_clock_mode = mode;
|
||||
|
||||
n = priv->streams->len;
|
||||
for (i = 0; i < n; i++) {
|
||||
GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
|
||||
|
||||
gst_rtsp_stream_set_publish_clock_mode (stream, mode);
|
||||
}
|
||||
g_mutex_unlock (&priv->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_get_publish_clock_mode:
|
||||
* @factory: a #GstRTSPMedia
|
||||
*
|
||||
* Gets if and how the media clock should be published according to RFC7273.
|
||||
*
|
||||
* Returns: The GstRTSPPublishClockMode
|
||||
*
|
||||
* Since: 1.8
|
||||
*/
|
||||
GstRTSPPublishClockMode
|
||||
gst_rtsp_media_get_publish_clock_mode (GstRTSPMedia * media)
|
||||
{
|
||||
GstRTSPMediaPrivate *priv;
|
||||
GstRTSPPublishClockMode ret;
|
||||
|
||||
priv = media->priv;
|
||||
g_mutex_lock (&priv->lock);
|
||||
ret = priv->publish_clock_mode;
|
||||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_media_set_address_pool:
|
||||
* @media: a #GstRTSPMedia
|
||||
|
@ -1744,6 +1822,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_publish_clock_mode (stream, priv->publish_clock_mode);
|
||||
|
||||
g_ptr_array_add (priv->streams, stream);
|
||||
|
||||
|
@ -2072,6 +2151,18 @@ gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
|
|||
/* TODO: Seeking for RECORD? */
|
||||
priv->seekable = FALSE;
|
||||
} else {
|
||||
guint i, n = priv->streams->len;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
|
||||
|
||||
if (gst_rtsp_stream_get_publish_clock_mode (stream) ==
|
||||
GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET) {
|
||||
priv->seekable = FALSE;
|
||||
goto not_seekable;
|
||||
}
|
||||
}
|
||||
|
||||
query = gst_query_new_seeking (GST_FORMAT_TIME);
|
||||
if (gst_element_query (priv->pipeline, query)) {
|
||||
GstFormat format;
|
||||
|
@ -2081,6 +2172,7 @@ gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
|
|||
gst_query_parse_seeking (query, &format, &seekable, &start, &end);
|
||||
priv->seekable = seekable;
|
||||
}
|
||||
|
||||
gst_query_unref (query);
|
||||
}
|
||||
|
||||
|
|
|
@ -88,12 +88,29 @@ typedef enum {
|
|||
GST_RTSP_TRANSPORT_MODE_RECORD = 2,
|
||||
} GstRTSPTransportMode;
|
||||
|
||||
/**
|
||||
* GstRTSPPublishClockMode:
|
||||
* @GST_RTSP_PUBLISH_CLOCK_MODE_NONE: Publish nothing
|
||||
* @GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK: Publish the clock but not the offset
|
||||
* @GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET: Publish the clock and offset
|
||||
*
|
||||
* Whether the clock and possibly RTP/clock offset should be published according to RFC7273.
|
||||
*/
|
||||
typedef enum {
|
||||
GST_RTSP_PUBLISH_CLOCK_MODE_NONE,
|
||||
GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK,
|
||||
GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET
|
||||
} GstRTSPPublishClockMode;
|
||||
|
||||
#define GST_TYPE_RTSP_TRANSPORT_MODE (gst_rtsp_transport_mode_get_type())
|
||||
GType gst_rtsp_transport_mode_get_type (void);
|
||||
|
||||
#define GST_TYPE_RTSP_SUSPEND_MODE (gst_rtsp_suspend_mode_get_type())
|
||||
GType gst_rtsp_suspend_mode_get_type (void);
|
||||
|
||||
#define GST_TYPE_RTSP_PUBLISH_CLOCK_MODE (gst_rtsp_publish_clock_mode_get_type())
|
||||
GType gst_rtsp_publish_clock_mode_get_type (void);
|
||||
|
||||
#include "rtsp-stream.h"
|
||||
#include "rtsp-thread-pool.h"
|
||||
#include "rtsp-permissions.h"
|
||||
|
@ -226,6 +243,10 @@ GstNetTimeProvider * gst_rtsp_media_get_time_provider (GstRTSPMedia *media,
|
|||
|
||||
void gst_rtsp_media_set_clock (GstRTSPMedia *media, GstClock * clock);
|
||||
|
||||
|
||||
void gst_rtsp_media_set_publish_clock_mode (GstRTSPMedia * media, GstRTSPPublishClockMode mode);
|
||||
GstRTSPPublishClockMode gst_rtsp_media_get_publish_clock_mode (GstRTSPMedia * media);
|
||||
|
||||
/* prepare the media for playback */
|
||||
gboolean gst_rtsp_media_prepare (GstRTSPMedia *media, GstRTSPThread *thread);
|
||||
gboolean gst_rtsp_media_unprepare (GstRTSPMedia *media);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include <gst/net/net.h>
|
||||
#include <gst/sdp/gstmikey.h>
|
||||
|
||||
#include "rtsp-sdp.h"
|
||||
|
@ -169,6 +170,100 @@ make_media (GstSDPMessage * sdp, GstSDPInfo * info,
|
|||
gst_mikey_message_unref (mikey_msg);
|
||||
}
|
||||
|
||||
/* RFC 7273 clock signalling */
|
||||
{
|
||||
GstBin *joined_bin = gst_rtsp_stream_get_joined_bin (stream);
|
||||
GstClock *clock = gst_element_get_clock (GST_ELEMENT_CAST (joined_bin));
|
||||
gchar *ts_refclk = NULL;
|
||||
gchar *mediaclk = NULL;
|
||||
guint rtptime, clock_rate;
|
||||
GstClockTime running_time, base_time, clock_time;
|
||||
GstRTSPPublishClockMode publish_clock_mode =
|
||||
gst_rtsp_stream_get_publish_clock_mode (stream);
|
||||
|
||||
gst_rtsp_stream_get_rtpinfo (stream, &rtptime, NULL, &clock_rate,
|
||||
&running_time);
|
||||
base_time = gst_element_get_base_time (GST_ELEMENT_CAST (joined_bin));
|
||||
g_assert (base_time != GST_CLOCK_TIME_NONE);
|
||||
clock_time = running_time + base_time;
|
||||
|
||||
if (publish_clock_mode != GST_RTSP_PUBLISH_CLOCK_MODE_NONE && clock) {
|
||||
if (GST_IS_NTP_CLOCK (clock) || GST_IS_PTP_CLOCK (clock)) {
|
||||
if (publish_clock_mode == GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET) {
|
||||
guint32 mediaclk_offset;
|
||||
|
||||
/* Calculate RTP time at the clock's epoch. That's the direct offset */
|
||||
clock_time =
|
||||
gst_util_uint64_scale (clock_time, clock_rate, GST_SECOND);
|
||||
|
||||
clock_time &= 0xffffffff;
|
||||
mediaclk_offset =
|
||||
G_GUINT64_CONSTANT (0xffffffff) + rtptime - clock_time;
|
||||
mediaclk = g_strdup_printf ("direct=%u", (guint32) mediaclk_offset);
|
||||
}
|
||||
|
||||
if (GST_IS_NTP_CLOCK (clock)) {
|
||||
gchar *ntp_address;
|
||||
guint ntp_port;
|
||||
|
||||
g_object_get (clock, "address", &ntp_address, "port", &ntp_port,
|
||||
NULL);
|
||||
|
||||
if (ntp_port == 123)
|
||||
ts_refclk = g_strdup_printf ("ntp=%s", ntp_address);
|
||||
else
|
||||
ts_refclk = g_strdup_printf ("ntp=%s:%u", ntp_address, ntp_port);
|
||||
|
||||
g_free (ntp_address);
|
||||
} else {
|
||||
guint64 ptp_clock_id;
|
||||
guint ptp_domain;
|
||||
|
||||
g_object_get (clock, "grandmaster-clock-id", &ptp_clock_id, "domain",
|
||||
&ptp_domain, NULL);
|
||||
|
||||
if (ptp_domain != 0)
|
||||
ts_refclk =
|
||||
g_strdup_printf
|
||||
("ptp=IEEE1588-2008:%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X:%u",
|
||||
(guint) (ptp_clock_id >> 56) & 0xff,
|
||||
(guint) (ptp_clock_id >> 48) & 0xff,
|
||||
(guint) (ptp_clock_id >> 40) & 0xff,
|
||||
(guint) (ptp_clock_id >> 32) & 0xff,
|
||||
(guint) (ptp_clock_id >> 24) & 0xff,
|
||||
(guint) (ptp_clock_id >> 16) & 0xff,
|
||||
(guint) (ptp_clock_id >> 8) & 0xff,
|
||||
(guint) (ptp_clock_id >> 0) & 0xff, ptp_domain);
|
||||
else
|
||||
ts_refclk =
|
||||
g_strdup_printf
|
||||
("ptp=IEEE1588-2008:%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
|
||||
(guint) (ptp_clock_id >> 56) & 0xff,
|
||||
(guint) (ptp_clock_id >> 48) & 0xff,
|
||||
(guint) (ptp_clock_id >> 40) & 0xff,
|
||||
(guint) (ptp_clock_id >> 32) & 0xff,
|
||||
(guint) (ptp_clock_id >> 24) & 0xff,
|
||||
(guint) (ptp_clock_id >> 16) & 0xff,
|
||||
(guint) (ptp_clock_id >> 8) & 0xff,
|
||||
(guint) (ptp_clock_id >> 0) & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clock)
|
||||
gst_object_unref (clock);
|
||||
|
||||
if (!ts_refclk)
|
||||
ts_refclk = g_strdup ("local");
|
||||
if (!mediaclk)
|
||||
mediaclk = g_strdup ("sender");
|
||||
|
||||
gst_sdp_media_add_attribute (smedia, "ts-refclk", ts_refclk);
|
||||
gst_sdp_media_add_attribute (smedia, "mediaclk", mediaclk);
|
||||
g_free (ts_refclk);
|
||||
g_free (mediaclk);
|
||||
gst_object_unref (joined_bin);
|
||||
}
|
||||
|
||||
update_sdp_from_tags (stream, smedia);
|
||||
|
||||
if ((profile == GST_RTSP_PROFILE_AVPF || profile == GST_RTSP_PROFILE_SAVPF)
|
||||
|
|
|
@ -71,6 +71,7 @@ struct _GstRTSPStreamPrivate
|
|||
GstElement *payloader;
|
||||
guint buffer_size;
|
||||
gboolean is_joined;
|
||||
GstBin *joined_bin;
|
||||
|
||||
/* TRUE if this stream is running on
|
||||
* the client side of an RTSP link (for RECORD) */
|
||||
|
@ -164,6 +165,8 @@ struct _GstRTSPStreamPrivate
|
|||
|
||||
/* pt->caps map for RECORD streams */
|
||||
GHashTable *ptmap;
|
||||
|
||||
GstRTSPPublishClockMode publish_clock_mode;
|
||||
};
|
||||
|
||||
#define DEFAULT_CONTROL NULL
|
||||
|
@ -259,6 +262,7 @@ gst_rtsp_stream_init (GstRTSPStream * stream)
|
|||
priv->control = g_strdup (DEFAULT_CONTROL);
|
||||
priv->profiles = DEFAULT_PROFILES;
|
||||
priv->protocols = DEFAULT_PROTOCOLS;
|
||||
priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
|
||||
|
||||
g_mutex_init (&priv->lock);
|
||||
|
||||
|
@ -2281,6 +2285,51 @@ gst_rtsp_stream_set_pt_map (GstRTSPStream * stream, guint pt, GstCaps * caps)
|
|||
g_mutex_unlock (&priv->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_stream_set_publish_clock_mode:
|
||||
* @stream: a #GstRTSPStream
|
||||
* @mode: the clock publish mode
|
||||
*
|
||||
* Sets if and how the stream clock should be published according to RFC7273.
|
||||
*
|
||||
* Since: 1.8
|
||||
*/
|
||||
void
|
||||
gst_rtsp_stream_set_publish_clock_mode (GstRTSPStream * stream,
|
||||
GstRTSPPublishClockMode mode)
|
||||
{
|
||||
GstRTSPStreamPrivate *priv;
|
||||
|
||||
priv = stream->priv;
|
||||
g_mutex_lock (&priv->lock);
|
||||
priv->publish_clock_mode = mode;
|
||||
g_mutex_unlock (&priv->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_stream_get_publish_clock_mode:
|
||||
* @factory: a #GstRTSPStream
|
||||
*
|
||||
* Gets if and how the stream clock should be published according to RFC7273.
|
||||
*
|
||||
* Returns: The GstRTSPPublishClockMode
|
||||
*
|
||||
* Since: 1.8
|
||||
*/
|
||||
GstRTSPPublishClockMode
|
||||
gst_rtsp_stream_get_publish_clock_mode (GstRTSPStream * stream)
|
||||
{
|
||||
GstRTSPStreamPrivate *priv;
|
||||
GstRTSPPublishClockMode ret;
|
||||
|
||||
priv = stream->priv;
|
||||
g_mutex_lock (&priv->lock);
|
||||
ret = priv->publish_clock_mode;
|
||||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
request_pt_map (GstElement * rtpbin, guint session, guint pt,
|
||||
GstRTSPStream * stream)
|
||||
|
@ -2730,6 +2779,7 @@ gst_rtsp_stream_join_bin (GstRTSPStream * stream, GstBin * bin,
|
|||
(GCallback) caps_notify, stream);
|
||||
}
|
||||
|
||||
priv->joined_bin = bin;
|
||||
priv->is_joined = TRUE;
|
||||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
|
@ -2839,6 +2889,8 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin,
|
|||
if (!priv->is_joined)
|
||||
goto was_not_joined;
|
||||
|
||||
priv->joined_bin = NULL;
|
||||
|
||||
/* all transports must be removed by now */
|
||||
if (priv->transports != NULL)
|
||||
goto transports_not_removed;
|
||||
|
@ -3013,6 +3065,31 @@ transports_not_removed:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_stream_get_joined_bin:
|
||||
* @stream: a #GstRTSPStream
|
||||
*
|
||||
* Get the previous joined bin with gst_rtsp_stream_join_bin() or NULL.
|
||||
*
|
||||
* Return: (transfer full): the joined bin or NULL.
|
||||
*/
|
||||
GstBin *
|
||||
gst_rtsp_stream_get_joined_bin (GstRTSPStream * stream)
|
||||
{
|
||||
GstRTSPStreamPrivate *priv;
|
||||
GstBin *bin = NULL;
|
||||
|
||||
g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
|
||||
|
||||
priv = stream->priv;
|
||||
|
||||
g_mutex_lock (&priv->lock);
|
||||
bin = priv->joined_bin ? gst_object_ref (priv->joined_bin) : NULL;
|
||||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_stream_get_rtpinfo:
|
||||
* @stream: a #GstRTSPStream
|
||||
|
|
|
@ -43,6 +43,7 @@ typedef struct _GstRTSPStreamPrivate GstRTSPStreamPrivate;
|
|||
#include "rtsp-stream-transport.h"
|
||||
#include "rtsp-address-pool.h"
|
||||
#include "rtsp-session.h"
|
||||
#include "rtsp-media.h"
|
||||
|
||||
/**
|
||||
* GstRTSPStream:
|
||||
|
@ -110,6 +111,7 @@ gboolean gst_rtsp_stream_join_bin (GstRTSPStream *stream,
|
|||
GstState state);
|
||||
gboolean gst_rtsp_stream_leave_bin (GstRTSPStream *stream,
|
||||
GstBin *bin, GstElement *rtpbin);
|
||||
GstBin * gst_rtsp_stream_get_joined_bin (GstRTSPStream *stream);
|
||||
|
||||
gboolean gst_rtsp_stream_set_blocked (GstRTSPStream * stream,
|
||||
gboolean blocked);
|
||||
|
@ -174,6 +176,10 @@ GstElement * gst_rtsp_stream_request_aux_sender (GstRTSPStream * st
|
|||
|
||||
gboolean gst_rtsp_stream_allocate_udp_sockets (GstRTSPStream * stream, GSocketFamily family,
|
||||
GstRTSPTransport *transport, gboolean use_client_setttings);
|
||||
|
||||
void gst_rtsp_stream_set_publish_clock_mode (GstRTSPStream * stream, GstRTSPPublishClockMode mode);
|
||||
GstRTSPPublishClockMode gst_rtsp_stream_get_publish_clock_mode (GstRTSPStream * stream);
|
||||
|
||||
/**
|
||||
* GstRTSPStreamTransportFilterFunc:
|
||||
* @stream: a #GstRTSPStream object
|
||||
|
|
Loading…
Reference in a new issue