From 14ea3f13a47948e320903f6e96d0d646775b1bca Mon Sep 17 00:00:00 2001 From: Jindrich Makovicka Date: Wed, 17 May 2006 08:10:31 +0000 Subject: [PATCH] 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 * 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). --- ChangeLog | 15 ++++ gst/matroska/ebml-read.c | 171 ++++++++++++++++++++++----------------- 2 files changed, 113 insertions(+), 73 deletions(-) diff --git a/ChangeLog b/ChangeLog index 363343a54b..67434efaae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2006-05-16 Tim-Philipp Müller + + Patch by: Jindrich Makovicka + + * 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 * ext/libpng/gstpngenc.c: (gst_pngenc_chain): diff --git a/gst/matroska/ebml-read.c b/gst/matroska/ebml-read.c index e9dbe5045c..8343910452 100644 --- a/gst/matroska/ebml-read.c +++ b/gst/matroska/ebml-read.c @@ -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; }