b=477899 update liboggz to svn r3835 and liboggplay to svn r3848 rs=roc
☠☠ backed out by bc871ee3a59a ☠ ☠
authorChris Double <chris.double@double.co.nz>
Fri, 20 Feb 2009 15:35:23 +1300
changeset 25260 45eb7626bca086dc1323722caf1c669c44b50377
parent 25259 4d8cbf6233b183f69469e813103550665ed696d9
child 25261 2b7e176d9e7397f423c4e91865bd33aa5936fb5c
child 25266 bc871ee3a59a3ff1847a6346b69ba43ec74b55d6
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs477899
milestone1.9.2a1pre
b=477899 update liboggz to svn r3835 and liboggplay to svn r3848 rs=roc
media/liboggplay/README_MOZILLA
media/liboggplay/src/liboggplay/config.h
media/liboggplay/src/liboggplay/oggplay.c
media/liboggplay/src/liboggplay/oggplay_callback_info.c
media/liboggplay/src/liboggplay/oggplay_file_reader.c
media/liboggplay/src/liboggplay/oggplay_file_reader.h
media/liboggplay/src/liboggplay/oggplay_private.h
media/liboggplay/src/liboggplay/oggplay_tcp_reader.c
media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
media/liboggplay/update.sh
media/liboggplay/yuv2rgb-vanilla-fix.patch
media/liboggz/README
media/liboggz/README_MOZILLA
media/liboggz/include/oggz/config.h
media/liboggz/include/oggz/config_win32.h
media/liboggz/include/oggz/oggz.h
media/liboggz/include/oggz/oggz_comments.h
media/liboggz/include/oggz/oggz_constants.h
media/liboggz/include/oggz/oggz_io.h
media/liboggz/include/oggz/oggz_read.h
media/liboggz/include/oggz/oggz_seek.h
media/liboggz/include/oggz/oggz_table.h
media/liboggz/include/oggz/oggz_write.h
media/liboggz/oggz_off_t.patch
media/liboggz/src/liboggz/Makefile.in
media/liboggz/src/liboggz/dirac.c
media/liboggz/src/liboggz/dirac.h
media/liboggz/src/liboggz/metric_internal.c
media/liboggz/src/liboggz/oggz.c
media/liboggz/src/liboggz/oggz_auto.c
media/liboggz/src/liboggz/oggz_auto.h
media/liboggz/src/liboggz/oggz_comments.c
media/liboggz/src/liboggz/oggz_dlist.c
media/liboggz/src/liboggz/oggz_dlist.h
media/liboggz/src/liboggz/oggz_io.c
media/liboggz/src/liboggz/oggz_private.h
media/liboggz/src/liboggz/oggz_read.c
media/liboggz/src/liboggz/oggz_seek.c
media/liboggz/src/liboggz/oggz_stream.c
media/liboggz/src/liboggz/oggz_stream_private.h
media/liboggz/src/liboggz/oggz_table.c
media/liboggz/src/liboggz/oggz_vector.c
media/liboggz/src/liboggz/oggz_vector.h
media/liboggz/src/liboggz/oggz_write.c
media/liboggz/update.sh
media/liboggz/warning.patch
--- a/media/liboggplay/README_MOZILLA
+++ b/media/liboggplay/README_MOZILLA
@@ -1,19 +1,16 @@
 The source from this directory was copied from the liboggplay svn
 source using the update.sh script. The only changes made were those
 applied by update.sh and the addition/upate of Makefile.in files for
 the Mozilla build system.
 
 http://svn.annodex.net/liboggplay/trunk/
 
-The svn revision number used was r3774.
-
-The patch from Annodex trac ticket 421 is applied to fix bug 459938:
-  http://trac.annodex.net/ticket/421
+The svn revision number used was r3848.
 
 The patch from Bug 468327 (yuv_disable_optimized.patch) is applied
 to disable optimized yuv to rgb routines.
 
 The patch from Bug 452698 (yuv2argb.patch) is applied to fix
 yuv to rgb conversion on PPC Mac OS X.
 
 The patch from Bug 464007 (bug464007.patch) is applied
--- a/media/liboggplay/src/liboggplay/config.h
+++ b/media/liboggplay/src/liboggplay/config.h
@@ -1,37 +1,43 @@
 /* config.h.  Generated from config.h.in by configure.  */
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
+/* Define to 1 if you have the `assert' function. */
+/* #undef HAVE_ASSERT */
+
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #define HAVE_DLFCN_H 1
 
 /* Define if have libfishsound */
-#define HAVE_FISHSOUND 
+#define HAVE_FISHSOUND /**/
 
 /* Define if we have GLUT. */
-#define HAVE_GLUT 
+#define HAVE_GLUT /**/
 
 /* Define if have Imlib2 */
-/* #undef HAVE_IMLIB2 */
+#define HAVE_IMLIB2 /**/
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #define HAVE_INTTYPES_H 1
 
 /* Define if have libkate */
 /* #undef HAVE_KATE */
 
 /* Define if have libsndfile */
-/* #undef HAVE_LIBSNDFILE1 */
+#define HAVE_LIBSNDFILE1 /**/
 
 /* Define to 1 if you have the <memory.h> header file. */
 #define HAVE_MEMORY_H 1
 
 /* Define if have liboggz */
-#define HAVE_OGGZ 
+#define HAVE_OGGZ /**/
 
 /* Define to 1 if you have the <stdint.h> header file. */
 #define HAVE_STDINT_H 1
 
 /* Define to 1 if you have the <stdlib.h> header file. */
 #define HAVE_STDLIB_H 1
 
 /* Define to 1 if you have the <strings.h> header file. */
@@ -44,16 +50,20 @@
 #define HAVE_SYS_STAT_H 1
 
 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
 
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
 
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#define LT_OBJDIR ".libs/"
+
 /* Define to 1 if your C compiler doesn't accept -c and -o together. */
 /* #undef NO_MINUS_C_MINUS_O */
 
 /* Name of package */
 #define PACKAGE "liboggplay"
 
 /* Define to the address where bug reports for this package should be sent. */
 #define PACKAGE_BUGREPORT ""
@@ -71,19 +81,27 @@
 #define PACKAGE_VERSION ""
 
 /* Define to 1 if you have the ANSI C header files. */
 #define STDC_HEADERS 1
 
 /* Version number of package */
 #define VERSION "0.0.1"
 
-/* Define to 1 if your processor stores words with the most significant byte
-   first (like Motorola and SPARC, unlike Intel and VAX). */
-/* #undef WORDS_BIGENDIAN */
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* #  undef WORDS_BIGENDIAN */
+# endif
+#endif
 
 /* use MMX SSE2 compiler intrinsics */
 
 
 /* Define to empty if `const' does not conform to ANSI C. */
 /* #undef const */
 #undef HAVE_GLUT
 
