Previously we tried to route an incoming RTCP FB FIR to the correct ssrc
using the "media source" component of the RTCP FB message. However,
according to RFC5104 (section 4.3.1.2) the "media source" SHALL be set
to 0. Instead the ssrc(s) in use are propagated via the FCI data. Now
a specific GstForceKeyUnit event is sent for every ssrc.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3292>
static gboolean
rtp_session_request_local_key_unit (RTPSession * sess, RTPSource * src,
static gboolean
rtp_session_request_local_key_unit (RTPSession * sess, RTPSource * src,
- guint32 media_ssrc, gboolean fir, GstClockTime current_time)
+ const guint32 * ssrcs, guint num_ssrcs, gboolean fir,
+ GstClockTime current_time)
{
guint32 round_trip = 0;
{
guint32 round_trip = 0;
+ gint i;
+
+ g_return_val_if_fail (ssrcs != NULL && num_ssrcs > 0, FALSE);
rtp_source_get_last_rb (src, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
&round_trip);
rtp_source_get_last_rb (src, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
&round_trip);
src->last_keyframe_request = current_time;
src->last_keyframe_request = current_time;
- GST_LOG ("received %s request from %X about %X %p(%p)", fir ? "FIR" : "PLI",
- rtp_source_get_ssrc (src), media_ssrc, sess->callbacks.process_rtp,
- sess->callbacks.request_key_unit);
+ for (i = 0; i < num_ssrcs; ++i) {
+ GST_LOG ("received %s request from %X about %X %p(%p)",
+ fir ? "FIR" : "PLI",
+ rtp_source_get_ssrc (src), ssrcs[i], sess->callbacks.process_rtp,
+ sess->callbacks.request_key_unit);
- RTP_SESSION_UNLOCK (sess);
- sess->callbacks.request_key_unit (sess, media_ssrc, fir,
- sess->request_key_unit_user_data);
- RTP_SESSION_LOCK (sess);
+ RTP_SESSION_UNLOCK (sess);
+ sess->callbacks.request_key_unit (sess, ssrcs[i], fir,
+ sess->request_key_unit_user_data);
+ RTP_SESSION_LOCK (sess);
+ }
- rtp_session_request_local_key_unit (sess, src, media_ssrc, FALSE,
+ rtp_session_request_local_key_unit (sess, src, &media_ssrc, 1, FALSE,
current_time);
}
static void
rtp_session_process_fir (RTPSession * sess, guint32 sender_ssrc,
current_time);
}
static void
rtp_session_process_fir (RTPSession * sess, guint32 sender_ssrc,
- guint32 media_ssrc, guint8 * fci_data, guint fci_length,
- GstClockTime current_time)
+ guint8 * fci_data, guint fci_length, GstClockTime current_time)
{
RTPSource *src;
guint32 ssrc;
guint position = 0;
{
RTPSource *src;
guint32 ssrc;
guint position = 0;
- gboolean our_request = FALSE;
+ guint32 ssrcs[32];
+ guint num_ssrcs = 0;
if (!sess->callbacks.request_key_unit)
return;
if (!sess->callbacks.request_key_unit)
return;
if (own == NULL)
continue;
if (own == NULL)
continue;
- if (own->internal) {
- our_request = TRUE;
- break;
+ if (own->internal && num_ssrcs < 32) {
+ ssrcs[num_ssrcs++] = ssrc;
- rtp_session_request_local_key_unit (sess, src, media_ssrc, TRUE,
+ rtp_session_request_local_key_unit (sess, src, ssrcs, num_ssrcs, TRUE,
case GST_RTCP_PSFB_TYPE_FIR:
if (src)
src->stats.recv_fir_count++;
case GST_RTCP_PSFB_TYPE_FIR:
if (src)
src->stats.recv_fir_count++;
- rtp_session_process_fir (sess, sender_ssrc, media_ssrc, fci_data,
- fci_length, current_time);
+ rtp_session_process_fir (sess, sender_ssrc, fci_data, fci_length,
+ current_time);
{
SessionHarness *h = session_harness_new ();
GstEvent *ev;
{
SessionHarness *h = session_harness_new ();
GstEvent *ev;
/* PLI packet */
guint8 rtcp_pkt[] = {
/* PLI packet */
guint8 rtcp_pkt[] = {
fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
fail_unless_equals_int (GST_EVENT_CUSTOM_UPSTREAM, GST_EVENT_TYPE (ev));
fail_unless (gst_video_event_is_force_key_unit (ev));
fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
fail_unless_equals_int (GST_EVENT_CUSTOM_UPSTREAM, GST_EVENT_TYPE (ev));
fail_unless (gst_video_event_is_force_key_unit (ev));
+ s = gst_event_get_structure (ev);
+ fail_unless (s);
+ fail_unless (G_VALUE_HOLDS_UINT (gst_structure_get_value (s, "ssrc")));
gst_event_unref (ev);
session_harness_free (h);
gst_event_unref (ev);
session_harness_free (h);
{
SessionHarness *h = session_harness_new ();
GstEvent *ev;
{
SessionHarness *h = session_harness_new ();
GstEvent *ev;
/* PLI packet */
guint8 rtcp_pkt[] = {
/* PLI packet */
guint8 rtcp_pkt[] = {
fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
fail_unless_equals_int (GST_EVENT_CUSTOM_UPSTREAM, GST_EVENT_TYPE (ev));
fail_unless (gst_video_event_is_force_key_unit (ev));
fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
fail_unless_equals_int (GST_EVENT_CUSTOM_UPSTREAM, GST_EVENT_TYPE (ev));
fail_unless (gst_video_event_is_force_key_unit (ev));
+ s = gst_event_get_structure (ev);
+ fail_unless (s);
+ fail_unless (G_VALUE_HOLDS_UINT (gst_structure_get_value (s, "ssrc")));
gst_event_unref (ev);
session_harness_free (h);
gst_event_unref (ev);
session_harness_free (h);