Bug 1074004 - Update nestegg from upstream. r=giles
authorMatthew Gregan <kinetik@flim.org>
Mon, 29 Sep 2014 13:13:10 +1300
changeset 208091 27bcbf49cfd7de5bf9eb356069ead2eebc4747a1
parent 208090 6122db43cad3586390bc490d2f2342a6bc4616b5
child 208092 5997c0f393ba4f67eeb35a60c3cc1370824362a4
push id27575
push usercbook@mozilla.com
push dateWed, 01 Oct 2014 12:52:17 +0000
treeherdermozilla-central@fe0afc101ad2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgiles
bugs1074004
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1074004 - Update nestegg from upstream. r=giles
media/libnestegg/README
media/libnestegg/README.md
media/libnestegg/README_MOZILLA
media/libnestegg/include/nestegg.h
media/libnestegg/src/halloc.c
media/libnestegg/src/nestegg.c
media/libnestegg/update.sh
rename from media/libnestegg/README
rename to media/libnestegg/README.md
--- a/media/libnestegg/README
+++ b/media/libnestegg/README.md
@@ -1,6 +1,8 @@
+[![Build Status](https://travis-ci.org/kinetiknz/nestegg.svg?branch=master)](https://travis-ci.org/kinetiknz/nestegg)
+
 See INSTALL for build instructions.
 
 Licensed under an ISC-style license.  See LICENSE for details.
 
 The source under the halloc/ directory is licensed under a BSD license.  See
 halloc/halloc.h for details.
--- a/media/libnestegg/README_MOZILLA
+++ b/media/libnestegg/README_MOZILLA
@@ -1,8 +1,8 @@
 The source from this directory was copied from the nestegg
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The nestegg git repository is: git://github.com/kinetiknz/nestegg.git
 
-The git commit ID used was 46ab96bcc8b099704cc8a15993f80fe0269a5284.
+The git commit ID used was 59220ae3e801cbad0f8160129c4df315469af671.
--- a/media/libnestegg/include/nestegg.h
+++ b/media/libnestegg/include/nestegg.h
@@ -376,16 +376,19 @@ int nestegg_has_cues(nestegg * context);
  * @retval 0 The file is not a WebM file.
  * @retval 1 The file is a WebM file. */
 int nestegg_sniff(unsigned char const * buffer, size_t length);
 
 /**
  * Set the underlying allocation function for library allocations.
  *
  * @param realloc_func The desired function.
+ * @retval 0 realloc_func(p, 0) does not act as free()
+ * @retval 1 realloc_func(p, 0) acts as free()
+ * @retval -1 malloc failed during realloc_func test
  */
-void nestegg_set_halloc_func(void * (* realloc_func)(void *, size_t));
+int nestegg_set_halloc_func(void * (* realloc_func)(void *, size_t));
 
 #if defined(__cplusplus)
 }
 #endif
 
 #endif /* NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79 */
--- a/media/libnestegg/src/halloc.c
+++ b/media/libnestegg/src/halloc.c
@@ -41,33 +41,36 @@ typedef struct hblock
  */
 realloc_t halloc_allocator = NULL;
 
 #define allocator halloc_allocator
 
 /*
  *	static methods
  */
-static void _set_allocator(void);
+int halloc_set_allocator(realloc_t realloc_func);
 static void * _realloc(void * ptr, size_t n);
 
 static int  _relate(hblock_t * b, hblock_t * p);
 static void _free_children(hblock_t * p);
 
 /*
  *	Core API
  */
 void * halloc(void * ptr, size_t len)
 {
 	hblock_t * p;
 
 	/* set up default allocator */
 	if (! allocator)
 	{
-		_set_allocator();
+		if (halloc_set_allocator(realloc) == 0)
+		{
+			halloc_set_allocator(_realloc);
+		}
 		assert(allocator);
 	}
 
 	/* calloc */
 	if (! ptr)
 	{
 		if (! len)
 			return NULL;
@@ -167,42 +170,42 @@ char * h_strdup(const char * str)
 	size_t len = strlen(str);
 	char * ptr = halloc(0, len + 1);
 	return ptr ? (ptr[len] = 0, memcpy(ptr, str, len)) : NULL;
 }
 
 /*
  *	static stuff
  */
-static void _set_allocator(void)
+int halloc_set_allocator(realloc_t realloc_func)
 {
 	void * p;
 	assert(! allocator);
 	
 	/*
 	 *	the purpose of the test below is to check the behaviour
 	 *	of realloc(ptr, 0), which is defined in the standard
 	 *	as an implementation-specific. if it returns zero,
 	 *	then it's equivalent to free(). it can however return
 	 *	non-zero, in which case it cannot be used for freeing
 	 *	memory blocks and we'll need to supply our own version
 	 *
 	 *	Thanks to Stan Tobias for pointing this tricky part out.
 	 */
-	allocator = realloc;
-	if (! (p = malloc(1)))
+	if (! (p = realloc_func(NULL, 1)))
 		/* hmm */
-		return;
+		return -1;
 		
-	if ((p = realloc(p, 0)))
+	if ((p = realloc_func(p, 0)))
 	{
-		/* realloc cannot be used as free() */
-		allocator = _realloc;
-		free(p);
+		/* realloc_func cannot be used as free() */
+		return 0;
 	}
+	allocator = realloc_func;
+	return 1;
 }
 
 static void * _realloc(void * ptr, size_t n)
 {
 	/*
 	 *	free'ing realloc()
 	 */
 	if (n)
--- a/media/libnestegg/src/nestegg.c
+++ b/media/libnestegg/src/nestegg.c
@@ -316,19 +316,28 @@ struct frame {
 
 struct block_additional {
   unsigned int id;
   unsigned char * data;
   size_t length;
   struct block_additional * next;
 };
 
+#define NE_IO_BUFSZ 16384
+
+struct nestegg_io_buf {
+  nestegg_io io;
+  unsigned char buffer[NE_IO_BUFSZ];
+  size_t bufsz;
+  int offset;
+};
+
 /* Public (opaque) Structures */
 struct nestegg {
-  nestegg_io * io;
+  struct nestegg_io_buf * io;
   nestegg_log log;
   struct pool_ctx * alloc_pool;
   uint64_t last_id;
   uint64_t last_size;
   int last_valid;
   struct list_node * ancestor;
   struct ebml ebml;
   struct segment segment;
@@ -541,53 +550,127 @@ ne_pool_alloc(size_t size, struct pool_c
 
 static void *
 ne_alloc(size_t size)
 {
   return calloc(1, size);
 }
 
 static int
-ne_io_read(nestegg_io * io, void * buffer, size_t length)
+ne_io_read(struct nestegg_io_buf * io, void * buffer, size_t length)
 {
-  return io->read(buffer, length, io->userdata);
+  int64_t off;
+  int r;
+  size_t avail;
+
+  assert(io->offset == -1 || (io->offset >= 0 && (unsigned int) io->offset < io->bufsz));
+
+  /* Too big to buffer, invalidate buffer and read through */
+  if (length > io->bufsz) {
+    if (io->offset != -1) {
+      r = io->io.seek(-(io->bufsz - io->offset), NESTEGG_SEEK_CUR, io->io.userdata);
+      if (r != 0) {
+        return -1;
+      }
+    }
+    io->offset = -1;
+    return io->io.read(buffer, length, io->io.userdata);
+  }
+
+  /* Buffer invalid */
+  if (io->offset == -1) {
+    off = io->io.tell(io->io.userdata);
+    if (off == -1) {
+      return -1;
+    }
+    /* Refill buffer */
+    r = io->io.read(io->buffer, io->bufsz, io->io.userdata);
+    if (r != 1) {
+      /* Read truncated due to being within io->bufsz of EOS, reset read
+         position and switch to read through mode */
+      io->offset = -1;
+      io->bufsz = 0;
+      if (r == 0) {
+        r = io->io.seek(off, NESTEGG_SEEK_SET, io->io.userdata);
+      }
+      if (r == 0) {
+        return io->io.read(buffer, length, io->io.userdata);
+      }
+      return -1;
+    }
+    if (r == 1) {
+      io->offset = 0;
+    }
+  }
+
+  /* Service request with what we have */
+  avail = length;
+  if (io->bufsz - io->offset < length) {
+    avail = io->bufsz - io->offset;
+  }
+  memcpy(buffer, io->buffer + io->offset, avail);
+  io->offset += avail;
+
+  if ((unsigned int) io->offset == io->bufsz) {
+    io->offset = -1;
+  }
+
+  /* Still more to read, invalidate buffer and read more */
+  if (length - avail > 0) {
+    return ne_io_read(io, (char *) buffer + avail, length - avail);
+  }
+
+  return 1;
 }
 
 static int
-ne_io_seek(nestegg_io * io, int64_t offset, int whence)
+ne_io_seek(struct nestegg_io_buf * io, int64_t offset, int whence)
+{
+  /* Invalidate buffer */
+  io->offset = -1;
+
+  return io->io.seek(offset, whence, io->io.userdata);
+}
+
+static int64_t
+ne_io_tell(struct nestegg_io_buf * io)
 {
-  return io->seek(offset, whence, io->userdata);
+  int64_t off;
+
+  off = io->io.tell(io->io.userdata);
+  if (off == -1) {
+    return -1;
+  }
+  if (io->offset == -1) {
+    return off;
+  }
+  assert(off >= (int64_t) io->bufsz - io->offset);
+  return off - io->bufsz + (unsigned int) io->offset;
 }
 
 static int
-ne_io_read_skip(nestegg_io * io, size_t length)
+ne_io_read_skip(struct nestegg_io_buf * io, size_t length)
 {
   size_t get;
   unsigned char buf[8192];
   int r = 1;
 
   while (length > 0) {
     get = length < sizeof(buf) ? length : sizeof(buf);
     r = ne_io_read(io, buf, get);
     if (r != 1)
       break;
     length -= get;
   }
 
   return r;
 }
 
-static int64_t
-ne_io_tell(nestegg_io * io)
-{
-  return io->tell(io->userdata);
-}
-
 static int
-ne_bare_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag)
+ne_bare_read_vint(struct nestegg_io_buf * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag)
 {
   int r;
   unsigned char b;
   size_t maxlen = 8;
   unsigned int count = 1, mask = 1 << 7;
 
   r = ne_io_read(io, &b, 1);
   if (r != 1)
@@ -614,29 +697,29 @@ ne_bare_read_vint(nestegg_io * io, uint6
     *value <<= 8;
     *value |= b;
   }
 
   return 1;
 }
 
 static int
-ne_read_id(nestegg_io * io, uint64_t * value, uint64_t * length)
+ne_read_id(struct nestegg_io_buf * io, uint64_t * value, uint64_t * length)
 {
   return ne_bare_read_vint(io, value, length, MASK_NONE);
 }
 
 static int
-ne_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length)
+ne_read_vint(struct nestegg_io_buf * io, uint64_t * value, uint64_t * length)
 {
   return ne_bare_read_vint(io, value, length, MASK_FIRST_BIT);
 }
 
 static int
-ne_read_svint(nestegg_io * io, int64_t * value, uint64_t * length)
+ne_read_svint(struct nestegg_io_buf * io, int64_t * value, uint64_t * length)
 {
   int r;
   uint64_t uvalue;
   uint64_t ulength;
   int64_t svint_subtr[] = {
     0x3f, 0x1fff,
     0xfffff, 0x7ffffff,
     0x3ffffffffLL, 0x1ffffffffffLL,
@@ -648,17 +731,17 @@ ne_read_svint(nestegg_io * io, int64_t *
     return r;
   *value = uvalue - svint_subtr[ulength - 1];
   if (length)
     *length = ulength;
   return r;
 }
 
 static int
-ne_read_uint(nestegg_io * io, uint64_t * val, uint64_t length)
+ne_read_uint(struct nestegg_io_buf * io, uint64_t * val, uint64_t length)
 {
   unsigned char b;
   int r;
 
   if (length == 0 || length > 8)
     return -1;
   r = ne_io_read(io, &b, 1);
   if (r != 1)
@@ -670,44 +753,44 @@ ne_read_uint(nestegg_io * io, uint64_t *
       return r;
     *val <<= 8;
     *val |= b;
   }
   return 1;
 }
 
 static int
-ne_read_int(nestegg_io * io, int64_t * val, uint64_t length)
+ne_read_int(struct nestegg_io_buf * io, int64_t * val, uint64_t length)
 {
   int r;
   uint64_t uval, base;
 
   r = ne_read_uint(io, &uval, length);
   if (r != 1)
     return r;
 
   if (length < sizeof(int64_t)) {
     base = 1;
     base <<= length * 8 - 1;
     if (uval >= base) {
-        base = 1;
-        base <<= length * 8;
+      base = 1;
+      base <<= length * 8;
     } else {
       base = 0;
     }
     *val = uval - base;
   } else {
     *val = (int64_t) uval;
   }
 
   return 1;
 }
 
 static int
-ne_read_float(nestegg_io * io, double * val, uint64_t length)
+ne_read_float(struct nestegg_io_buf * io, double * val, uint64_t length)
 {
   union {
     uint64_t u;
     float f;
     double d;
   } value;
   int r;
 
@@ -731,19 +814,19 @@ ne_read_string(nestegg * ctx, char ** va
   int r;
 
   if (length > LIMIT_STRING)
     return -1;
   str = ne_pool_alloc(length + 1, ctx->alloc_pool);
   if (!str)
     return -1;
   if (length) {
-      r = ne_io_read(ctx->io, (unsigned char *) str, length);
-      if (r != 1)
-        return r;
+    r = ne_io_read(ctx->io, (unsigned char *) str, length);
+    if (r != 1)
+      return r;
   }
   str[length] = '\0';
   *val = str;
   return 1;
 }
 
 static int
 ne_read_binary(nestegg * ctx, struct ebml_binary * val, uint64_t length)
@@ -1013,18 +1096,19 @@ ne_read_simple(nestegg * ctx, struct ebm
   case TYPE_STRING:
     r = ne_read_string(ctx, &storage->v.s, length);
     break;
   case TYPE_BINARY:
     r = ne_read_binary(ctx, &storage->v.b, length);
     break;
   case TYPE_MASTER:
   case TYPE_UNKNOWN:
+  default:
+    r = 0;
     assert(0);
-    r = 0;
     break;
   }
 
   if (r == 1)
     storage->read = 1;
 
   return r;
 }
@@ -1131,17 +1215,17 @@ ne_xiph_lace_value(unsigned char ** np)
   }
 
   *np = p;
 
   return value;
 }
 
 static int
-ne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed)
+ne_read_xiph_lace_value(struct nestegg_io_buf * io, uint64_t * value, size_t * consumed)
 {
   int r;
   uint64_t lace;
 
   r = ne_read_uint(io, &lace, 1);
   if (r != 1)
     return r;
   *consumed += 1;
@@ -1154,17 +1238,17 @@ ne_read_xiph_lace_value(nestegg_io * io,
     *consumed += 1;
     *value += lace;
   }
 
   return 1;
 }
 
 static int
-ne_read_xiph_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
+ne_read_xiph_lacing(struct nestegg_io_buf * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
 {
   int r;
   size_t i = 0;
   uint64_t sum = 0;
 
   while (--n) {
     r = ne_read_xiph_lace_value(io, &sizes[i], read);
     if (r != 1)
@@ -1177,17 +1261,17 @@ ne_read_xiph_lacing(nestegg_io * io, siz
     return -1;
 
   /* Last frame is the remainder of the block. */
   sizes[i] = block - *read - sum;
   return 1;
 }
 
 static int
-ne_read_ebml_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
+ne_read_ebml_lacing(struct nestegg_io_buf * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
 {
   int r;
   uint64_t lace, sum, length;
   int64_t slace;
   size_t i = 0;
 
   r = ne_read_vint(io, &lace, &length);
   if (r != 1)
@@ -1787,61 +1871,61 @@ ne_init_cue_points(nestegg * ctx, int64_
  * sniff_buffer. */
 struct sniff_buffer {
   unsigned char const * buffer;
   size_t length;
   int64_t offset;
 };
 
 static int
-ne_buffer_read(void * buffer, size_t length, void * user_data)
+ne_buffer_read(void * buffer, size_t length, void * userdata)
 {
-  struct sniff_buffer * sb = user_data;
+  struct sniff_buffer * sb = userdata;
 
   int rv = 1;
   size_t available = sb->length - sb->offset;
 
   if (available < length)
     return 0;
 
   memcpy(buffer, sb->buffer + sb->offset, length);
   sb->offset += length;
 
   return rv;
 }
 
 static int
-ne_buffer_seek(int64_t offset, int whence, void * user_data)
+ne_buffer_seek(int64_t offset, int whence, void * userdata)
 {
-  struct sniff_buffer * sb = user_data;
+  struct sniff_buffer * sb = userdata;
   int64_t o = sb->offset;
 
   switch(whence) {
-    case NESTEGG_SEEK_SET:
-      o = offset;
-      break;
-    case NESTEGG_SEEK_CUR:
-      o += offset;
-      break;
-    case NESTEGG_SEEK_END:
-      o = sb->length + offset;
-      break;
+  case NESTEGG_SEEK_SET:
+    o = offset;
+    break;
+  case NESTEGG_SEEK_CUR:
+    o += offset;
+    break;
+  case NESTEGG_SEEK_END:
+    o = sb->length + offset;
+    break;
   }
 
   if (o < 0 || o > (int64_t) sb->length)
     return -1;
 
   sb->offset = o;
   return 0;
 }
 
 static int64_t
-ne_buffer_tell(void * user_data)
+ne_buffer_tell(void * userdata)
 {
-  struct sniff_buffer * sb = user_data;
+  struct sniff_buffer * sb = userdata;
   return sb->offset;
 }
 
 static int
 ne_match_webm(nestegg_io io, int64_t max_offset)
 {
   int r;
   uint64_t id;
@@ -1855,17 +1939,19 @@ ne_match_webm(nestegg_io io, int64_t max
   if (!ctx)
     return -1;
 
   ctx->io = ne_alloc(sizeof(*ctx->io));
   if (!ctx->io) {
     nestegg_destroy(ctx);
     return -1;
   }
-  *ctx->io = io;
+  ctx->io->io = io;
+  ctx->io->bufsz = NE_IO_BUFSZ;
+  ctx->io->offset = -1;
   ctx->alloc_pool = ne_pool_init();
   if (!ctx->alloc_pool) {
     nestegg_destroy(ctx);
     return -1;
   }
   ctx->log = ne_null_log_callback;
 
   r = ne_peek_element(ctx, &id, NULL);
@@ -1913,17 +1999,19 @@ nestegg_init(nestegg ** context, nestegg
   if (!ctx)
     return -1;
 
   ctx->io = ne_alloc(sizeof(*ctx->io));
   if (!ctx->io) {
     nestegg_destroy(ctx);
     return -1;
   }
-  *ctx->io = io;
+  ctx->io->io = io;
+  ctx->io->bufsz = NE_IO_BUFSZ;
+  ctx->io->offset = -1;
   ctx->log = callback;
   ctx->alloc_pool = ne_pool_init();
   if (!ctx->alloc_pool) {
     nestegg_destroy(ctx);
     return -1;
   }
 
   if (!ctx->log)
@@ -2259,45 +2347,45 @@ nestegg_track_codec_data(nestegg * ctx, 
   *data = NULL;
   *length = 0;
 
   entry = ne_find_track_entry(ctx, track);
   if (!entry)
     return -1;
 
   if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS
-    && nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS)
+      && nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS)
     return -1;
 
   if (ne_get_binary(entry->codec_private, &codec_private) != 0)
     return -1;
 
   if (nestegg_track_codec_id(ctx, track) == NESTEGG_CODEC_VORBIS) {
-      p = codec_private.data;
-      count = *p++ + 1;
-
-      if (count > 3)
+    p = codec_private.data;
+    count = *p++ + 1;
+
+    if (count > 3)
+      return -1;
+
+    i = 0;
+    total = 0;
+    while (--count) {
+      sizes[i] = ne_xiph_lace_value(&p);
+      total += sizes[i];
+      i += 1;
+    }
+    sizes[i] = codec_private.length - total - (p - codec_private.data);
+
+    for (i = 0; i < item; ++i) {
+      if (sizes[i] > LIMIT_FRAME)
         return -1;
-
-      i = 0;
-      total = 0;
-      while (--count) {
-        sizes[i] = ne_xiph_lace_value(&p);
-        total += sizes[i];
-        i += 1;
-      }
-      sizes[i] = codec_private.length - total - (p - codec_private.data);
-
-      for (i = 0; i < item; ++i) {
-        if (sizes[i] > LIMIT_FRAME)
-          return -1;
-        p += sizes[i];
-      }
-      *data = p;
-      *length = sizes[item];
+      p += sizes[i];
+    }
+    *data = p;
+    *length = sizes[item];
   } else {
     *data = codec_private.data;
     *length = codec_private.length;
   }
 
   return 0;
 }
 
@@ -2489,17 +2577,17 @@ nestegg_free_packet(nestegg_packet * pkt
 
   while (pkt->block_additional) {
     block_additional = pkt->block_additional;
     pkt->block_additional = block_additional->next;
     free(block_additional->data);
     free(block_additional);
   }
 
- free(pkt);
+  free(pkt);
 }
 
 int
 nestegg_packet_track(nestegg_packet * pkt, unsigned int * track)
 {
   *track = pkt->track;
   return 0;
 }
@@ -2583,33 +2671,36 @@ nestegg_packet_additional_data(nestegg_p
 
   return -1;
 }
 
 int
 nestegg_has_cues(nestegg * ctx)
 {
   return ctx->segment.cues.cue_point.head ||
-         ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
+    ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
 }
 
 int
 nestegg_sniff(unsigned char const * buffer, size_t length)
 {
   nestegg_io io;
-  struct sniff_buffer user_data;
-
-  user_data.buffer = buffer;
-  user_data.length = length;
-  user_data.offset = 0;
+  struct sniff_buffer userdata;
+
+  userdata.buffer = buffer;
+  userdata.length = length;
+  userdata.offset = 0;
 
   io.read = ne_buffer_read;
   io.seek = ne_buffer_seek;
   io.tell = ne_buffer_tell;
-  io.userdata = &user_data;
+  io.userdata = &userdata;
   return ne_match_webm(io, length);
 }
 
-void
+/* From halloc.c */
+int halloc_set_allocator(realloc_t realloc_func);
+
+int
 nestegg_set_halloc_func(void * (* realloc_func)(void *, size_t))
 {
-  halloc_allocator = realloc_func;
+  return halloc_set_allocator(realloc_func);
 }
--- a/media/libnestegg/update.sh
+++ b/media/libnestegg/update.sh
@@ -2,17 +2,17 @@
 cp $1/include/nestegg/nestegg.h include
 cp $1/src/nestegg.c src
 cp $1/halloc/halloc.h src
 cp $1/halloc/src/align.h src
 cp $1/halloc/src/halloc.c src
 cp $1/halloc/src/hlist.h src
 cp $1/halloc/src/macros.h src
 cp $1/LICENSE .
-cp $1/README .
+cp $1/README.md .
 cp $1/AUTHORS .
 if [ -d $1/.git ]; then
   rev=$(cd $1 && git rev-parse --verify HEAD)
   dirty=$(cd $1 && git diff-index --name-only HEAD)
 fi
 
 if [ -n "$rev" ]; then
   version=$rev