diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 86a572ec92..e966aefc18 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -295,6 +295,8 @@ enum #define DEFAULT_NTP_TIME_SOURCE GST_RTP_NTP_TIME_SOURCE_NTP #define DEFAULT_RTCP_SYNC_SEND_TIME TRUE #define DEFAULT_MAX_RTCP_RTP_TIME_DIFF 1000 +#define DEFAULT_MAX_DROPOUT_TIME 60000 +#define DEFAULT_MAX_MISORDER_TIME 2000 enum { @@ -315,7 +317,9 @@ enum PROP_RTP_PROFILE, PROP_NTP_TIME_SOURCE, PROP_RTCP_SYNC_SEND_TIME, - PROP_MAX_RTCP_RTP_TIME_DIFF + PROP_MAX_RTCP_RTP_TIME_DIFF, + PROP_MAX_DROPOUT_TIME, + PROP_MAX_MISORDER_TIME }; #define GST_RTP_BIN_RTCP_SYNC_TYPE (gst_rtp_bin_rtcp_sync_get_type()) @@ -654,6 +658,9 @@ create_session (GstRtpBin * rtpbin, gint id) NULL); else g_object_set (session, "ntp-time-source", rtpbin->ntp_time_source, NULL); + + g_object_set (session, "max-dropout-time", rtpbin->max_dropout_time, + "max-misorder-time", rtpbin->max_misorder_time, NULL); GST_OBJECT_UNLOCK (rtpbin); /* provide clock_rate to the session manager when needed */ @@ -982,6 +989,21 @@ gst_rtp_bin_propagate_property_to_jitterbuffer (GstRtpBin * bin, GST_RTP_BIN_UNLOCK (bin); } +static void +gst_rtp_bin_propagate_property_to_session (GstRtpBin * bin, + const gchar * name, const GValue * value) +{ + GSList *sessions; + + GST_RTP_BIN_LOCK (bin); + for (sessions = bin->sessions; sessions; sessions = g_slist_next (sessions)) { + GstRtpBinSession *sess = (GstRtpBinSession *) sessions->data; + + g_object_set_property (G_OBJECT (sess->session), name, value); + } + GST_RTP_BIN_UNLOCK (bin); +} + /* get a client with the given SDES name. Must be called with RTP_BIN_LOCK */ static GstRtpBinClient * get_client (GstRtpBin * bin, guint8 len, guint8 * data, gboolean * created) @@ -1579,6 +1601,8 @@ create_stream (GstRtpBinSession * session, guint32 ssrc) g_object_set (buffer, "do-retransmission", rtpbin->do_retransmission, NULL); g_object_set (buffer, "max-rtcp-rtp-time-diff", rtpbin->max_rtcp_rtp_time_diff, NULL); + g_object_set (buffer, "max-dropout-time", rtpbin->max_dropout_time, + "max-misorder-time", rtpbin->max_misorder_time, NULL); g_signal_emit (rtpbin, gst_rtp_bin_signals[SIGNAL_NEW_JITTERBUFFER], 0, buffer, session->id, ssrc); @@ -2245,6 +2269,18 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) DEFAULT_MAX_RTCP_RTP_TIME_DIFF, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_DROPOUT_TIME, + g_param_spec_uint ("max-dropout-time", "Max dropout time", + "The maximum time (milliseconds) of missing packets tolerated.", + 0, G_MAXUINT, DEFAULT_MAX_DROPOUT_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MAX_MISORDER_TIME, + g_param_spec_uint ("max-misorder-time", "Max misorder time", + "The maximum time (milliseconds) of misordered packets tolerated.", + 0, G_MAXUINT, DEFAULT_MAX_MISORDER_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); @@ -2311,6 +2347,8 @@ gst_rtp_bin_init (GstRtpBin * rtpbin) rtpbin->ntp_time_source = DEFAULT_NTP_TIME_SOURCE; rtpbin->rtcp_sync_send_time = DEFAULT_RTCP_SYNC_SEND_TIME; rtpbin->max_rtcp_rtp_time_diff = DEFAULT_MAX_RTCP_RTP_TIME_DIFF; + rtpbin->max_dropout_time = DEFAULT_MAX_DROPOUT_TIME; + rtpbin->max_misorder_time = DEFAULT_MAX_MISORDER_TIME; /* some default SDES entries */ cname = g_strdup_printf ("user%u@host-%x", g_random_int (), g_random_int ()); @@ -2509,6 +2547,24 @@ gst_rtp_bin_set_property (GObject * object, guint prop_id, gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, "max-rtcp-rtp-time-diff", value); break; + case PROP_MAX_DROPOUT_TIME: + GST_RTP_BIN_LOCK (rtpbin); + rtpbin->max_dropout_time = g_value_get_uint (value); + GST_RTP_BIN_UNLOCK (rtpbin); + gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, + "max-dropout-time", value); + gst_rtp_bin_propagate_property_to_session (rtpbin, "max-dropout-time", + value); + break; + case PROP_MAX_MISORDER_TIME: + GST_RTP_BIN_LOCK (rtpbin); + rtpbin->max_misorder_time = g_value_get_uint (value); + GST_RTP_BIN_UNLOCK (rtpbin); + gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, + "max-misorder-time", value); + gst_rtp_bin_propagate_property_to_session (rtpbin, "max-dropout-time", + value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2584,6 +2640,12 @@ gst_rtp_bin_get_property (GObject * object, guint prop_id, GST_RTP_BIN_LOCK (rtpbin); g_value_set_int (value, rtpbin->max_rtcp_rtp_time_diff); GST_RTP_BIN_UNLOCK (rtpbin); + case PROP_MAX_DROPOUT_TIME: + g_value_set_uint (value, rtpbin->max_dropout_time); + break; + case PROP_MAX_MISORDER_TIME: + g_value_set_uint (value, rtpbin->max_misorder_time); + break; break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); diff --git a/gst/rtpmanager/gstrtpbin.h b/gst/rtpmanager/gstrtpbin.h index 20dab2bb4e..e74a718045 100644 --- a/gst/rtpmanager/gstrtpbin.h +++ b/gst/rtpmanager/gstrtpbin.h @@ -71,6 +71,8 @@ struct _GstRtpBin { GstRTPProfile rtp_profile; gboolean rtcp_sync_send_time; gint max_rtcp_rtp_time_diff; + guint32 max_dropout_time; + guint32 max_misorder_time; /* a list of session */ GSList *sessions; diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index a11c200b53..7fcb729e3e 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -137,6 +137,8 @@ enum #define DEFAULT_RTX_RETRY_PERIOD -1 #define DEFAULT_RTX_MAX_RETRIES -1 #define DEFAULT_MAX_RTCP_RTP_TIME_DIFF 1000 +#define DEFAULT_MAX_DROPOUT_TIME 60000 +#define DEFAULT_MAX_MISORDER_TIME 2000 #define DEFAULT_AUTO_RTX_DELAY (20 * GST_MSECOND) #define DEFAULT_AUTO_RTX_TIMEOUT (40 * GST_MSECOND) @@ -160,7 +162,9 @@ enum PROP_RTX_RETRY_PERIOD, PROP_RTX_MAX_RETRIES, PROP_STATS, - PROP_MAX_RTCP_RTP_TIME_DIFF + PROP_MAX_RTCP_RTP_TIME_DIFF, + PROP_MAX_DROPOUT_TIME, + PROP_MAX_MISORDER_TIME }; #define JBUF_LOCK(priv) (g_mutex_lock (&(priv)->jbuf_lock)) @@ -258,6 +262,8 @@ struct _GstRtpJitterBufferPrivate gint rtx_retry_period; gint rtx_max_retries; gint max_rtcp_rtp_time_diff; + guint32 max_dropout_time; + guint32 max_misorder_time; /* the last seqnum we pushed out */ guint32 last_popped_seqnum; @@ -664,6 +670,18 @@ gst_rtp_jitter_buffer_class_init (GstRtpJitterBufferClass * klass) "The maximum number of retries to request a retransmission. " "(-1 not limited)", -1, G_MAXINT, DEFAULT_RTX_MAX_RETRIES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MAX_DROPOUT_TIME, + g_param_spec_uint ("max-dropout-time", "Max dropout time", + "The maximum time (milliseconds) of missing packets tolerated.", + 0, G_MAXUINT, DEFAULT_MAX_DROPOUT_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MAX_MISORDER_TIME, + g_param_spec_uint ("max-misorder-time", "Max misorder time", + "The maximum time (milliseconds) of misordered packets tolerated.", + 0, G_MAXUINT, DEFAULT_MAX_MISORDER_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** * GstRtpJitterBuffer:stats: * @@ -842,6 +860,8 @@ gst_rtp_jitter_buffer_init (GstRtpJitterBuffer * jitterbuffer) priv->rtx_retry_period = DEFAULT_RTX_RETRY_PERIOD; priv->rtx_max_retries = DEFAULT_RTX_MAX_RETRIES; priv->max_rtcp_rtp_time_diff = DEFAULT_MAX_RTCP_RTP_TIME_DIFF; + priv->max_dropout_time = DEFAULT_MAX_DROPOUT_TIME; + priv->max_misorder_time = DEFAULT_MAX_MISORDER_TIME; priv->last_dts = -1; priv->last_rtptime = -1; @@ -3959,6 +3979,16 @@ gst_rtp_jitter_buffer_set_property (GObject * object, priv->max_rtcp_rtp_time_diff = g_value_get_int (value); JBUF_UNLOCK (priv); break; + case PROP_MAX_DROPOUT_TIME: + JBUF_LOCK (priv); + priv->max_dropout_time = g_value_get_uint (value); + JBUF_UNLOCK (priv); + break; + case PROP_MAX_MISORDER_TIME: + JBUF_LOCK (priv); + priv->max_misorder_time = g_value_get_uint (value); + JBUF_UNLOCK (priv); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -4069,6 +4099,16 @@ gst_rtp_jitter_buffer_get_property (GObject * object, g_value_set_int (value, priv->max_rtcp_rtp_time_diff); JBUF_UNLOCK (priv); break; + case PROP_MAX_DROPOUT_TIME: + JBUF_LOCK (priv); + g_value_set_uint (value, priv->max_dropout_time); + JBUF_UNLOCK (priv); + break; + case PROP_MAX_MISORDER_TIME: + JBUF_LOCK (priv); + g_value_set_uint (value, priv->max_misorder_time); + JBUF_UNLOCK (priv); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/rtpmanager/gstrtpsession.c b/gst/rtpmanager/gstrtpsession.c index 5d3e7a38a8..985b29b6e3 100644 --- a/gst/rtpmanager/gstrtpsession.c +++ b/gst/rtpmanager/gstrtpsession.c @@ -223,6 +223,8 @@ enum #define DEFAULT_USE_PIPELINE_CLOCK FALSE #define DEFAULT_RTCP_MIN_INTERVAL (RTP_STATS_MIN_INTERVAL * GST_SECOND) #define DEFAULT_PROBATION RTP_DEFAULT_PROBATION +#define DEFAULT_MAX_DROPOUT_TIME 60000 +#define DEFAULT_MAX_MISORDER_TIME 2000 #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 @@ -241,6 +243,8 @@ enum PROP_USE_PIPELINE_CLOCK, PROP_RTCP_MIN_INTERVAL, PROP_PROBATION, + PROP_MAX_DROPOUT_TIME, + PROP_MAX_MISORDER_TIME, PROP_STATS, PROP_RTP_PROFILE, PROP_NTP_TIME_SOURCE, @@ -700,6 +704,18 @@ gst_rtp_session_class_init (GstRtpSessionClass * klass) 0, G_MAXUINT, DEFAULT_PROBATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_DROPOUT_TIME, + g_param_spec_uint ("max-dropout-time", "Max dropout time", + "The maximum time (milliseconds) of missing packets tolerated.", + 0, G_MAXUINT, DEFAULT_MAX_DROPOUT_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MAX_MISORDER_TIME, + g_param_spec_uint ("max-misorder-time", "Max misorder time", + "The maximum time (milliseconds) of misordered packets tolerated.", + 0, G_MAXUINT, DEFAULT_MAX_MISORDER_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** * GstRtpSession::stats: * @@ -876,6 +892,14 @@ gst_rtp_session_set_property (GObject * object, guint prop_id, case PROP_PROBATION: g_object_set_property (G_OBJECT (priv->session), "probation", value); break; + case PROP_MAX_DROPOUT_TIME: + g_object_set_property (G_OBJECT (priv->session), "max-dropout-time", + value); + break; + case PROP_MAX_MISORDER_TIME: + g_object_set_property (G_OBJECT (priv->session), "max-misorder-time", + value); + break; case PROP_RTP_PROFILE: g_object_set_property (G_OBJECT (priv->session), "rtp-profile", value); break; @@ -939,6 +963,14 @@ gst_rtp_session_get_property (GObject * object, guint prop_id, case PROP_PROBATION: g_object_get_property (G_OBJECT (priv->session), "probation", value); break; + case PROP_MAX_DROPOUT_TIME: + g_object_get_property (G_OBJECT (priv->session), "max-dropout-time", + value); + break; + case PROP_MAX_MISORDER_TIME: + g_object_get_property (G_OBJECT (priv->session), "max-misorder-time", + value); + break; case PROP_STATS: g_value_take_boxed (value, gst_rtp_session_create_stats (rtpsession)); break; diff --git a/gst/rtpmanager/rtpsession.c b/gst/rtpmanager/rtpsession.c index 71eaaeb89e..aea3b54063 100644 --- a/gst/rtpmanager/rtpsession.c +++ b/gst/rtpmanager/rtpsession.c @@ -70,6 +70,8 @@ enum #define DEFAULT_RTCP_FEEDBACK_RETENTION_WINDOW (2 * GST_SECOND) #define DEFAULT_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD (3) #define DEFAULT_PROBATION RTP_DEFAULT_PROBATION +#define DEFAULT_MAX_DROPOUT_TIME 60000 +#define DEFAULT_MAX_MISORDER_TIME 2000 #define DEFAULT_RTP_PROFILE GST_RTP_PROFILE_AVP enum @@ -91,6 +93,8 @@ enum PROP_RTCP_FEEDBACK_RETENTION_WINDOW, PROP_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD, PROP_PROBATION, + PROP_MAX_DROPOUT_TIME, + PROP_MAX_MISORDER_TIME, PROP_STATS, PROP_RTP_PROFILE }; @@ -514,6 +518,18 @@ rtp_session_class_init (RTPSessionClass * klass) 0, G_MAXUINT, DEFAULT_PROBATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_DROPOUT_TIME, + g_param_spec_uint ("max-dropout-time", "Max dropout time", + "The maximum time (milliseconds) of missing packets tolerated.", + 0, G_MAXUINT, DEFAULT_MAX_DROPOUT_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MAX_MISORDER_TIME, + g_param_spec_uint ("max-misorder-time", "Max misorder time", + "The maximum time (milliseconds) of misordered packets tolerated.", + 0, G_MAXUINT, DEFAULT_MAX_MISORDER_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** * RTPSession::stats: * @@ -581,6 +597,8 @@ rtp_session_init (RTPSession * sess) sess->mtu = DEFAULT_RTCP_MTU; sess->probation = DEFAULT_PROBATION; + sess->max_dropout_time = DEFAULT_MAX_DROPOUT_TIME; + sess->max_misorder_time = DEFAULT_MAX_MISORDER_TIME; /* some default SDES entries */ sess->sdes = gst_structure_new_empty ("application/x-rtp-source-sdes"); @@ -754,6 +772,12 @@ rtp_session_set_property (GObject * object, guint prop_id, case PROP_PROBATION: sess->probation = g_value_get_uint (value); break; + case PROP_MAX_DROPOUT_TIME: + sess->max_dropout_time = g_value_get_uint (value); + break; + case PROP_MAX_MISORDER_TIME: + sess->max_misorder_time = g_value_get_uint (value); + break; case PROP_RTP_PROFILE: sess->rtp_profile = g_value_get_enum (value); /* trigger reconsideration */ @@ -824,6 +848,12 @@ rtp_session_get_property (GObject * object, guint prop_id, case PROP_PROBATION: g_value_set_uint (value, sess->probation); break; + case PROP_MAX_DROPOUT_TIME: + g_value_set_uint (value, sess->max_dropout_time); + break; + case PROP_MAX_MISORDER_TIME: + g_value_set_uint (value, sess->max_misorder_time); + break; case PROP_STATS: g_value_take_boxed (value, rtp_session_create_stats (sess)); break; @@ -1618,10 +1648,9 @@ obtain_source (RTPSession * sess, guint32 ssrc, gboolean * created, /* for RTP packets we need to set the source in probation. Receiving RTCP * packets of an SSRC, on the other hand, is a strong indication that we * are dealing with a valid source. */ - if (rtp) - g_object_set (source, "probation", sess->probation, NULL); - else - g_object_set (source, "probation", 0, NULL); + g_object_set (source, "probation", rtp ? sess->probation : 0, + "max-dropout-time", sess->max_dropout_time, "max-misorder-time", + sess->max_misorder_time, NULL); /* store from address, if any */ if (pinfo->address) { diff --git a/gst/rtpmanager/rtpsession.h b/gst/rtpmanager/rtpsession.h index 30ce32af66..7524645447 100644 --- a/gst/rtpmanager/rtpsession.h +++ b/gst/rtpmanager/rtpsession.h @@ -219,6 +219,8 @@ struct _RTPSession { GstStructure *sdes; guint probation; + guint32 max_dropout_time; + guint32 max_misorder_time; GstRTPProfile rtp_profile; diff --git a/gst/rtpmanager/rtpsource.c b/gst/rtpmanager/rtpsource.c index 6373bc3a3c..202bc3b8fd 100644 --- a/gst/rtpmanager/rtpsource.c +++ b/gst/rtpmanager/rtpsource.c @@ -40,6 +40,8 @@ enum #define DEFAULT_IS_SENDER FALSE #define DEFAULT_SDES NULL #define DEFAULT_PROBATION RTP_DEFAULT_PROBATION +#define DEFAULT_MAX_DROPOUT_TIME 60000 +#define DEFAULT_MAX_MISORDER_TIME 2000 enum { @@ -50,7 +52,9 @@ enum PROP_IS_SENDER, PROP_SDES, PROP_STATS, - PROP_PROBATION + PROP_PROBATION, + PROP_MAX_DROPOUT_TIME, + PROP_MAX_MISORDER_TIME }; /* GObject vmethods */ @@ -219,6 +223,18 @@ rtp_source_class_init (RTPSourceClass * klass) 0, G_MAXUINT, DEFAULT_PROBATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_DROPOUT_TIME, + g_param_spec_uint ("max-dropout-time", "Max dropout time", + "The maximum time (milliseconds) of missing packets tolerated.", + 0, G_MAXUINT, DEFAULT_MAX_DROPOUT_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MAX_MISORDER_TIME, + g_param_spec_uint ("max-misorder-time", "Max misorder time", + "The maximum time (milliseconds) of misordered packets tolerated.", + 0, G_MAXUINT, DEFAULT_MAX_MISORDER_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + GST_DEBUG_CATEGORY_INIT (rtp_source_debug, "rtpsource", 0, "RTP Source"); } @@ -265,6 +281,8 @@ rtp_source_init (RTPSource * src) src->probation = DEFAULT_PROBATION; src->curr_probation = src->probation; src->closing = FALSE; + src->max_dropout_time = DEFAULT_MAX_DROPOUT_TIME; + src->max_misorder_time = DEFAULT_MAX_MISORDER_TIME; src->sdes = gst_structure_new_empty ("application/x-rtp-source-sdes"); @@ -505,6 +523,12 @@ rtp_source_set_property (GObject * object, guint prop_id, case PROP_PROBATION: src->probation = g_value_get_uint (value); break; + case PROP_MAX_DROPOUT_TIME: + src->max_dropout_time = g_value_get_uint (value); + break; + case PROP_MAX_MISORDER_TIME: + src->max_misorder_time = g_value_get_uint (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -541,6 +565,12 @@ rtp_source_get_property (GObject * object, guint prop_id, case PROP_PROBATION: g_value_set_uint (value, src->probation); break; + case PROP_MAX_DROPOUT_TIME: + g_value_set_uint (value, src->max_dropout_time); + break; + case PROP_MAX_MISORDER_TIME: + g_value_set_uint (value, src->max_misorder_time); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/rtpmanager/rtpsource.h b/gst/rtpmanager/rtpsource.h index 0f47faea02..f24e25b388 100644 --- a/gst/rtpmanager/rtpsource.h +++ b/gst/rtpmanager/rtpsource.h @@ -174,6 +174,8 @@ struct _RTPSource { guint64 bytes_received; GQueue *packets; + guint32 max_dropout_time; + guint32 max_misorder_time; RTPSourceCallbacks callbacks; gpointer user_data;