--- a/media/liboggplay/src/liboggplay/oggplay.c
+++ b/media/liboggplay/src/liboggplay/oggplay.c
@@ -59,16 +59,17 @@ oggplay_new_with_reader(OggPlayReader *r
   me->callback = NULL;
   me->target = 0L;
   me->active_tracks = 0;
   me->buffer = NULL;
   me->shutdown = 0;
   me->trash = NULL;
   me->oggz = NULL;
   me->pt_update_valid = 1;
+  me->duration = -1;
 
   return me;
 
 }
 
 OggPlayErrorCode
 oggplay_initialise(OggPlay *me, int block) {
 
@@ -205,17 +206,17 @@ oggplay_set_offset(OggPlay *me, int trac
   if (me == NULL) {
     return E_OGGPLAY_BAD_OGGPLAY;
   }
 
   if (track <= 0 || track > me->num_tracks) {
     return E_OGGPLAY_BAD_TRACK;
   }
 
-  me->decode_data[track]->offset = (offset << 32);
+  me->decode_data[track]->offset = (offset << 32) / 1000;
 
   return E_OGGPLAY_OK;
 
 }
 
 OggPlayErrorCode
 oggplay_get_video_fps(OggPlay *me, int track, int* fps_denom, int* fps_num) {
   OggPlayTheoraDecode *decode;
@@ -504,17 +505,17 @@ read_more_data:
     chunk_count += 1;
 
     r = oggz_read(me->oggz, OGGZ_READ_CHUNK_SIZE);
 
     /* end-of-file */
     if (r == 0) {
       num_records = oggplay_callback_info_prepare(me, &info);
      /*
-       * set all of the tracks to active
+       * set all of the tracks to inactive
        */
       for (i = 0; i < me->num_tracks; i++) {
         me->decode_data[i]->active = 0;
         me->active_tracks = 0;
       }
 
       if (info != NULL) {
         me->callback (me, num_records, info, me->callback_user_ptr);
@@ -569,18 +570,21 @@ read_more_data:
 }
 
 OggPlayErrorCode
 oggplay_start_decoding(OggPlay *me) {
 
   int r;
 
   while (1) {
-    if ((r = oggplay_step_decoding(me)) != E_OGGPLAY_CONTINUE)
-      return (OggPlayErrorCode)r;
+    r = oggplay_step_decoding(me);
+    if (r == E_OGGPLAY_CONTINUE || r == E_OGGPLAY_TIMEOUT) {
+      continue;
+    }
+    return (OggPlayErrorCode)r;
   }
 }
 
 OggPlayErrorCode
 oggplay_close(OggPlay *me) {
 
   int i;
 
@@ -638,27 +642,40 @@ oggplay_get_available(OggPlay *me) {
 
 ogg_int64_t
 oggplay_get_duration(OggPlay *me) {
 
   if (me == NULL) {
     return E_OGGPLAY_BAD_OGGPLAY;
   }
 
-  if (me->reader->duration) 
-    return me->reader->duration(me->reader);
-  else {
+  /* If the reader has a duration function we always call that
+   * function to find the duration. We never cache the result
+   * of that function.
+   *
+   * If there is no reader duration function we use our cached
+   * duration value, or do a liboggz seek to find it and cache
+   * that.
+   */
+  if (me->reader->duration) {
+      ogg_int64_t d = me->reader->duration(me->reader);
+      if (d >= 0) {
+        me->duration = d;
+      }
+  }
+
+  if (me->duration < 0) {
     ogg_int64_t pos;
-    ogg_int64_t duration;
     pos = oggz_tell_units(me->oggz);
-    duration = oggz_seek_units(me->oggz, 0, SEEK_END);
+    me->duration = oggz_seek_units(me->oggz, 0, SEEK_END);
     oggz_seek_units(me->oggz, pos, SEEK_SET);
     oggplay_seek_cleanup(me, pos);
-    return duration;
   }
+
+  return me->duration;
 }
 
 int
 oggplay_media_finished_retrieving(OggPlay *me) {
 
   if (me == NULL) {
     return E_OGGPLAY_BAD_OGGPLAY;
   }
--- a/media/liboggplay/src/liboggplay/oggplay_callback_info.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback_info.c
@@ -43,17 +43,17 @@
 void _print_list(char *name, OggPlayDataHeader *p);
 
 int
 oggplay_callback_info_prepare(OggPlay *me, OggPlayCallbackInfo ***info) {
 
   int i;
   int tcount = 0;
   
-  int         added_required_record   = 1;
+  int         added_required_record   = me->num_tracks;
   ogg_int64_t diff;
   ogg_int64_t latest_first_record     = 0x0LL;
   //ogg_int64_t lpt = 0;
  
   /*
    * allocate the structure for return to the user
    */
   (*info) = malloc (me->num_tracks * sizeof (OggPlayCallbackInfo *));
@@ -74,16 +74,17 @@ oggplay_callback_info_prepare(OggPlay *m
      * this track is inactive and has no data - create an empty record
      * for it
      */
     if (track->active == 0 && track->data_list == NULL) {
       track_info->data_type = OGGPLAY_INACTIVE;
       track_info->available_records = track_info->required_records = 0;
       track_info->records = NULL;
       track_info->stream_info = OGGPLAY_STREAM_UNINITIALISED;
+      added_required_record --;
       continue;
     }
  
     /*
      * find the first not presented packet of data, count the total number that
      * have not been presented
      */
     for (p = track->data_list; p != NULL; p = p->next) {
@@ -139,17 +140,16 @@ oggplay_callback_info_prepare(OggPlay *m
     for (p = q; p != NULL; p = p->next) {
       track_info->records[count++] = p;
       if (p->presentation_time <= me->target + track->offset) {
         track_info->required_records++;
         p->has_been_presented = 1;
         //lpt = p->presentation_time;
       }
     }
-
      
     if (track_info->required_records > 0) {
       /*
        * if the StreamState is FIRST_DATA then update it to INITIALISED, 
        * as we've marked the first data instance
        */
       if 
       (
@@ -194,34 +194,40 @@ oggplay_callback_info_prepare(OggPlay *m
      *    <-timeslice1-><-timeslice2-><-timeslice3->
      * ^                              ^                    ^
      * pt                             target               current_loc
      *
      * How do we discriminate between these two cases?  We assume the pt update
      * needs to be explicitly required (e.g. by seeking or start of movie), and
      * create a new member in the player struct called pt_update_valid
      */
+     // TODO: I don't think that pt_update_valid is necessary any more, as this will only
+     // trigger now if there's no data in *ANY* of the tracks. Hence the audio timeslice case
+     // doesn't apply.
     if 
     (
-      track->decoded_type != OGGPLAY_CMML 
-      && 
-      track->decoded_type != OGGPLAY_KATE // TODO: check this is the right thing to do
-      && 
-      track_info->required_records == 0
-      &&
-      track->active == 1
-      && 
-      me->pt_update_valid
+      track->decoded_type == OGGPLAY_CMML 
+      ||
+      track->decoded_type == OGGPLAY_KATE // TODO: check this is the right thing to do
+      ||
+      (
+        track_info->required_records == 0
+        &&
+        track->active == 1
+        && 
+        me->pt_update_valid
+      )
     ) {
-      added_required_record = 0;
-      me->pt_update_valid = 0;
+      added_required_record --;
     }
 
   }
  
+   me->pt_update_valid = 0;
+    
   //printf("\n");
 
   /*
    * there are no required records!  This means that we need to advance the
    * target to the period before the first actual record - the bitstream has
    * lied about the presence of data here.
    *
    * This happens for example with some Annodex streams (a bug in libannodex
@@ -392,17 +398,17 @@ oggplay_callback_info_unlock_item(OggPla
 long
 oggplay_callback_info_get_presentation_time(OggPlayDataHeader *header) {
 
   if (header == NULL) {
     return -1;
   }
 
   /* SGS: is this correct? */
-  return (header->presentation_time >> 32) & 0xFFFFFFFF;
+  return (((header->presentation_time >> 16) * 1000) >> 16) & 0xFFFFFFFF;
 }
 
 OggPlayVideoData *
 oggplay_callback_info_get_video_data(OggPlayDataHeader *header) {
 
   if (header == NULL) {
     return NULL;
   }
--- a/media/liboggplay/src/liboggplay/oggplay_file_reader.c
+++ b/media/liboggplay/src/liboggplay/oggplay_file_reader.c
@@ -54,19 +54,19 @@ oggplay_file_reader_initialise(OggPlayRe
   }
 
   me->file = fopen(me->file_name, "rb");
 
   if (me->file == NULL) {
     return E_OGGPLAY_BAD_INPUT;
   }
 
-  fseek(me->file, SEEK_END, 0);
+  fseek(me->file, 0L, SEEK_END);
   me->size = ftell(me->file);
-  fseek(me->file, SEEK_SET, 0);
+  fseek(me->file, 0L, SEEK_SET);
 
   me->current_position = 0;
 
   return E_OGGPLAY_OK;
 }
 
 OggPlayErrorCode
 oggplay_file_reader_destroy(OggPlayReader * opr) {
@@ -141,15 +141,16 @@ oggplay_file_reader_new(char *file_name)
   me->file_name = file_name;
   me->file = NULL;
 
   me->functions.initialise = &oggplay_file_reader_initialise;
   me->functions.destroy = &oggplay_file_reader_destroy;
   me->functions.available = &oggplay_file_reader_available;
   me->functions.finished_retrieving = &oggplay_file_reader_finished_retrieving;
   me->functions.seek = NULL;
+  me->functions.duration = NULL;
   me->functions.io_read = &oggplay_file_reader_io_read;
   me->functions.io_seek = &oggplay_file_reader_io_seek;
   me->functions.io_tell = &oggplay_file_reader_io_tell;
 
   return (OggPlayReader *)me;
 
 }
--- a/media/liboggplay/src/liboggplay/oggplay_file_reader.h
+++ b/media/liboggplay/src/liboggplay/oggplay_file_reader.h
@@ -44,13 +44,13 @@
 
 #define FILE_READER_CHUNK_SIZE              8192
 #define FILE_READER_INITIAL_NUM_BUFFERS     8
 
 typedef struct {
   OggPlayReader     functions;
   char            * file_name;
   FILE            * file;
-  int               current_position;
-  int               size;
+  long              current_position;
+  long              size;
 } OggPlayFileReader;
 
 #endif
--- a/media/liboggplay/src/liboggplay/oggplay_private.h
+++ b/media/liboggplay/src/liboggplay/oggplay_private.h
@@ -34,21 +34,24 @@
  * oggplay_private.h
  *
  * Shane Stephens <shane.stephens@annodex.net>
  * Michael Martin
  */
 #ifndef __OGGPLAY_PRIVATE_H__
 #define __OGGPLAY_PRIVATE_H__
 
+#ifdef HAVE_CONFIG_H 
 #ifdef WIN32
 #include "config_win32.h"
 #else
 #include <config.h>
 #endif
+#endif
+
 #include <oggplay/oggplay.h>
 
 #include <oggz/oggz.h>
 #include <theora/theora.h>
 #include <fishsound/fishsound.h>
 
 #ifdef HAVE_KATE
 #include <kate/kate.h>
@@ -215,16 +218,17 @@ struct _OggPlay {
   void                    * callback_user_ptr;
   ogg_int64_t               target;
   int                       active_tracks;
   volatile OggPlayBuffer  * buffer;
   ogg_int64_t               presentation_time;
   OggPlaySeekTrash        * trash;
   int                       shutdown;
   int                       pt_update_valid;
+  ogg_int64_t               duration;	 /**< The value of the duration the last time it was retrieved.*/
 };
 
 void
 oggplay_set_data_callback_force(OggPlay *me, OggPlayDataCallback callback,
                 void *user);
 
 void
 oggplay_take_out_trash(OggPlay *me, OggPlaySeekTrash *trash);
--- a/media/liboggplay/src/liboggplay/oggplay_tcp_reader.c
+++ b/media/liboggplay/src/liboggplay/oggplay_tcp_reader.c
@@ -54,17 +54,21 @@
 #include <sys/fcntl.h>
 #include <sys/errno.h>
 #include <sys/time.h>
 #include <time.h>
 #include <netdb.h>
 #include <unistd.h>
 #endif
 
+#if HAVE_ASSERT
 #include <assert.h>
+#else
+#define assert(x)
+#endif
 
 #define PRINT_BUFFER(s,m) \
     printf("%s: in_mem: %d size: %d pos: %d stored: %d\n", \
             s, m->amount_in_memory, m->buffer_size, \
             m->current_position, m->stored_offset);
 
 #ifndef WIN32
 typedef int SOCKET;
--- a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
+++ b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
@@ -71,32 +71,34 @@
 
 /* YUV -> RGB Intel MMX implementation */
 void oggplay_yuv2rgb(OggPlayYUVChannels * yuv, OggPlayRGBChannels * rgb) {
 
   int               i;
   unsigned char   * restrict ptry;
   unsigned char   * restrict ptru;
   unsigned char   * restrict ptrv;
+  unsigned char   * ptro;
 
   register __m64    *y, *o;
   register __m64    zero, ut, vt, imm, imm2;
   register __m64    r, g, b;
   register __m64    tmp, tmp2;
 
   zero = _mm_setzero_si64();
 
+  ptro = rgb->ptro;
   ptry = yuv->ptry;
   ptru = yuv->ptru;
   ptrv = yuv->ptrv;
 
   for (i = 0; i < yuv->y_height; i++) {
     int j;
-    o = (__m64*)rgb->ptro;
-    rgb->ptro += rgb->rgb_width * 4;
+    o = (__m64*)ptro;
+    ptro += rgb->rgb_width * 4;
     for (j = 0; j < yuv->y_width; j += 8) {
 
       y = (__m64*)&ptry[j];
 
       ut = _m_from_int(*(int *)(ptru + j/2));
       vt = _m_from_int(*(int *)(ptrv + j/2));
 
       //ut = _m_from_int(0);
@@ -201,32 +203,34 @@ void oggplay_yuv2rgb(OggPlayYUVChannels 
 
 /* YUV -> BGR Intel MMX implementation */
 void oggplay_yuv2bgr(OggPlayYUVChannels * yuv, OggPlayRGBChannels * rgb) {
 
   int               i;
   unsigned char   * restrict ptry;
   unsigned char   * restrict ptru;
   unsigned char   * restrict ptrv;
+  unsigned char   * ptro;
 
   register __m64    *y, *o;
   register __m64    zero, ut, vt, imm, imm2;
   register __m64    r, g, b;
   register __m64    tmp, tmp2;
 
   zero = _mm_setzero_si64();
 
   ptry = yuv->ptry;
   ptru = yuv->ptru;
   ptrv = yuv->ptrv;
+  ptro = rgb->ptro;
 
   for (i = 0; i < yuv->y_height; i++) {
     int j;
-    o = (__m64*)rgb->ptro;
-    rgb->ptro += rgb->rgb_width * 4;
+    o = (__m64*)ptro;
+    ptro += rgb->rgb_width * 4;
     for (j = 0; j < yuv->y_width; j += 8) {
 
       y = (__m64*)&ptry[j];
 
       ut = _m_from_int(*(int *)(ptru + j/2));
       vt = _m_from_int(*(int *)(ptrv + j/2));
 
       //ut = _m_from_int(0);
--- a/media/liboggplay/update.sh
+++ b/media/liboggplay/update.sh
@@ -30,13 +30,12 @@ cp $1/src/liboggplay/oggplay.c ./src/lib
 cp $1/src/liboggplay/oggplay_callback.h ./src/liboggplay/oggplay_callback.h
 cp $1/src/liboggplay/oggplay_tcp_reader.c ./src/liboggplay/oggplay_tcp_reader.c
 cp $1/src/liboggplay/oggplay_query.c ./src/liboggplay/oggplay_query.c
 sed s/\#include\ \"config_win32.h\"//g $1/src/liboggplay/oggplay_private.h >./src/liboggplay/oggplay_private.h1
 sed s/\#include\ \<config.h\>/\#ifdef\ WIN32\\n\#include\ \"config_win32.h\"\\n\#else\\n\#include\ \<config.h\>\\n\#endif/g ./src/liboggplay/oggplay_private.h1 >./src/liboggplay/oggplay_private.h
 rm ./src/liboggplay/oggplay_private.h1
 sed s/\#ifdef\ HAVE_INTTYPES_H/\#if\ HAVE_INTTYPES_H/g $1/src/liboggplay/oggplay_data.c >./src/liboggplay/oggplay_data.c
 cd ./src/liboggplay
-patch <../../yuv2rgb-vanilla-fix.patch
 patch <../../yuv_disable_optimized.patch
 cd ../..
-patch -p4 <yuv2argb.patch
+patch -p3 <yuv2argb.patch
 patch -p3 <bug464007.patch
deleted file mode 100644
--- a/media/liboggplay/yuv2rgb-vanilla-fix.patch
+++ /dev/null
@@ -1,88 +0,0 @@
-Index: oggplay_yuv2rgb.c
-===================================================================
---- oggplay_yuv2rgb.c	(revision 3733)
-+++ oggplay_yuv2rgb.c	(working copy)
-@@ -357,29 +357,27 @@
-     ptro2 = ptro;
-     for (j = 0; j < yuv->y_width; j += 2) {
- 
--      short pr, pg, pb;
-+      short pr, pg, pb, y;
-       short r, g, b;
- 
--    //pr = ((128 + (ptrv[j/2] - 128) * 292) >> 8) - 16; /* 1.14 * 256 */
--      pr = (-41344 + ptrv[j/2] * 292) >> 8;
--    //pg = ((128 - (ptru[j/2] - 128) * 101 - (ptrv[j/2] - 128) * 149) >> 8)-16;
--    //                                /* 0.395 & 0.581 */
--      pg = (28032 - ptru[j/2] * 101 - ptrv[j/2] * 149) >> 8;
--    //pb = ((128 + (ptru[j/2] - 128) * 520) >> 8) - 16; /* 2.032 */
--      pb = (-70528 + ptru[j/2] * 520) >> 8;
-+      pr = (-56992 + ptrv[j/2] * 409) >> 8;
-+      pg = (34784 - ptru[j/2] * 100 - ptrv[j/2] * 208) >> 8;
-+      pb = (-70688 + ptru[j/2] * 516) >> 8;
- 
--      r = ptry[j] + pr;
--      g = ptry[j] + pg;
--      b = ptry[j] + pb;
-+      y = 298*ptry[j] >> 8;
-+      r = y + pr;
-+      g = y + pg;
-+      b = y + pb;
- 
-       *ptro2++ = CLAMP(r);
-       *ptro2++ = CLAMP(g);
-       *ptro2++ = CLAMP(b);
-       *ptro2++ = 255;
- 
--      r = ptry[j + 1] + pr;
--      g = ptry[j + 1] + pg;
--      b = ptry[j + 1] + pb;
-+      y = 298*ptry[j + 1] >> 8;
-+      r = y + pr;
-+      g = y + pg;
-+      b = y + pb;
- 
-       *ptro2++ = CLAMP(r);
-       *ptro2++ = CLAMP(g);
-@@ -409,29 +407,27 @@
-     ptro2 = ptro;
-     for (j = 0; j < yuv->y_width; j += 2) {
- 
--      short pr, pg, pb;
-+      short pr, pg, pb, y;
-       short r, g, b;
- 
--    //pr = ((128 + (ptrv[j/2] - 128) * 292) >> 8) - 16; /* 1.14 * 256 */
--      pr = (-41344 + ptrv[j/2] * 292) >> 8;
--    //pg = ((128 - (ptru[j/2] - 128) * 101 - (ptrv[j/2] - 128) * 149) >> 8)-16;
--    //                                /* 0.395 & 0.581 */
--      pg = (28032 - ptru[j/2] * 101 - ptrv[j/2] * 149) >> 8;
--    //pb = ((128 + (ptru[j/2] - 128) * 520) >> 8) - 16; /* 2.032 */
--      pb = (-70528 + ptru[j/2] * 520) >> 8;
-+      pr = (-56992 + ptrv[j/2] * 409) >> 8;
-+      pg = (34784 - ptru[j/2] * 100 - ptrv[j/2] * 208) >> 8;
-+      pb = (-70688 + ptru[j/2] * 516) >> 8;
- 
--      r = ptry[j] + pr;
--      g = ptry[j] + pg;
--      b = ptry[j] + pb;
-+      y = 298*ptry[j] >> 8;
-+      r = y + pr;
-+      g = y + pg;
-+      b = y + pb;
- 
-       *ptro2++ = CLAMP(b);
-       *ptro2++ = CLAMP(g);
-       *ptro2++ = CLAMP(r);
-       *ptro2++ = 255;
- 
--      r = ptry[j + 1] + pr;
--      g = ptry[j + 1] + pg;
--      b = ptry[j + 1] + pb;
-+      y = 298*ptry[j + 1] >> 8;
-+      r = y + pr;
-+      g = y + pg;
-+      b = y + pb;
- 
-       *ptro2++ = CLAMP(b);
-       *ptro2++ = CLAMP(g);
--- a/media/liboggz/README
+++ b/media/liboggz/README
@@ -1,40 +1,46 @@
 About Oggz
 ----------
 
-Oggz comprises liboggz and the command-line tools oggzinfo, oggzdump,
-oggzdiff, oggzmerge, oggzrip, oggz-comment, oggz-scan and oggz-validate.
+Oggz comprises liboggz and the tool oggz, which provides commands to
+inspect, edit and validate Ogg files. The oggz-chop tool can also be
+used to serve time ranges of Ogg media over HTTP by any web server that
+supports CGI.
 
-liboggz is a C library providing a simple programming interface for reading
-and writing Ogg files and streams. Ogg is an interleaving data container
-developed by Monty at Xiph.Org, originally to support the Ogg Vorbis audio
-format.
+liboggz is a C library for reading and writing Ogg files and streams.
+It offers various improvements over the reference libogg, including
+support for seeking, validation and timestamp interpretation. Ogg is
+an interleaving data container developed by Monty at Xiph.Org,
+originally to support the Ogg Vorbis audio format but now used for
+many free codecs including Dirac, FLAC, Speex and Theora.
 
 Dependencies
 ------------
 
 Oggz depends only on libogg, available in most free software
 distributions, or in source form at: http://xiph.org/downloads/
 
 Support is built-in for parsing the headers of and seeking to time
-positions in Ogg Speex, Vorbis, FLAC, Theora, PCM and CMML. Oggz is also
+positions in Ogg Dirac, FLAC, Speex, Theora and Vorbis. Oggz is also
 compatible with Annodex streams, and supports seeking on all tracks
 described in an Ogg Skeleton track.
 
 Installation
 ------------
 
-This library can be installed using the conventional commands:
+Release archives can be installed using the conventional commands:
 
     $ ./configure
     $ make check
     $ sudo make install
 
-sequence. Full details in the file INSTALL.
+sequence. Configuration details are in the file INSTALL. If you obtained
+this source by svn, first run "./autogen.sh" to create the configure script,
+then run the above commands.
 
 Read the file README.win32 for installing under MS Windows, and
 README.symbian for information about building for Symbian devices.
 
 Source layout
 -------------
 
 The src/ directory contains the source code.
@@ -99,43 +105,73 @@ and mux and demux examples can be read o
     http://www.annodex.net/software/liboggz/html/
 
 Tools
 -----
 
 The Oggz source tarball also contains the following command-line tools,
 which are useful for debugging and testing Ogg bitstreams:
 
-    * oggzinfo: Display information about one or more Ogg files and
-    their bitstreams.
-
-    * oggzdump: Hexdump packets of an Ogg file, or revert an Ogg file
-    from such a hexdump.
-
-    * oggzdiff: Hexdump the packets of two Ogg files and output
-    differences.
-
-    * oggzmerge: Merge Ogg files together, interleaving pages in order
-    of presentation time.
-
-    * oggzrip: Extract one or more logical bitstreams from an Ogg file.
+    * oggz-chop: Extract the part of an Ogg file between given start
+    and/or end times.
 
     * oggz-comment: List or edit comments in an Ogg file.
 
+    * oggz-diff: Hexdump the packets of two Ogg files and output
+    differences.
+
+    * oggz-dump: Hexdump packets of an Ogg file, or revert an Ogg file
+    from such a hexdump.
+
+    * oggz-info: Display information about one or more Ogg files and
+    their bitstreams.
+
+    * oggz-merge: Merge Ogg files together, interleaving pages in order
+    of presentation time.
+
+    * oggz-rip: Extract one or more logical bitstreams from an Ogg file.
+
     * oggz-scan: Scan an Ogg file and output characteristic landmarks.
 
+    * oggz-sort: Sort the pages of an Ogg file in order of presentation time.
+
     * oggz-validate: Validate the Ogg framing of one or more files.
 
+The script bash-completion/oggz enables completion of tool options and codec
+names when using the bash shell. Source it from your .profile, or install it
+in /etc/bash_completion.d to enable it system-wide.
+
+
+oggz-chop: General usage and CGI installation
+---------------------------------------------
+
+oggz-chop extracts the part of an Ogg file between given start and/or end
+times. The output file contains copies of the headers of the input file, and
+all the codec data required to correctly decode the content between the start
+and end times specified on the commandline. For codecs with data dependencies
+like video keyframes, the keyframe prior to the starting time will be included
+in the output.
+
+An Apache server can be configured to use oggz-chop to handle all Ogg files
+(or, all Ogg files in a particular directory). An example Apache configuration
+is in the liboggz source tree, along with a script for installing it on a
+Debian server.
+
+The oggz-chop binary checks if it is being run as a CGI script (by checking
+some environment variables), and if so acts based on the CGI query parameter
+t=, much like mod_annodex. It accepts all the time specifications that
+mod_annodex accepts (npt and various smpte framerates), and start and end
+times separated by a /.
+
 License
 -------
 
 Oggz is Free Software, available under a BSD style license.
 
 More information is available online at the Oggz homepage:
 
     http://www.annodex.net/software/liboggz/
 
 enjoy :)
 
 --
 Conrad Parker
-Senior Software Engineer, Continuous Media Web, CSIRO Australia
-http://www.annodex.net/   http://www.ict.csiro.au/cmweb/
+http://www.annodex.net/
--- a/media/liboggz/README_MOZILLA
+++ b/media/liboggz/README_MOZILLA
@@ -1,21 +1,12 @@
-The source from this directory was copied from the liboggz-0.9.7
-source distribution using the update.sh script. The only changes made
-were those applied by update.sh, which applies a patch from
-seek.patch, and the addition/upate of Makefile.in files for the
+The source from this directory was copied from the liboggz svn 
+source repository using the update.sh script. The only changes made
+were those applied by update.sh, which applies patches described
+below, and the addition/upate of Makefile.in files for the
 Mozilla build system.
 
-The seek.patch address a bug in liboggz when a seek call returns an
-error. It also addresses an issue where the guess for the seek
-position can exceed the file size. These will be upstreamed to liboggz.
-
-The warning.patch addresses a printf in liboggz that is not wrapped
-in a DEBUG #ifdef. See Mozilla bug 450891 and Annodex ticket 431:
+The svn revision number used was r3835.
 
-http://trac.annodex.net/ticket/431
-
-The oggz_off_t.patch fixes a compile error on Solaris see bug 449754
-for details
-
-The wince.patch addresses the lack of posix file IO suppor on windows ce see bug 461844 for details.
+The wince.patch addresses the lack of posix file IO support on windows ce,
+see bug 461844 for details.
 
 endian.patch is applied to fix bug 452698.
--- a/media/liboggz/include/oggz/config.h
+++ b/media/liboggz/include/oggz/config.h
@@ -1,19 +1,22 @@
 /* config.h.  Generated from config.h.in by configure.  */
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #define HAVE_DLFCN_H 1
 
 /* Define to 1 if you have the <fcntl.h> header file. */
 #define HAVE_FCNTL_H 1
 
 /* Define to 1 if you have the 'getopt_long' function */
-#define HAVE_GETOPT_LONG 
+#define HAVE_GETOPT_LONG /**/
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #define HAVE_INTTYPES_H 1
 
 /* Define to 1 if you have the `memmove' function. */
 #define HAVE_MEMMOVE 1
 
 /* Define to 1 if you have the <memory.h> header file. */
@@ -42,16 +45,20 @@
 #define HAVE_SYS_STAT_H 1
 
 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
 
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
 
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#define LT_OBJDIR ".libs/"
+
 /* Define to build experimental code */
 /* #undef OGGZ_CONFIG_EXPERIMENTAL */
 
 /* Do not build reading support */
 #define OGGZ_CONFIG_READ 1
 
 /* Do not build writing support */
 #define OGGZ_CONFIG_WRITE 1
@@ -96,29 +103,40 @@
 #define SIZEOF_SSIZE_T 4
 
 /* Define to 1 if you have the ANSI C header files. */
 #define STDC_HEADERS 1
 
 /* Version number of package */
 #define VERSION "0.9.8"
 
-/* Define to 1 if your processor stores words with the most significant byte
-   first (like Motorola and SPARC, unlike Intel and VAX). */
-/* #undef WORDS_BIGENDIAN */
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* #  undef WORDS_BIGENDIAN */
+# endif
+#endif
 
 /* Number of bits in a file offset, on hosts where this is settable. */
 #define _FILE_OFFSET_BITS 64
 
 /* Define to make fseeko etc. visible, on some hosts. */
 #define _LARGEFILE_SOURCE 1
 
 /* Define for large files, on AIX-style hosts. */
 /* #undef _LARGE_FILES */
 
+/* Some systems need _XOPEN_SOURCE for timezone */
+/* #undef _XOPEN_SOURCE */
+
 /* Define to empty if `const' does not conform to ANSI C. */
 /* #undef const */
 
 /* Define to `long int' if <sys/types.h> does not define. */
 /* #undef off_t */
 
 /* Define to rpl_realloc if the replacement function should be used. */
 /* #undef realloc */
--- a/media/liboggz/include/oggz/config_win32.h
+++ b/media/liboggz/include/oggz/config_win32.h
@@ -25,17 +25,17 @@
 /* Define to 1 if your system has a GNU libc compatible `realloc' function,
    and to 0 otherwise. */
 #undef HAVE_REALLOC
 
 /* Define to 1 if the system has the type `ssize_t'. */
 #define HAVE_SSIZE_T 1
 
 /* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
+#undef HAVE_STDINT_H
 
 /* Define to 1 if you have the <stdlib.h> header file. */
 #define HAVE_STDLIB_H 1
 
 /* Define to 1 if you have the <strings.h> header file. */
 #define HAVE_STRINGS_H 1
 
 /* Define to 1 if you have the <string.h> header file. */
@@ -126,9 +126,13 @@
 /* Define to `long' if <sys/types.h> does not define. */
 /* #undef off_t */
 
 /* Define to rpl_realloc if the replacement function should be used. */
 #undef realloc
 
 /* Define to `unsigned' if <sys/types.h> does not define. */
 #undef size_t
-#undef DEBUG
+
+/* Define for MSVC as <stdint.h> is unavailable there */
+typedef unsigned char uint8_t;
+
+#define inline __inline // MSVC#undef DEBUG
--- a/media/liboggz/include/oggz/oggz.h
+++ b/media/liboggz/include/oggz/oggz.h
@@ -558,16 +558,25 @@ int oggz_get_numtracks (OGGZ * oggz);
  * Request a new serialno, as required for a new stream, ensuring the serialno
  * is not yet used for any other streams managed by this OGGZ.
  * \param oggz An OGGZ handle
  * \returns A new serialno, not already occuring in any logical bitstreams
  * in \a oggz.
  */
 long oggz_serialno_new (OGGZ * oggz);
 
+/**
+ * Return human-readable string representation of a content type
+ *
+ * \retval string the name of the content type
+ * \retval NULL \a content invalid
+ */
+const char *
+oggz_content_type (OggzStreamContent content);
+
 #include <oggz/oggz_off_t.h>
 #include <oggz/oggz_read.h>
 #include <oggz/oggz_stream.h>
 #include <oggz/oggz_seek.h>
 #include <oggz/oggz_write.h>
 #include <oggz/oggz_io.h>
 #include <oggz/oggz_comments.h>
 #include <oggz/oggz_deprecated.h>
--- a/media/liboggz/include/oggz/oggz_comments.h
+++ b/media/liboggz/include/oggz/oggz_comments.h
@@ -115,16 +115,17 @@ oggz_comment_get_vendor (OGGZ * oggz, lo
 /**
  * Set the vendor string
  * \param oggz A OGGZ* handle
  * \param serialno Identify a logical bitstream within \a oggz
  * \param vendor_string The contents of the vendor string to add
  * \retval 0 Success
  * \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
+ * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
  * \note The vendor string should identify the library used to produce
  * the stream, e.g. libvorbis 1.0 used "Xiph.Org libVorbis I 20020717".
  * If copying a bitstream it should be the same as the source.
  */
 int
 oggz_comment_set_vendor (OGGZ * oggz, long serialno,
 			 const char * vendor_string);
 
@@ -185,29 +186,31 @@ oggz_comment_next_byname (OGGZ * oggz, l
 /**
  * Add a comment
  * \param oggz A OGGZ* handle (created with mode OGGZ_WRITE)
  * \param serialno Identify a logical bitstream within \a oggz
  * \param comment The comment to add
  * \retval 0 Success
  * \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
+ * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
  */
 int
 oggz_comment_add (OGGZ * oggz, long serialno, OggzComment * comment);
 
 /**
  * Add a comment by name and value.
  * \param oggz A OGGZ* handle (created with mode OGGZ_WRITE)
  * \param serialno Identify a logical bitstream within \a oggz
  * \param name The name of the comment to add
  * \param value The contents of the comment to add
  * \retval 0 Success
  * \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
+ * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
  */
 int
 oggz_comment_add_byname (OGGZ * oggz, long serialno,
                          const char * name, const char * value);
 
 /**
  * Remove a comment
  * \param oggz A OGGZ* handle (created with OGGZ_WRITE)
--- a/media/liboggz/include/oggz/oggz_constants.h
+++ b/media/liboggz/include/oggz/oggz_constants.h
@@ -36,17 +36,17 @@
 /** \file
  * General constants used by liboggz.
  */
 
 /**
  * Flags to oggz_new(), oggz_open(), and oggz_openfd().
  * Can be or'ed together in the following combinations:
  * - OGGZ_READ | OGGZ_AUTO
- * - OGGZ_WRITE | OGGZ_NONSTRICT
+ * - OGGZ_WRITE | OGGZ_NONSTRICT | OGGZ_PREFIX | OGGZ_SUFFIX
  */
 enum OggzFlags {
   /** Read only */
   OGGZ_READ         = 0x00,
 
   /** Write only */
   OGGZ_WRITE        = 0x01,
 
@@ -58,22 +58,26 @@ enum OggzFlags {
    * Scan for known headers while reading, and automatically set
    * metrics appropriately. Opening a file for reading with
    * \a flags = OGGZ_READ | OGGZ_AUTO will allow seeking on Speex,
    * Vorbis, FLAC, Theora, CMML and all Annodex streams in units of
    * milliseconds, once all bos pages have been delivered. */
   OGGZ_AUTO         = 0x20,
 
   /**
-   * Prefix
+   * Write Prefix: Assume that we are only writing the prefix of an
+   * Ogg stream, ie. disable checking for conformance with end-of-stream
+   * constraints.
    */
   OGGZ_PREFIX       = 0x40,
 
   /**
-   * Suffix
+   * Write Suffix: Assume that we are only writing the suffix of an
+   * Ogg stream, ie. disable checking for conformance with
+   * beginning-of-stream constraints.
    */
   OGGZ_SUFFIX       = 0x80
 
 };
 
 enum OggzStopCtl {
   /** Continue calling read callbacks */
   OGGZ_CONTINUE     = 0,
@@ -107,16 +111,17 @@ typedef enum OggzStreamContent {
   OGGZ_CONTENT_CMML,
   OGGZ_CONTENT_ANX2,
   OGGZ_CONTENT_SKELETON,
   OGGZ_CONTENT_FLAC0,
   OGGZ_CONTENT_FLAC,
   OGGZ_CONTENT_ANXDATA,
   OGGZ_CONTENT_CELT,
   OGGZ_CONTENT_KATE,
+  OGGZ_CONTENT_DIRAC,
   OGGZ_CONTENT_UNKNOWN
 } OggzStreamContent;
 
 /**
  * Definitions of error return values
  */
 enum OggzError {
   /** No error */
@@ -160,16 +165,22 @@ enum OggzError {
   /** Reading was stopped by an OggzReadCallback returning OGGZ_STOP_ERR
    * or writing was stopped by an OggzWriteHungry callback returning
    * OGGZ_STOP_ERR */
   OGGZ_ERR_STOP_ERR                     = -15,
 
   /** no data available from IO, try again */
   OGGZ_ERR_IO_AGAIN                     = -16,
 
+  /** Hole (sequence number gap) detected in input data */
+  OGGZ_ERR_HOLE_IN_DATA                 = -17,
+
+  /** Out of memory */
+  OGGZ_ERR_OUT_OF_MEMORY                = -18,
+
   /** The requested serialno does not exist in this OGGZ */
   OGGZ_ERR_BAD_SERIALNO                 = -20,
 
   /** Packet disallowed due to invalid byte length */
   OGGZ_ERR_BAD_BYTES                    = -21,
 
   /** Packet disallowed due to invalid b_o_s (beginning of stream) flag */
   OGGZ_ERR_BAD_B_O_S                    = -22,
--- a/media/liboggz/include/oggz/oggz_io.h
+++ b/media/liboggz/include/oggz/oggz_io.h
@@ -120,16 +120,17 @@ typedef int (*OggzIOFlush) (void * user_
  *
  * \param oggz An OGGZ handle
  * \param read Your reading function
  * \param user_handle Any arbitrary data you wish to pass to the function
  * \retval 0 Success
  * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ; \a oggz not
  * open for reading.
+ * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
  */
 int oggz_io_set_read (OGGZ * oggz, OggzIORead read, void * user_handle);
 
 /**
  * Retrieve the user_handle associated with the function you have provided
  * for reading input data.
  *
  * \param oggz An OGGZ handle
@@ -142,16 +143,17 @@ void * oggz_io_get_read_user_handle (OGG
  *
  * \param oggz An OGGZ handle
  * \param write Your writing function
  * \param user_handle Any arbitrary data you wish to pass to the function
  * \retval 0 Success
  * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ; \a oggz not
  * open for writing.
+ * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
  */
 int oggz_io_set_write (OGGZ * oggz, OggzIOWrite write, void * user_handle);
 
 /**
  * Retrieve the user_handle associated with the function you have provided
  * for writing output data.
  *
  * \param oggz An OGGZ handle
@@ -163,16 +165,17 @@ void * oggz_io_get_write_user_handle (OG
  * Set a function for Oggz to call when it needs to seek on its raw data.
  *
  * \param oggz An OGGZ handle
  * \param seek Your seeking function
  * \param user_handle Any arbitrary data you wish to pass to the function
  * \retval 0 Success
  * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
+ * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
  *
  * \note If you provide an OggzIOSeek function, you MUST also provide
  * an OggzIOTell function, or else all your seeks will fail.
  */
 int oggz_io_set_seek (OGGZ * oggz, OggzIOSeek seek, void * user_handle);
 
 /**
  * Retrieve the user_handle associated with the function you have provided
@@ -188,16 +191,17 @@ void * oggz_io_get_seek_user_handle (OGG
  * within its input data (if OGGZ_READ) or output data (if OGGZ_WRITE).
  *
  * \param oggz An OGGZ handle
  * \param tell Your tell function
  * \param user_handle Any arbitrary data you wish to pass to the function
  * \retval 0 Success
  * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
+ * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
  */
 int oggz_io_set_tell (OGGZ * oggz, OggzIOTell tell, void * user_handle);
 
 /**
  * Retrieve the user_handle associated with the function you have provided
  * for determining the current offset in input or output data.
  *
  * \param oggz An OGGZ handle
@@ -211,16 +215,17 @@ void * oggz_io_get_tell_user_handle (OGG
  *
  * \param oggz An OGGZ handle
  * \param flush Your flushing function
  * \param user_handle Any arbitrary data you wish to pass to the function
  * \retval 0 Success
  * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ; \a oggz not
  * open for writing.
+ * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
  */
 int oggz_io_set_flush (OGGZ * oggz, OggzIOFlush flush, void * user_handle);
 
 /**
  * Retrieve the user_handle associated with the function you have provided
  * for flushing output.
  *
  * \param oggz An OGGZ handle
--- a/media/liboggz/include/oggz/oggz_read.h
+++ b/media/liboggz/include/oggz/oggz_read.h
@@ -89,16 +89,17 @@ typedef int (*OggzReadPacket) (OGGZ * og
  * logical bitstreams in \a oggz.
  * \param read_packet Your callback function
  * \param user_data Arbitrary data you wish to pass to your callback
  * \retval 0 Success
  * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing
  * logical bitstream in \a oggz.
  * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
+ * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
  *
  * \note Values of \a serialno other than -1 allows you to specify different
  * callback functions for each logical bitstream.
  *
  * \note It is safe to call this callback from within an OggzReadPacket
  * function, in order to specify that subsequent packets should be handled
  * by a different OggzReadPacket function.
  */
@@ -126,16 +127,17 @@ typedef int (*OggzReadPage) (OGGZ * oggz
  * \param serialno Identify the logical bitstream in \a oggz to attach
  * this callback to, or -1 to attach this callback to all unattached
  * logical bitstreams in \a oggz.
  * \param read_page Your OggzReadPage callback function
  * \param user_data Arbitrary data you wish to pass to your callback
  * \retval 0 Success
  * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
+ * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
  *
  * \note Values of \a serialno other than -1 allows you to specify different
  * callback functions for each logical bitstream.
  *
  * \note It is safe to call this callback from within an OggzReadPage
  * function, in order to specify that subsequent pages should be handled
  * by a different OggzReadPage function.
  */
@@ -151,16 +153,17 @@ int oggz_set_read_page (OGGZ * oggz, lon
  * \retval 0 End of file
  * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
  * \retval OGGZ_ERR_SYSTEM System error; check errno for details
  * \retval OGGZ_ERR_STOP_OK Reading was stopped by a user callback
  * returning OGGZ_STOP_OK
  * \retval OGGZ_ERR_STOP_ERR Reading was stopped by a user callback
  * returning OGGZ_STOP_ERR
+ * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory
  */
 long oggz_read (OGGZ * oggz, long n);
 
 /**
  * Input data into \a oggz.
  * \param oggz An OGGZ handle previously opened for reading
  * \param buf A memory buffer
  * \param n A count of bytes to input
--- a/media/liboggz/include/oggz/oggz_seek.h
+++ b/media/liboggz/include/oggz/oggz_seek.h
@@ -254,16 +254,40 @@ long oggz_seek_packets (OGGZ * oggz, lon
  * decode headers should not be considered part of the metric space. To
  * inform Oggz not to seek earlier than the end of the decode headers,
  * use oggz_set_data_start().
  *
  * \{
  */
 
 /**
+ * Retrieve the preroll of a logical bitstream.
+ * \param oggz An OGGZ handle
+ * \param serialno Identify the logical bitstream in \a oggz
+ * \returns The preroll of the specified logical bitstream.
+ * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing
+ * logical bitstream in \a oggz.
+ * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
+ */
+int oggz_get_preroll (OGGZ * oggz, long serialno);
+
+/**
+ * Specify the preroll of a logical bitstream.
+ * \param oggz An OGGZ handle
+ * \param serialno Identify the logical bitstream in \a oggz to attach
+ * this preroll to.
+ * \param preroll The preroll
+ * \returns 0 Success
+ * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing
+ * logical bitstream in \a oggz.
+ * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
+ */
+int oggz_set_preroll (OGGZ * oggz, long serialno, int preroll);
+
+/**
  * Retrieve the granuleshift of a logical bitstream.
  * \param oggz An OGGZ handle
  * \param serialno Identify the logical bitstream in \a oggz
  * \returns The granuleshift of the specified logical bitstream.
  * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing
  * logical bitstream in \a oggz.
  * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
  */
@@ -419,16 +443,18 @@ int oggz_set_metric (OGGZ * oggz, long s
  *
  */
 typedef int (*OggzOrder) (OGGZ * oggz, ogg_packet * op, void * target,
 			 void * user_data);
 /**
  * \retval 0 Success
  * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
+ * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing
+ *                               logical bitstream in \a oggz, and is not -1
  */
 int oggz_set_order (OGGZ * oggz, long serialno, OggzOrder order,
 		    void * user_data);
 
 long oggz_seek_byorder (OGGZ * oggz, void * target);
 
 #endif /* _UNIMPLEMENTED */
 
--- a/media/liboggz/include/oggz/oggz_table.h
+++ b/media/liboggz/include/oggz/oggz_table.h
@@ -43,16 +43,17 @@
 /**
  * A table of key-value pairs.
  */
 typedef void OggzTable;
 
 /**
  * Instantiate a new OggzTable
  * \returns A new OggzTable
+ * \retval NULL Could not allocate memory for table
  */
 OggzTable *
 oggz_table_new (void);
 
 /**
  * Delete an OggzTable
  * \param table An OggzTable
  */
--- a/media/liboggz/include/oggz/oggz_write.h
+++ b/media/liboggz/include/oggz/oggz_write.h
@@ -172,16 +172,17 @@ int oggz_write_set_hungry_callback (OGGZ
  *         and \a oggz is not flagged OGGZ_NONSTRICT
  * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing
  *         logical bitstream in \a oggz,
  *         and \a oggz is not flagged OGGZ_NONSTRICT
  *         or \a serialno is equal to -1, or \a serialno does not fit in
  *         32 bits, ie. within the range (-(2^31), (2^31)-1)
  * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
  * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
+ * \retval OGGZ_ERR_OUT_OF_MEMORY Unable to allocate memory to queue packet
  *
  * \note If \a op->b_o_s is initialized to \a -1 before calling
  *       oggz_write_feed(), Oggz will fill it in with the appropriate
  *       value; ie. 1 for the first packet of a new stream, and 0 otherwise.
  */
 int oggz_write_feed (OGGZ * oggz, ogg_packet * op, long serialno, int flush,
 		     int * guard);
 
deleted file mode 100644
--- a/media/liboggz/oggz_off_t.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -r 070e364189c8 media/liboggz/include/oggz/oggz_off_t_generated.h
---- a/media/liboggz/include/oggz/oggz_off_t_generated.h	Wed Nov 26 09:04:13 2008 -0600
-+++ b/media/liboggz/include/oggz/oggz_off_t_generated.h	Thu Nov 27 17:56:54 2008 +0800
-@@ -59,7 +59,7 @@
- 
- #include <sys/types.h>
- 
--#ifdef __APPLE__
-+#if defined(__APPLE__) || defined(SOLARIS)
- typedef off_t oggz_off_t;
- #else
- typedef loff_t oggz_off_t;
--- a/media/liboggz/src/liboggz/Makefile.in
+++ b/media/liboggz/src/liboggz/Makefile.in
@@ -41,16 +41,17 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= oggz
 LIBRARY_NAME	= oggz
 FORCE_STATIC_LIB= 1
 
 CSRCS		= \
+		dirac.c \
 		metric_internal.c \
 		oggz.c \
 		oggz_auto.c \
 		oggz_comments.c \
 		oggz_dlist.c \
 		oggz_io.c \
 		oggz_read.c \
 		oggz_seek.c \
new file mode 100644
--- /dev/null
+++ b/media/liboggz/src/liboggz/dirac.c
@@ -0,0 +1,194 @@
+/*
+  dirac.c
+*/
+
+#ifdef WIN32
+#include "config_win32.h"
+#else
+#include "config.h"
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include "dirac.h"
+
+
+typedef struct
+dirac_bs_s
+{
+  uint8_t *p_start;
+  uint8_t *p;
+  uint8_t *p_end;
+
+  int     i_left;    /* i_count number of available bits */
+} dirac_bs_t;
+
+static inline void
+dirac_bs_init( dirac_bs_t *s, void *p_data, int i_data )
+{
+  s->p_start = p_data;
+  s->p       = p_data;
+  s->p_end   = s->p + i_data;
+  s->i_left  = 8;
+}
+
+static inline ogg_uint32_t
+dirac_bs_read( dirac_bs_t *s, int i_count )
+{
+   static ogg_uint32_t i_mask[33] =
+   {  0x00,
+      0x01,      0x03,      0x07,      0x0f,
+      0x1f,      0x3f,      0x7f,      0xff,
+      0x1ff,     0x3ff,     0x7ff,     0xfff,
+      0x1fff,    0x3fff,    0x7fff,    0xffff,
+      0x1ffff,   0x3ffff,   0x7ffff,   0xfffff,
+      0x1fffff,  0x3fffff,  0x7fffff,  0xffffff,
+      0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
+      0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
+  int      i_shr;
+  ogg_uint32_t i_result = 0;
+
+  while( i_count > 0 )
+  {
+    if( s->p >= s->p_end )
+    {
+      break;
+    }
+
+    if( ( i_shr = s->i_left - i_count ) >= 0 )
+    {
+      /* more in the buffer than requested */
+      i_result |= ( *s->p >> i_shr )&i_mask[i_count];
+      s->i_left -= i_count;
+      if( s->i_left == 0 )
+      {
+        s->p++;
+        s->i_left = 8;
+      }
+      return( i_result );
+    }
+    else
+    {
+        /* less in the buffer than requested */
+       i_result |= (*s->p&i_mask[s->i_left]) << -i_shr;
+       i_count  -= s->i_left;
+       s->p++;
+       s->i_left = 8;
+    }
+  }
+
+  return( i_result );
+}
+
+static inline void
+dirac_bs_skip( dirac_bs_t *s, int i_count )
+{
+  s->i_left -= i_count;
+
+  while( s->i_left <= 0 )
+  {
+    s->p++;
+    s->i_left += 8;
+  }
+}
+
+static ogg_uint32_t
+dirac_uint ( dirac_bs_t *p_bs )
+{
+  ogg_uint32_t count = 0, value = 0;
+  while( !dirac_bs_read ( p_bs, 1 ) ) {
+    count++;
+    value <<= 1;
+    value |= dirac_bs_read ( p_bs, 1 );
+  }
+
+  return (1<<count) - 1 + value;
+}
+
+static int
+dirac_bool ( dirac_bs_t *p_bs )
+{
+  return dirac_bs_read ( p_bs, 1 );
+}
+
+void
+dirac_parse_info (dirac_info *info, unsigned char * data, long len)
+{
+  dirac_bs_t bs;
+  ogg_uint32_t video_format;
+
+  static const struct {
+    ogg_uint32_t fps_numerator, fps_denominator;
+  } dirac_frate_tbl[] = { /* table 10.3 */
+    {1,1}, /* this first value is never used */
+    {24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1},
+    {50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2}
+  };
+
+  static const ogg_uint32_t dirac_vidfmt_frate[] = { /* table C.1 */
+    1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6
+  };
+
+  static const int dirac_source_sampling[] = { /* extracted from table C.1 */
+    0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
+  };
+  static const int dirac_top_field_first[] = { /* from table C.1 */
+    0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+  };
+
+  static const struct {
+    ogg_uint32_t width, height;
+  } dirac_fsize_tbl[] = { /* table 10.3 framesize */
+    {640,460}, {24,1}, {176,120}, {352,240}, {352,288},
+    {704,480}, {704,576}, {720,480}, {720,576},
+    {1280, 720}, {1280, 720}, {1920, 1080}, {1920, 1080},
+    {1920, 1080}, {1920, 1080}, {2048, 1080}, {4096, 2160}
+  };
+
+  /* read in useful bits from sequence header */
+  dirac_bs_init( &bs, data, len);
+  dirac_bs_skip( &bs, 13*8); /* parse_info_header */
+  info->major_version = dirac_uint( &bs ); /* major_version */
+  info->minor_version = dirac_uint( &bs ); /* minor_version */
+  info->profile = dirac_uint( &bs ); /* profile */
+  info->level = dirac_uint( &bs ); /* level */
+  info->video_format = video_format = dirac_uint( &bs ); /* index */
+
+  info->width = dirac_fsize_tbl[video_format].width;
+  info->height = dirac_fsize_tbl[video_format].height;
+  if (dirac_bool( &bs )) {
+    info->width = dirac_uint( &bs ); /* frame_width */
+    info->height = dirac_uint( &bs ); /* frame_height */
+  }
+
+  if (dirac_bool( &bs )) {
+    info->chroma_format = dirac_uint( &bs ); /* chroma_format */
+  }
+
+  if (dirac_bool( &bs )) { /* custom_scan_format_flag */
+    int scan_format = dirac_uint( &bs ); /* scan_format */
+    if (scan_format < 2) {
+      info->interlaced = scan_format;
+    } else { /* other scan_format values are reserved */
+      info->interlaced = 0;
+    }
+  } else { /* no custom scan_format, use the preset value */
+    info->interlaced = dirac_source_sampling[video_format];
+  }
+  /* field order is set by video_format and cannot be custom */
+  info->top_field_first = dirac_top_field_first[video_format];
+
+  info->fps_numerator = dirac_frate_tbl[dirac_vidfmt_frate[video_format]].fps_numerator;
+  info->fps_denominator = dirac_frate_tbl[dirac_vidfmt_frate[video_format]].fps_denominator;
+  if (dirac_bool( &bs )) {
+    ogg_uint32_t frame_rate_index = dirac_uint( &bs );
+    info->fps_numerator = dirac_frate_tbl[frame_rate_index].fps_numerator;
+    info->fps_denominator = dirac_frate_tbl[frame_rate_index].fps_denominator;
+    if (frame_rate_index == 0) {
+      info->fps_numerator = dirac_uint( &bs );
+      info->fps_denominator = dirac_uint( &bs );
+    }
+  }
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/media/liboggz/src/liboggz/dirac.h
@@ -0,0 +1,29 @@
+/*
+ * dirac.h
+ */
+
+#ifndef _DIRAC_H
+#define _DIRAC_H
+
+#include <ogg/ogg.h>
+
+typedef struct {
+  ogg_uint32_t major_version;
+  ogg_uint32_t minor_version;
+  ogg_uint32_t profile;
+  ogg_uint32_t level;
+  ogg_uint32_t chroma_format;
+  ogg_uint32_t video_format;
+
+  ogg_uint32_t width;
+  ogg_uint32_t height;
+  ogg_uint32_t fps_numerator;
+  ogg_uint32_t fps_denominator;
+
+  ogg_uint32_t interlaced;
+  ogg_uint32_t top_field_first;
+} dirac_info;
+
+extern void dirac_parse_info (dirac_info *info, unsigned char *data, long len);
+
+#endif
--- a/media/liboggz/src/liboggz/metric_internal.c
+++ b/media/liboggz/src/liboggz/metric_internal.c
@@ -34,16 +34,47 @@
 #include "config_win32.h"
 #else
 #include "config.h"
 #endif
 
 #include "oggz_private.h"
 
 static ogg_int64_t
+oggz_metric_dirac (OGGZ * oggz, long serialno,
+                   ogg_int64_t granulepos, void * user_data)
+{
+  oggz_stream_t * stream;
+  ogg_int64_t iframe, pframe;
+  ogg_uint32_t pt;
+  ogg_uint16_t dist;
+  ogg_uint16_t delay;
+  ogg_int64_t dt;
+  ogg_int64_t units;
+
+  stream = oggz_get_stream (oggz, serialno);
+  if (stream == NULL) return -1;
+
+  iframe = granulepos >> stream->granuleshift;
+  pframe = granulepos - (iframe << stream->granuleshift);
+  pt = (iframe + pframe) >> 9;
+  delay = pframe >> 9;
+  dt = (ogg_int64_t)pt - delay;
+
+  units = dt * stream->granulerate_d / stream->granulerate_n;
+
+#ifdef DEBUG
+  printf ("oggz_..._granuleshift: serialno %010lu Got frame or field %lld (%lld + %lld): %lld units\n",
+	  serialno, dt, iframe, pframe, units);
+#endif
+
+  return units;
+}
+
+static ogg_int64_t
 oggz_metric_default_granuleshift (OGGZ * oggz, long serialno,
 				  ogg_int64_t granulepos, void * user_data)
 {
   oggz_stream_t * stream;
   ogg_int64_t iframe, pframe;
   ogg_int64_t units;
 
   stream = oggz_get_stream (oggz, serialno);
@@ -51,17 +82,17 @@ oggz_metric_default_granuleshift (OGGZ *
 
   iframe = granulepos >> stream->granuleshift;
   pframe = granulepos - (iframe << stream->granuleshift);
   granulepos = (iframe + pframe);
 
   units = granulepos * stream->granulerate_d / stream->granulerate_n;
 
 #ifdef DEBUG
-  printf ("oggz_..._granuleshift: serialno %010ld Got frame %lld (%lld + %lld): %lld units\n",
+  printf ("oggz_..._granuleshift: serialno %010lu Got frame %lld (%lld + %lld): %lld units\n",
 	  serialno, granulepos, iframe, pframe, units);
 #endif
 
   return units;
 }
 
 static ogg_int64_t
 oggz_metric_default_linear (OGGZ * oggz, long serialno, ogg_int64_t granulepos,
@@ -91,16 +122,20 @@ oggz_metric_update (OGGZ * oggz, long se
     stream->granulerate_n= 1;
     stream->granulerate_d = 0;
   }
 
   if (stream->granuleshift == 0) {
     return oggz_set_metric_internal (oggz, serialno,
 				     oggz_metric_default_linear,
 				     NULL, 1);
+  } else if (oggz_stream_get_content (oggz, serialno) == OGGZ_CONTENT_DIRAC) {
+    return oggz_set_metric_internal (oggz, serialno,
+				     oggz_metric_dirac,
+				     NULL, 1);
   } else {
     return oggz_set_metric_internal (oggz, serialno,
 				     oggz_metric_default_granuleshift,
 				     NULL, 1);
   }
 }
 
 int
@@ -157,17 +192,17 @@ oggz_get_granulerate (OGGZ * oggz, long 
   oggz_stream_t * stream;
 
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
 
   stream = oggz_get_stream (oggz, serialno);
   if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
 
   *granulerate_n = stream->granulerate_n;
-  *granulerate_d = stream->granulerate_d;
+  *granulerate_d = stream->granulerate_d / OGGZ_AUTO_MULT;
 
   return 0;
 }
 
 /** DEPRECATED **/
 int
 oggz_set_metric_linear (OGGZ * oggz, long serialno,
 			ogg_int64_t granule_rate_numerator,
--- a/media/liboggz/src/liboggz/oggz.c
+++ b/media/liboggz/src/liboggz/oggz.c
@@ -91,34 +91,50 @@ oggz_new (int flags)
 
   oggz->offset = 0;
   oggz->offset_data_begin = 0;
 
   oggz->run_blocksize = 1024;
   oggz->cb_next = 0;
 
   oggz->streams = oggz_vector_new ();
+  if (oggz->streams == NULL) {
+    goto err_oggz_new;
+  }
+  
   oggz->all_at_eos = 0;
 
   oggz->metric = NULL;
   oggz->metric_user_data = NULL;
   oggz->metric_internal = 0;
 
   oggz->order = NULL;
   oggz->order_user_data = NULL;
 
   oggz->packet_buffer = oggz_dlist_new ();
+  if (oggz->packet_buffer == NULL) {
+    goto err_streams_new;
+  }
 
   if (OGGZ_CONFIG_WRITE && (oggz->flags & OGGZ_WRITE)) {
-    oggz_write_init (oggz);
+    if (oggz_write_init (oggz) == NULL)
+      goto err_packet_buffer_new;
   } else if (OGGZ_CONFIG_READ) {
     oggz_read_init (oggz);
   }
 
   return oggz;
+
+err_packet_buffer_new:
+  oggz_free (oggz->packet_buffer);
+err_streams_new:
+  oggz_free (oggz->streams);
+err_oggz_new:
+  oggz_free (oggz);
+  return NULL;
 }
 
 OGGZ *
 oggz_open (char * filename, int flags)
 {
   OGGZ * oggz = NULL;
   FILE * file = NULL;
 
@@ -320,17 +336,20 @@ oggz_add_stream (OGGZ * oggz, long seria
 {
   oggz_stream_t * stream;
 
   stream = oggz_malloc (sizeof (oggz_stream_t));
   if (stream == NULL) return NULL;
 
   ogg_stream_init (&stream->ogg_stream, (int)serialno);
 
-  oggz_comments_init (stream);
+  if (oggz_comments_init (stream) == -1) {
+    oggz_free (stream);
+    return NULL;
+  }
 
   stream->content = OGGZ_CONTENT_UNKNOWN;
   stream->numheaders = 3; /* Default to 3 headers for Ogg logical bitstreams */
   stream->preroll = 0;
   stream->granulerate_n = 1;
   stream->granulerate_d = 1;
   stream->basegranule = 0;
   stream->granuleshift = 0;
@@ -593,16 +612,18 @@ oggz_set_order (OGGZ * oggz, long serial
     return OGGZ_ERR_INVALID;
   }
 
   if (serialno == -1) {
     oggz->order = order;
     oggz->order_user_data = user_data;
   } else {
     stream = oggz_get_stream (oggz, serialno);
+    if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
+
     stream->order = order;
     stream->order_user_data = user_data;
   }
 
   return 0;
 }
 
 /* Map callback return values to error return values */
@@ -616,8 +637,33 @@ oggz_map_return_value_to_error (int cb_r
     return OGGZ_ERR_STOP_OK;
   case OGGZ_STOP_ERR:
     return OGGZ_ERR_STOP_ERR;
   default:
     return OGGZ_ERR_STOP_ERR;
   }
 }
 
+const char *
+oggz_content_type (OggzStreamContent content)
+{
+  /* 20080805:
+   * Re: http://lists.xiph.org/pipermail/ogg-dev/2008-July/001108.html
+   *
+   * "The ISO C standard, in section 6.7.2.2 "enumeration specifiers",
+   * paragraph 4, says
+   *
+   *   Each enumerated type shall be compatible with *char*, a signed
+   *   integer type, or an unsigned integer type.  The choice of type is
+   *   implementation-defined, but shall be capable of representing the
+   *   values of all the members of the declaration."
+   *
+   * -- http://gcc.gnu.org/ml/gcc-bugs/2000-09/msg00271.html
+   *
+   *  Hence, we cannot remove the (content < 0) guard, even though current
+   *  GCC gives a warning for it -- other compilers (including earlier GCC
+   *  versions) may use a signed type for enum OggzStreamContent.
+   */
+  if (content < 0 || content >= OGGZ_CONTENT_UNKNOWN)
+    return NULL;
+
+  return oggz_auto_codec_ident[content].content_type;
+}
--- a/media/liboggz/src/liboggz/oggz_auto.c
+++ b/media/liboggz/src/liboggz/oggz_auto.c
@@ -42,16 +42,17 @@
 #include "config.h"
 #endif
 
 #include <stdlib.h>
 #include <string.h>
 
 #include "oggz_private.h"
 #include "oggz_byteorder.h"
+#include "dirac.h"
 
 #include <oggz/oggz_stream.h>
 
 /*#define DEBUG*/
 
 /* Allow use of internal metrics; ie. the user_data for these gets free'd
  * when the metric is overwritten, or on close */
 int oggz_set_metric_internal (OGGZ * oggz, long serialno, OggzMetric metric,
@@ -61,70 +62,72 @@ int oggz_set_metric_linear (OGGZ * oggz,
 			    ogg_int64_t granule_rate_numerator,
 			    ogg_int64_t granule_rate_denominator);
 
 #define INT16_BE_AT(x) _be_16((*(ogg_int32_t *)(x)))
 #define INT32_LE_AT(x) _le_32((*(ogg_int32_t *)(x)))
 #define INT32_BE_AT(x) _be_32((*(ogg_int32_t *)(x)))
 #define INT64_LE_AT(x) _le_64((*(ogg_int64_t *)(x)))
 
-#define OGGZ_AUTO_MULT 1000Ull
-
 static int
 oggz_stream_set_numheaders (OGGZ * oggz, long serialno, int numheaders)
 {
   oggz_stream_t * stream;
 
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
 
   stream = oggz_get_stream (oggz, serialno);
   if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
 
   stream->numheaders = numheaders;
 
   return 0;
 }
 
 static int
-auto_speex (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_speex (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
-  unsigned char * header = op->packet;
+  unsigned char * header = data;
   ogg_int64_t granule_rate = 0;
   int numheaders;
 
-  if (op->bytes < 68) return 0;
+  if (length < 68) return 0;
 
   granule_rate = (ogg_int64_t) INT32_LE_AT(&header[36]);
 #ifdef DEBUG
   printf ("Got speex rate %d\n", (int)granule_rate);
 #endif
 
   oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
 
+  oggz_set_preroll (oggz, serialno, 3);
+
   numheaders = (ogg_int64_t) INT32_LE_AT(&header[68]) + 2;
   oggz_stream_set_numheaders (oggz, serialno, numheaders);
 
   return 1;
 }
 
 static int
-auto_vorbis (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_vorbis (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
-  unsigned char * header = op->packet;
+  unsigned char * header = data;
   ogg_int64_t granule_rate = 0;
 
-  if (op->bytes < 30) return 0;
+  if (length < 30) return 0;
 
   granule_rate = (ogg_int64_t) INT32_LE_AT(&header[12]);
 #ifdef DEBUG
   printf ("Got vorbis rate %d\n", (int)granule_rate);
 #endif
 
   oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
 
+  oggz_set_preroll (oggz, serialno, 2);
+
   oggz_stream_set_numheaders (oggz, serialno, 3);
 
   return 1;
 }
 
 #if USE_THEORA_PRE_ALPHA_3_FORMAT
 static int intlog(int num) {
   int ret=0;
@@ -132,25 +135,25 @@ static int intlog(int num) {
     num=num/2;
     ret=ret+1;
   }
   return(ret);
 }
 #endif
 
 static int
-auto_theora (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_theora (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
-  unsigned char * header = op->packet;
+  unsigned char * header = data;
   ogg_int32_t fps_numerator, fps_denominator;
   char keyframe_granule_shift = 0;
   int keyframe_shift;
 
   /* TODO: this should check against 42 for the relevant version numbers */
-  if (op->bytes < 41) return 0;
+  if (length < 41) return 0;
 
   fps_numerator = INT32_BE_AT(&header[22]);
   fps_denominator = INT32_BE_AT(&header[26]);
 
   /* Very old theora versions used a value of 0 to mean 1.
    * Unfortunately theora hasn't incremented its version field,
    * hence we hardcode this workaround for old or broken streams.
    */
@@ -170,81 +173,82 @@ auto_theora (OGGZ * oggz, ogg_packet * o
   printf ("Got theora fps %d/%d, keyframe_shift %d\n",
 	  fps_numerator, fps_denominator, keyframe_shift);
 #endif
 
   oggz_set_granulerate (oggz, serialno, (ogg_int64_t)fps_numerator,
 			OGGZ_AUTO_MULT * (ogg_int64_t)fps_denominator);
   oggz_set_granuleshift (oggz, serialno, keyframe_shift);
 
+
   oggz_stream_set_numheaders (oggz, serialno, 3);
 
   return 1;
 }
 
 static int
-auto_annodex (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_annodex (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
   /* Apply a zero metric */
   oggz_set_granulerate (oggz, serialno, 0, 1);
 
   return 1;
 }
 
 static int
-auto_anxdata (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_anxdata (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
-  unsigned char * header = op->packet;
+  unsigned char * header = data;
   ogg_int64_t granule_rate_numerator = 0, granule_rate_denominator = 0;
 
-  if (op->bytes < 28) return 0;
+  if (length < 28) return 0;
 
   granule_rate_numerator = INT64_LE_AT(&header[8]);
   granule_rate_denominator = INT64_LE_AT(&header[16]);
 #ifdef DEBUG
   printf ("Got AnxData rate %lld/%lld\n", granule_rate_numerator,
 	  granule_rate_denominator);
 #endif
 
   oggz_set_granulerate (oggz, serialno,
 			granule_rate_numerator,
 			OGGZ_AUTO_MULT * granule_rate_denominator);
 
   return 1;
 }
 
 static int
-auto_flac0 (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_flac0 (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
-  unsigned char * header = op->packet;
+  unsigned char * header = data;
   ogg_int64_t granule_rate = 0;
 
-  granule_rate = (ogg_int64_t) (header[14] << 12) | (header[15] << 4) | 
+  granule_rate = (ogg_int64_t) (header[14] << 12) | (header[15] << 4) |
             ((header[16] >> 4)&0xf);
 #ifdef DEBUG
     printf ("Got flac rate %d\n", (int)granule_rate);
 #endif
-    
+
   oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
 
   oggz_stream_set_numheaders (oggz, serialno, 3);
 
   return 1;
 }
 
 static int
-auto_flac (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_flac (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
-  unsigned char * header = op->packet;
+  unsigned char * header = data;
   ogg_int64_t granule_rate = 0;
   int numheaders;
 
-  if (op->bytes < 51) return 0;
+  if (length < 51) return 0;
 
-  granule_rate = (ogg_int64_t) (header[27] << 12) | (header[28] << 4) | 
+  granule_rate = (ogg_int64_t) (header[27] << 12) | (header[28] << 4) |
             ((header[29] >> 4)&0xf);
 #ifdef DEBUG
   printf ("Got flac rate %d\n", (int)granule_rate);
 #endif
 
   oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
 
   numheaders = INT16_BE_AT(&header[7]);
@@ -253,69 +257,69 @@ auto_flac (OGGZ * oggz, ogg_packet * op,
   return 1;
 }
 
 /**
  * Recognizer for OggPCM2:
  * http://wiki.xiph.org/index.php/OggPCM2
  */
 static int
-auto_oggpcm2 (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_oggpcm2 (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
-  unsigned char * header = op->packet;
+  unsigned char * header = data;
   ogg_int64_t granule_rate;
 
-  if (op->bytes < 28) return 0;
+  if (length < 28) return 0;
 
   granule_rate = (ogg_int64_t) INT32_BE_AT(&header[16]);
 #ifdef DEBUG
   printf ("Got OggPCM2 rate %d\n", (int)granule_rate);
 #endif
 
   oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
 
   oggz_stream_set_numheaders (oggz, serialno, 3);
 
   return 1;
 }
 
 static int
-auto_celt (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_celt (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
-  unsigned char * header = op->packet;
+  unsigned char * header = data;
   ogg_int64_t granule_rate = 0;
   int numheaders;
 
-  if (op->bytes < 56) return 0;
+  if (length < 56) return 0;
 
   granule_rate = (ogg_int64_t) INT32_LE_AT(&header[40]);
 #ifdef DEBUG
   printf ("Got celt sample rate %d\n", (int)granule_rate);
 #endif
 
   oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
 
   numheaders = (ogg_int64_t) INT32_LE_AT(&header[52]) + 2;
   oggz_stream_set_numheaders (oggz, serialno, numheaders);
 
   return 1;
 }
 
 static int
-auto_cmml (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_cmml (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
-  unsigned char * header = op->packet;
+  unsigned char * header = data;
   ogg_int64_t granule_rate_numerator = 0, granule_rate_denominator = 0;
   int granuleshift;
 
-  if (op->bytes < 28) return 0;
+  if (length < 28) return 0;
 
   granule_rate_numerator = INT64_LE_AT(&header[12]);
   granule_rate_denominator = INT64_LE_AT(&header[20]);
-  if (op->bytes > 28)
+  if (length > 28)
     granuleshift = (int)header[28];
   else
     granuleshift = 0;
 
 #ifdef DEBUG
   printf ("Got CMML rate %lld/%lld\n", granule_rate_numerator,
 	  granule_rate_denominator);
 #endif
@@ -326,144 +330,167 @@ auto_cmml (OGGZ * oggz, ogg_packet * op,
   oggz_set_granuleshift (oggz, serialno, granuleshift);
 
   oggz_stream_set_numheaders (oggz, serialno, 3);
 
   return 1;
 }
 
 static int
-auto_kate (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_kate (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
-  unsigned char * header = op->packet;
+  unsigned char * header = data;
   ogg_int32_t gps_numerator, gps_denominator;
   unsigned char granule_shift = 0;
   int numheaders;
 
-  if (op->bytes < 64) return 0;
+  if (length < 64) return 0;
 
   gps_numerator = INT32_LE_AT(&header[24]);
   gps_denominator = INT32_LE_AT(&header[28]);
 
   granule_shift = (header[15]);
   numheaders = (header[11]);
 
 #ifdef DEBUG
   printf ("Got kate gps %d/%d, granule shift %d\n",
 	  gps_numerator, gps_denominator, granule_shift);
 #endif
 
   oggz_set_granulerate (oggz, serialno, gps_numerator,
 			OGGZ_AUTO_MULT * gps_denominator);
   oggz_set_granuleshift (oggz, serialno, granule_shift);
- 
+
   oggz_stream_set_numheaders (oggz, serialno, numheaders);
 
   return 1;
 }
 
 static int
-auto_fisbone (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_dirac (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
-  unsigned char * header = op->packet;
+  int granule_shift = 22; /* not a typo */
+  dirac_info *info;
+
+  info = oggz_malloc(sizeof(dirac_info));
+
+  dirac_parse_info(info, data, length);
+
+#ifdef DEBUG
+  printf ("Got dirac fps %d/%d granule_shift %d\n",
+    fps_numerator, fps_denominator, granule_shift);
+#endif
+
+  /* the granulerate is twice the frame rate (in order to handle interlace) */
+  oggz_set_granulerate (oggz, serialno,
+	2 * (ogg_int64_t)info->fps_numerator,
+	OGGZ_AUTO_MULT * (ogg_int64_t)info->fps_denominator);
+  oggz_set_granuleshift (oggz, serialno, granule_shift);
+
+  oggz_stream_set_numheaders (oggz, serialno, 0);
+
+  oggz_free(info);
+  return 1;
+}
+
+static int
+auto_fisbone (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
+{
+  unsigned char * header = data;
   long fisbone_serialno; /* The serialno referred to in this fisbone */
   ogg_int64_t granule_rate_numerator = 0, granule_rate_denominator = 0;
   int granuleshift, numheaders;
 
-  if (op->bytes < 48) return 0;
+  if (length < 48) return 0;
 
   fisbone_serialno = (long) INT32_LE_AT(&header[12]);
 
   /* Don't override an already assigned metric */
   if (oggz_stream_has_metric (oggz, fisbone_serialno)) return 1;
 
   granule_rate_numerator = INT64_LE_AT(&header[20]);
   granule_rate_denominator = INT64_LE_AT(&header[28]);
   granuleshift = (int)header[48];
 
 #ifdef DEBUG
-  printf ("Got fisbone granulerate %lld/%lld, granuleshift %d for serialno %010ld\n",
+  printf ("Got fisbone granulerate %lld/%lld, granuleshift %d for serialno %010lu\n",
 	  granule_rate_numerator, granule_rate_denominator, granuleshift,
 	  fisbone_serialno);
 #endif
 
   oggz_set_granulerate (oggz, fisbone_serialno,
 			granule_rate_numerator,
 			OGGZ_AUTO_MULT * granule_rate_denominator);
   oggz_set_granuleshift (oggz, fisbone_serialno, granuleshift);
 
   /* Increment the number of headers for this stream */
   numheaders = oggz_stream_get_numheaders (oggz, serialno);
   oggz_stream_set_numheaders (oggz, serialno, numheaders+1);
-				
+
   return 1;
 }
 
 static int
-auto_fishead (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+auto_fishead (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
 {
-  if (!op->b_o_s)
-  {
-    return auto_fisbone(oggz, op, serialno, user_data);
-  }
-  
   oggz_set_granulerate (oggz, serialno, 0, 1);
 
   /* For skeleton, numheaders will get incremented as each header is seen */
   oggz_stream_set_numheaders (oggz, serialno, 1);
-  
+
   return 1;
 }
 
 /*
  * The first two speex packets are header and comment packets (granulepos = 0)
  */
 
 typedef struct {
   int headers_encountered;
   int packet_size;
   int encountered_first_data_packet;
 } auto_calc_speex_info_t;
 
-static ogg_int64_t 
+static ogg_int64_t
 auto_calc_speex(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
-  
+
   /*
    * on the first (b_o_s) packet, set calculate_data to be the number
    * of speex frames per packet
    */
 
-  auto_calc_speex_info_t *info 
+  auto_calc_speex_info_t *info
           = (auto_calc_speex_info_t *)stream->calculate_data;
 
   if (stream->calculate_data == NULL) {
-    stream->calculate_data = malloc(sizeof(auto_calc_speex_info_t));
+    stream->calculate_data = oggz_malloc(sizeof(auto_calc_speex_info_t));
+    if (stream->calculate_data == NULL) return -1;
     info = stream->calculate_data;
     info->encountered_first_data_packet = 0;
-    info->packet_size = 
+    info->packet_size =
             (*(int *)(op->packet + 64)) * (*(int *)(op->packet + 56));
     info->headers_encountered = 1;
     return 0;
   }
-  
+
   if (info->headers_encountered < 2) {
     info->headers_encountered += 1;
   } else {
     info->encountered_first_data_packet = 1;
   }
 
   if (now > -1) {
     return now;
   }
 
   if (info->encountered_first_data_packet) {
     if (stream->last_granulepos > 0) {
       return stream->last_granulepos + info->packet_size;
     }
-    
+
     return -1;
   }
 
   return 0;
 
 }
 
 /*
@@ -471,100 +498,103 @@ auto_calc_speex(ogg_int64_t now, oggz_st
  */
 
 typedef struct {
   int headers_encountered;
   int packet_size;
   int encountered_first_data_packet;
 } auto_calc_celt_info_t;
 
-static ogg_int64_t 
+static ogg_int64_t
 auto_calc_celt (ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
-  
+
   /*
    * on the first (b_o_s) packet, set calculate_data to be the number
    * of celt frames per packet
    */
 
-  auto_calc_celt_info_t *info 
+  auto_calc_celt_info_t *info
           = (auto_calc_celt_info_t *)stream->calculate_data;
 
   if (stream->calculate_data == NULL) {
-    stream->calculate_data = malloc(sizeof(auto_calc_celt_info_t));
+    stream->calculate_data = oggz_malloc(sizeof(auto_calc_celt_info_t));
+    if (stream->calculate_data == NULL) return -1;
+
     info = stream->calculate_data;
     info->encountered_first_data_packet = 0;
 
     /* In general, the number of frames per packet depends on the mode.
      * Currently (20080213) both available modes, mono and stereo, have 256
      * frames per packet.
      */
     info->packet_size = 256;
 
     info->headers_encountered = 1;
     return 0;
   }
-  
+
   if (info->headers_encountered < 2) {
     info->headers_encountered += 1;
   } else {
     info->encountered_first_data_packet = 1;
   }
 
   if (now > -1) {
     return now;
   }
 
   if (info->encountered_first_data_packet) {
     if (stream->last_granulepos > 0) {
       return stream->last_granulepos + info->packet_size;
     }
-    
+
     return -1;
   }
 
   return 0;
 
 }
 /*
  * Header packets are marked by a set MSB in the first byte.  Inter packets
  * are marked by a set 2MSB in the first byte.  Intra packets (keyframes)
  * are any that are left over ;-)
- * 
- * (see http://www.theora.org/doc/Theora_I_spec.pdf for the theora 
+ *
+ * (see http://www.theora.org/doc/Theora_I_spec.pdf for the theora
  * specification)
  */
 
 typedef struct {
   int encountered_first_data_packet;
 } auto_calc_theora_info_t;
 
 
-static ogg_int64_t 
+static ogg_int64_t
 auto_calc_theora(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
 
   long keyframe_no;
   int keyframe_shift;
   unsigned char first_byte;
   auto_calc_theora_info_t *info;
 
   first_byte = op->packet[0];
 
   info = (auto_calc_theora_info_t *)stream->calculate_data;
 
   /* header packet */
   if (first_byte & 0x80)
   {
     if (info == NULL) {
-      stream->calculate_data = malloc(sizeof(auto_calc_theora_info_t));
+      stream->calculate_data = oggz_malloc(sizeof(auto_calc_theora_info_t));
+      if (stream->calculate_data == NULL) return -1;
       info = stream->calculate_data;
     }
     info->encountered_first_data_packet = 0;
     return (ogg_int64_t)0;
   }
-  
+
   /* known granulepos */
   if (now > (ogg_int64_t)(-1)) {
     info->encountered_first_data_packet = 1;
     return now;
   }
 
   /* last granulepos unknown */
   if (stream->last_granulepos == -1) {
@@ -581,32 +611,32 @@ auto_calc_theora(ogg_int64_t now, oggz_s
   }
 
   /* inter-coded packet */
   if (first_byte & 0x40)
   {
     return stream->last_granulepos + 1;
   }
 
-  keyframe_shift = stream->granuleshift; 
+  keyframe_shift = stream->granuleshift;
   /*
    * retrieve last keyframe number
    */
   keyframe_no = (int)(stream->last_granulepos >> keyframe_shift);
   /*
    * add frames since last keyframe number
    */
   keyframe_no += (stream->last_granulepos & ((1 << keyframe_shift) - 1)) + 1;
   return ((ogg_int64_t)keyframe_no) << keyframe_shift;
-  
+
 
 }
 
 static ogg_int64_t
-auto_rcalc_theora(ogg_int64_t next_packet_gp, oggz_stream_t *stream, 
+auto_rcalc_theora(ogg_int64_t next_packet_gp, oggz_stream_t *stream,
                   ogg_packet *this_packet, ogg_packet *next_packet) {
 
   int keyframe = (int)(next_packet_gp >> stream->granuleshift);
   int offset = (int)(next_packet_gp - (keyframe << stream->granuleshift));
 
   /* assume kf is 60 frames ago. NOTE: This is going to cause problems,
    * but I can't think of what else to do.  The position of the last kf
    * is fundamentally unknowable.
@@ -637,51 +667,53 @@ auto_rcalc_theora(ogg_int64_t next_packe
  * sls:           l/2             0
  * ssl:           s/2
  * sss:           s/2
  *
  * The previous and next packet types can be inferred from the current packet
  * (additional information is not required)
  *
  * The two blocksizes can be determined from the first header packet, by reading
- * byte 28.  1 << (packet[28] >> 4) == long_size.  
+ * byte 28.  1 << (packet[28] >> 4) == long_size.
  * 1 << (packet[28] & 0xF) == short_size.
- * 
+ *
  * (see http://xiph.org/vorbis/doc/Vorbis_I_spec.html for specification)
  */
 
 typedef struct {
   int nln_increments[4];
   int nsn_increment;
   int short_size;
   int long_size;
   int encountered_first_data_packet;
   int last_was_long;
   int log2_num_modes;
   int mode_sizes[1];
 } auto_calc_vorbis_info_t;
-        
+
 
-static ogg_int64_t 
+static ogg_int64_t
 auto_calc_vorbis(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
 
   auto_calc_vorbis_info_t *info;
-  
+
   if (stream->calculate_data == NULL) {
     /*
      * on the first (b_o_s) packet, determine the long and short sizes,
      * and then calculate l/2, l/4 - s/4, 3 * l/4 - s/4, l/2 - s/2 and s/2
      */
     int short_size;
     int long_size;
-  
+
     long_size = 1 << (op->packet[28] >> 4);
     short_size = 1 << (op->packet[28] & 0xF);
 
-    stream->calculate_data = malloc(sizeof(auto_calc_vorbis_info_t));
+    stream->calculate_data = oggz_malloc(sizeof(auto_calc_vorbis_info_t));
+    if (stream->calculate_data == NULL) return -1;
+
     info = (auto_calc_vorbis_info_t *)stream->calculate_data;
     info->nln_increments[3] = long_size >> 1;
     info->nln_increments[2] = 3 * (long_size >> 2) - (short_size >> 2);
     info->nln_increments[1] = (long_size >> 2) + (short_size >> 2);
     info->nln_increments[0] = info->nln_increments[3];
     info->short_size = short_size;
     info->long_size = long_size;
     info->nsn_increment = short_size >> 1;
@@ -693,66 +725,66 @@ auto_calc_vorbis(ogg_int64_t now, oggz_s
 
   /*
    * marker for header packets
    */
   if (op->packet[0] & 0x1) {
     /*
      * the code pages, a whole bunch of other fairly useless stuff, AND,
      * RIGHT AT THE END (of a bunch of variable-length compressed rubbish that
-     * basically has only one actual set of values that everyone uses BUT YOU 
+     * basically has only one actual set of values that everyone uses BUT YOU
      * CAN'T BE SURE OF THAT, OH NO YOU CAN'T) is the only piece of data that's
      * actually useful to us - the packet modes (because it's inconceivable to
-     * think people might want _just that_ and nothing else, you know, for 
+     * think people might want _just that_ and nothing else, you know, for
      * seeking and stuff).
      *
      * Fortunately, because of the mandate that non-used bits must be zero
      * at the end of the packet, we might be able to sneakily work backwards
      * and find out the information we need (namely a mapping of modes to
      * packet sizes)
      */
     if (op->packet[0] == 5) {
       unsigned char *current_pos = &op->packet[op->bytes - 1];
       int offset;
       int size;
       int size_check;
       int *mode_size_ptr;
       int i;
-      
-      /* 
+
+      /*
        * This is the format of the mode data at the end of the packet for all
        * Vorbis Version 1 :
-       * 
+       *
        * [ 6:number_of_modes ]
        * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]
        * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]
        * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]
        * [ 1:framing(1) ]
        *
        * e.g.:
        *
        *              <-
        * 0 0 0 0 0 1 0 0
        * 0 0 1 0 0 0 0 0
        * 0 0 1 0 0 0 0 0
-       * 0 0 1|0 0 0 0 0 
+       * 0 0 1|0 0 0 0 0
        * 0 0 0 0|0|0 0 0
        * 0 0 0 0 0 0 0 0
        * 0 0 0 0|0 0 0 0
        * 0 0 0 0 0 0 0 0
        * 0 0 0 0|0 0 0 0
        * 0 0 0|1|0 0 0 0 |
        * 0 0 0 0 0 0 0 0 V
        * 0 0 0|0 0 0 0 0
        * 0 0 0 0 0 0 0 0
-       * 0 0 1|0 0 0 0 0 
-       * 0 0|1|0 0 0 0 0 
-       * 
-       *  
-       * i.e. each entry is an important bit, 32 bits of 0, 8 bits of blah, a 
+       * 0 0 1|0 0 0 0 0
+       * 0 0|1|0 0 0 0 0
+       *
+       *
+       * i.e. each entry is an important bit, 32 bits of 0, 8 bits of blah, a
        * bit of 1.
        * Let's find our last 1 bit first.
        *
        */
 
       size = 0;
 
       offset = 8;
@@ -760,110 +792,112 @@ auto_calc_vorbis(ogg_int64_t now, oggz_s
         if (offset == 0) {
           offset = 8;
           current_pos -= 1;
         }
       }
 
       while (1)
       {
-        
+
         /*
          * from current_pos-5:(offset+1) to current_pos-1:(offset+1) should
          * be zero
          */
         offset = (offset + 7) % 8;
         if (offset == 7)
           current_pos -= 1;
-        
-        if 
+
+        if
         (
           ((current_pos[-5] & ~((1 << (offset + 1)) - 1)) != 0)
           ||
-          current_pos[-4] != 0 
-          || 
-          current_pos[-3] != 0 
-          || 
+          current_pos[-4] != 0
+          ||
+          current_pos[-3] != 0
+          ||
           current_pos[-2] != 0
           ||
           ((current_pos[-1] & ((1 << (offset + 1)) - 1)) != 0)
         )
         {
           break;
         }
-        
+
         size += 1;
-        
+
         current_pos -= 5;
-        
-      } 
+
+      }
 
       if (offset > 4) {
         size_check = (current_pos[0] >> (offset - 5)) & 0x3F;
       } else {
         /* mask part of byte from current_pos */
         size_check = (current_pos[0] & ((1 << (offset + 1)) - 1));
         /* shift to appropriate position */
         size_check <<= (5 - offset);
         /* or in part of byte from current_pos - 1 */
-        size_check |= (current_pos[-1] & ~((1 << (offset + 3)) - 1)) >> 
+        size_check |= (current_pos[-1] & ~((1 << (offset + 3)) - 1)) >>
                 (offset + 3);
       }
-      
+
       size_check += 1;
 #ifdef DEBUG
       if (size_check != size)
       {
         printf("WARNING: size parsing failed for VORBIS mode packets\n");
       }
 #endif
 
       /*
        * store mode size information in our info struct
        */
-      stream->calculate_data = realloc(stream->calculate_data,
+      info = realloc(stream->calculate_data,
               sizeof(auto_calc_vorbis_info_t) + (size - 1) * sizeof(int));
-      info = (auto_calc_vorbis_info_t *)(stream->calculate_data);
-      
+      if (info == NULL) return -1;
+
+      stream->calculate_data = info;
+
       i = -1;
       while ((1 << (++i)) < size);
       info->log2_num_modes = i;
 
       mode_size_ptr = info->mode_sizes;
 
       for(i = 0; i < size; i++)
       {
         offset = (offset + 1) % 8;
         if (offset == 0)
           current_pos += 1;
         *mode_size_ptr++ = (current_pos[0] >> offset) & 0x1;
         current_pos += 5;
       }
-      
+
     }
-    
+
     return 0;
   }
 
   info = (auto_calc_vorbis_info_t *)stream->calculate_data;
 
   return -1;
 
-  { 
+  {
     /*
      * we're in a data packet!  First we need to get the mode of the packet,
      * and from the mode, the size
      */
     int mode;
     int size;
     ogg_int64_t result;
 
     mode = (op->packet[0] >> 1) & ((1 << info->log2_num_modes) - 1);
     size = info->mode_sizes[mode];
-  
+
     /*
      * if we have a working granulepos, we use it, but only if we can't
      * calculate a valid gp value.
      */
     if (now > -1 && stream->last_granulepos == -1) {
       info->encountered_first_data_packet = 1;
       info->last_was_long = size;
       return now;
@@ -879,38 +913,38 @@ auto_calc_vorbis(ogg_int64_t now, oggz_s
      * otherwise, if we haven't yet had a working granulepos, we return
      * -1
      */
     if (stream->last_granulepos == -1) {
       info->last_was_long = size;
       return -1;
     }
 
-    result = stream->last_granulepos + 
+    result = stream->last_granulepos +
       (
-        (info->last_was_long ? info->long_size  : info->short_size) 
-        + 
+        (info->last_was_long ? info->long_size  : info->short_size)
+        +
         (size ? info->long_size : info->short_size)
       ) / 4;
     info->last_was_long = size;
 
     return result;
-    
+
   }
-  
+
 }
 
 ogg_int64_t
 auto_rcalc_vorbis(ogg_int64_t next_packet_gp, oggz_stream_t *stream,
                   ogg_packet *this_packet, ogg_packet *next_packet) {
 
-  auto_calc_vorbis_info_t *info = 
+  auto_calc_vorbis_info_t *info =
                   (auto_calc_vorbis_info_t *)stream->calculate_data;
 
-  int mode = 
+  int mode =
       (this_packet->packet[0] >> 1) & ((1 << info->log2_num_modes) - 1);
   int this_size = info->mode_sizes[mode] ? info->long_size : info->short_size;
   int next_size;
   ogg_int64_t r;
 
   mode = (next_packet->packet[0] >> 1) & ((1 << info->log2_num_modes) - 1);
   next_size = info->mode_sizes[mode] ? info->long_size : info->short_size;
 
@@ -935,23 +969,25 @@ auto_rcalc_vorbis(ogg_int64_t next_packe
  * http://rafb.net/paste/results/Pkib5w72.html
  */
 
 typedef struct {
   ogg_int64_t previous_gp;
   int encountered_first_data_packet;
 } auto_calc_flac_info_t;
 
-static ogg_int64_t 
+static ogg_int64_t
 auto_calc_flac (ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op)
 {
   auto_calc_flac_info_t *info;
 
   if (stream->calculate_data == NULL) {
-    stream->calculate_data = malloc(sizeof(auto_calc_flac_info_t));
+    stream->calculate_data = oggz_malloc(sizeof(auto_calc_flac_info_t));
+    if (stream->calculate_data == NULL) return -1;
+
     info = (auto_calc_flac_info_t *)stream->calculate_data;
     info->previous_gp = 0;
     info->encountered_first_data_packet = 0;
 
     /* this is a header packet */
     goto out;
   }
 
@@ -1040,41 +1076,42 @@ const oggz_auto_contenttype_t oggz_auto_
   {"\200theora", 7, "Theora", auto_theora, auto_calc_theora, auto_rcalc_theora},
   {"\001vorbis", 7, "Vorbis", auto_vorbis, auto_calc_vorbis, auto_rcalc_vorbis},
   {"Speex", 5, "Speex", auto_speex, auto_calc_speex, NULL},
   {"PCM     ", 8, "PCM", auto_oggpcm2, NULL, NULL},
   {"CMML\0\0\0\0", 8, "CMML", auto_cmml, NULL, NULL},
   {"Annodex", 8, "Annodex", auto_annodex, NULL, NULL},
   {"fishead", 7, "Skeleton", auto_fishead, NULL, NULL},
   {"fLaC", 4, "Flac0", auto_flac0, auto_calc_flac, NULL},
-  {"\177FLAC", 4, "Flac", auto_flac, auto_calc_flac, NULL},
+  {"\177FLAC", 5, "Flac", auto_flac, auto_calc_flac, NULL},
   {"AnxData", 7, "AnxData", auto_anxdata, NULL, NULL},
   {"CELT    ", 8, "CELT", auto_celt, auto_calc_celt, NULL},
   {"\200kate\0\0\0", 8, "Kate", auto_kate, NULL, NULL},
+  {"BBCD\0", 5, "Dirac", auto_dirac, NULL, NULL},
   {"", 0, "Unknown", NULL, NULL, NULL}
-}; 
+};
 
 static int
 oggz_auto_identify (OGGZ * oggz, long serialno, unsigned char * data, long len)
 {
   int i;
-  
+
   for (i = 0; i < OGGZ_CONTENT_UNKNOWN; i++)
   {
     const oggz_auto_contenttype_t *codec = oggz_auto_codec_ident + i;
-    
+
     if (len >= codec->bos_str_len &&
         memcmp (data, codec->bos_str, codec->bos_str_len) == 0) {
-      
+
       oggz_stream_set_content (oggz, serialno, i);
-      
+
       return 1;
     }
   }
-                      
+
   oggz_stream_set_content (oggz, serialno, OGGZ_CONTENT_UNKNOWN);
   return 0;
 }
 
 int
 oggz_auto_identify_page (OGGZ * oggz, ogg_page *og, long serialno)
 {
   return oggz_auto_identify (oggz, serialno, og->body, og->body_len);
@@ -1082,37 +1119,54 @@ oggz_auto_identify_page (OGGZ * oggz, og
 
 int
 oggz_auto_identify_packet (OGGZ * oggz, ogg_packet * op, long serialno)
 {
   return oggz_auto_identify (oggz, serialno, op->packet, op->bytes);
 }
 
 int
-oggz_auto_get_granulerate (OGGZ * oggz, ogg_packet * op, long serialno, 
-                void * user_data)
+oggz_auto_read_bos_page (OGGZ * oggz, ogg_page * og, long serialno,
+                         void * user_data)
 {
   int content = 0;
 
   content = oggz_stream_get_content(oggz, serialno);
   if (content < 0 || content >= OGGZ_CONTENT_UNKNOWN) {
     return 0;
+  } else if (content == OGGZ_CONTENT_SKELETON && !ogg_page_bos(og)) {
+    return auto_fisbone(oggz, serialno, og->body, og->body_len, user_data);
+  } else {
+    return oggz_auto_codec_ident[content].reader(oggz, serialno, og->body, og->body_len, user_data);
   }
-
-  oggz_auto_codec_ident[content].reader(oggz, op, serialno, user_data);
-  return 0;
 }
 
-ogg_int64_t 
-oggz_auto_calculate_granulepos(int content, ogg_int64_t now, 
+int
+oggz_auto_read_bos_packet (OGGZ * oggz, ogg_packet * op, long serialno,
+                           void * user_data)
+{
+  int content = 0;
+
+  content = oggz_stream_get_content(oggz, serialno);
+  if (content < 0 || content >= OGGZ_CONTENT_UNKNOWN) {
+    return 0;
+  } else if (content == OGGZ_CONTENT_SKELETON && !op->b_o_s) {
+    return auto_fisbone(oggz, serialno, op->packet, op->bytes, user_data);
+  } else {
+    return oggz_auto_codec_ident[content].reader(oggz, serialno, op->packet, op->bytes, user_data);
+  }
+}
+
+ogg_int64_t
+oggz_auto_calculate_granulepos(int content, ogg_int64_t now,
                 oggz_stream_t *stream, ogg_packet *op) {
   if (oggz_auto_codec_ident[content].calculator != NULL) {
     ogg_int64_t r = oggz_auto_codec_ident[content].calculator(now, stream, op);
     return r;
-  } 
+  }
 
   return now;
 }
 
 ogg_int64_t
 oggz_auto_calculate_gp_backwards(int content, ogg_int64_t next_packet_gp,
       oggz_stream_t *stream, ogg_packet *this_packet, ogg_packet *next_packet) {
 
--- a/media/liboggz/src/liboggz/oggz_auto.h
+++ b/media/liboggz/src/liboggz/oggz_auto.h
@@ -424,33 +424,33 @@ This was the Theora header for theora-al
 | bytes_per_packet                                              | 48-51
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | extra_headers                                                 | 52-55
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
  */
 
 /**
- * Kate bitstream version 0.1
+ * Kate bitstream version 0.x
  *
  * Default field type: LITTLE ENDIAN unsigned integer
 
  0               1               2               3              |
  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1| Byte
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | packtype      | Identifier char[7]: 'kate\0\0\0'              | 0-3
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | kate magic continued                                          | 4-7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | reserved - 0  | version major | version minor | num headers   | 8-11
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | text encoding | directionality| reserved - 0  | granule shift | 12-15
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| reserved - 0                                                  | 16-19
+| cw sh |  canvas width         | ch sh | canvcas height        | 16-19
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | reserved - 0                                                  | 20-23
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | granule rate numerator                                        | 24-27
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | granule rate denominator                                      | 28-31
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | language (NUL terminated)                                     | 32-35
@@ -465,13 +465,15 @@ This was the Theora header for theora-al
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | category (continued)                                          | 52-55
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | category (continued)                                          | 56-59
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | category (continued)                                          | 60-63
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
+ since bitstream 0.3: cw sh, canvas width, ch sh, canvas height
+
  */
 
 int oggz_auto_identify (OGGZ *oggz, ogg_page *og, long serialno);
 
 #endif /* __OGGZ_AUTO_H__ */
--- a/media/liboggz/src/liboggz/oggz_comments.c
+++ b/media/liboggz/src/liboggz/oggz_comments.c
@@ -56,16 +56,18 @@
 
 
 static char *
 oggz_strdup (const char * s)
 {
   char * ret;
   if (s == NULL) return NULL;
   ret = oggz_malloc (strlen(s) + 1);
+  if (ret == NULL) return NULL;
+
   return strcpy (ret, s);
 }
 
 static char *
 oggz_strdup_len (const char * s, int len)
 {
   char * ret;
   if (s == NULL) return NULL;
@@ -88,21 +90,16 @@ oggz_index_len (const char * s, char c, 
 
   for (i = 0; *s && i < len; i++, s++) {
     if (*s == c) return (char *)s;
   }
 
   return NULL;
 }
 
-#if 0
-static void comment_init(char **comments, int* length, char *vendor_string);
-static void comment_add(char **comments, int* length, char *tag, char *val);
-#endif
-
 /*
  Comments will be stored in the Vorbis style.
  It is describled in the "Structure" section of
     http://www.xiph.org/ogg/vorbis/doc/v-comment.html
 
 The comment header is decoded as follows:
   1) [vendor_length] = read an unsigned integer of 32 bits
   2) [vendor_string] = read a UTF-8 vector as [vendor_length] octets
@@ -129,57 +126,16 @@ The comment header is decoded as follows
 
 /* The FLAC header will encode the length of the comments in
    24bit BE format.
 */
 #define writeint24be(buf, base, val) buf[base]=(char)(((val)>>16)&0xff); \
                                      buf[base+1]=(char)(((val)>>8)&0xff); \
                                      buf[base+2]=(char)((val)&0xff);
 
-#if 0
-static void
-comment_init(char **comments, int* length, char *vendor_string)
-{
-  int vendor_length=strlen(vendor_string);
-  int user_comment_list_length=0;
-  int len=4+vendor_length+4;
-  char *p=(char*)oggz_malloc(len);
-  if(p==NULL){
-  }
-  writeint(p, 0, vendor_length);
-  memcpy(p+4, vendor_string, vendor_length);
-  writeint(p, 4+vendor_length, user_comment_list_length);
-  *length=len;
-  *comments=p;
-}
-
-static void
-comment_add(char **comments, int* length, char *tag, char *val)
-{
-  char* p=*comments;
-  int vendor_length=readint(p, 0);
-  int user_comment_list_length=readint(p, 4+vendor_length);
-  int tag_len=(tag?strlen(tag):0);
-  int val_len=strlen(val);
-  int len=(*length)+4+tag_len+val_len;
-
-  p=(char*)oggz_realloc(p, len);
-  if(p==NULL){
-  }
-
-  writeint(p, *length, tag_len+val_len);      /* length of comment */
-  if(tag) memcpy(p+*length+4, tag, tag_len);  /* comment */
-  memcpy(p+*length+4+tag_len, val, val_len);  /* comment */
-  writeint(p, 4+vendor_length, user_comment_list_length+1);
-
-  *comments=p;
-  *length=len;
-}
-#endif
-
 static int
 oggz_comment_validate_byname (const char * name, const char * value)
 {
   const char * c;
 
   if (!name || !value) return 0;
 
   for (c = name; *c; c++) {
@@ -199,16 +155,18 @@ oggz_comment_validate_byname (const char
 static OggzComment *
 oggz_comment_new (const char * name, const char * value)
 {
   OggzComment * comment;
 
   if (!oggz_comment_validate_byname (name, value)) return NULL;
 
   comment = oggz_malloc (sizeof (OggzComment));
+  if (comment == NULL) return NULL;
+
   comment->name = oggz_strdup (name);
   comment->value = oggz_strdup (value);
 
   return comment;
 }
 
 static void
 oggz_comment_free (OggzComment * comment)
@@ -266,17 +224,20 @@ oggz_comment_get_vendor (OGGZ * oggz, lo
 
 int
 oggz_comment_set_vendor (OGGZ * oggz, long serialno, const char * vendor_string)
 {
   oggz_stream_t * stream;
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
 
   stream = oggz_get_stream (oggz, serialno);
-  if (stream == NULL) stream = oggz_add_stream (oggz, serialno);
+  if (stream == NULL)
+    stream = oggz_add_stream (oggz, serialno);
+  if (stream == NULL)
+    return OGGZ_ERR_OUT_OF_MEMORY;
 
   if (oggz->flags & OGGZ_WRITE) {
     if (OGGZ_CONFIG_WRITE) {
 
       return _oggz_comment_set_vendor (oggz, serialno, vendor_string);
 
     } else {
       return OGGZ_ERR_DISABLED;
@@ -372,17 +333,20 @@ int
 oggz_comment_add (OGGZ * oggz, long serialno, const OggzComment * comment)
 {
   oggz_stream_t * stream;
   OggzComment * new_comment;
 
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
 
   stream = oggz_get_stream (oggz, serialno);
-  if (stream == NULL) stream = oggz_add_stream (oggz, serialno);
+  if (stream == NULL)
+    stream = oggz_add_stream (oggz, serialno);
+  if (stream == NULL)
+    return OGGZ_ERR_OUT_OF_MEMORY;
 
   if (oggz->flags & OGGZ_WRITE) {
     if (OGGZ_CONFIG_WRITE) {
 
       if (!oggz_comment_validate_byname (comment->name, comment->value))
         return OGGZ_ERR_COMMENT_INVALID;
 
       new_comment = oggz_comment_new (comment->name, comment->value);
@@ -403,17 +367,20 @@ oggz_comment_add_byname (OGGZ * oggz, lo
                          const char * name, const char * value)
 {
   oggz_stream_t * stream;
   OggzComment * new_comment;
 
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
 
   stream = oggz_get_stream (oggz, serialno);
-  if (stream == NULL) stream = oggz_add_stream (oggz, serialno);
+  if (stream == NULL)
+    stream = oggz_add_stream (oggz, serialno);
+  if (stream == NULL)
+    return OGGZ_ERR_OUT_OF_MEMORY;
 
   if (oggz->flags & OGGZ_WRITE) {
     if (OGGZ_CONFIG_WRITE) {
 
       if (!oggz_comment_validate_byname (name, value))
         return OGGZ_ERR_COMMENT_INVALID;
 
       new_comment = oggz_comment_new (name, value);
@@ -518,16 +485,18 @@ oggz_comments_copy (OGGZ * src, long src
 }
 
 /* Internal API */
 int
 oggz_comments_init (oggz_stream_t * stream)
 {
   stream->vendor = NULL;
   stream->comments = oggz_vector_new ();
+  if (stream->comments == NULL) return -1;
+
   oggz_vector_set_cmp (stream->comments, (OggzCmpFunc) oggz_comment_cmp, NULL);
 
   return 0;
 }
 
 int
 oggz_comments_free (oggz_stream_t * stream)
 {
@@ -774,21 +743,21 @@ oggz_comment_generate(OGGZ * oggz, long 
   }
 
   buf_size = preamble_length + comment_length;
 
   if(packet_type == OGGZ_CONTENT_FLAC && comment_length >= 0x00ffffff) {
     return NULL;
   }
 
-  c_packet = malloc(sizeof *c_packet);
+  c_packet = oggz_malloc(sizeof *c_packet);
   if(c_packet) {
     memset(c_packet, 0, sizeof *c_packet);
     c_packet->packetno = 1;
-    c_packet->packet = malloc(buf_size);
+    c_packet->packet = oggz_malloc(buf_size);
   }
 
   if(c_packet && c_packet->packet) {
     buffer = c_packet->packet;
     if(preamble_length) {
       memcpy(buffer, preamble, preamble_length);
       if(packet_type == OGGZ_CONTENT_FLAC) {
 	/* Use comment_length-1 as we will be stripping the Vorbis
@@ -806,17 +775,17 @@ oggz_comment_generate(OGGZ * oggz, long 
     c_packet->bytes = buf_size;
     /* The framing byte for Vorbis shouldn't affect any of the other
        types, but strip it anyway. */
     if(packet_type != OGGZ_CONTENT_VORBIS)
       {
 	c_packet->bytes -= 1;
       }
   } else {
-    free(c_packet);
+    oggz_free(c_packet);
     c_packet = 0;
   }
 
   return c_packet;
 }
 
 /* In Flac, OggPCM, Speex, Theora Vorbis, and Kate the comment packet will
    be second in the stream, i.e. packetno=1, and it will have granulepos=0 */
@@ -831,14 +800,14 @@ oggz_comments_generate(OGGZ * oggz, long
   return oggz_comment_generate (oggz, serialno, packet_type,
                                 FLAC_final_metadata_block);
 }
 
 void oggz_packet_destroy(ogg_packet *packet) {
   if(packet) {
     if(packet->packet)
       {
-	free(packet->packet);
+	oggz_free(packet->packet);
       }
-    free(packet);
+    oggz_free(packet);
   }
   return;
 }
--- a/media/liboggz/src/liboggz/oggz_dlist.c
+++ b/media/liboggz/src/liboggz/oggz_dlist.c
@@ -33,91 +33,118 @@
 #ifdef WIN32
 #include "config_win32.h"
 #else
 #include "config.h"
 #endif
 #include <stdlib.h>
 
 #include "oggz_dlist.h"
+#include "oggz_macros.h"
 
 typedef struct OggzDListElem {
   struct OggzDListElem  * next;
   struct OggzDListElem  * prev;
   void                  * data;
 } OggzDListElem;
 
 struct _OggzDList {
   OggzDListElem * head;
   OggzDListElem * tail;
 };
 
 OggzDList *
 oggz_dlist_new (void) {
 
-  OggzDList *dlist = malloc(sizeof(OggzDList));
+  OggzDList *dlist;
+  OggzDListElem *dummy_front, *dummy_back;
+  
+  dlist = oggz_malloc(sizeof(OggzDList));
+  if (dlist == NULL) return NULL;
 
-  OggzDListElem * dummy_front = malloc(sizeof(OggzDListElem));
-  OggzDListElem * dummy_back = malloc(sizeof(OggzDListElem));
-  
+  dummy_front = oggz_malloc(sizeof(OggzDListElem));
+  if (dummy_front == NULL) {
+    oggz_free (dlist);
+    return NULL;
+  }
+
+  dummy_back = oggz_malloc(sizeof(OggzDListElem));
+  if (dummy_back == NULL) {
+    oggz_free (dummy_front);
+    oggz_free (dlist);
+    return NULL;
+  }
+
   dummy_front->next = dummy_back;
   dummy_front->prev = NULL;
 
   dummy_back->prev = dummy_front;
   dummy_back->next = NULL;
 
   dlist->head = dummy_front;
   dlist->tail = dummy_back;
 
   return dlist;
-
 }
 
 void
 oggz_dlist_delete(OggzDList *dlist) {
 
   OggzDListElem *p;
 
   for (p = dlist->head->next; p != NULL; p = p->next) {
-    free(p->prev);
+    oggz_free(p->prev);
   }
 
-  free(dlist->tail);
-  free(dlist);
+  oggz_free(dlist->tail);
+  oggz_free(dlist);
 
 }
 
 int
 oggz_dlist_is_empty(OggzDList *dlist) {
   return (dlist->head->next == dlist->tail);
 }
 
-void
+int
 oggz_dlist_append(OggzDList *dlist, void *elem) {
 
-  OggzDListElem *new_elem = malloc(sizeof(OggzDListElem));
+  OggzDListElem *new_elem;
+
+  if (dlist == NULL) return -1;
+
+  new_elem = oggz_malloc(sizeof(OggzDListElem));
+  if (new_elem == NULL) return -1;
 
   new_elem->data = elem;
   new_elem->next = dlist->tail;
   new_elem->prev = dlist->tail->prev;
   new_elem->prev->next = new_elem;
   new_elem->next->prev = new_elem;
+
+  return 0;
 }
 
-void
+int
 oggz_dlist_prepend(OggzDList *dlist, void *elem) {
 
-  OggzDListElem *new_elem = malloc(sizeof(OggzDListElem));
+  OggzDListElem *new_elem;
+
+  if (dlist == NULL) return -1;
+
+  new_elem = oggz_malloc(sizeof(OggzDListElem));
+  if (new_elem == NULL) return -1;
 
   new_elem->data = elem;
   new_elem->prev = dlist->head;
   new_elem->next = dlist->head->next;
   new_elem->prev->next = new_elem;
   new_elem->next->prev = new_elem;
 
+  return 0;
 }
 
 void
 oggz_dlist_iter(OggzDList *dlist, OggzDListIterFunc func) {
 
   OggzDListElem *p;
 
   for (p = dlist->head->next; p != dlist->tail; p = p->next) {
@@ -149,17 +176,17 @@ oggz_dlist_deliter(OggzDList *dlist, Ogg
     if (func(p->data) == DLIST_ITER_CANCEL) {
       break;
     }
 
     q = p->next;
     p->prev->next = p->next;
     p->next->prev = p->prev;
 
-    free(p);
+    oggz_free(p);
   }
 
 }
 
 void
 oggz_dlist_reverse_deliter(OggzDList *dlist, OggzDListIterFunc func) {
 
   OggzDListElem *p, *q;
@@ -168,12 +195,12 @@ oggz_dlist_reverse_deliter(OggzDList *dl
     if (func(p->data) == DLIST_ITER_CANCEL) {
       break;
     }
 
     q = p->prev;
     p->prev->next = p->next;
     p->next->prev = p->prev;
 
-    free(p);
+    oggz_free(p);
   }
 
 }
--- a/media/liboggz/src/liboggz/oggz_dlist.h
+++ b/media/liboggz/src/liboggz/oggz_dlist.h
@@ -44,20 +44,20 @@ OggzDList *
 oggz_dlist_new (void);
 
 void
 oggz_dlist_delete(OggzDList *dlist);
 
 int
 oggz_dlist_is_empty(OggzDList *dlist);
 
-void
+int
 oggz_dlist_append(OggzDList *dlist, void *elem);
 
-void
+int
 oggz_dlist_prepend(OggzDList *dlist, void *elem);
 
 void
 oggz_dlist_iter(OggzDList *dlist, OggzDListIterFunc func);
 
 void
 oggz_dlist_reverse_iter(OggzDList *dlist, OggzDListIterFunc func);
 
--- a/media/liboggz/src/liboggz/oggz_io.c
+++ b/media/liboggz/src/liboggz/oggz_io.c
@@ -175,30 +175,37 @@ oggz_io_flush (OGGZ * oggz)
 
   else return OGGZ_ERR_INVALID;
 
   return 0;
 }
 
 /* get/set functions */
 
-static void
+static int
 oggz_io_init (OGGZ * oggz)
 {
   oggz->io = (OggzIO *) oggz_malloc (sizeof (OggzIO));
+  if (oggz->io == NULL) return -1;
+
   memset (oggz->io, 0, sizeof (OggzIO));
+
+  return 0;
 }
 
 int
 oggz_io_set_read (OGGZ * oggz, OggzIORead read, void * user_handle)
 {
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
   if (oggz->file != NULL) return OGGZ_ERR_INVALID;
 
-  if (oggz->io == NULL) oggz_io_init (oggz);
+  if (oggz->io == NULL) {
+    if (oggz_io_init (oggz) == -1)
+      return OGGZ_ERR_OUT_OF_MEMORY;
+  }
 
   oggz->io->read = read;
   oggz->io->read_user_handle = user_handle;
 
   return 0;
 }
 
 void *
@@ -213,17 +220,20 @@ oggz_io_get_read_user_handle (OGGZ * ogg
 }
 
 int
 oggz_io_set_write (OGGZ * oggz, OggzIOWrite write, void * user_handle)
 {
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
   if (oggz->file != NULL) return OGGZ_ERR_INVALID;
 
-  if (oggz->io == NULL) oggz_io_init (oggz);
+  if (oggz->io == NULL) {
+    if (oggz_io_init (oggz) == -1)
+      return OGGZ_ERR_OUT_OF_MEMORY;
+  }
 
   oggz->io->write = write;
   oggz->io->write_user_handle = user_handle;
 
   return 0;
 }
 
 void *
@@ -238,17 +248,20 @@ oggz_io_get_write_user_handle (OGGZ * og
 }
 
 int
 oggz_io_set_seek (OGGZ * oggz, OggzIOSeek seek, void * user_handle)
 {
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
   if (oggz->file != NULL) return OGGZ_ERR_INVALID;
 
-  if (oggz->io == NULL) oggz_io_init (oggz);
+  if (oggz->io == NULL) {
+    if (oggz_io_init (oggz) == -1)
+      return OGGZ_ERR_OUT_OF_MEMORY;
+  }
 
   oggz->io->seek = seek;
   oggz->io->seek_user_handle = user_handle;
 
   return 0;
 }
 
 void *
@@ -263,17 +276,20 @@ oggz_io_get_seek_user_handle (OGGZ * ogg
 }
 
 int
 oggz_io_set_tell (OGGZ * oggz, OggzIOTell tell, void * user_handle)
 {
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
   if (oggz->file != NULL) return OGGZ_ERR_INVALID;
 
-  if (oggz->io == NULL) oggz_io_init (oggz);
+  if (oggz->io == NULL) {
+    if (oggz_io_init (oggz) == -1)
+      return OGGZ_ERR_OUT_OF_MEMORY;
+  }
 
   oggz->io->tell = tell;
   oggz->io->tell_user_handle = user_handle;
 
   return 0;
 }
 
 void *
@@ -288,17 +304,20 @@ oggz_io_get_tell_user_handle (OGGZ * ogg
 }
 
 int
 oggz_io_set_flush (OGGZ * oggz, OggzIOFlush flush, void * user_handle)
 {
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
   if (oggz->file != NULL) return OGGZ_ERR_INVALID;
 
-  if (oggz->io == NULL) oggz_io_init (oggz);
+  if (oggz->io == NULL) {
+    if (oggz_io_init (oggz) == -1)
+      return OGGZ_ERR_OUT_OF_MEMORY;
+  }
 
   oggz->io->flush = flush;
   oggz->io->flush_user_handle = user_handle;
 
   return 0;
 }
 
 void *
--- a/media/liboggz/src/liboggz/oggz_private.h
+++ b/media/liboggz/src/liboggz/oggz_private.h
@@ -39,16 +39,18 @@
 #include <ogg/ogg.h>
 #include <oggz/oggz_constants.h>
 #include <oggz/oggz_off_t.h>
 
 #include "oggz_macros.h"
 #include "oggz_vector.h"
 #include "oggz_dlist.h"
 
+#define OGGZ_AUTO_MULT 1000Ull
+
 typedef struct _OGGZ OGGZ;
 typedef struct _OggzComment OggzComment;
 typedef struct _OggzIO OggzIO;
 typedef struct _OggzReader OggzReader;
 typedef struct _OggzWriter OggzWriter;
 
 
 typedef int (*OggzReadPacket) (OGGZ * oggz, ogg_packet * op, long serialno,
@@ -272,23 +274,28 @@ oggz_set_granulerate (OGGZ * oggz, long 
                                     ogg_int64_t granule_rate_denominator);
 
 int
 oggz_get_granulerate (OGGZ * oggz, long serialno,
                                     ogg_int64_t * granulerate_n,
                                     ogg_int64_t * granulerate_d);
 
 int oggz_set_granuleshift (OGGZ * oggz, long serialno, int granuleshift);
+int oggz_get_granuleshift (OGGZ * oggz, long serialno);
 
-int oggz_get_granuleshift (OGGZ * oggz, long serialno);
+int oggz_set_preroll (OGGZ * oggz, long serialno, int preroll);
+int oggz_get_preroll (OGGZ * oggz, long serialno);
 
 /* oggz_auto */
  
 int
-oggz_auto_get_granulerate (OGGZ * oggz, ogg_packet * op, long serialno, 
+oggz_auto_read_bos_page (OGGZ * oggz, ogg_page * og, long serialno,
+                         void * user_data);
+int
+oggz_auto_read_bos_packet (OGGZ * oggz, ogg_packet * op, long serialno, 
                            void * user_data);
 
 int
 oggz_auto_read_comments (OGGZ * oggz, oggz_stream_t * stream, long serialno,
                          ogg_packet * op);
 
 int oggz_auto_identify_page (OGGZ *oggz, ogg_page *og, long serialno);
 int oggz_auto_identify_packet (OGGZ * oggz, ogg_packet * op, long serialno);
--- a/media/liboggz/src/liboggz/oggz_read.c
+++ b/media/liboggz/src/liboggz/oggz_read.c
@@ -119,22 +119,20 @@ oggz_set_read_callback (OGGZ * oggz, lon
     return OGGZ_ERR_INVALID;
   }
 
   if (serialno == -1) {
     reader->read_packet = read_packet;
     reader->read_user_data = user_data;
   } else {
     stream = oggz_get_stream (oggz, serialno);
-#if 0
-    if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
-#else
     if (stream == NULL)
       stream = oggz_add_stream (oggz, serialno);
-#endif
+    if (stream == NULL)
+      return OGGZ_ERR_OUT_OF_MEMORY;
 
     stream->read_packet = read_packet;
     stream->read_user_data = user_data;
   }
 
   return 0;
 }
 
@@ -153,75 +151,53 @@ oggz_set_read_page (OGGZ * oggz, long se
     return OGGZ_ERR_INVALID;
   }
 
   if (serialno == -1) {
     reader->read_page = read_page;
     reader->read_page_user_data = user_data;
   } else {
     stream = oggz_get_stream (oggz, serialno);
-#if 0
-    if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
-#else
     if (stream == NULL)
       stream = oggz_add_stream (oggz, serialno);
-#endif
+    if (stream == NULL)
+      return OGGZ_ERR_OUT_OF_MEMORY;
 
     stream->read_page = read_page;
     stream->read_page_user_data = user_data;
   }
 
   return 0;
 }
 
 /*
- * oggz_get_next_page_7 (oggz, og, do_read)
+ * oggz_read_get_next_page (oggz, og, do_read)
  *
- * MODIFIED COPY OF CODE FROM BELOW SEEKING STUFF
+ * This differs from oggz_get_next_page() in oggz_seek.c in that it
+ * does not attempt to call oggz_io_read() if the sync buffer is empty.
  *
  * retrieves the next page.
  * returns >= 0 if found; return value is offset of page start
  * returns -1 on error
  * returns -2 if EOF was encountered
  */
 static oggz_off_t
-oggz_get_next_page_7 (OGGZ * oggz, ogg_page * og)
+oggz_read_get_next_page (OGGZ * oggz, ogg_page * og)
 {
   OggzReader * reader = &oggz->x.reader;
-#if _UNMODIFIED
-  char * buffer;
-#endif
   long bytes = 0, more;
   oggz_off_t page_offset = 0, ret;
   int found = 0;
 
   do {
     more = ogg_sync_pageseek (&reader->ogg_sync, og);
 
     if (more == 0) {
       page_offset = 0;
-#if _UMMODIFIED_
-      buffer = ogg_sync_buffer (&reader->ogg_sync, CHUNKSIZE);
-      if ((bytes = oggz_io_read (oggz, buffer, CHUNKSIZE)) == 0) {
-#if 0
-  if (ferror (oggz->file)) {
-    oggz_set_error (oggz, OGGZ_ERR_SYSTEM);
-    return -1;
-  }
-#endif
-      }
-
-      if (bytes == 0) {
-        return -2;
-      }
-
-      ogg_sync_wrote(&reader->ogg_sync, bytes);
-#else
       return -2;
-#endif
     } else if (more < 0) {
 #ifdef DEBUG_VERBOSE
       printf ("get_next_page: skipped %ld bytes\n", -more);
 #endif
       page_offset -= more;
     } else {
 #ifdef DEBUG_VERBOSE
       printf ("get_next_page: page has %ld bytes\n", more);
@@ -253,35 +229,37 @@ typedef struct {
   long            serialno;
 } OggzBufferedPacket;
 
 OggzBufferedPacket *
 oggz_read_new_pbuffer_entry(OGGZ *oggz, ogg_packet *packet, 
             ogg_int64_t granulepos, long serialno, oggz_stream_t * stream, 
             OggzReader *reader) {
 
-  OggzBufferedPacket *p = malloc(sizeof(OggzBufferedPacket));
+  OggzBufferedPacket *p = oggz_malloc(sizeof(OggzBufferedPacket));
+  if (p == NULL) return NULL;
+
   memcpy(&(p->packet), packet, sizeof(ogg_packet));
-  p->packet.packet = malloc(packet->bytes);
+  p->packet.packet = oggz_malloc(packet->bytes);
   memcpy(p->packet.packet, packet->packet, packet->bytes);
 
   p->calced_granulepos = granulepos;
   p->stream = stream;
   p->serialno = serialno;
   p->reader = reader;
   p->oggz = oggz;
 
   return p;
 }
 
 void
 oggz_read_free_pbuffer_entry(OggzBufferedPacket *p) {
   
-  free(p->packet.packet);
-  free(p);
+  oggz_free(p->packet.packet);
+  oggz_free(p);
 
 }
 
 OggzDListIterResponse
 oggz_read_update_gp(void *elem) {
 
   OggzBufferedPacket *p = (OggzBufferedPacket *)elem;
 
@@ -366,40 +344,46 @@ oggz_read_sync (OGGZ * oggz)
         serialno = reader->current_serialno;
 
         stream = oggz_get_stream (oggz, serialno);
 
         if (stream == NULL) {
           /* new stream ... check bos etc. */
           if ((stream = oggz_add_stream (oggz, serialno)) == NULL) {
             /* error -- could not add stream */
-            return -7;
+            return OGGZ_ERR_OUT_OF_MEMORY;
           }
         }
         os = &stream->ogg_stream;
 
         result = ogg_stream_packetout(os, op);
 
+        /*
+         * libogg flags "holes in the data" (which are really inconsistencies
+         * in the page sequence number) by returning -1.
+         */
         if(result == -1) {
 #ifdef DEBUG
           printf ("oggz_read_sync: hole in the data\n");
 #endif
+          /* We can't tolerate holes in headers, so bail out. */
+          if (stream->packetno < 3) return OGGZ_ERR_HOLE_IN_DATA;
+
+          /* Holes in content occur in some files and pretty much don't matter,
+           * so we silently swallow the notification and reget the packet.
+           */
           result = ogg_stream_packetout(os, op);
           if (result == -1) {
+            /* If the result is *still* -1 then something strange is
+             * happening.
+             */
 #ifdef DEBUG
-            /*
-             * libogg flags "holes in the data" (which are really 
-             * inconsistencies in the page sequence number) by returning
-             * -1.  This occurs in some files and pretty much doesn't matter,
-             *  so we silently swallow the notification and reget the packet.
-             *  If the result is *still* -1 then something strange is happening.
-             */
-            printf ("shouldn't get here");
+            printf ("Multiple holes in data!");
 #endif
-            return -7;
+            return OGGZ_ERR_HOLE_IN_DATA;
           }
         }
 
         if(result > 0){
           int content;
 
           stream->packetno++;
           
@@ -413,17 +397,17 @@ oggz_read_sync (OGGZ * oggz)
            */      
           if 
           (
             (!stream->metric || (content == OGGZ_CONTENT_SKELETON)) 
             && 
             (oggz->flags & OGGZ_AUTO)
           ) 
           {
-            oggz_auto_get_granulerate (oggz, op, serialno, NULL);
+            oggz_auto_read_bos_packet (oggz, op, serialno, NULL);
           }
 
           /* attempt to determine granulepos for this packet */
           if (oggz->flags & OGGZ_AUTO) {
             reader->current_granulepos = 
               oggz_auto_calculate_granulepos (content, granulepos, stream, op); 
             /* make sure that we accept any "real" gaps in the granulepos
              */
@@ -506,33 +490,37 @@ oggz_read_sync (OGGZ * oggz)
         else
           break;
       }
     }
 
     /* If we've got a stop already, don't read more data in */
     if (cb_ret == OGGZ_STOP_OK || cb_ret == OGGZ_STOP_ERR) return cb_ret;
 
-    if(oggz_get_next_page_7 (oggz, &og) < 0)
+    if(oggz_read_get_next_page (oggz, &og) < 0)
       return OGGZ_READ_EMPTY; /* eof. leave uninitialized */
 
     serialno = ogg_page_serialno (&og);
     reader->current_serialno = serialno; /* XXX: maybe not necessary */
 
     stream = oggz_get_stream (oggz, serialno);
 
     if (stream == NULL) {
       /* new stream ... check bos etc. */
       if ((stream = oggz_add_stream (oggz, serialno)) == NULL) {
         /* error -- could not add stream */
-        return -7;
+        return OGGZ_ERR_OUT_OF_MEMORY;
       }
 
       /* identify stream type */
       oggz_auto_identify_page (oggz, &og, serialno);
+
+      /* read bos data */
+      if (oggz->flags & OGGZ_AUTO)
+        oggz_auto_read_bos_page (oggz, &og, serialno, NULL);
     }
     else if (oggz_stream_get_content(oggz, serialno) == OGGZ_CONTENT_ANXDATA)
     {
       /*
        * re-identify ANXDATA streams as these are now content streams
        */
       oggz_auto_identify_page (oggz, &og, serialno);
     }
@@ -555,22 +543,16 @@ oggz_read_sync (OGGZ * oggz)
     if (stream->read_page) {
       cb_ret =
         stream->read_page (oggz, &og, serialno, stream->read_page_user_data);
     } else if (reader->read_page) {
       cb_ret =
         reader->read_page (oggz, &og, serialno, reader->read_page_user_data);
     }
 
-#if 0
-    /* bitrate tracking; add the header's bytes here, the body bytes
-       are done by packet above */
-    vf->bittrack+=og.header_len*8;
-#endif
-
     ogg_stream_pagein(os, &og);
   }
 
   return cb_ret;
 }
 
 long
 oggz_read (OGGZ * oggz, long n)
@@ -589,49 +571,37 @@ oggz_read (OGGZ * oggz, long n)
   if ((cb_ret = oggz->cb_next) != OGGZ_CONTINUE) {
     oggz->cb_next = 0;
     return oggz_map_return_value_to_error (cb_ret);
   }
 
   reader = &oggz->x.reader;
 
   cb_ret = oggz_read_sync (oggz);
-
-#if 0
-  if (cb_ret == OGGZ_READ_EMPTY) {
-    /* If there's nothing to read yet, don't return 0 (eof) */
-    if (reader->current_unit == 0) cb_ret = 0;
-    else {
-#if 0
-      printf ("oggz_read: EMPTY, current_unit %ld != 0\n",
-              reader->current_unit);
-      return 0;
-#endif
-    }
-  }
-#endif
+  if (cb_ret == OGGZ_ERR_OUT_OF_MEMORY)
+    return cb_ret;
 
   while (cb_ret != OGGZ_STOP_ERR && cb_ret != OGGZ_STOP_OK &&
          bytes_read > 0 && remaining > 0) {
     bytes = MIN (remaining, CHUNKSIZE);
     buffer = ogg_sync_buffer (&reader->ogg_sync, bytes);
-    if ((bytes_read = (long) oggz_io_read (oggz, buffer, bytes)) == 0) {
-      /* schyeah! */
-    }
+    bytes_read = (long) oggz_io_read (oggz, buffer, bytes);
     if (bytes_read == OGGZ_ERR_SYSTEM) {
       return OGGZ_ERR_SYSTEM;
     }
 
     if (bytes_read > 0) {
       ogg_sync_wrote (&reader->ogg_sync, bytes_read);
       
       remaining -= bytes_read;
       nread += bytes_read;
       
       cb_ret = oggz_read_sync (oggz);
+      if (cb_ret == OGGZ_ERR_OUT_OF_MEMORY)
+        return cb_ret;
     }
   }
 
   if (cb_ret == OGGZ_STOP_ERR) oggz_purge (oggz);
 
   /* Don't return 0 unless it's actually an EOF condition */
   if (nread == 0) {
     switch (bytes_read) {
@@ -673,37 +643,33 @@ oggz_read_input (OGGZ * oggz, unsigned c
   if ((cb_ret = oggz->cb_next) != OGGZ_CONTINUE) {
     oggz->cb_next = 0;
     return oggz_map_return_value_to_error (cb_ret);
   }
 
   reader = &oggz->x.reader;
 
   cb_ret = oggz_read_sync (oggz);
-
-#if 0
-  if (cb_ret == OGGZ_READ_EMPTY) {
-    /* If there's nothing to read yet, don't return 0 (eof) */
-    if (reader->current_unit == 0) cb_ret = 0;
-    else return 0;
-  }
-#endif
+  if (cb_ret == OGGZ_ERR_OUT_OF_MEMORY)
+    return cb_ret;
 
   while (cb_ret != OGGZ_STOP_ERR && cb_ret != OGGZ_STOP_OK  &&
          /* !oggz->eos && */ remaining > 0) {
     bytes = MIN (remaining, 4096);
     buffer = ogg_sync_buffer (&reader->ogg_sync, bytes);
     memcpy (buffer, buf, bytes);
     ogg_sync_wrote (&reader->ogg_sync, bytes);
 
     buf += bytes;
     remaining -= bytes;
     nread += bytes;
 
     cb_ret = oggz_read_sync (oggz);
+    if (cb_ret == OGGZ_ERR_OUT_OF_MEMORY)
+      return cb_ret;
   }
 
   if (cb_ret == OGGZ_STOP_ERR) oggz_purge (oggz);
 
   if (nread == 0) {
     /* Don't return 0 unless it's actually an EOF condition */
     if (cb_ret == OGGZ_READ_EMPTY) {
       return OGGZ_ERR_STOP_OK;
--- a/media/liboggz/src/liboggz/oggz_seek.c
+++ b/media/liboggz/src/liboggz/oggz_seek.c
@@ -229,24 +229,16 @@ oggz_get_next_page (OGGZ * oggz, ogg_pag
 	  return -1;
       }
 
       if (bytes == 0) {
 #ifdef DEBUG_VERBOSE
 	printf ("get_next_page: bytes == 0, returning -2\n");
 #endif
 	return -2;
-#if 0
-      } else if (oggz->file && feof (oggz->file)) {
-#ifdef DEBUG_VERBOSE
-	printf ("get_next_page: feof (oggz->file), returning -2\n");
-#endif
-	clearerr (oggz->file);
-	return -2;
-#endif
       }
 
       ogg_sync_wrote(&reader->ogg_sync, bytes);
 
     } else if (more < 0) {
 #ifdef DEBUG_VERBOSE
       printf ("get_next_page: skipped %ld bytes\n", -more);
 #endif
@@ -627,17 +619,17 @@ oggz_offset_end (OGGZ * oggz)
   }
 
   return offset_end;
 }
 
 static ogg_int64_t
 oggz_seek_set (OGGZ * oggz, ogg_int64_t unit_target)
 {
-  OggzReader * reader = &oggz->x.reader;
+  OggzReader * reader;
   oggz_off_t offset_orig, offset_at, offset_guess;
   oggz_off_t offset_begin, offset_end = -1, offset_next;
   ogg_int64_t granule_at;
   ogg_int64_t unit_at, unit_begin = 0, unit_end = -1, unit_last_iter = -1;
   long serialno;
   ogg_page * og;
   int hit_eof = 0;
 
@@ -654,16 +646,18 @@ oggz_seek_set (OGGZ * oggz, ogg_int64_t 
 
   if ((offset_end = oggz_offset_end (oggz)) == -1) {
 #ifdef DEBUG
     printf ("oggz_seek_set: oggz_offset_end == -1, FAIL\n");
 #endif
     return -1;
   }
 
+  reader = &oggz->x.reader;
+
   if (unit_target == reader->current_unit) {
 #ifdef DEBUG
     printf ("oggz_seek_set: unit_target == reader->current_unit, SKIP\n");
 #endif
     return (long)reader->current_unit;
   }
 
   if (unit_target == 0) {
@@ -838,39 +832,41 @@ oggz_seek_end (OGGZ * oggz, ogg_int64_t 
 #endif
 
   return oggz_seek_set (oggz, unit_end + unit_offset);
 }
 
 off_t
 oggz_seek (OGGZ * oggz, oggz_off_t offset, int whence)
 {
-  OggzReader * reader = &oggz->x.reader;
+  OggzReader * reader;
   ogg_int64_t units = -1;
 
   if (oggz == NULL) return -1;
 
   if (oggz->flags & OGGZ_WRITE) {
     return -1;
   }
 
   if (offset == 0 && whence == SEEK_SET) units = 0;
-  
+
+  reader = &oggz->x.reader;
+
   if (!(offset == 0 && whence == SEEK_CUR)) {
     /* Invalidate current_unit */
     reader->current_unit = -1;
   }
 
   return (off_t)oggz_reset (oggz, offset, units, whence);
 }
 
 ogg_int64_t
 oggz_seek_units (OGGZ * oggz, ogg_int64_t units, int whence)
 {
-  OggzReader * reader = &oggz->x.reader;
+  OggzReader * reader;
 
   ogg_int64_t r;
 
   if (oggz == NULL) {
 #ifdef DEBUG
     printf ("oggz_seek_units: oggz NULL, FAIL\n");
 #endif
     return -1;
@@ -885,16 +881,18 @@ oggz_seek_units (OGGZ * oggz, ogg_int64_
 
   if (!oggz_has_metrics (oggz)) {
 #ifdef DEBUG
     printf ("oggz_seek_units: !has_metrics, FAIL\n");
 #endif
     return -1;
   }
 
+  reader = &oggz->x.reader;
+
   switch (whence) {
   case SEEK_SET:
     r = oggz_seek_set (oggz, units);
     break;
   case SEEK_CUR:
     units += reader->current_unit;
     r = oggz_seek_set (oggz, units);
     break;
--- a/media/liboggz/src/liboggz/oggz_stream.c
+++ b/media/liboggz/src/liboggz/oggz_stream.c
@@ -85,8 +85,35 @@ oggz_stream_get_numheaders (OGGZ * oggz,
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
   
   stream = oggz_get_stream (oggz, serialno);
   if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
 
   return stream->numheaders;
 }
 
+int
+oggz_set_preroll (OGGZ * oggz, long serialno, int preroll)
+{
+  oggz_stream_t * stream;
+
+  if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
+
+  stream = oggz_get_stream (oggz, serialno);
+  if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
+
+  stream->preroll = preroll;
+
+  return 0;
+}
+
+int
+oggz_get_preroll (OGGZ * oggz, long serialno)
+{
+  oggz_stream_t * stream;
+
+  if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
+
+  stream = oggz_get_stream (oggz, serialno);
+  if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
+
+  return stream->preroll;
+}
--- a/media/liboggz/src/liboggz/oggz_stream_private.h
+++ b/media/liboggz/src/liboggz/oggz_stream_private.h
@@ -30,21 +30,25 @@
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #ifndef __OGGZ_STREAM_PRIVATE_H__
 #define __OGGZ_STREAM_PRIVATE_H__
 
 typedef struct _oggz_stream_t oggz_stream_t;
 
+typedef int (*OggzReadBOS) (OGGZ * oggz, long serialno,
+                            unsigned char * data, long length,
+			    void * user_data);
+
 typedef struct {
   const char      *bos_str;
   int             bos_str_len;
   const char      *content_type;
-  OggzReadPacket  reader;
+  OggzReadBOS     reader;
   ogg_int64_t     (*calculator)(ogg_int64_t now, oggz_stream_t *stream, 
                   ogg_packet *op);
   ogg_int64_t     (*r_calculator)(ogg_int64_t next_packet_gp, 
                   oggz_stream_t *stream, ogg_packet *this_packet, 
                   ogg_packet *next_packet);
 } oggz_auto_contenttype_t;
 
 extern const oggz_auto_contenttype_t oggz_auto_codec_ident[];
--- a/media/liboggz/src/liboggz/oggz_table.c
+++ b/media/liboggz/src/liboggz/oggz_table.c
@@ -48,16 +48,18 @@ struct _OggzTable {
 };
 
 OggzTable *
 oggz_table_new (void)
 {
   OggzTable * table;
 
   table = oggz_malloc (sizeof (OggzTable));
+  if (table == NULL) return NULL;
+
   table->keys = oggz_vector_new ();
   table->data = oggz_vector_new ();
 
   return table;
 }
 
 void
 oggz_table_delete (OggzTable * table)
@@ -69,16 +71,18 @@ oggz_table_delete (OggzTable * table)
   oggz_free (table);
 }
 
 void *
 oggz_table_lookup (OggzTable * table, long key)
 {
   int i, size;
 
+  if (table == NULL) return NULL;
+
   size = oggz_vector_size (table->keys);
   for (i = 0; i < size; i++) {
     if (oggz_vector_nth_l (table->keys, i) == key) {
       return oggz_vector_nth_p (table->data, i);
     }
   }
 
   return NULL;
--- a/media/liboggz/src/liboggz/oggz_vector.c
+++ b/media/liboggz/src/liboggz/oggz_vector.c
@@ -77,16 +77,17 @@ struct _OggzVector {
  */
 
 OggzVector *
 oggz_vector_new (void)
 {
   OggzVector * vector;
 
   vector = oggz_malloc (sizeof (OggzVector));
+  if (vector == NULL) return NULL;
 
   vector->max_elements = 0;
   vector->nr_elements = 0;
   vector->data = NULL;
   vector->compare = NULL;
   vector->compare_user_data = NULL;
 
   return vector;
@@ -265,17 +266,16 @@ oggz_vector_grow (OggzVector * vector)
       new_max_elements = vector->max_elements * 2;
     }
 
     new_elements =
       oggz_realloc (vector->data, (size_t)new_max_elements * sizeof (oggz_data_t));
 
     if (new_elements == NULL) {
       vector->nr_elements--;
-      vector->data = NULL;
       return NULL;
     }
 
     vector->max_elements = new_max_elements;
     vector->data = new_elements;
   }
 
   return vector;
@@ -358,18 +358,17 @@ oggz_vector_remove_nth (OggzVector * vec
 
     if (vector->nr_elements < vector->max_elements/2) {
       new_max_elements = vector->max_elements/2;
 
       new_elements =
         oggz_realloc (vector->data,
         (size_t)new_max_elements * sizeof (oggz_data_t));
 
-      if (new_elements == NULL)
-      {
+      if (new_elements == NULL) {
         vector->data = NULL;
         return NULL;
       }
 
       vector->max_elements = new_max_elements;
       vector->data = new_elements;
     }
   }
@@ -404,57 +403,18 @@ oggz_vector_remove_l (OggzVector * vecto
 
   return vector;
 }
 
 void *
 oggz_vector_pop (OggzVector * vector)
 {
   void * data;
-#if 0
-  void * new_elements;
-  int new_max_elements;
-#endif
 
-  if (!vector || vector->data == NULL) return NULL;
+  if (vector == NULL || vector->data == NULL) return NULL;
 
   data = vector->data[0].p;
 
-#if 0
-  vector->nr_elements--;
-
-  if (vector->nr_elements == 0) {
-    oggz_vector_clear (vector);
-  } else {
-#if 0
-    memmove (vector->data, &vector->data[1],
-	     vector->nr_elements * sizeof (void *));
-#else
-    {
-      int i;
-      for (i = 0; i < vector->nr_elements; i++) {
-	vector->data[i].p = vector->data[i+1].p;
-      }
-    }
-#endif
-    if (vector->nr_elements < vector->max_elements/2) {
-      new_max_elements = vector->max_elements/2;
-
-      new_elements =
-        oggz_realloc (vector->data,
-        (size_t)new_max_elements * sizeof (oggz_data_t));
-
-      if (new_elements != NULL) {
-        vector->max_elements = new_max_elements;
-        vector->data = new_elements;
-      }
-    }
-
-  }
-#else
-
   oggz_vector_remove_nth (vector, 0);
 
-#endif
-
   return data;
 
 }
--- a/media/liboggz/src/liboggz/oggz_vector.h
+++ b/media/liboggz/src/liboggz/oggz_vector.h
@@ -35,19 +35,27 @@
 
 typedef void OggzVector;
 
 typedef int (*OggzFunc) (void * data);
 typedef int (*OggzFunc1) (void * data, void *arg);
 typedef int (*OggzFindFunc) (void * data, long serialno);
 typedef int (*OggzCmpFunc) (const void * a, const void * b, void * user_data);
 
+/**
+ * Create a new vector object.
+ * \retval a pointer to the new vector.
+ * \retval NULL on failure.
+ */
 OggzVector *
 oggz_vector_new (void);
 
+/**
+ * Destroy a vector object.
+ */
 void
 oggz_vector_delete (OggzVector * vector);
 
 void *
 oggz_vector_find_p (OggzVector * vector, const void * data);
 
 int
 oggz_vector_find_index_p (OggzVector * vector, const void * data);
@@ -56,37 +64,69 @@ void *
 oggz_vector_find_with (OggzVector * vector, OggzFindFunc func, long serialno);
 
 void *
 oggz_vector_nth_p (OggzVector * vector, int n);
 
 long
 oggz_vector_nth_l (OggzVector * vector, int n);
 
+/**
+ * Call a function on each element of a vector, in order.
+ * \param vector The OggzVector to iterate over
+ * \param func The OggzFunc to be called on each element
+ * \retval 0 on success
+ */
 int
 oggz_vector_foreach (OggzVector * vector, OggzFunc func);
 
+/**
+ * Call a function with a userdata pointer on each element
+ * of a vector, in order. This allows the function to access
+ * shared data when operating on the element sequence.
+ * \param vector The OggzVector to iterate over
+ * \param func The OggzFunc1 to be called on each element
+ * \param arg The userdata pointer to be passed to the function
+ * along with the vector member
+ * \retval 0 on success
+ */
 int
 oggz_vector_foreach1 (OggzVector * vector, OggzFunc1 func, void *arg);
 
+/**
+ * Return the number of elements in a vector.
+ * \param vector The vector to query
+ * \retval The number of elements
+ */
 int
 oggz_vector_size (OggzVector * vector);
 
 /**
  * Add an element to a vector. If the vector has a comparison function,
  * the new element is inserted in sorted order, otherwise it is appended
- * to the tail.
+ * to the tail. Use this function to add pointer elements to the vector.
+ * Use ogg_vector_insert_l for long values.
  * \param vector An OggzVector
  * \param data The new element to add
  * \retval data If the element was successfully added
  * \retval NULL If adding the element failed due to a realloc() error
  */
 void *
 oggz_vector_insert_p (OggzVector * vector, void * data);
 
+/**
+ * Add an element to a vector. If the vector has a comparison function,
+ * the new element is inserted in sorted order, otherwise it is appended
+ * to the tail. Use this function to add long value elements to the
+ * vector. Use ogg_vector_insert_p for pointer values.
+ * \param vector An OggzVector
+ * \param ldata The new element to add
+ * \retval ldata If the element was successfully added
+ * \retval -1L If adding the element failed
+ */
 long
 oggz_vector_insert_l (OggzVector * vector, long ldata);
 
 /**
  * Remove a (void *) element of a vector
  * \retval \a vector on success
  * \retval NULL on failure (realloc error)
  */
@@ -96,16 +136,35 @@ oggz_vector_remove_p (OggzVector * vecto
 /**
  * Remove a (long) element of a vector
  * \retval \a vector on success
  * \retval NULL on failure (realloc error)
  */
 OggzVector *
 oggz_vector_remove_l (OggzVector * vector, long ldata);
 
+/**
+ * Set a comparison function for a vector.
+ * Vectors can be sorted, or stored in append order, depending on
+ * whether they have a comparison function defined. When a comparison
+ * function is first set, it will be used to sort the entire vector,
+ * and subsequence insertions will maintain the sort. If no comparison
+ * function is set, new elements are appended at the end of the vector.
+ * Call oggz_vector_set_cmp(vector, NULL, NULL) to remove the current
+ * comparison function. This does not affect the member order.
+ * \param vector the vector to associate the comparison function with
+ * \param compare the OggzCmpFunc to use for comparisons
+ * \param user_data private data pointer for the compare function
+ * \retval 0 on success
+ */
 int
 oggz_vector_set_cmp (OggzVector * vector, OggzCmpFunc compare,
 		     void * user_data);
 
+/**
+ * Pop a member off a vector.
+ * \retval pointer to the popped member
+ * \retval NULL if the vector is empty
+ */
 void *
 oggz_vector_pop (OggzVector * vector);
 
 #endif /* __OGGZ_VECTOR_H__ */
--- a/media/liboggz/src/liboggz/oggz_write.c
+++ b/media/liboggz/src/liboggz/oggz_write.c
@@ -90,16 +90,17 @@ oggz_zpacket_cmp (oggz_writer_packet_t *
 OGGZ *
 oggz_write_init (OGGZ * oggz)
 {
   OggzWriter * writer = &oggz->x.writer;
 
   writer->next_zpacket = NULL;
 
   writer->packet_queue = oggz_vector_new ();
+  if (writer->packet_queue == NULL) return NULL;
 
 #ifdef ZPACKET_CMP
   /* XXX: comparison function should only kick in when a metric is set */
   oggz_vector_set_cmp (writer->packet_queue,
 		       (OggzCmpFunc)oggz_zpacket_cmp, oggz);
 #endif
 
   writer->hungry = NULL;
@@ -204,17 +205,17 @@ oggz_write_set_hungry_callback (OGGZ * o
 int
 oggz_write_feed (OGGZ * oggz, ogg_packet * op, long serialno, int flush,
 		 int * guard)
 {
   OggzWriter * writer;
   oggz_stream_t * stream;
   oggz_writer_packet_t * packet;
   ogg_packet * new_op;
-  unsigned char * new_buf;
+  unsigned char * new_buf = NULL;
   int b_o_s, e_o_s, bos_auto;
   int strict, prefix, suffix;
 
 #ifdef DEBUG
   printf ("oggz_write_feed: IN\n");
 #endif
 
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
@@ -226,23 +227,23 @@ oggz_write_feed (OGGZ * oggz, ogg_packet
   writer = &oggz->x.writer;
 
   if (guard && *guard != 0) return OGGZ_ERR_BAD_GUARD;
 
   /* Check that the serialno is in the valid range for an Ogg page header,
    * ie. that it fits within 32 bits and does not equal the special value -1 */
   if ((long)((ogg_int32_t)serialno) != serialno || serialno == -1) {
 #ifdef DEBUG
-    printf ("oggz_write_feed: serialno %010ld\n", serialno);
+    printf ("oggz_write_feed: serialno %010lu\n", serialno);
 #endif
     return OGGZ_ERR_BAD_SERIALNO;
   }
 
 #ifdef DEBUG
-  printf ("oggz_write_feed: (%010ld) FLUSH: %d\n", serialno, flush);
+  printf ("oggz_write_feed: (%010lu) FLUSH: %d\n", serialno, flush);
 #endif
 
   /* Cache strict, prefix, suffix */
   strict = !(oggz->flags & OGGZ_NONSTRICT);
   prefix = (oggz->flags & OGGZ_PREFIX);
   suffix = (oggz->flags & OGGZ_SUFFIX);
 
   /* Set bos, eos to canonical values */
@@ -255,32 +256,36 @@ oggz_write_feed (OGGZ * oggz, ogg_packet
     if (bos_auto) b_o_s = 1;
 
     if (strict && b_o_s && !oggz_get_bos (oggz, -1)) {
 	return OGGZ_ERR_BOS;
     }
 
     if (b_o_s || !strict || suffix) {
       stream = oggz_add_stream (oggz, serialno);
+      if (stream == NULL)
+        return OGGZ_ERR_OUT_OF_MEMORY;
       oggz_auto_identify_packet (oggz, op, serialno);
     } else {
       return OGGZ_ERR_BAD_SERIALNO;
     }
   } else {
     if (bos_auto) b_o_s = 0;
 
     if (!suffix && strict && stream->e_o_s)
       return OGGZ_ERR_EOS;
   }
 
   /* Check packet against mapping restrictions */
   if (strict) {
     if (op->bytes < 0) return OGGZ_ERR_BAD_BYTES;
     if (!suffix && b_o_s != stream->b_o_s) return OGGZ_ERR_BAD_B_O_S;
-    if (op->granulepos != -1 && op->granulepos < stream->granulepos)
+    if (op->granulepos != -1 && op->granulepos < stream->granulepos &&
+        /* Allow negative granulepos immediately after headers, for Dirac: */
+        !(stream->granulepos == 0 && op->granulepos < 0))
       return OGGZ_ERR_BAD_GRANULEPOS;
 
     /* Allow packetno == -1 to indicate oggz should fill it in; otherwise:
      * if op is the first packet in the stream, initialize the stream's
      * packetno to the given one, otherwise check it for strictness.
      * For stream suffixes, believe the packetno value */
     if (op->packetno != -1) {
       if (b_o_s || suffix) {
@@ -289,36 +294,42 @@ oggz_write_feed (OGGZ * oggz, ogg_packet
 	return OGGZ_ERR_BAD_PACKETNO;
       }
     }
   }
 
   /* OK -- Update stream's memory of packet details */
 
   if (!stream->metric && (oggz->flags & OGGZ_AUTO)) {
-    oggz_auto_get_granulerate (oggz, op, serialno, NULL);
+    oggz_auto_read_bos_packet (oggz, op, serialno, NULL);
   }
 
   stream->b_o_s = 0; /* The stream is henceforth no longer at bos */
   stream->e_o_s = e_o_s; /* We believe the eos value */
   stream->granulepos = op->granulepos; /* and the granulepos */
 
   /* If the user specified a packetno of -1, fill it in automatically;
    * otherwise, use the user-specified value */
   stream->packetno = (op->packetno != -1) ? op->packetno : stream->packetno+1;
 
   /* Now set up the packet and add it to the queue */
   if (guard == NULL) {
     new_buf = oggz_malloc ((size_t)op->bytes);
+    if (new_buf == NULL) return OGGZ_ERR_OUT_OF_MEMORY;
+
     memcpy (new_buf, op->packet, (size_t)op->bytes);
   } else {
     new_buf = op->packet;
   }
 
   packet = oggz_malloc (sizeof (oggz_writer_packet_t));
+  if (packet == NULL) {
+    if (guard == NULL && new_buf != NULL) oggz_free (new_buf);
+    return OGGZ_ERR_OUT_OF_MEMORY;
+  }
 
   new_op = &packet->op;
   new_op->packet = new_buf;
   new_op->bytes = op->bytes;
   new_op->b_o_s = b_o_s;
   new_op->e_o_s = e_o_s;
   new_op->granulepos = op->granulepos;
   new_op->packetno = stream->packetno;
@@ -370,23 +381,24 @@ oggz_write_feed (OGGZ * oggz, ogg_packet
  *
  * Initialises the next page of the current packet.
  *
  * If this returns 0, the page is not ready for writing.
  */
 static long
 oggz_page_init (OGGZ * oggz)
 {
-  OggzWriter * writer = &oggz->x.writer;
+  OggzWriter * writer;
   ogg_stream_state * os;
   ogg_page * og;
   int ret;
 
   if (oggz == NULL) return -1;
 
+  writer = &oggz->x.writer;
   os = writer->current_stream;
   og = &oggz->current_page;
 
   if (ALWAYS_FLUSH || writer->flushing) {
 #ifdef DEBUG
     printf ("oggz_page_init: ATTEMPT FLUSH: ");
 #endif
     ret = oggz_write_flush (oggz);
@@ -411,23 +423,24 @@ oggz_page_init (OGGZ * oggz)
 /*
  * oggz_packet_init (oggz, buf, n)
  *
  * Initialises the next packet with data from buf, length n
  */
 static long
 oggz_packet_init (OGGZ * oggz, oggz_writer_packet_t * next_zpacket)
 {
-  OggzWriter * writer = &oggz->x.writer;
+  OggzWriter * writer;
   oggz_stream_t * stream;
   ogg_stream_state * os;
   ogg_packet * op;
 
   if (oggz == NULL) return -1L;
 
+  writer = &oggz->x.writer;
   writer->current_zpacket = next_zpacket;
   op = &next_zpacket->op;
 
 #ifdef DEBUG
   printf ("oggz_packet_init: %ld bytes\n", (long)op->bytes);
 #endif
 
   stream = next_zpacket->stream;
@@ -446,22 +459,23 @@ oggz_packet_init (OGGZ * oggz, oggz_writ
   writer->packet_offset = 0;
 
   return 0;
 }
 
 static long
 oggz_page_copyout (OGGZ * oggz, unsigned char * buf, long n)
 {
-  OggzWriter * writer = &oggz->x.writer;
+  OggzWriter * writer;
   long h, b;
   ogg_page * og;
 
   if (oggz == NULL) return -1L;
 
+  writer = &oggz->x.writer;
   og = &oggz->current_page;
 
   h = MIN (n, og->header_len - writer->page_offset);
   if (h > 0) {
     memcpy (buf, og->header + writer->page_offset, h);
     writer->page_offset += h;
     n -= h;
     buf += h;
@@ -488,26 +502,27 @@ oggz_page_copyout (OGGZ * oggz, unsigned
   }
 
   return h + b;
 }
 
 static long
 oggz_page_writeout (OGGZ * oggz, long n)
 {
-  OggzWriter * writer = &oggz->x.writer;
+  OggzWriter * writer;
   long h, b, nwritten;
   ogg_page * og;
 
 #ifdef OGGZ_WRITE_DIRECT
   int fd;
 #endif
 
   if (oggz == NULL) return -1L;
 
+  writer = &oggz->x.writer;
   og = &oggz->current_page;
 
 #ifdef OGGZ_WRITE_DIRECT
   fd = fileno (oggz->file);
 #endif
 
   h = MIN (n, og->header_len - writer->page_offset);
   if (h > 0) {
@@ -649,31 +664,31 @@ oggz_writer_make_packet (OGGZ * oggz)
 	oggz_packet_init (oggz, next_zpacket);
       }
     }
   }
 
 #ifdef DEBUG
   printf("oggz_writer_make_packet: cb_ret is %d\n", cb_ret);
 #endif
-  
+
   if (cb_ret == 0 && next_zpacket == NULL) return OGGZ_WRITE_EMPTY;
 
   return cb_ret;
 }
 
 long
 oggz_write_output (OGGZ * oggz, unsigned char * buf, long n)
 {
   OggzWriter * writer;
   long bytes, bytes_written = 1, remaining = n, nwritten = 0;
   int active = 1, cb_ret = 0;
 
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
- 
+
   writer = &oggz->x.writer;
 
   if (!(oggz->flags & OGGZ_WRITE)) {
     return OGGZ_ERR_INVALID;
   }
 
   if (writer->writing) return OGGZ_ERR_RECURSIVE_WRITE;
   writer->writing = 1;
@@ -815,17 +830,17 @@ oggz_write (OGGZ * oggz, long n)
       if ((cb_ret = oggz_writer_make_packet (oggz)) != OGGZ_CONTINUE) {
 #ifdef DEBUG
         printf ("oggz_write: no packets (cb_ret is %d)\n", cb_ret);
 #endif
         /*
          * if we're out of packets because we're at the end of the file,
          * we can't finish just yet.  Instead we need to force a page flush,
          * and write the page out.  So we set flushing and no_more_packets to
-         * 1.  This causes oggz_page_init to flush the page, then we 
+         * 1.  This causes oggz_page_init to flush the page, then we
          * will switch the state to OGGZ_WRITING_PAGES, which will trigger
          * the writing code below.
          */
         if (cb_ret == OGGZ_WRITE_EMPTY) {
 #ifdef DEBUG
           printf ("oggz_write: Inferred end of data, forcing a page flush.\n");
 #endif
           writer->flushing = 1;
@@ -898,21 +913,23 @@ oggz_write (OGGZ * oggz, long n)
   }
 
   return nwritten;
 }
 
 long
 oggz_write_get_next_page_size (OGGZ * oggz)
 {
-  OggzWriter * writer = &oggz->x.writer;
+  OggzWriter * writer;
   ogg_page * og;
 
   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
 
+  writer = &oggz->x.writer;
+
   if (!(oggz->flags & OGGZ_WRITE)) {
     return OGGZ_ERR_INVALID;
   }
 
   og = &oggz->current_page;
 
   return (og->header_len + og->body_len - (long)writer->page_offset);
 }
--- a/media/liboggz/update.sh
+++ b/media/liboggz/update.sh
@@ -35,14 +35,14 @@ sed s/\#include\ \"config.h\"/\#ifdef\ W
 cp $1/src/liboggz/oggz_stream_private.h ./src/liboggz/oggz_stream_private.h
 cp $1/src/liboggz/oggz_vector.h ./src/liboggz/oggz_vector.h
 cp $1/src/liboggz/oggz_auto.h ./src/liboggz/oggz_auto.h
 sed s/\#include\ \"config.h\"/\#ifdef\ WIN32\\n\#include\ \"config_win32.h\"\\n\#else\\n\#include\ \"config.h\"\\n\#endif/g $1/src/liboggz/oggz_io.c >./src/liboggz/oggz_io.c
 sed s/\#include\ \"config.h\"/\#ifdef\ WIN32\\n\#include\ \"config_win32.h\"\\n\#else\\n\#include\ \"config.h\"\\n\#endif/g $1/src/liboggz/oggz_vector.c >./src/liboggz/oggz_vector.c
 sed s/\#include\ \"config.h\"/\#ifdef\ WIN32\\n\#include\ \"config_win32.h\"\\n\#else\\n\#include\ \"config.h\"\\n\#endif/g $1/src/liboggz/oggz_seek.c >./src/liboggz/oggz_seek.c
 cp $1/src/liboggz/oggz_dlist.h ./src/liboggz/oggz_dlist.h
 sed s/\#include\ \"config.h\"/\#ifdef\ WIN32\\n\#include\ \"config_win32.h\"\\n\#else\\n\#include\ \"config.h\"\\n\#endif/g $1/src/liboggz/metric_internal.c >./src/liboggz/metric_internal.c
+cp $1/src/liboggz/dirac.h ./src/liboggz/dirac.h
+sed s/\#include\ \"config.h\"/\#ifdef\ WIN32\\n\#include\ \"config_win32.h\"\\n\#else\\n\#include\ \"config.h\"\\n\#endif/g $1/src/liboggz/dirac.c >./src/liboggz/dirac.c
 cp $1/AUTHORS ./AUTHORS
+patch -p3 <wince.patch
+patch -p3 <endian.patch
 patch -p4 <seek.patch
-patch -p4 <warning.patch
-patch -p3 <oggz_off_t.patch
-patch -p3 <wince.patch
-patch -p4 <endian.patch
deleted file mode 100644
--- a/media/liboggz/warning.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-diff --git a/media/liboggz/src/liboggz/oggz_auto.c b/media/liboggz/src/liboggz/oggz_auto.c
-index 6d83fa9..95ffe6c 100644
---- a/media/liboggz/src/liboggz/oggz_auto.c
-+++ b/media/liboggz/src/liboggz/oggz_auto.c
-@@ -809,10 +809,12 @@ auto_calc_vorbis(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
-       }
-       
-       size_check += 1;
-+#ifdef DEBUG
-       if (size_check != size)
-       {
-         printf("WARNING: size parsing failed for VORBIS mode packets\n");
-       }
-+#endif
- 
-       /*
-        * store mode size information in our info struct