rtp: Update codes based on 1.18.4
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtpmp4apay.c
index 59c7e60..ab1eeb5 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 <string.h>
 
 #include <gst/rtp/gstrtpbuffer.h>
+#include <gst/audio/audio.h>
 
 #include "gstrtpmp4apay.h"
+#include "gstrtputils.h"
 
 GST_DEBUG_CATEGORY_STATIC (rtpmp4apay_debug);
 #define GST_CAT_DEFAULT (rtpmp4apay_debug)
@@ -59,35 +61,36 @@ GST_STATIC_PAD_TEMPLATE ("src",
 
 static void gst_rtp_mp4a_pay_finalize (GObject * object);
 
-static gboolean gst_rtp_mp4a_pay_setcaps (GstBaseRTPPayload * payload,
+static gboolean gst_rtp_mp4a_pay_setcaps (GstRTPBasePayload * payload,
     GstCaps * caps);
-static GstFlowReturn gst_rtp_mp4a_pay_handle_buffer (GstBaseRTPPayload *
+static GstFlowReturn gst_rtp_mp4a_pay_handle_buffer (GstRTPBasePayload *
     payload, GstBuffer * buffer);
 
 #define gst_rtp_mp4a_pay_parent_class parent_class
-G_DEFINE_TYPE (GstRtpMP4APay, gst_rtp_mp4a_pay, GST_TYPE_BASE_RTP_PAYLOAD)
+G_DEFINE_TYPE (GstRtpMP4APay, gst_rtp_mp4a_pay, GST_TYPE_RTP_BASE_PAYLOAD);
 
-     static void gst_rtp_mp4a_pay_class_init (GstRtpMP4APayClass * klass)
+static void
+gst_rtp_mp4a_pay_class_init (GstRtpMP4APayClass * klass)
 {
   GObjectClass *gobject_class;
   GstElementClass *gstelement_class;
-  GstBaseRTPPayloadClass *gstbasertppayload_class;
+  GstRTPBasePayloadClass *gstrtpbasepayload_class;
 
   gobject_class = (GObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
-  gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
+  gstrtpbasepayload_class = (GstRTPBasePayloadClass *) klass;
 
   gobject_class->finalize = gst_rtp_mp4a_pay_finalize;
 
-  gstbasertppayload_class->set_caps = gst_rtp_mp4a_pay_setcaps;
-  gstbasertppayload_class->handle_buffer = gst_rtp_mp4a_pay_handle_buffer;
+  gstrtpbasepayload_class->set_caps = gst_rtp_mp4a_pay_setcaps;
+  gstrtpbasepayload_class->handle_buffer = gst_rtp_mp4a_pay_handle_buffer;
 
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_rtp_mp4a_pay_src_template));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_rtp_mp4a_pay_sink_template));
+  gst_element_class_add_static_pad_template (gstelement_class,
+      &gst_rtp_mp4a_pay_src_template);
+  gst_element_class_add_static_pad_template (gstelement_class,
+      &gst_rtp_mp4a_pay_sink_template);
 
-  gst_element_class_set_details_simple (gstelement_class,
+  gst_element_class_set_static_metadata (gstelement_class,
       "RTP MPEG4 audio payloader", "Codec/Payloader/Network/RTP",
       "Payload MPEG4 audio as RTP packets (RFC 3016)",
       "Wim Taymans <wim.taymans@gmail.com>");
@@ -132,13 +135,16 @@ static gboolean
 gst_rtp_mp4a_pay_parse_audio_config (GstRtpMP4APay * rtpmp4apay,
     GstBuffer * buffer)
 {
+  GstMapInfo map;
   guint8 *data;
   gsize size;
   guint8 objectType;
   guint8 samplingIdx;
   guint8 channelCfg;
 
-  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+  gst_buffer_map (buffer, &map, GST_MAP_READ);
+  data = map.data;
+  size = map.size;
 
   if (size < 2)
     goto too_short;
@@ -182,7 +188,7 @@ gst_rtp_mp4a_pay_parse_audio_config (GstRtpMP4APay * rtpmp4apay,
       "objectType: %d, samplingIdx: %d (%d), channelCfg: %d", objectType,
       samplingIdx, rtpmp4apay->rate, channelCfg);
 
-  gst_buffer_unmap (buffer, data, -1);
+  gst_buffer_unmap (buffer, &map);
 
   return TRUE;
 
@@ -190,29 +196,31 @@ gst_rtp_mp4a_pay_parse_audio_config (GstRtpMP4APay * rtpmp4apay,
 too_short:
   {
     GST_ELEMENT_ERROR (rtpmp4apay, STREAM, FORMAT,
-        (NULL), ("config string too short, expected 2 bytes, got %d", size));
-    gst_buffer_unmap (buffer, data, -1);
+        (NULL),
+        ("config string too short, expected 2 bytes, got %" G_GSIZE_FORMAT,
+            size));
+    gst_buffer_unmap (buffer, &map);
     return FALSE;
   }
 invalid_object:
   {
     GST_ELEMENT_ERROR (rtpmp4apay, STREAM, FORMAT,
         (NULL), ("invalid object type 0"));
-    gst_buffer_unmap (buffer, data, -1);
+    gst_buffer_unmap (buffer, &map);
     return FALSE;
   }
 wrong_freq:
   {
     GST_ELEMENT_ERROR (rtpmp4apay, STREAM, NOT_IMPLEMENTED,
         (NULL), ("unsupported frequency index %d", samplingIdx));
-    gst_buffer_unmap (buffer, data, -1);
+    gst_buffer_unmap (buffer, &map);
     return FALSE;
   }
 wrong_channels:
   {
     GST_ELEMENT_ERROR (rtpmp4apay, STREAM, NOT_IMPLEMENTED,
         (NULL), ("unsupported number of channels %d, must < 8", channelCfg));
-    gst_buffer_unmap (buffer, data, -1);
+    gst_buffer_unmap (buffer, &map);
     return FALSE;
   }
 }
@@ -228,7 +236,7 @@ gst_rtp_mp4a_pay_new_caps (GstRtpMP4APay * rtpmp4apay)
   gst_value_set_buffer (&v, rtpmp4apay->config);
   config = gst_value_serialize (&v);
 
-  res = gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4apay),
+  res = gst_rtp_base_payload_set_outcaps (GST_RTP_BASE_PAYLOAD (rtpmp4apay),
       "cpresent", G_TYPE_STRING, "0", "config", G_TYPE_STRING, config, NULL);
 
   g_value_unset (&v);
@@ -238,7 +246,7 @@ gst_rtp_mp4a_pay_new_caps (GstRtpMP4APay * rtpmp4apay)
 }
 
 static gboolean
