rtpvorbisdepay: also accept in-line configuration
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Thu, 22 Apr 2010 10:27:35 +0000 (12:27 +0200)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Fri, 30 Apr 2010 11:54:52 +0000 (13:54 +0200)
Fixes #574416 (vorbis).

gst/rtp/gstrtpvorbisdepay.c

index acb7630..622418c 100644 (file)
@@ -152,25 +152,20 @@ gst_rtp_vorbis_depay_finalize (GObject * object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+/* takes ownership of confbuf */
 static gboolean
 gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay,
-    const gchar * configuration)
+    GstBuffer * confbuf)
 {
   GstBuffer *buf;
   guint32 num_headers;
   guint8 *data;
-  GstBuffer *confbuf;
-  gsize size;
+  guint size;
   guint offset;
   gint i, j;
 
-  /* deserialize base64 to buffer */
-  data = g_base64_decode (configuration, &size);
-
-  confbuf = gst_buffer_new ();
-  GST_BUFFER_DATA (confbuf) = data;
-  GST_BUFFER_MALLOCDATA (confbuf) = data;
-  GST_BUFFER_SIZE (confbuf) = size;
+  data = GST_BUFFER_DATA (confbuf);
+  size = GST_BUFFER_SIZE (confbuf);
 
   GST_DEBUG_OBJECT (rtpvorbisdepay, "config size %" G_GSIZE_FORMAT, size);
 
@@ -242,6 +237,8 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay,
         "header %d, ident 0x%08x, length %u, left %" G_GSIZE_FORMAT, i, ident,
         length, size);
 
+    /* FIXME check if we already got this ident */
+
     if (size < length)
       goto too_small;
 
@@ -309,6 +306,29 @@ too_small:
 }
 
 static gboolean
+gst_rtp_vorbis_depay_parse_inband_configuration (GstRtpVorbisDepay *
+    rtpvorbisdepay, guint ident, guint8 * configuration, guint size)
+{
+  GstBuffer *confbuf;
+  guint8 *conf;
+
+  if (G_UNLIKELY (size < 4))
+    return FALSE;
+
+  /* transform inline to out-of-band and parse that one */
+  confbuf = gst_buffer_new_and_alloc (size + 3);
+  conf = GST_BUFFER_DATA (confbuf);
+  /* 1 header */
+  GST_WRITE_UINT32_BE (conf, 1);
+  /* write Ident */
+  GST_WRITE_UINT24_BE (conf + 4, ident);
+  /* copy remainder */
+  memcpy (conf + 7, configuration + 4, size - 4);
+
+  return gst_rtp_vorbis_depay_parse_configuration (rtpvorbisdepay, confbuf);
+}
+
+static gboolean
 gst_rtp_vorbis_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
 {
   GstStructure *structure;
@@ -329,8 +349,18 @@ gst_rtp_vorbis_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
   /* read and parse configuration string */
   configuration = gst_structure_get_string (structure, "configuration");
   if (configuration) {
-    if (!gst_rtp_vorbis_depay_parse_configuration (rtpvorbisdepay,
-            configuration))
+    GstBuffer *confbuf;
+    guint8 *data;
+    gsize size;
+
+    /* deserialize base64 to buffer */
+    data = g_base64_decode (configuration, &size);
+
+    confbuf = gst_buffer_new ();
+    GST_BUFFER_DATA (confbuf) = data;
+    GST_BUFFER_MALLOCDATA (confbuf) = data;
+    GST_BUFFER_SIZE (confbuf) = size;
+    if (!gst_rtp_vorbis_depay_parse_configuration (rtpvorbisdepay, confbuf))
       goto invalid_configuration;
   } else {
     GST_WARNING_OBJECT (rtpvorbisdepay, "no configuration specified");
@@ -540,6 +570,15 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
     if (G_UNLIKELY (length > payload_len))
       goto length_short;
 
+    /* handle in-band configuration */
+    if (G_UNLIKELY (VDT == 1)) {
+      GST_DEBUG_OBJECT (rtpvorbisdepay, "in-band configuration");
+      if (!gst_rtp_vorbis_depay_parse_inband_configuration (rtpvorbisdepay,
+              ident, payload, payload_len))
+        goto invalid_configuration;
+      goto no_output;
+    }
+
     /* create buffer for packet */
     if (G_UNLIKELY (to_free)) {
       outbuf = gst_buffer_new ();
@@ -601,6 +640,13 @@ length_short:
         (NULL), ("Packet contains invalid data"));
     return NULL;
   }
+invalid_configuration:
+  {
+    /* fatal, as we otherwise risk carrying on without output */
+    GST_ELEMENT_ERROR (rtpvorbisdepay, STREAM, DECODE,
+        (NULL), ("Packet contains invalid configuration"));
+    return NULL;
+  }
 }
 
 static GstStateChangeReturn