gst/matroska/ebml-read.c: Don't create unnecessary sub-buffers all the time. Dramatically improves performance with m...

Original commit message from CVS:
Patch by: Jindrich Makovicka  <jindrich.makivicka at itonis tv>
* gst/matroska/ebml-read.c: (gst_ebml_read_peek_bytes),
(gst_ebml_read_pull_bytes), (gst_ebml_read_element_id),
(gst_ebml_read_element_length), (gst_ebml_read_buffer),
(gst_ebml_read_bytes), (gst_ebml_read_uint), (gst_ebml_read_sint),
(gst_ebml_read_float), (gst_ebml_read_ascii),
(gst_ebml_read_binary):
Don't create unnecessary sub-buffers all the time. Dramatically
improves performance with multiple concurrently running
matroskademux instances (#341818) (and avoids doing
unnecessarily inefficient things in the general case).
This commit is contained in:
Jindrich Makovicka 2006-05-17 08:10:31 +00:00 committed by Tim-Philipp Müller
parent e57d09e835
commit 14ea3f13a4
2 changed files with 113 additions and 73 deletions

View file

@ -1,3 +1,18 @@
2006-05-16 Tim-Philipp Müller <tim at centricular dot net>
Patch by: Jindrich Makovicka <jindrich.makivicka at itonis tv>
* gst/matroska/ebml-read.c: (gst_ebml_read_peek_bytes),
(gst_ebml_read_pull_bytes), (gst_ebml_read_element_id),
(gst_ebml_read_element_length), (gst_ebml_read_buffer),
(gst_ebml_read_bytes), (gst_ebml_read_uint), (gst_ebml_read_sint),
(gst_ebml_read_float), (gst_ebml_read_ascii),
(gst_ebml_read_binary):
Don't create unnecessary sub-buffers all the time. Dramatically
improves performance with multiple concurrently running
matroskademux instances (#341818) (and avoids doing
unnecessarily inefficient things in the general case).
2006-05-16 Edward Hervey <edward@fluendo.com>
* ext/libpng/gstpngenc.c: (gst_pngenc_chain):

View file

