gst/rtp/gstrtpmp4adepay.*: Fix depayloading when multiple frames are inside one RTP...
authorWim Taymans <wim.taymans@gmail.com>
Mon, 26 Nov 2007 19:17:10 +0000 (19:17 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Mon, 26 Nov 2007 19:17:10 +0000 (19:17 +0000)
Original commit message from CVS:
Based on Path by: Jayarama S. Santana <sundarsantana at gmail dot com>
* gst/rtp/gstrtpmp4adepay.c: (gst_rtp_mp4a_depay_setcaps),
(gst_rtp_mp4a_depay_process):
* gst/rtp/gstrtpmp4adepay.h:
Fix depayloading when multiple frames are inside one RTP packet.
Fixes #499239.

ChangeLog
gst/rtp/gstrtpmp4adepay.c
gst/rtp/gstrtpmp4adepay.h

index d02b12d..d83a26f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2007-11-26  Wim Taymans  <wim.taymans@gmail.com>
+
+       Based on Path by: Jayarama S. Santana <sundarsantana at gmail dot com>
+
+       * gst/rtp/gstrtpmp4adepay.c: (gst_rtp_mp4a_depay_setcaps),
+       (gst_rtp_mp4a_depay_process):
+       * gst/rtp/gstrtpmp4adepay.h:
+       Fix depayloading when multiple frames are inside one RTP packet.
+       Fixes #499239.
+
 2007-11-26  Stefan Kost  <ensonic@users.sf.net>
 
        * gst/level/gstlevel.c:
index 959c3c1..f3be606 100644 (file)
@@ -191,6 +191,7 @@ gst_rtp_mp4a_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
 
       data = GST_BUFFER_DATA (buffer);
       size = GST_BUFFER_SIZE (buffer);
+
       if (size < 2) {
         GST_WARNING_OBJECT (depayload, "config too short (%d < 2)", size);
         goto bad_config;
@@ -200,7 +201,7 @@ gst_rtp_mp4a_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
        *
        * audioMuxVersion           == 0 (1 bit)
        * allStreamsSameTimeFraming == 1 (1 bit)
-       * numSubFrames              == 0 (6 bits)
+       * numSubFrames              == rtpmp4adepay->numSubFrames (6 bits)
        * numProgram                == 0 (4 bits)
        * numLayer                  == 0 (3 bits)
        *
@@ -214,6 +215,11 @@ gst_rtp_mp4a_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
         goto bad_config;
       }
 
+      rtpmp4adepay->numSubFrames = (data[0] & 0x3F);
+
+      GST_LOG_OBJECT (rtpmp4adepay, "numSubFrames %d",
+          rtpmp4adepay->numSubFrames);
+
       /* shift rest of string 15 bits down */
       size -= 2;
       for (i = 0; i < size; i++) {
@@ -261,47 +267,91 @@ gst_rtp_mp4a_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
    * and push a buffer */
   if (gst_rtp_buffer_get_marker (buf)) {
     guint avail;
-    guint latm_header_len;
-    guint data_len;
+    guint i;
     guint8 *data;
+    guint pos;
 
     avail = gst_adapter_available (rtpmp4adepay->adapter);
 
-    outbuf = gst_adapter_take_buffer (rtpmp4adepay->adapter, avail);
+    GST_LOG_OBJECT (rtpmp4adepay, "have marker and %u available", avail);
 
-    /* determine payload length and set buffer data pointer accordingly */
-    /* FIXME, check for overrun */
-    latm_header_len = 0;
-    data_len = 0;
+    outbuf = gst_adapter_take_buffer (rtpmp4adepay->adapter, avail);
     data = GST_BUFFER_DATA (outbuf);
-    do {
-      data_len += data[latm_header_len];
-    } while (data[latm_header_len++] == 0xff);
-
-    /* just a check that lengths match, possibly there can be more than one
-     * audioMuxElement in the payload? */
-    if ((data_len + latm_header_len) != avail) {
-      GST_WARNING_OBJECT (depayload, "not all payload consumed");
-    }
+    /* position in data we are at */
+    pos = 0;
+
+    /* looping through the number of sub-frames in the audio payload */
+    for (i = 0; i <= rtpmp4adepay->numSubFrames; i++) {
+      /* determine payload length and set buffer data pointer accordingly */
+      guint skip;
+      guint data_len;
+      guint32 timestamp;
+
+      GstBuffer *tmp = NULL;
+
+      timestamp = gst_rtp_buffer_get_timestamp (buf);
+
+      /* each subframe starts with a variable length encoding */
+      data_len = 0;
+      for (skip = 0; skip < avail; skip++) {
+        data_len += data[skip];
+        if (data[skip] != 0xff)
+          break;
+      }
+      skip++;
+
+      /* this can not be possible, we have not enough data or the length
+       * decoding failed because we ran out of data. */
+      if (skip + data_len < avail)
+        goto wrong_size;
+
+      GST_LOG_OBJECT (rtpmp4adepay,
+          "subframe %u, header len %u, data len %u, left %u", i, skip, data_len,
+          avail);
 
-    GST_BUFFER_SIZE (outbuf) = avail - latm_header_len;
-    GST_BUFFER_DATA (outbuf) += latm_header_len;
+      /* take data out, skip the header */
+      pos += skip;
+      tmp = gst_buffer_create_sub (outbuf, pos, data_len);
 
-    gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));
+      /* skip data too */
+      skip += data_len;
+      pos += data_len;
 
-    GST_DEBUG ("gst_rtp_mp4a_depay_process: pushing buffer of size %d",
-        GST_BUFFER_SIZE (outbuf));
+      /* update our pointers whith what we consumed */
+      data += skip;
+      avail -= skip;
 
-    return outbuf;
+      gst_buffer_set_caps (tmp, GST_PAD_CAPS (depayload->srcpad));
+
+      /* only apply the timestamp for the first buffer. Based on gstrtpmp4gdepay.c */
+      if (i == 0)
+        gst_base_rtp_depayload_push_ts (depayload, timestamp, tmp);
+      else
+        gst_base_rtp_depayload_push (depayload, tmp);
+    }
+
+    /* just a check that lengths match */
+    if (avail) {
+      GST_ELEMENT_WARNING (depayload, STREAM, DECODE,
+          ("Packet invalid"), ("Not all payload consumed: "
+              "possible wrongly encoded packet."));
+    }
   }
   return NULL;
 
+  /* ERRORS */
 bad_packet:
   {
     GST_ELEMENT_WARNING (rtpmp4adepay, STREAM, DECODE,
         ("Packet did not validate"), (NULL));
     return NULL;
   }
+wrong_size:
+  {
+    GST_ELEMENT_WARNING (rtpmp4adepay, STREAM, DECODE,
+        ("Packet did not validate"), ("wrong packet size"));
+    return NULL;
+  }
 }
 
 static void
index 03b6156..36ed714 100644 (file)
@@ -42,8 +42,8 @@ typedef struct _GstRtpMP4ADepayClass GstRtpMP4ADepayClass;
 struct _GstRtpMP4ADepay
 {
   GstBaseRTPDepayload depayload;
-  
   GstAdapter *adapter;
+  guint8 numSubFrames;
 };
 
 struct _GstRtpMP4ADepayClass