-gst_rtp_mp4a_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
+gst_rtp_mp4a_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps)
 {
   GstRtpMP4APay *rtpmp4apay;
   GstStructure *structure;
@@ -270,10 +278,9 @@ gst_rtp_mp4a_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
     GST_LOG_OBJECT (rtpmp4apay, "got codec_data");
     if (G_VALUE_TYPE (codec_data) == GST_TYPE_BUFFER) {
       GstBuffer *buffer, *cbuffer;
-      guint8 *config;
-      guint8 *data;
+      GstMapInfo map;
+      GstMapInfo cmap;
       guint i;
-      gsize size;
 
       buffer = gst_value_get_buffer (codec_data);
       GST_LOG_OBJECT (rtpmp4apay, "configuring codec_data");
@@ -284,11 +291,13 @@ gst_rtp_mp4a_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
       if (!res)
         goto config_failed;
 
-      data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+      gst_buffer_map (buffer, &map, GST_MAP_READ);
 
       /* make the StreamMuxConfig, we need 15 bits for the header */
-      cbuffer = gst_buffer_new_and_alloc (size + 2);
-      config = gst_buffer_map (cbuffer, NULL, NULL, GST_MAP_WRITE);
+      cbuffer = gst_buffer_new_and_alloc (map.size + 2);
+      gst_buffer_map (cbuffer, &cmap, GST_MAP_WRITE);
+
+      memset (cmap.data, 0, map.size + 2);
 
       /* Create StreamMuxConfig according to ISO/IEC 14496-3:
        *
@@ -298,17 +307,17 @@ gst_rtp_mp4a_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
        * numProgram                == 0 (4 bits)
        * numLayer                  == 0 (3 bits)
        */
-      config[0] = 0x40;
-      config[1] = 0x00;
+      cmap.data[0] = 0x40;
+      cmap.data[1] = 0x00;
 
       /* append the config bits, shifting them 1 bit left */
-      for (i = 0; i < size; i++) {
-        config[i + 1] |= ((data[i] & 0x80) >> 7);
-        config[i + 2] |= ((data[i] & 0x7f) << 1);
+      for (i = 0; i < map.size; i++) {
+        cmap.data[i + 1] |= ((map.data[i] & 0x80) >> 7);
+        cmap.data[i + 2] |= ((map.data[i] & 0x7f) << 1);
       }
 
-      gst_buffer_unmap (cbuffer, config, -1);
-      gst_buffer_unmap (buffer, data, -1);
+      gst_buffer_unmap (cbuffer, &cmap);
+      gst_buffer_unmap (buffer, &map);
 
       /* now we can configure the buffer */
       if (rtpmp4apay->config)
@@ -321,7 +330,7 @@ gst_rtp_mp4a_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
     GST_WARNING_OBJECT (payload, "Need framed AAC data as input!");
   }
 
-  gst_basertppayload_set_options (payload, "audio", TRUE, "MP4A-LATM",
+  gst_rtp_base_payload_set_options (payload, "audio", TRUE, "MP4A-LATM",
       rtpmp4apay->rate);
 
   res = gst_rtp_mp4a_pay_new_caps (rtpmp4apay);
@@ -336,18 +345,20 @@ config_failed:
   }
 }
 
+#define RTP_HEADER_LEN 12
+
 /* we expect buffers as exactly one complete AU
  */
 static GstFlowReturn
-gst_rtp_mp4a_pay_handle_buffer (GstBaseRTPPayload * basepayload,
+gst_rtp_mp4a_pay_handle_buffer (GstRTPBasePayload * basepayload,
     GstBuffer * buffer)
 {
   GstRtpMP4APay *rtpmp4apay;
   GstFlowReturn ret;
-  GstBuffer *outbuf;
-  guint count, mtu;
+  GstBufferList *list;
+  guint mtu;
+  guint offset;
   gsize size;
-  guint8 *data, *bdata;
   gboolean fragmented;
   GstClockTime timestamp;
 
@@ -355,80 +366,92 @@ gst_rtp_mp4a_pay_handle_buffer (GstBaseRTPPayload * basepayload,
 
   rtpmp4apay = GST_RTP_MP4A_PAY (basepayload);
 
-  data = bdata = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
-  timestamp = GST_BUFFER_TIMESTAMP (buffer);
+  offset = 0;
+  size = gst_buffer_get_size (buffer);
+
+  timestamp = GST_BUFFER_PTS (buffer);
 
   fragmented = FALSE;
-  mtu = GST_BASE_RTP_PAYLOAD_MTU (rtpmp4apay);
+  mtu = GST_RTP_BASE_PAYLOAD_MTU (rtpmp4apay);
+
+  list = gst_buffer_list_new_sized (size / (mtu - RTP_HEADER_LEN) + 1);
 
   while (size > 0) {
     guint towrite;
-    guint8 *payload;
+    GstBuffer *outbuf;
     guint payload_len;
     guint packet_len;
-    GstRTPBuffer rtp;
-
-    /* this will be the total lenght of the packet */
-    packet_len = gst_rtp_buffer_calc_packet_len (size, 0, 0);
+    guint header_len;
+    GstBuffer *paybuf;
+    GstRTPBuffer rtp = { NULL };
 
+    header_len = 0;
     if (!fragmented) {
+      guint count;
       /* first packet calculate space for the packet including the header */
       count = size;
       while (count >= 0xff) {
-        packet_len++;
+        header_len++;
         count -= 0xff;
       }
-      packet_len++;
+      header_len++;
     }
 
-    /* fill one MTU or all available bytes */
+    packet_len = gst_rtp_buffer_calc_packet_len (header_len + size, 0, 0);
     towrite = MIN (packet_len, mtu);
-
-    /* this is the payload length */
     payload_len = gst_rtp_buffer_calc_payload_len (towrite, 0, 0);
+    payload_len -= header_len;
 
     GST_DEBUG_OBJECT (rtpmp4apay,
-        "avail %d, towrite %d, packet_len %d, payload_len %d", size, towrite,
+        "avail %" G_GSIZE_FORMAT
+        ", header_len %d, packet_len %d, payload_len %d", size, header_len,
         packet_len, payload_len);
 
     /* create buffer to hold the payload. */
-    outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
+    outbuf = gst_rtp_base_payload_allocate_output_buffer (basepayload,
+        header_len, 0, 0);
 
     /* copy payload */
     gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
-    payload = gst_rtp_buffer_get_payload (&rtp);
 
     if (!fragmented) {
+      guint8 *payload = gst_rtp_buffer_get_payload (&rtp);
+      guint count;
+
       /* first packet write the header */
       count = size;
       while (count >= 0xff) {
         *payload++ = 0xff;
-        payload_len--;
         count -= 0xff;
       }
       *payload++ = count;
-      payload_len--;
     }
 
-    /* copy data to payload */
-    memcpy (payload, data, payload_len);
-    data += payload_len;
-    size -= payload_len;
-
     /* marker only if the packet is complete */
-    gst_rtp_buffer_set_marker (&rtp, size == 0);
+    gst_rtp_buffer_set_marker (&rtp, size == payload_len);
 
     gst_rtp_buffer_unmap (&rtp);
 
-    /* copy incomming timestamp (if any) to outgoing buffers */
-    GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
+    /* create a new buf to hold the payload */
+    paybuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL,
+        offset, payload_len);
 
-    ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtpmp4apay), outbuf);
+    /* join memory parts */
+    gst_rtp_copy_audio_meta (rtpmp4apay, outbuf, paybuf);
+    outbuf = gst_buffer_append (outbuf, paybuf);
+    gst_buffer_list_add (list, outbuf);
+    offset += payload_len;
+    size -= payload_len;
+
+    /* copy incoming timestamp (if any) to outgoing buffers */
+    GST_BUFFER_PTS (outbuf) = timestamp;
 
     fragmented = TRUE;
   }
 
-  gst_buffer_unmap (buffer, bdata, -1);
+  ret =
+      gst_rtp_base_payload_push_list (GST_RTP_BASE_PAYLOAD (rtpmp4apay), list);
+
   gst_buffer_unref (buffer);
 
   return ret;