#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_RTP_PROFILE GST_RTP_PROFILE_AVP
enum
{
PROP_USE_PIPELINE_CLOCK,
PROP_RTCP_MIN_INTERVAL,
PROP_PROBATION,
- PROP_STATS
+ PROP_STATS,
+ PROP_RTP_PROFILE
};
#define GST_RTP_SESSION_GET_PRIVATE(obj) \
"Various statistics", GST_TYPE_STRUCTURE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_RTP_PROFILE,
+ g_param_spec_enum ("rtp-profile", "RTP Profile",
+ "RTP profile to use", GST_TYPE_RTP_PROFILE, DEFAULT_RTP_PROFILE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_rtp_session_change_state);
gstelement_class->request_new_pad =
case PROP_PROBATION:
g_object_set_property (G_OBJECT (priv->session), "probation", value);
break;
+ case PROP_RTP_PROFILE:
+ g_object_set_property (G_OBJECT (priv->session), "rtp-profile", value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_STATS:
g_value_take_boxed (value, gst_rtp_session_create_stats (rtpsession));
break;
+ case PROP_RTP_PROFILE:
+ g_object_get_property (G_OBJECT (priv->session), "rtp-profile", value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
#define DEFAULT_RTCP_FEEDBACK_RETENTION_WINDOW (2 * GST_SECOND)
#define DEFAULT_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD (3)
#define DEFAULT_PROBATION RTP_DEFAULT_PROBATION
+#define DEFAULT_RTP_PROFILE GST_RTP_PROFILE_AVP
enum
{
PROP_RTCP_FEEDBACK_RETENTION_WINDOW,
PROP_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD,
PROP_PROBATION,
- PROP_STATS
+ PROP_STATS,
+ PROP_RTP_PROFILE
};
/* update average packet size */
*
* Requests that the #RTPSession initiate a new RTCP packet as soon as
* possible within the requested delay.
+ *
+ * This sets feedback to %TRUE if not already done before.
*/
rtp_session_signals[SIGNAL_SEND_RTCP] =
g_signal_new ("send-rtcp", G_TYPE_FROM_CLASS (klass),
* Requests that the #RTPSession initiate a new RTCP packet as soon as
* possible within the requested delay.
*
+ * This sets feedback to %TRUE if not already done before.
+ *
* Returns: TRUE if the new RTCP packet could be scheduled within the
* requested delay, FALSE otherwise.
*
"Various statistics", GST_TYPE_STRUCTURE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_RTP_PROFILE,
+ g_param_spec_enum ("rtp-profile", "RTP Profile",
+ "RTP profile to use for this session", GST_TYPE_RTP_PROFILE,
+ DEFAULT_RTP_PROFILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
klass->get_source_by_ssrc =
GST_DEBUG_FUNCPTR (rtp_session_get_source_by_ssrc);
klass->send_rtcp = GST_DEBUG_FUNCPTR (rtp_session_send_rtcp);
sess->rtcp_feedback_retention_window = DEFAULT_RTCP_FEEDBACK_RETENTION_WINDOW;
sess->rtcp_immediate_feedback_threshold =
DEFAULT_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD;
+ sess->rtp_profile = DEFAULT_RTP_PROFILE;
sess->last_keyframe_request = GST_CLOCK_TIME_NONE;
case PROP_PROBATION:
sess->probation = g_value_get_uint (value);
break;
+ case PROP_RTP_PROFILE:
+ sess->rtp_profile = g_value_get_enum (value);
+ /* trigger reconsideration */
+ RTP_SESSION_LOCK (sess);
+ sess->next_rtcp_check_time = 0;
+ RTP_SESSION_UNLOCK (sess);
+ if (sess->callbacks.reconsider)
+ sess->callbacks.reconsider (sess, sess->reconsider_user_data);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_STATS:
g_value_take_boxed (value, rtp_session_create_stats (sess));
break;
+ case PROP_RTP_PROFILE:
+ g_value_set_enum (value, sess->rtp_profile);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
stats = &sess->bye_stats;
result = rtp_stats_calculate_bye_interval (stats);
} else {
+ session_update_ptp (sess);
+
stats = &sess->stats;
result = rtp_stats_calculate_rtcp_interval (stats,
- stats->internal_sender_sources > 0, first);
+ stats->internal_sender_sources > 0, sess->rtp_profile,
+ sess->is_doing_ptp, first);
}
GST_DEBUG ("next deterministic interval: %" GST_TIME_FORMAT ", first %d",
sess->next_rtcp_check_time = current_time + interval;
} else if (interval != GST_CLOCK_TIME_NONE) {
/* Apply the rules from RFC 4585 section 3.5.3 */
- if (stats->min_interval != 0 && !sess->first_rtcp) {
+ if ((sess->rtp_profile == GST_RTP_PROFILE_AVPF
+ || sess->rtp_profile == GST_RTP_PROFILE_SAVPF)
+ && stats->min_interval != 0 && !sess->first_rtcp) {
GstClockTime T_rr_current_interval =
g_random_double_range (0.5, 1.5) * stats->min_interval * GST_SECOND;
RTP_SESSION_LOCK (sess);
+ /* We assume a feedback profile if something is requesting RTCP
+ * to be sent */
+ sess->rtp_profile = GST_RTP_PROFILE_AVPF;
+
/* Check if already requested */
/* RFC 4585 section 3.5.2 step 2 */
if (GST_CLOCK_TIME_IS_VALID (sess->next_early_rtcp_time)) {
}
/* RFC 4585 section 3.5.2 step 4a */
- if (sess->allow_early == FALSE) {
+ if (!sess->allow_early) {
/* Ignore the request a scheduled packet will be in time anyway */
if (current_time + max_delay > sess->next_rtcp_check_time) {
GST_LOG_OBJECT (sess,
ret = TRUE;
} else {
GST_LOG_OBJECT (sess,
- "can't allow early feedback, next scheduled time is too late %"
+ "can't allow early feedback and next scheduled time is too late %"
GST_TIME_FORMAT " + %" GST_TIME_FORMAT " < %" GST_TIME_FORMAT,
GST_TIME_ARGS (current_time), GST_TIME_ARGS (max_delay),
GST_TIME_ARGS (sess->next_rtcp_check_time));
* rtp_stats_calculate_rtcp_interval:
* @stats: an #RTPSessionStats struct
* @sender: if we are a sender
+ * @profile: RTP profile of this session
+ * @ptp: if this session is a point-to-point session
* @first: if this is the first time
*
* Calculate the RTCP interval. The result of this function is the amount of
*/
GstClockTime
rtp_stats_calculate_rtcp_interval (RTPSessionStats * stats, gboolean we_send,
- gboolean first)
+ GstRTPProfile profile, gboolean ptp, gboolean first)
{
gdouble members, senders, n;
gdouble avg_rtcp_size, rtcp_bw;
gdouble interval;
gdouble rtcp_min_time;
- /* Very first call at application start-up uses half the min
- * delay for quicker notification while still allowing some time
- * before reporting for randomization and to learn about other
- * sources so the report interval will converge to the correct
- * interval more quickly.
- */
- rtcp_min_time = stats->min_interval;
- if (first)
- rtcp_min_time /= 2.0;
+ if (profile == GST_RTP_PROFILE_AVPF || profile == GST_RTP_PROFILE_SAVPF) {
+ /* RFC 4585 3.4d), 3.5.1 */
+
+ if (first && !ptp)
+ rtcp_min_time = 1.0;
+ else
+ rtcp_min_time = 0.0;
+ } else {
+ /* Very first call at application start-up uses half the min
+ * delay for quicker notification while still allowing some time
+ * before reporting for randomization and to learn about other
+ * sources so the report interval will converge to the correct
+ * interval more quickly.
+ */
+ rtcp_min_time = stats->min_interval;
+ if (first)
+ rtcp_min_time /= 2.0;
+ }
/* Dedicate a fraction of the RTCP bandwidth to senders unless
* the number of senders is large enough that their share is