rtp: Update codes based on 1.18.4
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtpvorbisdepay.c
index 08ef282..556bd76 100644 (file)
@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 #ifdef HAVE_CONFIG_H
 
 #include <gst/tag/tag.h>
 #include <gst/rtp/gstrtpbuffer.h>
+#include <gst/audio/audio.h>
 
 #include <string.h>
 #include "gstrtpvorbisdepay.h"
+#include "gstrtputils.h"
 
 GST_DEBUG_CATEGORY_STATIC (rtpvorbisdepay_debug);
 #define GST_CAT_DEFAULT (rtpvorbisdepay_debug)
@@ -40,7 +42,6 @@ GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("application/x-rtp, "
         "media = (string) \"audio\", "
-        "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
         "clock-rate = (int) [1, MAX ], " "encoding-name = (string) \"VORBIS\""
         /* All required parameters 
          *
@@ -59,12 +60,12 @@ GST_STATIC_PAD_TEMPLATE ("src",
 
 #define gst_rtp_vorbis_depay_parent_class parent_class
 G_DEFINE_TYPE (GstRtpVorbisDepay, gst_rtp_vorbis_depay,
-    GST_TYPE_BASE_RTP_DEPAYLOAD);
+    GST_TYPE_RTP_BASE_DEPAYLOAD);
 
-static gboolean gst_rtp_vorbis_depay_setcaps (GstBaseRTPDepayload * depayload,
+static gboolean gst_rtp_vorbis_depay_setcaps (GstRTPBaseDepayload * depayload,
     GstCaps * caps);
-static GstBuffer *gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload,
-    GstBuffer * buf);
+static GstBuffer *gst_rtp_vorbis_depay_process (GstRTPBaseDepayload * depayload,
+    GstRTPBuffer * rtp);
 
 static void gst_rtp_vorbis_depay_finalize (GObject * object);
 
@@ -76,25 +77,25 @@ gst_rtp_vorbis_depay_class_init (GstRtpVorbisDepayClass * klass)
 {
   GObjectClass *gobject_class;
   GstElementClass *gstelement_class;
-  GstBaseRTPDepayloadClass *gstbasertpdepayload_class;
+  GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
 
   gobject_class = (GObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
-  gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass;
+  gstrtpbasedepayload_class = (GstRTPBaseDepayloadClass *) klass;
 
   gobject_class->finalize = gst_rtp_vorbis_depay_finalize;
 
   gstelement_class->change_state = gst_rtp_vorbis_depay_change_state;
 
-  gstbasertpdepayload_class->process = gst_rtp_vorbis_depay_process;
-  gstbasertpdepayload_class->set_caps = gst_rtp_vorbis_depay_setcaps;
+  gstrtpbasedepayload_class->process_rtp_packet = gst_rtp_vorbis_depay_process;
+  gstrtpbasedepayload_class->set_caps = gst_rtp_vorbis_depay_setcaps;
 
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_rtp_vorbis_depay_sink_template));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_rtp_vorbis_depay_src_template));
+  gst_element_class_add_static_pad_template (gstelement_class,
+      &gst_rtp_vorbis_depay_sink_template);
+  gst_element_class_add_static_pad_template (gstelement_class,
+      &gst_rtp_vorbis_depay_src_template);
 
-  gst_element_class_set_details_simple (gstelement_class,
+  gst_element_class_set_static_metadata (gstelement_class,
       "RTP Vorbis depayloader", "Codec/Depayloader/Network/RTP",
       "Extracts Vorbis Audio from RTP packets (RFC 5215)",
       "Wim Taymans <wim.taymans@gmail.com>");
@@ -112,26 +113,14 @@ gst_rtp_vorbis_depay_init (GstRtpVorbisDepay * rtpvorbisdepay)
 static void
 free_config (GstRtpVorbisConfig * conf)
 {
-  GList *headers;
-
-  for (headers = conf->headers; headers; headers = g_list_next (headers)) {
-    GstBuffer *header = GST_BUFFER_CAST (headers->data);
-
-    gst_buffer_unref (header);
-  }
-  g_list_free (conf->headers);
+  g_list_free_full (conf->headers, (GDestroyNotify) gst_buffer_unref);
   g_free (conf);
 }
 
 static void
 free_indents (GstRtpVorbisDepay * rtpvorbisdepay)
 {
-  GList *walk;
-
-  for (walk = rtpvorbisdepay->configs; walk; walk = g_list_next (walk)) {
-    free_config ((GstRtpVorbisConfig *) walk->data);
-  }
-  g_list_free (rtpvorbisdepay->configs);
+  g_list_free_full (rtpvorbisdepay->configs, (GDestroyNotify) free_config);
   rtpvorbisdepay->configs = NULL;
 }
 
@@ -145,6 +134,22 @@ gst_rtp_vorbis_depay_finalize (GObject * object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static gboolean
+gst_rtp_vorbis_depay_has_ident (GstRtpVorbisDepay * rtpvorbisdepay,
+    guint32 ident)
+{
+  GList *walk;
+
+  for (walk = rtpvorbisdepay->configs; walk; walk = g_list_next (walk)) {
+    GstRtpVorbisConfig *conf = (GstRtpVorbisConfig *) walk->data;
+
+    if (conf->ident == ident)
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
 /* takes ownership of confbuf */
 static gboolean
 gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay,
@@ -152,12 +157,15 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay,
 {
   GstBuffer *buf;
   guint32 num_headers;
-  guint8 *data, *bdata;
+  GstMapInfo map;
+  guint8 *data;
   gsize size;
   guint offset;
   gint i, j;
 
-  bdata = data = gst_buffer_map (confbuf, &size, NULL, GST_MAP_READ);
+  gst_buffer_map (confbuf, &map, GST_MAP_READ);
+  data = map.data;
+  size = map.size;
 
   GST_DEBUG_OBJECT (rtpvorbisdepay, "config size %" G_GSIZE_FORMAT, size);
 
@@ -227,7 +235,8 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay,
     offset += 6;
 
     GST_DEBUG_OBJECT (rtpvorbisdepay,
-        "header %d, ident 0x%08x, length %u, left %u", i, ident, length, size);
+        "header %d, ident 0x%08x, length %u, left %" G_GSIZE_FORMAT, i, ident,
+        length, size);
 
     /* FIXME check if we already got this ident */
 
@@ -235,6 +244,13 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay,
     if (size < length && size + 1 != length)
       goto too_small;
 
+    if (gst_rtp_vorbis_depay_has_ident (rtpvorbisdepay, ident)) {
+      size -= length;
+      data += length;
+      offset += length;
+      continue;
+    }
+
     /* read header sizes we read 2 sizes, the third size (for which we allocate
      * space) must be derived from the total packed header length. */
     h_sizes = g_newa (guint, n_headers + 1);
@@ -285,7 +301,7 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay,
       GST_DEBUG_OBJECT (rtpvorbisdepay, "reading header %d, size %u", j,
           h_size);
 
-      buf = gst_buffer_copy_region (confbuf, GST_BUFFER_COPY_MEMORY, offset,
+      buf = gst_buffer_copy_region (confbuf, GST_BUFFER_COPY_ALL, offset,
           h_size);
       conf->headers = g_list_append (conf->headers, buf);
       offset += h_size;
@@ -294,7 +310,7 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay,
     rtpvorbisdepay->configs = g_list_append (rtpvorbisdepay->configs, conf);
   }
 
-  gst_buffer_unmap (confbuf, bdata, -1);
+  gst_buffer_unmap (confbuf, &map);
   gst_buffer_unref (confbuf);
 
   return TRUE;
@@ -303,7 +319,7 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay,
 too_small:
   {
     GST_DEBUG_OBJECT (rtpvorbisdepay, "configuration too small");
-    gst_buffer_unmap (confbuf, bdata, -1);
+    gst_buffer_unmap (confbuf, &map);
     gst_buffer_unref (confbuf);
     return FALSE;
   }
@@ -315,29 +331,29 @@ gst_rtp_vorbis_depay_parse_inband_configuration (GstRtpVorbisDepay *
     guint length)
 {
   GstBuffer *confbuf;
-  guint8 *conf;
+  GstMapInfo map;
 
   if (G_UNLIKELY (size < 4))
     return FALSE;
 
   /* transform inline to out-of-band and parse that one */
   confbuf = gst_buffer_new_and_alloc (size + 9);
-  conf = gst_buffer_map (confbuf, NULL, NULL, -1);
+  gst_buffer_map (confbuf, &map, GST_MAP_WRITE);
   /* 1 header */
-  GST_WRITE_UINT32_BE (conf, 1);
+  GST_WRITE_UINT32_BE (map.data, 1);
   /* write Ident */
-  GST_WRITE_UINT24_BE (conf + 4, ident);
+  GST_WRITE_UINT24_BE (map.data + 4, ident);
   /* write sort-of-length */
-  GST_WRITE_UINT16_BE (conf + 7, length);
+  GST_WRITE_UINT16_BE (map.data + 7, length);
   /* copy remainder */
-  memcpy (conf + 9, configuration, size);
-  gst_buffer_unmap (confbuf, conf, -1);
+  memcpy (map.data + 9, configuration, size);
+  gst_buffer_unmap (confbuf, &map);
 
   return gst_rtp_vorbis_depay_parse_configuration (rtpvorbisdepay, confbuf);
 }
 
 static gboolean
-gst_rtp_vorbis_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
+gst_rtp_vorbis_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
 {
   GstStructure *structure;
   GstRtpVorbisDepay *rtpvorbisdepay;
@@ -365,8 +381,8 @@ gst_rtp_vorbis_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
     data = g_base64_decode (configuration, &size);
 
     confbuf = gst_buffer_new ();
-    gst_buffer_take_memory (confbuf, -1,
-        gst_memory_new_wrapped (0, data, g_free, size, 0, size));
+    gst_buffer_append_memory (confbuf,
+        gst_memory_new_wrapped (0, data, size, 0, size, data, g_free));
     if (!gst_rtp_vorbis_depay_parse_configuration (rtpvorbisdepay, confbuf))
       goto invalid_configuration;
   } else {
@@ -377,7 +393,7 @@ gst_rtp_vorbis_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
   depayload->clock_rate = clock_rate;
 
   /* set caps on pad and on header */
-  srccaps = gst_caps_new_simple ("audio/x-vorbis", NULL);
+  srccaps = gst_caps_new_empty_simple ("audio/x-vorbis");
   res = gst_pad_set_caps (depayload->srcpad, srccaps);
   gst_caps_unref (srccaps);
 
@@ -417,7 +433,7 @@ gst_rtp_vorbis_depay_switch_codebook (GstRtpVorbisDepay * rtpvorbisdepay,
         GstBuffer *header = GST_BUFFER_CAST (headers->data);
 
         gst_buffer_ref (header);
-        gst_base_rtp_depayload_push (GST_BASE_RTP_DEPAYLOAD (rtpvorbisdepay),
+        gst_rtp_base_depayload_push (GST_RTP_BASE_DEPAYLOAD (rtpvorbisdepay),
             header);
       }
       /* remember the current config */
@@ -433,23 +449,23 @@ gst_rtp_vorbis_depay_switch_codebook (GstRtpVorbisDepay * rtpvorbisdepay,
 }
 
 static GstBuffer *
-gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
+gst_rtp_vorbis_depay_process (GstRTPBaseDepayload * depayload,
+    GstRTPBuffer * rtp)
 {
   GstRtpVorbisDepay *rtpvorbisdepay;
   GstBuffer *outbuf;
   GstFlowReturn ret;
   gint payload_len;
-  guint8 *payload, *to_free = NULL;
-  guint32 timestamp;
+  GstBuffer *payload_buffer = NULL;
+  guint8 *payload;
+  GstMapInfo map;
   guint32 header, ident;
   guint8 F, VDT, packets;
-  GstRTPBuffer rtp;
+  guint length;
 
   rtpvorbisdepay = GST_RTP_VORBIS_DEPAY (depayload);
 
-  gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
-
-  payload_len = gst_rtp_buffer_get_payload_len (&rtp);
+  payload_len = gst_rtp_buffer_get_payload_len (rtp);
 
   GST_DEBUG_OBJECT (depayload, "got RTP packet of size %d", payload_len);
 
@@ -457,8 +473,7 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
   if (G_UNLIKELY (payload_len < 4))
     goto packet_short;
 
-  payload = gst_rtp_buffer_get_payload (&rtp);
-
+  payload = gst_rtp_buffer_get_payload (rtp);
   header = GST_READ_UINT32_BE (payload);
   /*
    *  0                   1                   2                   3
@@ -500,17 +515,12 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
     }
   }
 
-  /* skip header */
-  payload += 4;
-  payload_len -= 4;
-
   GST_DEBUG_OBJECT (depayload, "ident: %u, F: %d, VDT: %d, packets: %d", ident,
       F, VDT, packets);
 
   /* fragmented packets, assemble */
   if (F != 0) {
     GstBuffer *vdata;
-    guint headerskip;
 
     if (F == 1) {
       /* if we start a packet, clear adapter and start assembling. */
@@ -522,10 +532,8 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
     if (!rtpvorbisdepay->assembling)
       goto no_output;
 
-    /* first assembled packet, reuse 2 bytes to store the length */
-    headerskip = (F == 1 ? 4 : 6);
     /* skip header and length. */
-    vdata = gst_rtp_buffer_get_payload_subbuffer (&rtp, headerskip, -1);
+    vdata = gst_rtp_buffer_get_payload_subbuffer (rtp, 6, -1);
 
     GST_DEBUG_OBJECT (depayload, "assemble vorbis packet");
     gst_adapter_push (rtpvorbisdepay->adapter, vdata);
@@ -535,16 +543,19 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
       goto no_output;
 
     /* construct assembled buffer */
-    payload_len = gst_adapter_available (rtpvorbisdepay->adapter);
-    payload = gst_adapter_take (rtpvorbisdepay->adapter, payload_len);
-    /* fix the length */
-    payload[0] = ((payload_len - 2) >> 8) & 0xff;
-    payload[1] = (payload_len - 2) & 0xff;
-    to_free = payload;
+    length = gst_adapter_available (rtpvorbisdepay->adapter);
+    payload_buffer = gst_adapter_take_buffer (rtpvorbisdepay->adapter, length);
+  } else {
+    payload_buffer = gst_rtp_buffer_get_payload_subbuffer (rtp, 4, -1);
+    length = 0;
   }
 
   GST_DEBUG_OBJECT (depayload, "assemble done");
 
+  gst_buffer_map (payload_buffer, &map, GST_MAP_READ);
+  payload = map.data;
+  payload_len = map.size;
+
   /* we not assembling anymore now */
   rtpvorbisdepay->assembling = FALSE;
   gst_adapter_clear (rtpvorbisdepay->adapter);
@@ -564,14 +575,16 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
    * ..                        vorbis data                           |
    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*
    */
-  timestamp = gst_rtp_buffer_get_timestamp (&rtp);
-
   while (payload_len > 2) {
-    guint16 length;
-
-    length = GST_READ_UINT16_BE (payload);
-    payload += 2;
-    payload_len -= 2;
+    /* If length is not 0, we have a reassembled packet for which we
+     * calculated the length already and don't have to skip over the
+     * length field anymore
+     */
+    if (length == 0) {
+      length = GST_READ_UINT16_BE (payload);
+      payload += 2;
+      payload_len -= 2;
+    }
 
     GST_DEBUG_OBJECT (depayload, "read length %u, avail: %d", length,
         payload_len);
@@ -590,75 +603,59 @@ gst_rtp_vorbis_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
     }
 
     /* create buffer for packet */
-    if (G_UNLIKELY (to_free)) {
-      outbuf = gst_buffer_new ();
-      gst_buffer_take_memory (outbuf, -1,
-          gst_memory_new_wrapped (0, to_free, g_free,
-              (payload - to_free) + length, payload - to_free, length));
-      to_free = NULL;
-    } else {
-      guint8 *data;
-
-      outbuf = gst_buffer_new_and_alloc (length);
-      data = gst_buffer_map (outbuf, NULL, NULL, GST_MAP_WRITE);
-      memcpy (data, payload, length);
-      gst_buffer_unmap (outbuf, data, -1);
-    }
+    outbuf =
+        gst_buffer_copy_region (payload_buffer, GST_BUFFER_COPY_ALL,
+        payload - map.data, length);
 
     payload += length;
     payload_len -= length;
+    /* make sure to read next length */
+    length = 0;
 
-    if (timestamp != -1)
-      /* push with timestamp of the last packet, which is the same timestamp that
-       * should apply to the first assembled packet. */
-      ret = gst_base_rtp_depayload_push_ts (depayload, timestamp, outbuf);
-    else
-      ret = gst_base_rtp_depayload_push (depayload, outbuf);
-
+    ret = gst_rtp_base_depayload_push (depayload, outbuf);
     if (ret != GST_FLOW_OK)
       break;
-
-    /* make sure we don't set a timestamp on next buffers */
-    timestamp = -1;
   }
 
-  g_free (to_free);
-
-  gst_rtp_buffer_unmap (&rtp);
+  gst_buffer_unmap (payload_buffer, &map);
+  gst_buffer_unref (payload_buffer);
 
   return NULL;
 
 no_output:
   {
-    gst_rtp_buffer_unmap (&rtp);
+    if (payload_buffer) {
+      gst_buffer_unmap (payload_buffer, &map);
+      gst_buffer_unref (payload_buffer);
+    }
     return NULL;
   }
-  /* ERORRS */
+  /* ERRORS */
 switch_failed:
   {
     GST_ELEMENT_WARNING (rtpvorbisdepay, STREAM, DECODE,
         (NULL), ("Could not switch codebooks"));
-    gst_rtp_buffer_unmap (&rtp);
     return NULL;
   }
 packet_short:
   {
     GST_ELEMENT_WARNING (rtpvorbisdepay, STREAM, DECODE,
         (NULL), ("Packet was too short (%d < 4)", payload_len));
-    gst_rtp_buffer_unmap (&rtp);
     return NULL;
   }
 ignore_reserved:
   {
     GST_WARNING_OBJECT (rtpvorbisdepay, "reserved VDT ignored");
-    gst_rtp_buffer_unmap (&rtp);
     return NULL;
   }
 length_short:
   {
     GST_ELEMENT_WARNING (rtpvorbisdepay, STREAM, DECODE,
         (NULL), ("Packet contains invalid data"));
-    gst_rtp_buffer_unmap (&rtp);
+    if (payload_buffer) {
+      gst_buffer_unmap (payload_buffer, &map);
+      gst_buffer_unref (payload_buffer);
+    }
     return NULL;
   }
 invalid_configuration:
@@ -666,7 +663,10 @@ invalid_configuration:
     /* fatal, as we otherwise risk carrying on without output */
     GST_ELEMENT_ERROR (rtpvorbisdepay, STREAM, DECODE,
         (NULL), ("Packet contains invalid configuration"));
-    gst_rtp_buffer_unmap (&rtp);
+    if (payload_buffer) {
+      gst_buffer_unmap (payload_buffer, &map);
+      gst_buffer_unref (payload_buffer);
+    }
     return NULL;
   }
 }