rtpbin/session: Add new ntp-time-source property and deprecate use-pipeline-clock property

The new property allows to select the time source that should be used for the
NTP time in RTCP packets. By default it will continue to calculate the NTP
timestamp (1900 epoch) based on the realtime clock. Alternatively it can use
the UNIX timestamp (1970 epoch), the pipeline's running time or the pipeline's
clock time. The latter is especially useful for synchronizing multiple
receivers if all of them share the same clock.

If use-pipeline-clock is set to TRUE, it will override the ntp-time-source
setting and continue to use the running time plus 70 years. This is only kept
for backwards compatibility.
This commit is contained in:
Sebastian Dröge 2015-06-12 23:29:19 +02:00
parent 74dcd85de4
commit dc513eb949
4 changed files with 142 additions and 26 deletions

View file

@ -289,6 +289,7 @@ enum
#define DEFAULT_DO_SYNC_EVENT FALSE
#define DEFAULT_DO_RETRANSMISSION FALSE
#define DEFAULT_RTP_PROFILE GST_RTP_PROFILE_AVPF
#define DEFAULT_NTP_TIME_SOURCE GST_RTP_NTP_TIME_SOURCE_NTP
enum
{
@ -306,7 +307,8 @@ enum
PROP_USE_PIPELINE_CLOCK,
PROP_DO_SYNC_EVENT,
PROP_DO_RETRANSMISSION,
PROP_RTP_PROFILE
PROP_RTP_PROFILE,
PROP_NTP_TIME_SOURCE
};
#define GST_RTP_BIN_RTCP_SYNC_TYPE (gst_rtp_bin_rtcp_sync_get_type())
@ -622,8 +624,13 @@ create_session (GstRtpBin * rtpbin, gint id)
/* configure SDES items */
GST_OBJECT_LOCK (rtpbin);
g_object_set (session, "sdes", rtpbin->sdes, "use-pipeline-clock",
rtpbin->use_pipeline_clock, "rtp-profile", rtpbin->rtp_profile, NULL);
g_object_set (session, "sdes", rtpbin->sdes, "rtp-profile",
rtpbin->rtp_profile, NULL);
if (rtpbin->use_pipeline_clock)
g_object_set (session, "use-pipeline-clock", rtpbin->use_pipeline_clock,
NULL);
else
g_object_set (session, "ntp-time-source", rtpbin->ntp_time_source, NULL);
GST_OBJECT_UNLOCK (rtpbin);
/* provide clock_rate to the session manager when needed */
@ -1004,24 +1011,41 @@ get_current_times (GstRtpBin * bin, GstClockTime * running_time,
gst_object_ref (clock);
GST_OBJECT_UNLOCK (bin);
/* get current clock time and convert to running time */
clock_time = gst_clock_get_time (clock);
rt = clock_time - base_time;
if (bin->use_pipeline_clock) {
ntpns = clock_time - base_time;
ntpns = rt;
/* add constant to convert from 1970 based time to 1900 based time */
ntpns += (2208988800LL * GST_SECOND);
} else {
GTimeVal current;
switch (bin->ntp_time_source) {
case GST_RTP_NTP_TIME_SOURCE_NTP:
case GST_RTP_NTP_TIME_SOURCE_UNIX:{
GTimeVal current;
/* get current NTP time */
g_get_current_time (&current);
ntpns = GST_TIMEVAL_TO_TIME (current);
/* get current NTP time */
g_get_current_time (&current);
ntpns = GST_TIMEVAL_TO_TIME (current);
/* add constant to convert from 1970 based time to 1900 based time */
if (bin->ntp_time_source == GST_RTP_NTP_TIME_SOURCE_NTP)
ntpns += (2208988800LL * GST_SECOND);
break;
}
case GST_RTP_NTP_TIME_SOURCE_RUNNING_TIME:
ntpns = rt;
break;
case GST_RTP_NTP_TIME_SOURCE_CLOCK_TIME:
ntpns = clock_time;
break;
default:
g_assert_not_reached ();
break;
}
}
/* add constant to convert from 1970 based time to 1900 based time */
ntpns += (2208988800LL * GST_SECOND);
/* get current clock time and convert to running time */
rt = clock_time - base_time;
gst_object_unref (clock);
} else {
GST_OBJECT_UNLOCK (bin);
@ -2061,9 +2085,10 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass)
g_object_class_install_property (gobject_class, PROP_USE_PIPELINE_CLOCK,
g_param_spec_boolean ("use-pipeline-clock", "Use pipeline clock",
"Use the pipeline running-time to set the NTP time in the RTCP SR messages",
"Use the pipeline running-time to set the NTP time in the RTCP SR messages "
"(DEPRECATED: Use ntp-source property)",
DEFAULT_USE_PIPELINE_CLOCK,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
/**
* GstRtpBin:buffer-mode:
*
@ -2140,6 +2165,12 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass)
GST_TYPE_RTP_PROFILE, DEFAULT_RTP_PROFILE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_NTP_TIME_SOURCE,
g_param_spec_enum ("ntp-time-source", "NTP Time Source",
"NTP time source for RTCP packets",
gst_rtp_ntp_time_source_get_type (), DEFAULT_NTP_TIME_SOURCE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_bin_change_state);
gstelement_class->request_new_pad =
GST_DEBUG_FUNCPTR (gst_rtp_bin_request_new_pad);
@ -2203,6 +2234,7 @@ gst_rtp_bin_init (GstRtpBin * rtpbin)
rtpbin->send_sync_event = DEFAULT_DO_SYNC_EVENT;
rtpbin->do_retransmission = DEFAULT_DO_RETRANSMISSION;
rtpbin->rtp_profile = DEFAULT_RTP_PROFILE;
rtpbin->ntp_time_source = DEFAULT_NTP_TIME_SOURCE;
/* some default SDES entries */
cname = g_strdup_printf ("user%u@host-%x", g_random_int (), g_random_int ());
@ -2366,6 +2398,20 @@ gst_rtp_bin_set_property (GObject * object, guint prop_id,
case PROP_RTP_PROFILE:
rtpbin->rtp_profile = g_value_get_enum (value);
break;
case PROP_NTP_TIME_SOURCE:{
GSList *sessions;
GST_RTP_BIN_LOCK (rtpbin);
rtpbin->ntp_time_source = g_value_get_enum (value);
for (sessions = rtpbin->sessions; sessions;
sessions = g_slist_next (sessions)) {
GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
g_object_set (G_OBJECT (session->session),
"ntp-time-source", rtpbin->ntp_time_source, NULL);
}
GST_RTP_BIN_UNLOCK (rtpbin);
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -2431,6 +2477,9 @@ gst_rtp_bin_get_property (GObject * object, guint prop_id,
case PROP_RTP_PROFILE:
g_value_set_enum (value, rtpbin->rtp_profile);
break;
case PROP_NTP_TIME_SOURCE:
g_value_set_enum (value, rtpbin->ntp_time_source);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;

View file

@ -23,6 +23,7 @@
#include <gst/gst.h>
#include "rtpsession.h"
#include "gstrtpsession.h"
#include "rtpjitterbuffer.h"
#define GST_TYPE_RTP_BIN \
@ -63,6 +64,7 @@ struct _GstRtpBin {
RTPJitterBufferMode buffer_mode;
gboolean buffering;
gboolean use_pipeline_clock;
GstRtpNtpTimeSource ntp_time_source;
gboolean send_sync_event;
GstClockTime buffer_start;
gboolean do_retransmission;

View file

@ -122,6 +122,26 @@
GST_DEBUG_CATEGORY_STATIC (gst_rtp_session_debug);
#define GST_CAT_DEFAULT gst_rtp_session_debug
GType
gst_rtp_ntp_time_source_get_type (void)
{
static GType type = 0;
static const GEnumValue values[] = {
{GST_RTP_NTP_TIME_SOURCE_NTP, "NTP time based on realtime clock", "ntp"},
{GST_RTP_NTP_TIME_SOURCE_UNIX, "UNIX time based on realtime clock", "unix"},
{GST_RTP_NTP_TIME_SOURCE_RUNNING_TIME,
"Running time based on pipeline clock",
"running-time"},
{GST_RTP_NTP_TIME_SOURCE_CLOCK_TIME, "Pipeline clock time", "clock-time"},
{0, NULL, NULL},
};
if (!type) {
type = g_enum_register_static ("GstRtpNtpTimeSource", values);
}
return type;
}
/* sink pads */
static GstStaticPadTemplate rtpsession_recv_rtp_sink_template =
GST_STATIC_PAD_TEMPLATE ("recv_rtp_sink",
@ -202,6 +222,7 @@ enum
#define DEFAULT_RTCP_MIN_INTERVAL (RTP_STATS_MIN_INTERVAL * GST_SECOND)
#define DEFAULT_PROBATION RTP_DEFAULT_PROBATION
#define DEFAULT_RTP_PROFILE GST_RTP_PROFILE_AVP
#define DEFAULT_NTP_TIME_SOURCE GST_RTP_NTP_TIME_SOURCE_NTP
enum
{
@ -218,7 +239,8 @@ enum
PROP_RTCP_MIN_INTERVAL,
PROP_PROBATION,
PROP_STATS,
PROP_RTP_PROFILE
PROP_RTP_PROFILE,
PROP_NTP_TIME_SOURCE
};
#define GST_RTP_SESSION_GET_PRIVATE(obj) \
@ -251,6 +273,7 @@ struct _GstRtpSessionPrivate
GstClockTime send_latency;
gboolean use_pipeline_clock;
GstRtpNtpTimeSource ntp_time_source;
guint rtx_count;
};
@ -611,9 +634,10 @@ gst_rtp_session_class_init (GstRtpSessionClass * klass)
g_object_class_install_property (gobject_class, PROP_USE_PIPELINE_CLOCK,
g_param_spec_boolean ("use-pipeline-clock", "Use pipeline clock",
"Use the pipeline running-time to set the NTP time in the RTCP SR messages",
"Use the pipeline running-time to set the NTP time in the RTCP SR messages "
"(DEPRECATED: Use ntp-source property)",
DEFAULT_USE_PIPELINE_CLOCK,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
g_object_class_install_property (gobject_class, PROP_RTCP_MIN_INTERVAL,
g_param_spec_uint64 ("rtcp-min-interval", "Minimum RTCP interval",
@ -652,6 +676,12 @@ gst_rtp_session_class_init (GstRtpSessionClass * klass)
"RTP profile to use", GST_TYPE_RTP_PROFILE, DEFAULT_RTP_PROFILE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_NTP_TIME_SOURCE,
g_param_spec_enum ("ntp-time-source", "NTP Time Source",
"NTP time source for RTCP packets",
gst_rtp_ntp_time_source_get_type (), DEFAULT_NTP_TIME_SOURCE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_rtp_session_change_state);
gstelement_class->request_new_pad =
@ -727,6 +757,8 @@ gst_rtp_session_init (GstRtpSession * rtpsession)
rtpsession->priv->thread_stopped = TRUE;
rtpsession->priv->rtx_count = 0;
rtpsession->priv->ntp_time_source = DEFAULT_NTP_TIME_SOURCE;
}
static void
@ -786,6 +818,9 @@ gst_rtp_session_set_property (GObject * object, guint prop_id,
case PROP_RTP_PROFILE:
g_object_set_property (G_OBJECT (priv->session), "rtp-profile", value);
break;
case PROP_NTP_TIME_SOURCE:
priv->ntp_time_source = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -846,6 +881,9 @@ gst_rtp_session_get_property (GObject * object, guint prop_id,
case PROP_RTP_PROFILE:
g_object_get_property (G_OBJECT (priv->session), "rtp-profile", value);
break;
case PROP_NTP_TIME_SOURCE:
g_value_set_enum (value, priv->ntp_time_source);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -884,17 +922,35 @@ get_current_times (GstRtpSession * rtpsession, GstClockTime * running_time,
if (rtpsession->priv->use_pipeline_clock) {
ntpns = rt;
/* add constant to convert from 1970 based time to 1900 based time */
ntpns += (2208988800LL * GST_SECOND);
} else {
GTimeVal current;
switch (rtpsession->priv->ntp_time_source) {
case GST_RTP_NTP_TIME_SOURCE_NTP:
case GST_RTP_NTP_TIME_SOURCE_UNIX:{
GTimeVal current;
/* get current NTP time */
g_get_current_time (&current);
ntpns = GST_TIMEVAL_TO_TIME (current);
/* get current NTP time */
g_get_current_time (&current);
ntpns = GST_TIMEVAL_TO_TIME (current);
/* add constant to convert from 1970 based time to 1900 based time */
if (rtpsession->priv->ntp_time_source == GST_RTP_NTP_TIME_SOURCE_NTP)
ntpns += (2208988800LL * GST_SECOND);
break;
}
case GST_RTP_NTP_TIME_SOURCE_RUNNING_TIME:
ntpns = rt;
break;
case GST_RTP_NTP_TIME_SOURCE_CLOCK_TIME:
ntpns = clock_time;
break;
default:
g_assert_not_reached ();
break;
}
}
/* add constant to convert from 1970 based time to 1900 based time */
ntpns += (2208988800LL * GST_SECOND);
gst_object_unref (clock);
} else {
GST_OBJECT_UNLOCK (rtpsession);

View file

@ -76,4 +76,13 @@ struct _GstRtpSessionClass {
GType gst_rtp_session_get_type (void);
typedef enum {
GST_RTP_NTP_TIME_SOURCE_NTP,
GST_RTP_NTP_TIME_SOURCE_UNIX,
GST_RTP_NTP_TIME_SOURCE_RUNNING_TIME,
GST_RTP_NTP_TIME_SOURCE_CLOCK_TIME
} GstRtpNtpTimeSource;
GType gst_rtp_ntp_time_source_get_type (void);
#endif /* __GST_RTP_SESSION_H__ */