rtpbuffer: add gst_rtp_buffer_get_payload_bytes
authorBranko Subasic <branko@axis.com>
Sun, 16 Jun 2013 20:39:30 +0000 (22:39 +0200)
committerSebastian Dröge <slomo@circular-chaos.org>
Tue, 18 Jun 2013 09:23:40 +0000 (11:23 +0200)
The function gst_rtp_buffer_get_payload can not be used in Python
because it lacks necessary length parameter. This patch adds a new
function, gst_rtp_buffer_get_payload_bytes, to use from Python
bindings. The new function has the advisory "Rename to:" annotation
so it can replace the gst_rtp_buffer_get_payload whan creating
bindings.

The function gst_rtp_buffer_get_extension_bytes is also added. It wraps
gst_rtp_buffer_get_extension_data which doesn't work in Python due to
incomplete annotation and because it returns the length as number of
32-bit words.

https://bugzilla.gnome.org/show_bug.cgi?id=698562

gst-libs/gst/rtp/gstrtpbuffer.c
gst-libs/gst/rtp/gstrtpbuffer.h
tests/check/libs/rtp.c

index f28d3ce..ebc0824 100644 (file)
@@ -651,7 +651,7 @@ gst_rtp_buffer_set_extension (GstRTPBuffer * rtp, gboolean extension)
 }
 
 /**
- * gst_rtp_buffer_get_extension_data:
+ * gst_rtp_buffer_get_extension_data: (skip)
  * @rtp: the RTP packet
  * @bits: (out): location for result bits
  * @data: (out) (array) (element-type guint8) (transfer none): location for data
@@ -688,6 +688,47 @@ gst_rtp_buffer_get_extension_data (GstRTPBuffer * rtp, guint16 * bits,
   return TRUE;
 }
 
+/**
+ * gst_rtp_buffer_get_extension_bytes:
+ * @rtp: the RTP packet
+ * @bits: (out): location for header bits
+ *
+ * Similar to gst_rtp_buffer_get_extension_data, but more suitable for language
+ * bindings usage. @bits will contain the extension 16 bits of custom data and
+ * the extension data (not including the extension header) is placed in a new
+ * #GBytes structure.
+ *
+ * If @rtp did not contain an extension, this function will return %NULL, with
+ * @bits unchanged. If there is an extension header but no extension data then
+ * an empty #GBytes will be returned.
+ *
+ * Returns: (transfer full): A new #GBytes if an extension header was present
+ * and %NULL otherwise.
+ *
+ * Rename to: gst_rtp_buffer_get_extension_data
+ *
+ * Since: 1.2
+ */
+GBytes *
+gst_rtp_buffer_get_extension_bytes (GstRTPBuffer * rtp, guint16 * bits)
+{
+  gpointer buf_data = NULL;
+  guint buf_len;
+
+  g_return_val_if_fail (rtp != NULL, FALSE);
+
+  if (!gst_rtp_buffer_get_extension_data (rtp, bits, &buf_data, &buf_len))
+    return NULL;
+
+  if (buf_len == 0) {
+    /* if no extension data is present return an empty GBytes */
+    buf_data = NULL;
+  }
+
+  /* multiply length with 4 to get length in bytes */
+  return g_bytes_new (buf_data, 4 * buf_len);
+}
+
 /* ensure header, payload and padding are in separate buffers */
 static void
 ensure_buffers (GstRTPBuffer * rtp)
