From a0ae6b5b5a73d1afeeeced38e61bf1f106f9eb12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 16 Sep 2015 19:28:11 +0200 Subject: [PATCH] rtpbin/session: Allow RTCP sync to happen based on capture time or send time Send time is the previous behaviour and the default, but there are use cases where you want to synchronize based on the capture time. https://bugzilla.gnome.org/show_bug.cgi?id=755125 --- gst/rtpmanager/gstrtpbin.c | 32 ++++++++++++++++++++++++++++++-- gst/rtpmanager/gstrtpbin.h | 1 + gst/rtpmanager/gstrtpsession.c | 22 ++++++++++++++++++++-- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 21e1cd8263..a65fc7cb99 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -290,6 +290,7 @@ enum #define DEFAULT_DO_RETRANSMISSION FALSE #define DEFAULT_RTP_PROFILE GST_RTP_PROFILE_AVP #define DEFAULT_NTP_TIME_SOURCE GST_RTP_NTP_TIME_SOURCE_NTP +#define DEFAULT_RTCP_SYNC_SEND_TIME TRUE enum { @@ -308,7 +309,8 @@ enum PROP_DO_SYNC_EVENT, PROP_DO_RETRANSMISSION, PROP_RTP_PROFILE, - PROP_NTP_TIME_SOURCE + PROP_NTP_TIME_SOURCE, + PROP_RTCP_SYNC_SEND_TIME }; #define GST_RTP_BIN_RTCP_SYNC_TYPE (gst_rtp_bin_rtcp_sync_get_type()) @@ -625,7 +627,8 @@ create_session (GstRtpBin * rtpbin, gint id) /* configure SDES items */ GST_OBJECT_LOCK (rtpbin); g_object_set (session, "sdes", rtpbin->sdes, "rtp-profile", - rtpbin->rtp_profile, NULL); + rtpbin->rtp_profile, "rtcp-sync-send-time", rtpbin->rtcp_sync_send_time, + NULL); if (rtpbin->use_pipeline_clock) g_object_set (session, "use-pipeline-clock", rtpbin->use_pipeline_clock, NULL); @@ -2171,6 +2174,13 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) gst_rtp_ntp_time_source_get_type (), DEFAULT_NTP_TIME_SOURCE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_RTCP_SYNC_SEND_TIME, + g_param_spec_boolean ("rtcp-sync-send-time", "RTCP Sync Send Time", + "Use send time or capture time for RTCP sync " + "(TRUE = send time, FALSE = capture time)", + DEFAULT_RTCP_SYNC_SEND_TIME, + 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); @@ -2235,6 +2245,7 @@ gst_rtp_bin_init (GstRtpBin * rtpbin) rtpbin->do_retransmission = DEFAULT_DO_RETRANSMISSION; rtpbin->rtp_profile = DEFAULT_RTP_PROFILE; rtpbin->ntp_time_source = DEFAULT_NTP_TIME_SOURCE; + rtpbin->rtcp_sync_send_time = DEFAULT_RTCP_SYNC_SEND_TIME; /* some default SDES entries */ cname = g_strdup_printf ("user%u@host-%x", g_random_int (), g_random_int ()); @@ -2412,6 +2423,20 @@ gst_rtp_bin_set_property (GObject * object, guint prop_id, GST_RTP_BIN_UNLOCK (rtpbin); break; } + case PROP_RTCP_SYNC_SEND_TIME:{ + GSList *sessions; + GST_RTP_BIN_LOCK (rtpbin); + rtpbin->rtcp_sync_send_time = g_value_get_boolean (value); + for (sessions = rtpbin->sessions; sessions; + sessions = g_slist_next (sessions)) { + GstRtpBinSession *session = (GstRtpBinSession *) sessions->data; + + g_object_set (G_OBJECT (session->session), + "rtcp-sync-send-time", rtpbin->rtcp_sync_send_time, NULL); + } + GST_RTP_BIN_UNLOCK (rtpbin); + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2480,6 +2505,9 @@ gst_rtp_bin_get_property (GObject * object, guint prop_id, case PROP_NTP_TIME_SOURCE: g_value_set_enum (value, rtpbin->ntp_time_source); break; + case PROP_RTCP_SYNC_SEND_TIME: + g_value_set_boolean (value, rtpbin->rtcp_sync_send_time); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/rtpmanager/gstrtpbin.h b/gst/rtpmanager/gstrtpbin.h index 87c1fada4c..41ab38cfba 100644 --- a/gst/rtpmanager/gstrtpbin.h +++ b/gst/rtpmanager/gstrtpbin.h @@ -69,6 +69,7 @@ struct _GstRtpBin { GstClockTime buffer_start; gboolean do_retransmission; GstRTPProfile rtp_profile; + gboolean rtcp_sync_send_time; /* a list of session */ GSList *sessions; diff --git a/gst/rtpmanager/gstrtpsession.c b/gst/rtpmanager/gstrtpsession.c index 2604c61fd3..844a75f5de 100644 --- a/gst/rtpmanager/gstrtpsession.c +++ b/gst/rtpmanager/gstrtpsession.c @@ -223,6 +223,7 @@ enum #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 +#define DEFAULT_RTCP_SYNC_SEND_TIME TRUE enum { @@ -240,7 +241,8 @@ enum PROP_PROBATION, PROP_STATS, PROP_RTP_PROFILE, - PROP_NTP_TIME_SOURCE + PROP_NTP_TIME_SOURCE, + PROP_RTCP_SYNC_SEND_TIME }; #define GST_RTP_SESSION_GET_PRIVATE(obj) \ @@ -274,6 +276,7 @@ struct _GstRtpSessionPrivate gboolean use_pipeline_clock; GstRtpNtpTimeSource ntp_time_source; + gboolean rtcp_sync_send_time; guint rtx_count; }; @@ -682,6 +685,13 @@ gst_rtp_session_class_init (GstRtpSessionClass * klass) gst_rtp_ntp_time_source_get_type (), DEFAULT_NTP_TIME_SOURCE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_RTCP_SYNC_SEND_TIME, + g_param_spec_boolean ("rtcp-sync-send-time", "RTCP Sync Send Time", + "Use send time or capture time for RTCP sync " + "(TRUE = send time, FALSE = capture time)", + DEFAULT_RTCP_SYNC_SEND_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_session_change_state); gstelement_class->request_new_pad = @@ -726,6 +736,7 @@ gst_rtp_session_init (GstRtpSession * rtpsession) rtpsession->priv->sysclock = gst_system_clock_obtain (); rtpsession->priv->session = rtp_session_new (); rtpsession->priv->use_pipeline_clock = DEFAULT_USE_PIPELINE_CLOCK; + rtpsession->priv->rtcp_sync_send_time = DEFAULT_RTCP_SYNC_SEND_TIME; /* configure callbacks */ rtp_session_set_callbacks (rtpsession->priv->session, &callbacks, rtpsession); @@ -821,6 +832,9 @@ gst_rtp_session_set_property (GObject * object, guint prop_id, case PROP_NTP_TIME_SOURCE: priv->ntp_time_source = g_value_get_enum (value); break; + case PROP_RTCP_SYNC_SEND_TIME: + priv->rtcp_sync_send_time = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -884,6 +898,9 @@ gst_rtp_session_get_property (GObject * object, guint prop_id, case PROP_NTP_TIME_SOURCE: g_value_set_enum (value, priv->ntp_time_source); break; + case PROP_RTCP_SYNC_SEND_TIME: + g_value_set_boolean (value, priv->rtcp_sync_send_time); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2174,7 +2191,8 @@ gst_rtp_session_chain_send_rtp_common (GstRtpSession * rtpsession, running_time = gst_segment_to_running_time (&rtpsession->send_rtp_seg, GST_FORMAT_TIME, timestamp); - running_time += priv->send_latency; + if (priv->rtcp_sync_send_time) + running_time += priv->send_latency; } else { /* no timestamp. */ running_time = -1;