diff options
| -rw-r--r-- | ChangeLog | 15 | ||||
| -rw-r--r-- | gst/matroska/ebml-read.c | 171 | 
2 files changed, 113 insertions, 73 deletions
@@ -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):  diff --git a/gst/matroska/ebml-read.c b/gst/matroska/ebml-read.c index e9dbe504..83439104 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,9 +445,41 @@ 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;  } @@ -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;  }  | 
