gdppay: optimise payloading of buffers with multiple memories

Add function to calculate a payload CRC across multiple memories
so we don't have to merge buffers with multiple memories just to
calculate the CRC. Also make CRC calculation function static,
since it's not used outside dataprotocol.h and move special-casing
of length = 0 -> CRC = 0 into CRC function (from caller).

Perhaps more importantly, since payload CRC is off by default:
don't map buffer (and possibly merge memories in the process)
if we are not going to use it to calculate a CRC anyway.
This commit is contained in:
Tim-Philipp Müller 2014-12-13 15:23:48 +00:00
parent 3853f8c070
commit d790ba9a06
2 changed files with 80 additions and 11 deletions

View file

@ -125,6 +125,10 @@ G_STMT_START { \
#define POLY 0x1021
#define CRC_INIT 0xFFFF
static guint16 gst_dp_crc (const guint8 * buffer, guint length);
static guint16 gst_dp_crc_from_memory_maps (const GstMapInfo * maps,
guint n_maps);
/*** HELPER FUNCTIONS ***/
static gboolean
@ -133,7 +137,8 @@ gst_dp_header_from_buffer_any (GstBuffer * buffer, GstDPHeaderFlag flags,
{
guint8 *h;
guint16 flags_mask;
GstMapInfo map;
guint16 header_crc = 0, crc = 0;
gsize buffer_size;
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
g_return_val_if_fail (length, FALSE);
@ -145,10 +150,35 @@ gst_dp_header_from_buffer_any (GstBuffer * buffer, GstDPHeaderFlag flags,
/* version, flags, type */
GST_DP_INIT_HEADER (h, version, flags, GST_DP_PAYLOAD_BUFFER);
gst_buffer_map ((GstBuffer *) buffer, &map, GST_MAP_READ);
if ((flags & GST_DP_HEADER_FLAG_CRC_PAYLOAD)) {
GstMapInfo *maps;
guint n_maps, i;
buffer_size = 0;
n_maps = gst_buffer_n_memory (buffer);
if (n_maps > 0) {
maps = g_newa (GstMapInfo, n_maps);
for (i = 0; i < n_maps; ++i) {
GstMemory *mem;
mem = gst_buffer_peek_memory (buffer, i);
gst_memory_map (mem, &maps[i], GST_MAP_READ);
buffer_size += maps[i].size;
}
crc = gst_dp_crc_from_memory_maps (maps, n_maps);
for (i = 0; i < n_maps; ++i)
gst_memory_unmap (maps[i].memory, &maps[i]);
}
} else {
buffer_size = gst_buffer_get_size (buffer);
}
/* buffer properties */
GST_WRITE_UINT32_BE (h + 6, map.size);
GST_WRITE_UINT32_BE (h + 6, buffer_size);
GST_WRITE_UINT64_BE (h + 10, GST_BUFFER_TIMESTAMP (buffer));
GST_WRITE_UINT64_BE (h + 18, GST_BUFFER_DURATION (buffer));
GST_WRITE_UINT64_BE (h + 26, GST_BUFFER_OFFSET (buffer));
@ -164,9 +194,17 @@ gst_dp_header_from_buffer_any (GstBuffer * buffer, GstDPHeaderFlag flags,
/* from gstreamer 1.x, buffers also have the DTS */
GST_WRITE_UINT64_BE (h + 44, GST_BUFFER_DTS (buffer));
GST_DP_SET_CRC (h, flags, map.data, map.size);
/* header CRC */
if ((flags & GST_DP_HEADER_FLAG_CRC_HEADER))
/* we don't crc the last four bytes since they are crc's */
header_crc = gst_dp_crc (h, 58);
else
header_crc = 0;
gst_buffer_unmap ((GstBuffer *) buffer, &map);
GST_WRITE_UINT16_BE (h + 58, header_crc);
/* payload CRC */
GST_WRITE_UINT16_BE (h + 60, crc);
GST_MEMDUMP ("created header from buffer", h, GST_DP_HEADER_LENGTH);
*header = h;
@ -259,12 +297,15 @@ static const guint16 gst_dp_crc_table[256] = {
*
* Returns: a two-byte CRC checksum.
*/
guint16
static guint16
gst_dp_crc (const guint8 * buffer, guint length)
{
guint16 crc_register = CRC_INIT;
g_return_val_if_fail (buffer != NULL || length == 0, 0);
if (length == 0)
return 0;
g_assert (buffer != NULL);
/* calc CRC */
for (; length--;) {
@ -274,6 +315,38 @@ gst_dp_crc (const guint8 * buffer, guint length)
return (0xffff ^ crc_register);
}
static guint16
gst_dp_crc_from_memory_maps (const GstMapInfo * maps, guint n_maps)
{
guint16 crc_register = CRC_INIT;
gsize total_length = 0;
if (n_maps == 0)
return 0;
g_assert (maps != NULL);
/* calc CRC */
while (n_maps > 0) {
guint8 *buffer = maps->data;
gsize length = maps->size;
total_length += length;
while (length-- > 0) {
crc_register = (guint16) ((crc_register << 8) ^
gst_dp_crc_table[((crc_register >> 8) & 0x00ff) ^ *buffer++]);
}
--n_maps;
++maps;
}
if (G_UNLIKELY (total_length == 0))
return 0;
return (0xffff ^ crc_register);
}
GType
gst_dp_version_get_type (void)
{

View file

@ -140,10 +140,6 @@ GstDPPacketizer *
gst_dp_packetizer_new (GstDPVersion version);
void gst_dp_packetizer_free (GstDPPacketizer *packetizer);
/* crc checksum */
guint16 gst_dp_crc (const guint8 * buffer,
guint length);
/* payload information from header */
guint32 gst_dp_header_payload_length (const guint8 * header);
GstDPPayloadType