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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1146>
This commit is contained in:
Matthew Waters 2021-08-24 21:26:54 +10:00 committed by GStreamer Marge Bot
parent 320bc6362b
commit b7d4d371f9
2 changed files with 93 additions and 0 deletions

View file

@ -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 */

View file

@ -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;
}