From b7d4d371f9d1049a3aff01387f67e7ca839d1bf1 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Tue, 24 Aug 2021 21:26:54 +1000 Subject: [PATCH] rtp: also support shrinking the extension data Currently the extension data length specified in the RTP header would say it was shorter then the data serialised to a packet. When combining the resulting buffer, the underlying memory would still contain the extra (now 0-filled) padding data. This would mean that parsing the resulting RTP packet would potentially start with a number of 0-filled bytes which many RTP formats are not expecting. Such usage is found by e.g. RTP header extension when allocating the maximum buffer (which may be larger than the written size) and shrinking to the required size the data once all the rtp header extension data has been written. Part-of: --- .../gst-libs/gst/rtp/gstrtpbuffer.c | 11 +++ .../gst-plugins-base/tests/check/libs/rtp.c | 82 ++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/subprojects/gst-plugins-base/gst-libs/gst/rtp/gstrtpbuffer.c b/subprojects/gst-plugins-base/gst-libs/gst/rtp/gstrtpbuffer.c index ce3949a..399724d 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/rtp/gstrtpbuffer.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/rtp/gstrtpbuffer.c @@ -833,6 +833,8 @@ ensure_buffers (GstRTPBuffer * rtp) * extension header. If the existing extension data is not large enough, it will * be made larger. * + * Will also shorten the extension data from 1.20. + * * Returns: True if done. */ gboolean @@ -882,6 +884,15 @@ gst_rtp_buffer_set_extension_data (GstRTPBuffer * rtp, guint16 bits, gst_memory_ref (mem); rtp->data[1] = rtp->map[1].data; rtp->size[1] = rtp->map[1].size; + } else if (min_size < rtp->size[1]) { + GstMemory *mem = rtp->map[1].memory; + + gst_memory_ref (mem); + gst_buffer_unmap (rtp->buffer, &rtp->map[1]); + gst_memory_resize (mem, 0, min_size); + gst_memory_map (mem, &rtp->map[1], GST_MAP_READWRITE); + rtp->data[1] = rtp->map[1].data; + rtp->size[1] = rtp->map[1].size; } /* now we can set the extension bit */ diff --git a/subprojects/gst-plugins-base/tests/check/libs/rtp.c b/subprojects/gst-plugins-base/tests/check/libs/rtp.c index 029260d..11eec6d 100644 --- a/subprojects/gst-plugins-base/tests/check/libs/rtp.c +++ b/subprojects/gst-plugins-base/tests/check/libs/rtp.c @@ -421,6 +421,87 @@ GST_START_TEST (test_rtp_buffer_set_extension_data) GST_END_TEST; +GST_START_TEST (test_rtp_buffer_set_extension_data_shrink_data) +{ + GstBuffer *buf; + guint16 bits; + guint size; + gpointer pointer; + GstRTPBuffer rtp = GST_RTP_BUFFER_INIT; + guint8 scratch_cmp[4 * 4] = { 0, }; + GstMapInfo info = GST_MAP_INFO_INIT; + gsize i; + + buf = gst_rtp_buffer_new_allocate (20, 0, 0); + gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp); + + fail_unless (gst_rtp_buffer_set_extension_data (&rtp, 270, 4) == TRUE); + fail_unless (gst_rtp_buffer_get_extension (&rtp) == TRUE); + gst_rtp_buffer_get_extension_data (&rtp, &bits, &pointer, &size); + GST_MEMDUMP ("", pointer, size * 4); + fail_unless (bits == 270); + fail_unless (size == 4); + for (i = 0; i < size * 4; i++) { + guint8 *bytes = pointer; + bytes[i] = i; + } + memcpy (scratch_cmp, pointer, size * 4); + fail_unless_equals_int64 ((guint64) gst_buffer_get_size (buf), 52); + gst_rtp_buffer_unmap (&rtp); + + /* ensure that the mapped buffer size matches */ + gst_buffer_map (buf, &info, GST_MAP_READ); + GST_MEMDUMP ("", info.data, info.size); + fail_unless_equals_int64 ((guint64) info.size, 52); + gst_buffer_unmap (buf, &info); + + gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp); + /* shrinking the extension data should still succeed and only output the + * relevant data */ + fail_unless (gst_rtp_buffer_set_extension_data (&rtp, 180, 2) == TRUE); + gst_rtp_buffer_get_extension_data (&rtp, &bits, &pointer, &size); + GST_MEMDUMP ("", pointer, size * 4); + fail_unless (bits == 180); + fail_unless (size == 2); + fail_unless_equals_int64 ((guint64) gst_buffer_get_size (buf), 44); + for (i = 0; i < 8; i++) { + guint8 *ext_data = pointer; + fail_unless_equals_int_hex (ext_data[i], scratch_cmp[i]); + } + gst_rtp_buffer_unmap (&rtp); + + gst_buffer_map (buf, &info, GST_MAP_READ); + GST_MEMDUMP ("", info.data, info.size); + fail_unless_equals_int64 ((guint64) info.size, 44); + gst_buffer_unmap (buf, &info); + + gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp); + fail_unless (gst_rtp_buffer_set_extension_data (&rtp, 308, 3) == TRUE); + gst_rtp_buffer_get_extension_data (&rtp, &bits, &pointer, &size); + GST_MEMDUMP ("", pointer, size * 4); + fail_unless (bits == 308); + fail_unless (size == 3); + for (i = 0; i < 8; i++) { + guint8 *ext_data = pointer; + fail_unless_equals_int_hex (ext_data[i], scratch_cmp[i]); + } + /* new data will be zero-initialized */ + for (i = 8; i < size * 4; i++) { + guint8 *ext_data = pointer; + fail_unless_equals_int_hex (ext_data[i], 0); + } + fail_unless_equals_int64 ((guint64) gst_buffer_get_size (buf), 48); + gst_rtp_buffer_unmap (&rtp); + + gst_buffer_map (buf, &info, GST_MAP_READ); + GST_MEMDUMP ("", info.data, info.size); + fail_unless_equals_int64 ((guint64) info.size, 48); + gst_buffer_unmap (buf, &info); + gst_buffer_unref (buf); +} + +GST_END_TEST; + #if 0 GST_START_TEST (test_rtp_buffer_list_set_extension) { @@ -2290,6 +2371,7 @@ rtp_suite (void) tcase_add_test (tc_chain, test_rtcp_compound_padding); tcase_add_test (tc_chain, test_rtp_buffer_extlen_wraparound); tcase_add_test (tc_chain, test_rtp_buffer_remove_extension_data); + tcase_add_test (tc_chain, test_rtp_buffer_set_extension_data_shrink_data); return s; } -- 2.7.4