@ -38,9 +38,9 @@ static GstStateChangeReturn gst_ebml_read_change_state (GstElement * element,
/* convenience functions */
static gboolean gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size,
GstBuffer ** p_buf);
GstBuffer ** p_buf, guint8 ** bytes);
static gboolean gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size,
GstBuffer ** p_buf);
GstBuffer ** p_buf, guint8 ** bytes);
static GstElementClass *parent_class; /* NULL */
@ -163,7 +163,8 @@ gst_ebml_read_element_level_up (GstEbmlRead * ebml)
* Calls pull_range for (offset,size) without advancing our offset
*/
static gboolean
gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf)
gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
guint8 ** bytes)
{
GstFlowReturn ret;
@ -175,8 +176,12 @@ gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf)
if (cache_offset <= ebml->offset &&
(ebml->offset + size) < (cache_offset + cache_size)) {
*p_buf = gst_buffer_create_sub (ebml->cached_buffer,
ebml->offset - cache_offset, size);
if (p_buf)
*p_buf = gst_buffer_create_sub (ebml->cached_buffer,
ebml->offset - cache_offset, size);
if (bytes)
*bytes =
GST_BUFFER_DATA (ebml->cached_buffer) + ebml->offset - cache_offset;
return TRUE;
}
gst_buffer_unref (ebml->cached_buffer);
@ -186,10 +191,16 @@ gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf)
if (gst_pad_pull_range (ebml->sinkpad, ebml->offset, MAX (size, 64 * 1024),
&ebml->cached_buffer) == GST_FLOW_OK &&
GST_BUFFER_SIZE (ebml->cached_buffer) >= size) {
*p_buf = gst_buffer_create_sub (ebml->cached_buffer, 0, size);
if (p_buf)
*p_buf = gst_buffer_create_sub (ebml->cached_buffer, 0, size);
if (bytes)
*bytes = GST_BUFFER_DATA (ebml->cached_buffer);
return TRUE;
}
if (!p_buf)
return FALSE;
ret = gst_pad_pull_range (ebml->sinkpad, ebml->offset, size, p_buf);
if (ret != GST_FLOW_OK) {
GST_DEBUG ("pull_range returned %d", ret);
@ -202,9 +213,14 @@ gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf)
size, GST_BUFFER_SIZE (*p_buf));
gst_buffer_unref (*p_buf);
*p_buf = NULL;
if (bytes)
*bytes = NULL;
return FALSE;
}
if (bytes)
*bytes = GST_BUFFER_DATA (*p_buf);
return TRUE;
}
@ -212,9 +228,10 @@ gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf)
* Calls pull_range for (offset,size) and advances our offset by size
*/
static gboolean
gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf)
gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
guint8 ** bytes)
{
if (!gst_ebml_read_peek_bytes (ebml, size, p_buf))
if (!gst_ebml_read_peek_bytes (ebml, size, p_buf, bytes))
return FALSE;
ebml->offset += size;
@ -229,16 +246,15 @@ gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf)
static gboolean
gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
{
GstBuffer *buf;
guint8 *buf;
gint len_mask = 0x80, read = 1, n = 1;
guint32 total;
guint8 b;
if (!gst_ebml_read_peek_bytes (ebml, 1, &buf))
if (!gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf))
return FALSE;
b = GST_READ_UINT8 (GST_BUFFER_DATA (buf));
gst_buffer_unref (buf);
b = GST_READ_UINT8 (buf);
total = (guint32) b;
@ -255,11 +271,11 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
return FALSE;
}
if (!gst_ebml_read_peek_bytes (ebml, read, &buf))
if (!gst_ebml_read_peek_bytes (ebml, read, NULL, &buf))
return FALSE;
while (n < read) {
b = GST_READ_UINT8 (GST_BUFFER_DATA (buf) + n);
b = GST_READ_UINT8 (buf + n);
total = (total << 8) | b;
++n;
}
@ -270,8 +286,6 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
if (level_up)
*level_up = gst_ebml_read_element_level_up (ebml);
gst_buffer_unref (buf);
ebml->offset += read;
return TRUE;
}
@ -284,16 +298,15 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
static gint
gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length)
{
GstBuffer *buf;
guint8 *buf;
gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
guint64 total;
guint8 b;
if (!gst_ebml_read_peek_bytes (ebml, 1, &buf))
if (!gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf))
return -1;
b = GST_READ_UINT8 (GST_BUFFER_DATA (buf));
gst_buffer_unref (buf);
b = GST_READ_UINT8 (buf);
total = (guint64) b;
@ -313,18 +326,17 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length)
if ((total &= (len_mask - 1)) == len_mask - 1)
num_ffs++;
if (!gst_ebml_read_peek_bytes (ebml, read, &buf))
if (!gst_ebml_read_peek_bytes (ebml, read, NULL, &buf))
return -1;
while (n < read) {
guint8 b = GST_READ_UINT8 (GST_BUFFER_DATA (buf) + n);
guint8 b = GST_READ_UINT8 (buf + n);
if (b == 0xff)
num_ffs++;
total = (total << 8) | b;
++n;
}
gst_buffer_unref (buf);
if (read == num_ffs)
*length = G_MAXUINT64;
@ -433,12 +445,44 @@ gst_ebml_read_buffer (GstEbmlRead * ebml, guint32 * id, GstBuffer ** buf)
}
*buf = NULL;
if (!gst_ebml_read_pull_bytes (ebml, (guint) length, buf))
if (!gst_ebml_read_pull_bytes (ebml, (guint) length, buf, NULL))
return FALSE;
return TRUE;
}
/*
* Read the next element, return a pointer to it and its size.
*/
static gboolean
gst_ebml_read_bytes (GstEbmlRead * ebml, guint32 * id, guint8 ** data,
guint * size)
{
guint64 length;
*size = 0;
if (!gst_ebml_read_element_id (ebml, id, NULL))
return FALSE;
if (gst_ebml_read_element_length (ebml, &length) < 0)
return FALSE;
if (length == 0) {
*data = NULL;
return TRUE;
}
*data = NULL;
if (!gst_ebml_read_pull_bytes (ebml, (guint) length, NULL, data))
return FALSE;
*size = (guint) length;
return TRUE;
}
/*
* Read the next element as an unsigned int.
*/
@ -446,30 +490,25 @@ gst_ebml_read_buffer (GstEbmlRead * ebml, guint32 * id, GstBuffer ** buf)
gboolean
gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num)
{
GstBuffer *buf;
guint8 *data;
guint size;
if (!gst_ebml_read_buffer (ebml, id, &buf))
if (!gst_ebml_read_bytes (ebml, id, &data, &size))
return FALSE;
data = GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf);
if (size < 1 || size > 8) {
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
("Invalid integer element size %d at position %llu (0x%llu)",
size, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET (buf)));
gst_buffer_unref (buf);
size, ebml->offset - size, ebml->offset - size));
return FALSE;
}
*num = 0;
while (size > 0) {
*num = (*num << 8) | data[GST_BUFFER_SIZE (buf) - size];
*num = (*num << 8) | *data;
size--;
data++;
}
gst_buffer_unref (buf);
return TRUE;
}
@ -480,34 +519,32 @@ gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num)
gboolean
gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
{
GstBuffer *buf;
guint8 *data;
guint size, negative = 0, n = 0;
guint size;
gboolean negative = 0;
if (!gst_ebml_read_buffer (ebml, id, &buf))
if (!gst_ebml_read_bytes (ebml, id, &data, &size))
return FALSE;
size = GST_BUFFER_SIZE (buf);
if (size < 1 || size > 8) {
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
("Invalid integer element size %d at position %llu (0x%llx)",
size, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET (buf)));
gst_buffer_unref (buf);
size, ebml->offset - size, ebml->offset - size));
return FALSE;
}
buf = gst_buffer_make_writable (buf);
data = GST_BUFFER_DATA (buf);
if (data[0] & 0x80) {
*num = 0;
if (*data & 0x80) {
negative = 1;
data[0] &= ~0x80;
*num = *data & ~0x80;
size--;
data++;
}
*num = 0;
while (n < size) {
*num = (*num << 8) | data[n++];
while (size > 0) {
*num = (*num << 8) | *data;
size--;
data++;
}
/* make signed */
@ -515,8 +552,6 @@ gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
*num = 0 - *num;
}
gst_buffer_unref (buf);
return TRUE;
}
@ -527,28 +562,22 @@ gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
gboolean
gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
{
GstBuffer *buf;
guint8 *data;
guint size;
if (!gst_ebml_read_buffer (ebml, id, &buf))
if (!gst_ebml_read_bytes (ebml, id, &data, &size))
return FALSE;
data = GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf);
if (size != 4 && size != 8 && size != 10) {
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
("Invalid float element size %d at position %llu (0x%llx)",
size, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET (buf)));
gst_buffer_unref (buf);
size, ebml->offset - size, ebml->offset - size));
return FALSE;
}
if (size == 10) {
GST_ELEMENT_ERROR (ebml, CORE, NOT_IMPLEMENTED, (NULL),
("FIXME! 10-byte floats unimplemented"));
gst_buffer_unref (buf);
return FALSE;
}
@ -580,8 +609,6 @@ gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
*num = d;
}
gst_buffer_unref (buf);
return TRUE;
}
@ -592,16 +619,15 @@ gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
gboolean
gst_ebml_read_ascii (GstEbmlRead * ebml, guint32 * id, gchar ** str)
{
GstBuffer *buf;
guint8 *data;
guint size;
if (!gst_ebml_read_buffer (ebml, id, &buf))
if (!gst_ebml_read_bytes (ebml, id, &data, &size))
return FALSE;
*str = g_malloc (GST_BUFFER_SIZE (buf) + 1);
memcpy (*str, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
(*str)[GST_BUFFER_SIZE (buf)] = '\0';
gst_buffer_unref (buf);
*str = g_malloc (size + 1);
memcpy (*str, data, size);
(*str)[size] = '\0';
return TRUE;
}
@ -678,15 +704,14 @@ gboolean
gst_ebml_read_binary (GstEbmlRead * ebml,
guint32 * id, guint8 ** binary, guint64 * length)
{
GstBuffer *buf;
guint8 *data;
guint size;
if (!gst_ebml_read_buffer (ebml, id, &buf))
if (!gst_ebml_read_bytes (ebml, id, &data, &size))
return FALSE;
*length = GST_BUFFER_SIZE (buf);
*binary = g_memdup (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
gst_buffer_unref (buf);
*length = size;
*binary = g_memdup (data, size);
return TRUE;
}