webrtc: add all SSRC attributes getting CAPS for a PT

The transport stream only returned the CAPS for the first matching PT entry
from the `ptmap`. Other SSRC with the same PT where not included. For a stream
which bundled multiple audio streams for instance, only the first SSRC was
knowed to the SSRC demux and downstream elements.

This commit adds all the `ssrc-` attributes from the matching PT entries.

The RTP jitter buffer can now find the CNAME corresponding its SSRC even if it
was not the first to be registered for a particular PT.

The RTP PT demux removes `ssrc-*` attributes cooresponding to other SSRCs
before pushing SSRC specific CAPS to downstream elements.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6119>
This commit is contained in:
François Laignel 2024-03-07 17:36:33 +01:00 committed by GStreamer Marge Bot
parent d83184cf9a
commit 7d5bb1ea7a
3 changed files with 57 additions and 6 deletions

View file

@ -5122,6 +5122,8 @@ _set_internal_rtpbin_element_props_from_stream (GstWebRTCBin * webrtc,
GST_LOG_OBJECT (stream, "setting rtx mapping: %s -> %u", apt, rtx_pt[i]);
gst_structure_set (pt_map, apt, G_TYPE_UINT, rtx_pt[i], NULL);
gst_caps_unref (rtx_caps);
}
GST_DEBUG_OBJECT (stream, "setting payload map on %" GST_PTR_FORMAT " : %"
@ -7446,8 +7448,7 @@ on_rtpbin_request_pt_map (GstElement * rtpbin, guint session_id, guint pt,
if (!stream)
goto unknown_session;
if ((ret = transport_stream_get_caps_for_pt (stream, pt)))
gst_caps_ref (ret);
ret = transport_stream_get_caps_for_pt (stream, pt);
GST_DEBUG_OBJECT (webrtc, "Found caps %" GST_PTR_FORMAT " for pt %d in "
"session %d", ret, pt, session_id);

View file

@ -47,15 +47,37 @@ enum
GstCaps *
transport_stream_get_caps_for_pt (TransportStream * stream, guint pt)
{
guint i, len;
GstCaps *ret = NULL;
GstStructure *ret_s, *item_s;
guint i, len, si, slen;
const gchar *field_name;
len = stream->ptmap->len;
for (i = 0; i < len; i++) {
PtMapItem *item = &g_array_index (stream->ptmap, PtMapItem, i);
if (item->pt == pt)
return item->caps;
if (item->pt == pt) {
if (item->caps) {
if (ret == NULL) {
ret = gst_caps_copy (item->caps);
ret_s = gst_caps_get_structure (ret, 0);
} else {
/* Append the "ssrc-*" fields for current PT entry to ret */
item_s = gst_caps_get_structure (item->caps, 0);
slen = gst_structure_n_fields (item_s);
for (si = 0; si < slen; ++si) {
field_name = gst_structure_nth_field_name (item_s, si);
if (!g_str_has_prefix (field_name, "ssrc-"))
continue;
gst_structure_set (ret_s, field_name, G_TYPE_STRING,
gst_structure_get_string (item_s, field_name), NULL);
}
}
}
}
}
return NULL;
return ret;
}
int

View file

@ -312,6 +312,29 @@ gst_rtp_pt_demux_finalize (GObject * object)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
/* Removes "ssrc-*" attributes matching other SSRCs. */
static gboolean
_filter_ssrc (GQuark field_id, GValue * value, gpointer ssrc)
{
const gchar *field_name = g_quark_to_string (field_id);
if (!g_str_has_prefix (field_name, "ssrc-"))
return TRUE;
gchar *endptr;
guint32 field_ssrc = g_ascii_strtoll (field_name + 5, &endptr, 10);
if (!endptr || *endptr != '-')
return TRUE;
/* Found a valid "ssrc-*" */
if (field_ssrc != *(guint32 *) ssrc)
/* Not the expected SSRC => remove this field */
return FALSE;
return TRUE;
}
static GstCaps *
gst_rtp_pt_demux_get_caps (GstRtpPtDemux * rtpdemux, guint pt)
{
@ -349,7 +372,12 @@ gst_rtp_pt_demux_get_caps (GstRtpPtDemux * rtpdemux, guint pt)
}
if (caps != NULL) {
GstStructure *s;
caps = gst_caps_make_writable (caps);
s = gst_caps_get_structure (caps, 0);
gst_structure_filter_and_map_in_place (s, _filter_ssrc, &ssrc);
gst_caps_set_simple (caps, "payload", G_TYPE_INT, pt, NULL);
if (have_ssrc)
gst_caps_set_simple (caps, "ssrc", G_TYPE_UINT, ssrc, NULL);