In early retransmission we are allowed to schedule 1 regular RTCP packet
at an earlier time. When we do that, we need to set allow_early to FALSE
and ignore/drop (or merge) all future requests for early transmission.
We now first check if we can schedule an early RTCP and if we can,
actually prepare the data for the next RTCP interval.
After we send the next regular RTCP after the early RTCP, we set
allow_early to TRUE again to allow more early requests.
Remove the condition for the immediate feedback for now.
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=738319
static void rtp_session_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void rtp_session_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
-static void rtp_session_send_rtcp (RTPSession * sess, GstClockTime max_delay);
+static gboolean rtp_session_send_rtcp (RTPSession * sess, GstClockTime max_delay);
static guint rtp_session_signals[LAST_SIGNAL] = { 0 };
static guint rtp_session_signals[LAST_SIGNAL] = { 0 };
sess->next_early_rtcp_time = GST_CLOCK_TIME_NONE;
sess->scheduled_bye = FALSE;
sess->next_early_rtcp_time = GST_CLOCK_TIME_NONE;
sess->scheduled_bye = FALSE;
+ /* RFC 4585 section 3.5.2 step 6 */
+ if (!data.is_early) {
+ sess->allow_early = TRUE;
+ }
+
done:
RTP_SESSION_UNLOCK (sess);
done:
RTP_SESSION_UNLOCK (sess);
* @max_delay: maximum delay
*
* Request transmission of early RTCP
* @max_delay: maximum delay
*
* Request transmission of early RTCP
+ *
+ * Returns: %TRUE if the related RTCP can be scheduled.
rtp_session_request_early_rtcp (RTPSession * sess, GstClockTime current_time,
GstClockTime max_delay)
{
GstClockTime T_dither_max;
rtp_session_request_early_rtcp (RTPSession * sess, GstClockTime current_time,
GstClockTime max_delay)
{
GstClockTime T_dither_max;
/* Implements the algorithm described in RFC 4585 section 3.5.2 */
/* Implements the algorithm described in RFC 4585 section 3.5.2 */
/* RFC 4585 section 3.5.2 step 2 */
if (GST_CLOCK_TIME_IS_VALID (sess->next_early_rtcp_time)) {
GST_LOG_OBJECT (sess, "already have next early rtcp time");
/* RFC 4585 section 3.5.2 step 2 */
if (GST_CLOCK_TIME_IS_VALID (sess->next_early_rtcp_time)) {
GST_LOG_OBJECT (sess, "already have next early rtcp time");
+ ret = TRUE;
+ goto end;
}
if (!GST_CLOCK_TIME_IS_VALID (sess->next_rtcp_check_time)) {
GST_LOG_OBJECT (sess, "no next RTCP check time");
}
if (!GST_CLOCK_TIME_IS_VALID (sess->next_rtcp_check_time)) {
GST_LOG_OBJECT (sess, "no next RTCP check time");
- goto dont_send;
- }
-
- /* 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, "next scheduled time is soon %" 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));
- goto dont_send;
+ ret = FALSE;
+ goto end;
}
/* RFC 4585 section 3.5.2 step 2b */
}
/* RFC 4585 section 3.5.2 step 2b */
/* RFC 4585 section 3.5.2 step 3 */
if (current_time + T_dither_max > sess->next_rtcp_check_time) {
GST_LOG_OBJECT (sess, "don't send because of dither");
/* RFC 4585 section 3.5.2 step 3 */
if (current_time + T_dither_max > sess->next_rtcp_check_time) {
GST_LOG_OBJECT (sess, "don't send because of dither");
- goto dont_send;
- }
-
- /* RFC 4585 section 3.5.2 step 4
- * Don't send if allow_early is FALSE, but not if we are in
- * immediate mode, meaning we are part of a group of at most the
- * application-specific threshold.
- */
- if (sess->total_sources > sess->rtcp_immediate_feedback_threshold &&
- sess->allow_early == FALSE) {
- GST_LOG_OBJECT (sess, "can't allow early feedback");
- goto dont_send;
+ ret = FALSE;
+ goto end;
+ }
+
+ /* RFC 4585 section 3.5.2 step 4a */
+ if (sess->allow_early == FALSE) {
+ /* 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, "next scheduled time is soon %" 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));
+ ret = TRUE;
+ } else {
+ GST_LOG_OBJECT (sess, "can't allow early feedback");
+ ret = FALSE;
+ }
+ goto end;
+ /* RFC 4585 section 3.5.2 step 4b */
if (T_dither_max) {
/* Schedule an early transmission later */
sess->next_early_rtcp_time = g_random_double () * T_dither_max +
if (T_dither_max) {
/* Schedule an early transmission later */
sess->next_early_rtcp_time = g_random_double () * T_dither_max +
sess->next_early_rtcp_time = current_time;
}
sess->next_early_rtcp_time = current_time;
}
+ /* RFC 4585 section 3.5.2 step 6 */
+ sess->allow_early = FALSE;
+ /* TODO(mparis): "R MUST recalculate tn = tp + 2*T_rr,
+ * and MUST set tp to the previous tn" */
+
GST_LOG_OBJECT (sess, "next early RTCP time %" GST_TIME_FORMAT,
GST_TIME_ARGS (sess->next_early_rtcp_time));
RTP_SESSION_UNLOCK (sess);
GST_LOG_OBJECT (sess, "next early RTCP time %" GST_TIME_FORMAT,
GST_TIME_ARGS (sess->next_early_rtcp_time));
RTP_SESSION_UNLOCK (sess);
if (sess->callbacks.reconsider)
sess->callbacks.reconsider (sess, sess->reconsider_user_data);
if (sess->callbacks.reconsider)
sess->callbacks.reconsider (sess, sess->reconsider_user_data);
RTP_SESSION_UNLOCK (sess);
RTP_SESSION_UNLOCK (sess);
rtp_session_send_rtcp (RTPSession * sess, GstClockTime max_delay)
{
GstClockTime now;
if (!sess->callbacks.send_rtcp)
rtp_session_send_rtcp (RTPSession * sess, GstClockTime max_delay)
{
GstClockTime now;
if (!sess->callbacks.send_rtcp)
now = sess->callbacks.request_time (sess, sess->request_time_user_data);
now = sess->callbacks.request_time (sess, sess->request_time_user_data);
- rtp_session_request_early_rtcp (sess, now, max_delay);
+ return rtp_session_request_early_rtcp (sess, now, max_delay);
+ if (!rtp_session_send_rtcp (sess, 5 * GST_SECOND)) {
+ GST_DEBUG ("FIR/PLI not sent");
+ return FALSE;
+ }
+
RTP_SESSION_LOCK (sess);
src = find_source (sess, ssrc);
if (src == NULL)
RTP_SESSION_LOCK (sess);
src = find_source (sess, ssrc);
if (src == NULL)
}
RTP_SESSION_UNLOCK (sess);
}
RTP_SESSION_UNLOCK (sess);
- rtp_session_send_rtcp (sess, 200 * GST_MSECOND);
-
return TRUE;
/* ERRORS */
return TRUE;
/* ERRORS */
+ if (!rtp_session_send_rtcp (sess, max_delay)) {
+ GST_DEBUG ("NACK not sent");
+ return FALSE;
+ }
+
RTP_SESSION_LOCK (sess);
source = find_source (sess, ssrc);
if (source == NULL)
RTP_SESSION_LOCK (sess);
source = find_source (sess, ssrc);
if (source == NULL)
rtp_source_register_nack (source, seqnum);
RTP_SESSION_UNLOCK (sess);
rtp_source_register_nack (source, seqnum);
RTP_SESSION_UNLOCK (sess);
- rtp_session_send_rtcp (sess, max_delay);
-
return TRUE;
/* ERRORS */
return TRUE;
/* ERRORS */
gboolean early);
void (*on_feedback_rtcp) (RTPSession *sess, guint type, guint fbtype,
guint sender_ssrc, guint media_ssrc, GstBuffer *fci);
gboolean early);
void (*on_feedback_rtcp) (RTPSession *sess, guint type, guint fbtype,
guint sender_ssrc, guint media_ssrc, GstBuffer *fci);
- void (*send_rtcp) (RTPSession *sess, GstClockTime max_delay);
+ gboolean (*send_rtcp) (RTPSession *sess, GstClockTime max_delay);
};
GType rtp_session_get_type (void);
};
GType rtp_session_get_type (void);
guint64 ntpnstime, GstClockTime running_time);
/* request the transmittion of an early RTCP packet */
guint64 ntpnstime, GstClockTime running_time);
/* request the transmittion of an early RTCP packet */
-void rtp_session_request_early_rtcp (RTPSession * sess, GstClockTime current_time,
+gboolean rtp_session_request_early_rtcp (RTPSession * sess, GstClockTime current_time,
GstClockTime max_delay);
/* Notify session of a request for a new key unit */
GstClockTime max_delay);
/* Notify session of a request for a new key unit */