summaryrefslogtreecommitdiff
path: root/gst
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim@centricular.com>2014-12-13 15:23:48 +0000
committerTim-Philipp Müller <tim@centricular.com>2014-12-26 13:44:32 +0000
commitd790ba9a06084e16043cc10edfee7edab4c4bb87 (patch)
tree68c909870e63f893cd73626bf7895a4d748f9d47 /gst
parent3853f8c070607baff95d91ab923a485c371eef9a (diff)
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.
Diffstat (limited to 'gst')
-rw-r--r--gst/gdp/dataprotocol.c87
-rw-r--r--gst/gdp/dataprotocol.h4
2 files changed, 80 insertions, 11 deletions
diff --git a/gst/gdp/dataprotocol.c b/gst/gdp/dataprotocol.c
index 0afd41054..3efcc47df 100644
--- a/gst/gdp/dataprotocol.c
+++ b/gst/gdp/dataprotocol.c
@@ -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_WRITE_UINT16_BE (h + 58, header_crc);
- gst_buffer_unmap ((GstBuffer *) buffer, &map);
+ /* 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)
{
diff --git a/gst/gdp/dataprotocol.h b/gst/gdp/dataprotocol.h
index 1370c6557..ca0be1347 100644
--- a/gst/gdp/dataprotocol.h
+++ b/gst/gdp/dataprotocol.h
@@ -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