diff --git a/gst-libs/gst/rtp/gstrtpbuffer.c b/gst-libs/gst/rtp/gstrtpbuffer.c index f28d3ce6dc..ebc0824983 100644 --- a/gst-libs/gst/rtp/gstrtpbuffer.c +++ b/gst-libs/gst/rtp/gstrtpbuffer.c @@ -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 @@ -1092,6 +1133,34 @@ gst_rtp_buffer_get_payload (GstRTPBuffer * rtp) return rtp->data[2]; } +/** + * 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 diff --git a/gst-libs/gst/rtp/gstrtpbuffer.h b/gst-libs/gst/rtp/gstrtpbuffer.h index 423d210d7a..8a4e5d8728 100644 --- a/gst-libs/gst/rtp/gstrtpbuffer.h +++ b/gst-libs/gst/rtp/gstrtpbuffer.h @@ -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); diff --git a/tests/check/libs/rtp.c b/tests/check/libs/rtp.c index 0c9b003d9a..9d57dbda50 100644 --- a/tests/check/libs/rtp.c +++ b/tests/check/libs/rtp.c @@ -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;