From 0ad78db0a30bda6b9be9b674c4b1ecf90a8a69c0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 30 Aug 2011 19:06:13 -0400 Subject: [PATCH] rtpsession: Process received Full Intra Requests Process FIR requests according to RFC 5104 https://bugzilla.gnome.org/show_bug.cgi?id=658419 --- gst/rtpmanager/rtpsession.c | 96 +++++++++++++++++++++++++++++++++++---------- gst/rtpmanager/rtpsession.h | 1 + 2 files changed, 76 insertions(+), 21 deletions(-) diff --git a/gst/rtpmanager/rtpsession.c b/gst/rtpmanager/rtpsession.c index fe73e99..1a651e0 100644 --- a/gst/rtpmanager/rtpsession.c +++ b/gst/rtpmanager/rtpsession.c @@ -2158,45 +2158,93 @@ rtp_session_process_app (RTPSession * sess, GstRTCPPacket * packet, 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 rtp_session_process_pli (RTPSession * sess, guint32 sender_ssrc, guint32 media_ssrc, GstClockTime current_time) { RTPSource *src; - guint32 round_trip = 0; if (!sess->callbacks.request_key_unit) 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], + GINT_TO_POINTER (sender_ssrc)); if (!src) return; - if (sess->last_keyframe_request != GST_CLOCK_TIME_NONE && - rtp_source_get_last_rb (src, NULL, NULL, NULL, NULL, NULL, NULL, - &round_trip)) { - GstClockTime round_trip_in_ns = gst_util_uint64_scale (round_trip, - GST_SECOND, 65536); + for (position = 0; position < fci_length; position += 8) { + guint8 *data = fci_data + position; - if (sess->last_keyframe_request != GST_CLOCK_TIME_NONE && - current_time - sess->last_keyframe_request < round_trip_in_ns) { - GST_DEBUG ("Ignoring PLI because one was send without one RTT (%" - GST_TIME_FORMAT " < %" GST_TIME_FORMAT ")", - GST_TIME_ARGS (current_time - sess->last_keyframe_request), - GST_TIME_ARGS (round_trip_in_ns));; - return; + ssrc = GST_READ_UINT32_BE (data); + + if (ssrc == rtp_source_get_ssrc (sess->source)) { + our_request = TRUE; + break; } } + if (!our_request) + return; - sess->last_keyframe_request = 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); + rtp_session_request_local_key_unit (sess, src, TRUE, current_time); } static void @@ -2240,7 +2288,9 @@ rtp_session_process_feedback (RTPSession * sess, GstRTCPPacket * packet, 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) { case GST_RTCP_TYPE_PSFB: switch (fbtype) { @@ -2248,6 +2298,10 @@ rtp_session_process_feedback (RTPSession * sess, GstRTCPPacket * packet, rtp_session_process_pli (sess, sender_ssrc, media_ssrc, current_time); break; + case GST_RTCP_PSFB_TYPE_FIR: + rtp_session_process_fir (sess, sender_ssrc, fci_data, fci_length, + current_time); + break; default: break; } diff --git a/gst/rtpmanager/rtpsession.h b/gst/rtpmanager/rtpsession.h index 6b827f6..6177375 100644 --- a/gst/rtpmanager/rtpsession.h +++ b/gst/rtpmanager/rtpsession.h @@ -237,6 +237,7 @@ struct _RTPSession { GArray *rtcp_pli_requests; GstClockTime last_keyframe_request; + gboolean last_keyframe_all_headers; }; /** -- 2.7.4