sdp: Parse the RFC5576 Source-specific media SDP attributes into caps
authorSebastian Dröge <sebastian@centricular.com>
Thu, 7 Apr 2022 16:36:25 +0000 (19:36 +0300)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 20 Apr 2022 14:40:25 +0000 (14:40 +0000)
The format of the caps fields is
    ssrc-(SSRC_VALUE)-(ATTRIBUTE_NAME)=(ATTRIBUTE_VALUE)
.

Parsing of the attributes from the caps into the SDP is not implemented
as this depends not only a single stream's caps but on the whole rtpbin
configuration.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2132>

subprojects/gst-plugins-base/gst-libs/gst/sdp/gstsdpmessage.c

index 2fb6d68..9ad2aec 100644 (file)
@@ -3583,7 +3583,7 @@ gst_sdp_media_caps_adjust_h264 (GstCaps * caps)
  *
  * a=fmtp:(payload) (param)[=(value)];...
  *
- * Note that the extmap attribute is set only by gst_sdp_media_attributes_to_caps().
+ * Note that the extmap, ssrc and rid attributes are set only by gst_sdp_media_attributes_to_caps().
  *
  * Returns: a #GstCaps, or %NULL if an error happened
  *
@@ -4216,6 +4216,8 @@ sdp_add_attributes_to_caps (GArray * attributes, GstCaps * caps)
         continue;
       if (!strcmp (key, "extmap"))
         continue;
+      if (!strcmp (key, "ssrc"))
+        continue;
       if (!strcmp (key, "rid"))
         continue;
 
@@ -4343,6 +4345,73 @@ gst_sdp_media_add_extmap_attributes (GArray * attributes, GstCaps * caps)
   return GST_SDP_OK;
 }
 
+/* parses Source-specific media SDP attributes (RFC5576) into caps */
+static GstSDPResult
+gst_sdp_media_add_ssrc_attributes (GArray * attributes, GstCaps * caps)
+{
+  gchar *p, *tmp, *to_free;
+  guint i;
+  GstStructure *s;
+
+  g_return_val_if_fail (attributes != NULL, GST_SDP_EINVAL);
+  g_return_val_if_fail (caps != NULL && GST_IS_CAPS (caps), GST_SDP_EINVAL);
+
+  s = gst_caps_get_structure (caps, 0);
+
+  for (i = 0; i < attributes->len; i++) {
+    const gchar *value;
+    GstSDPAttribute *attr;
+    guint32 ssrc;
+    gchar *ssrc_val, *ssrc_attr;
+    gchar *key;
+
+    attr = &g_array_index (attributes, GstSDPAttribute, i);
+    if (strcmp (attr->key, "ssrc") != 0)
+      continue;
+
+    value = attr->value;
+
+    /* p is now of the format ssrc attribute[:value] */
+    to_free = p = g_strdup (value);
+
+    ssrc = strtoul (p, &tmp, 10);
+    if (*tmp != ' ') {
+      GST_ERROR ("Invalid ssrc attribute '%s'", to_free);
+      goto next;
+    }
+
+    /* At the space */
+    p = tmp;
+
+    SKIP_SPACES (p);
+
+    tmp = strstr (p, ":");
+    if (tmp == NULL) {
+      ssrc_attr = tmp;
+      ssrc_val = (gchar *) "";
+    } else {
+      ssrc_attr = p;
+      *tmp = '\0';
+      p = tmp + 1;
+      ssrc_val = p;
+    }
+
+    if (ssrc_attr == NULL || *ssrc_attr == '\0') {
+      GST_ERROR ("Invalid ssrc attribute '%s'", to_free);
+      goto next;
+    }
+
+    key = g_strdup_printf ("ssrc-%u-%s", ssrc, ssrc_attr);
+    gst_structure_set (s, key, G_TYPE_STRING, ssrc_val, NULL);
+    GST_DEBUG ("adding caps: %s=%s", key, ssrc_val);
+    g_free (key);
+
+  next:
+    g_free (to_free);
+  }
+  return GST_SDP_OK;
+}
+
 /* parses RID SDP attributes (RFC8851) into caps */
 static GstSDPResult
 gst_sdp_media_add_rid_attributes (GArray * attributes, GstCaps * caps)
@@ -4552,6 +4621,11 @@ gst_sdp_media_attributes_to_caps (const GstSDPMedia * media, GstCaps * caps)
   }
 
   if (res == GST_SDP_OK) {
+    /* parse media ssrc field */
+    res = gst_sdp_media_add_ssrc_attributes (media->attributes, caps);
+  }
+
+  if (res == GST_SDP_OK) {
     /* parse media rid fields */
     res = gst_sdp_media_add_rid_attributes (media->attributes, caps);
   }