rtpsession: Process received Full Intra Requests

Process FIR requests according to RFC 5104

https://bugzilla.gnome.org/show_bug.cgi?id=658419
This commit is contained in:
Olivier Crête 2011-08-30 19:06:13 -04:00 committed by Mark Nauwelaerts
parent e7ae593993
commit 0ad78db0a3
2 changed files with 76 additions and 21 deletions

View file

@ -2158,45 +2158,93 @@ rtp_session_process_app (RTPSession * sess, GstRTCPPacket * packet,
GST_DEBUG ("received APP"); GST_DEBUG ("received APP");
} }
static gboolean
rtp_session_request_local_key_unit (RTPSession * sess, RTPSource * src,
gboolean fir, GstClockTime current_time)
{
guint32 round_trip = 0;
rtp_source_get_last_rb (src, NULL, NULL, NULL, NULL, NULL, NULL, &round_trip);
if (sess->last_keyframe_request != GST_CLOCK_TIME_NONE && round_trip) {
GstClockTime round_trip_in_ns = gst_util_uint64_scale (round_trip,
GST_SECOND, 65536);
if (sess->last_keyframe_request != GST_CLOCK_TIME_NONE &&
current_time - sess->last_keyframe_request < 2 * round_trip_in_ns) {
GST_DEBUG ("Ignoring %s request because one was send without one "
"RTT (%" GST_TIME_FORMAT " < %" GST_TIME_FORMAT ")",
fir ? "FIR" : "PLI",
GST_TIME_ARGS (current_time - sess->last_keyframe_request),
GST_TIME_ARGS (round_trip_in_ns));;
return FALSE;
}
}
sess->last_keyframe_request = current_time;
GST_LOG ("received %s request from %X %p(%p)", fir ? "FIR" : "PLI",
rtp_source_get_ssrc (src), sess->callbacks.process_rtp,
sess->callbacks.request_key_unit);
sess->callbacks.request_key_unit (sess, fir,
sess->request_key_unit_user_data);
return TRUE;
}
static void static void
rtp_session_process_pli (RTPSession * sess, guint32 sender_ssrc, rtp_session_process_pli (RTPSession * sess, guint32 sender_ssrc,
guint32 media_ssrc, GstClockTime current_time) guint32 media_ssrc, GstClockTime current_time)
{ {
RTPSource *src; RTPSource *src;
guint32 round_trip = 0;
if (!sess->callbacks.request_key_unit) if (!sess->callbacks.request_key_unit)
return; return;
src = g_hash_table_lookup (sess->ssrcs[sess->mask_idx],
GINT_TO_POINTER (sender_ssrc));
if (!src)
return;
rtp_session_request_local_key_unit (sess, src, FALSE, current_time);
}
static void
rtp_session_process_fir (RTPSession * sess, guint32 sender_ssrc,
guint8 * fci_data, guint fci_length, GstClockTime current_time)
{
RTPSource *src;
guint32 ssrc;
guint position = 0;
gboolean our_request = FALSE;
if (!sess->callbacks.request_key_unit)
return;
if (fci_length < 8)
return;
src = g_hash_table_lookup (sess->ssrcs[sess->mask_idx], src = g_hash_table_lookup (sess->ssrcs[sess->mask_idx],
GINT_TO_POINTER (sender_ssrc)); GINT_TO_POINTER (sender_ssrc));
if (!src) if (!src)
return; return;
if (sess->last_keyframe_request != GST_CLOCK_TIME_NONE && for (position = 0; position < fci_length; position += 8) {
rtp_source_get_last_rb (src, NULL, NULL, NULL, NULL, NULL, NULL, guint8 *data = fci_data + position;
&round_trip)) {
GstClockTime round_trip_in_ns = gst_util_uint64_scale (round_trip,
GST_SECOND, 65536);
if (sess->last_keyframe_request != GST_CLOCK_TIME_NONE && ssrc = GST_READ_UINT32_BE (data);
current_time - sess->last_keyframe_request < round_trip_in_ns) {
GST_DEBUG ("Ignoring PLI because one was send without one RTT (%" if (ssrc == rtp_source_get_ssrc (sess->source)) {
GST_TIME_FORMAT " < %" GST_TIME_FORMAT ")", our_request = TRUE;
GST_TIME_ARGS (current_time - sess->last_keyframe_request), break;
GST_TIME_ARGS (round_trip_in_ns));;
return;
} }
} }
if (!our_request)
return;
sess->last_keyframe_request = current_time; rtp_session_request_local_key_unit (sess, src, TRUE, current_time);
GST_LOG ("received PLI from %X %p(%p)", sender_ssrc,
sess->callbacks.process_rtp, sess->callbacks.request_key_unit);
sess->callbacks.request_key_unit (sess, FALSE,
sess->request_key_unit_user_data);
} }
static void static void
@ -2240,7 +2288,9 @@ rtp_session_process_feedback (RTPSession * sess, GstRTCPPacket * packet,
rtp_source_retain_rtcp_packet (src, packet, arrival->running_time); rtp_source_retain_rtcp_packet (src, packet, arrival->running_time);
} }
if (rtp_source_get_ssrc (sess->source) == media_ssrc) { if (rtp_source_get_ssrc (sess->source) == media_ssrc ||
/* PSFB FIR puts the media ssrc inside the FCI */
(type == GST_RTCP_TYPE_PSFB && fbtype == GST_RTCP_PSFB_TYPE_FIR)) {
switch (type) { switch (type) {
case GST_RTCP_TYPE_PSFB: case GST_RTCP_TYPE_PSFB:
switch (fbtype) { switch (fbtype) {
@ -2248,6 +2298,10 @@ rtp_session_process_feedback (RTPSession * sess, GstRTCPPacket * packet,
rtp_session_process_pli (sess, sender_ssrc, media_ssrc, rtp_session_process_pli (sess, sender_ssrc, media_ssrc,
current_time); current_time);
break; break;
case GST_RTCP_PSFB_TYPE_FIR:
rtp_session_process_fir (sess, sender_ssrc, fci_data, fci_length,
current_time);
break;
default: default:
break; break;
} }

View file

@ -237,6 +237,7 @@ struct _RTPSession {
GArray *rtcp_pli_requests; GArray *rtcp_pli_requests;
GstClockTime last_keyframe_request; GstClockTime last_keyframe_request;
gboolean last_keyframe_all_headers;
}; };
/** /**