@@ -1057,7 +1098,7 @@ gst_rtp_buffer_get_payload_len (GstRTPBuffer * rtp)
 }
 
 /**
- * gst_rtp_buffer_get_payload:
+ * gst_rtp_buffer_get_payload: (skip)
  * @rtp: the RTP packet
  *
  * Get a pointer to the payload data in @buffer. This pointer is valid as long
@@ -1093,6 +1134,34 @@ gst_rtp_buffer_get_payload (GstRTPBuffer * rtp)
 }
 
 /**
+ * gst_rtp_buffer_get_payload_bytes:
+ * @rtp: the RTP packet
+ *
+ * Similar to gst_rtp_buffer_get_payload, but more suitable for language
+ * bindings usage. The return value is a pointer to a #GBytes structure
+ * containing the payload data in @rtp.
+ *
+ * Returns: (transfer full): A new #GBytes containing the payload data in @rtp.
+ *
+ * Rename to: gst_rtp_buffer_get_payload
+ *
+ * Since: 1.2
+ */
+GBytes *
+gst_rtp_buffer_get_payload_bytes (GstRTPBuffer * rtp)
+{
+  gpointer data;
+
+  g_return_val_if_fail (rtp != NULL, NULL);
+
+  data = gst_rtp_buffer_get_payload (rtp);
+  if (data == NULL)
+    return NULL;
+
+  return g_bytes_new (data, gst_rtp_buffer_get_payload_len (rtp));
+}
+
+/**
  * gst_rtp_buffer_default_clock_rate:
  * @payload_type: the static payload type
  *
index 423d210..8a4e5d8 100644 (file)
@@ -94,6 +94,7 @@ gboolean        gst_rtp_buffer_get_extension         (GstRTPBuffer *rtp);
 void            gst_rtp_buffer_set_extension         (GstRTPBuffer *rtp, gboolean extension);
 gboolean        gst_rtp_buffer_get_extension_data    (GstRTPBuffer *rtp, guint16 *bits,
                                                       gpointer *data, guint *wordlen);
+GBytes*         gst_rtp_buffer_get_extension_bytes   (GstRTPBuffer *rtp, guint16 *bits);
 gboolean        gst_rtp_buffer_set_extension_data    (GstRTPBuffer *rtp, guint16 bits, guint16 length);
 
 guint32         gst_rtp_buffer_get_ssrc              (GstRTPBuffer *rtp);
@@ -120,6 +121,7 @@ GstBuffer*      gst_rtp_buffer_get_payload_subbuffer (GstRTPBuffer *rtp, guint o
 
 guint           gst_rtp_buffer_get_payload_len       (GstRTPBuffer *rtp);
 gpointer        gst_rtp_buffer_get_payload           (GstRTPBuffer *rtp);
+GBytes*         gst_rtp_buffer_get_payload_bytes     (GstRTPBuffer *rtp);
 
 /* some helpers */
 guint32         gst_rtp_buffer_default_clock_rate    (guint8 payload_type);
index 0c9b003..9d57dbd 100644 (file)
@@ -838,6 +838,123 @@ GST_START_TEST (test_rtp_ntp56_extension)
 
 GST_END_TEST;
 
+GST_START_TEST (test_rtp_buffer_get_extension_bytes)
+{
+  GstBuffer *buf;
+  guint16 bits;
+  guint size;
+  guint8 misc_data[4] = { 1, 2, 3, 4 };
+  gpointer pointer;
+  GstRTPBuffer rtp = { NULL, };
+  GBytes *gb;
+  gsize gb_size;
+
+  /* create RTP buffer without extension header */
+  buf = gst_rtp_buffer_new_allocate (4, 0, 0);
+  gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp);
+  fail_if (gst_rtp_buffer_get_extension (&rtp));
+
+  /* verify that obtaining extension data returns NULL and bits are unchanged */
+  bits = 0xabcd;
+  gb = gst_rtp_buffer_get_extension_bytes (&rtp, &bits);
+  fail_unless (gb == NULL);
+  fail_unless (bits == 0xabcd);
+
+  g_bytes_unref (gb);
+
+  /* add extension header without data and verify that
+   * an empty GBytes is returned */
+  fail_unless (gst_rtp_buffer_set_extension_data (&rtp, 270, 0));
+  fail_unless (gst_rtp_buffer_get_extension (&rtp));
+  gb = gst_rtp_buffer_get_extension_bytes (&rtp, &bits);
+  fail_unless (gb != NULL);
+  fail_unless_equals_int (g_bytes_get_size (gb), 0);
+
+  g_bytes_unref (gb);
+  gst_rtp_buffer_unmap (&rtp);
+  gst_buffer_unref (buf);
+
+  /* create RTP buffer with extension header and extension data */
+  buf = gst_rtp_buffer_new_allocate (4, 0, 0);
+  gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp);
+  fail_unless (gst_rtp_buffer_add_extension_onebyte_header (&rtp, 5,
+          misc_data, 2));
+  fail_unless (gst_rtp_buffer_get_extension (&rtp));
+
+  /* verify that gst_rtp_buffer_get_extension_bytes returns the same
+   * header bits and data as does gst_rtp_buffer_get_extension_data */
+  fail_unless (gst_rtp_buffer_get_extension_data (&rtp, &bits, &pointer,
+          &size));
+  fail_unless (bits == 0xBEDE);
+  fail_unless (size == 1);
+  gb = gst_rtp_buffer_get_extension_bytes (&rtp, &bits);
+  fail_unless (gb != NULL);
+  fail_unless (bits == 0xBEDE);
+  fail_unless_equals_int (g_bytes_get_size (gb), size * 4);
+  fail_unless (memcmp (pointer, g_bytes_get_data (gb, &gb_size),
+          size * 4) == 0);
+  fail_unless_equals_int (gb_size, size * 4);
+
+  g_bytes_unref (gb);
+  gst_rtp_buffer_unmap (&rtp);
+  gst_buffer_unref (buf);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_rtp_buffer_get_payload_bytes)
+{
+  guint8 rtppacket[] = {
+    0x80, 0xe0, 0xdf, 0xd7, 0xef, 0x84, 0xbe, 0xed, 0x9b, 0xc5, 0x29, 0x14,
+    'H', 'e', 'l', 'l', 'o', '\0'
+  };
+
+  GstBuffer *buf;
+  GstMapInfo map;
+  gconstpointer data;
+  gsize size;
+  GstRTPBuffer rtp = { NULL, };
+  GBytes *gb;
+
+  /* create empty RTP buffer, i.e. no payload */
+  buf = gst_rtp_buffer_new_allocate (0, 4, 0);
+  fail_unless (buf != NULL);
+  gst_buffer_map (buf, &map, GST_MAP_READWRITE);
+  fail_unless_equals_int (map.size, RTP_HEADER_LEN + 4);
+  fail_unless (gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp));
+
+  /* verify that requesting payload data returns an empty GBytes */
+  gb = gst_rtp_buffer_get_payload_bytes (&rtp);
+  fail_unless (gb != NULL);
+  fail_unless_equals_int (g_bytes_get_size (gb), 0);
+
+  gst_rtp_buffer_unmap (&rtp);
+  gst_buffer_unmap (buf, &map);
+  gst_buffer_unref (buf);
+
+  /* create RTP buffer containing RTP packet */
+  buf = gst_buffer_new_and_alloc (sizeof (rtppacket));
+  fail_unless (buf != NULL);
+  gst_buffer_fill (buf, 0, rtppacket, sizeof (rtppacket));
+  gst_buffer_map (buf, &map, GST_MAP_READWRITE);
+  fail_unless_equals_int (map.size, sizeof (rtppacket));
+  fail_unless (gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp));
+
+  /* verify that the returned GBytes contains the correct payload data */
+  gb = gst_rtp_buffer_get_payload_bytes (&rtp);
+  fail_unless (gb != NULL);
+  data = g_bytes_get_data (gb, &size);
+  fail_unless (data != NULL);
+  fail_unless (size == (sizeof (rtppacket) - RTP_HEADER_LEN));
+  fail_unless_equals_string ("Hello", data);
+
+  gst_rtp_buffer_unmap (&rtp);
+  gst_buffer_unmap (buf, &map);
+  gst_buffer_unref (buf);
+}
+
+GST_END_TEST;
+
 static Suite *
 rtp_suite (void)
 {
@@ -855,6 +972,9 @@ rtp_suite (void)
   tcase_add_test (tc_chain, test_rtp_ntp64_extension);
   tcase_add_test (tc_chain, test_rtp_ntp56_extension);
 
+  tcase_add_test (tc_chain, test_rtp_buffer_get_payload_bytes);
+  tcase_add_test (tc_chain, test_rtp_buffer_get_extension_bytes);
+
   //tcase_add_test (tc_chain, test_rtp_buffer_list);
 
   return s;