Bug 559344 - Update libogg to SVN r17287. rs=chris.double
authorMatthew Gregan <kinetik@flim.org>
Fri, 11 Jun 2010 10:50:58 +1200
changeset 43668 4b7350039ab109f50e2cda9d79c40f1b9d1e77cb
parent 43667 eb396dc49f4acc866a96ba8f3ba2f418524095df
child 43669 db3e8b1ecb265d389707f60426f6478ab64c5a6b
push idunknown
push userunknown
push dateunknown
reviewerschris.double
bugs559344
milestone1.9.3a6pre
Bug 559344 - Update libogg to SVN r17287. rs=chris.double
media/libogg/CHANGES
media/libogg/README_MOZILLA
media/libogg/include/ogg/ogg.h
media/libogg/include/ogg/os_types.h
media/libogg/src/ogg_bitwise.c
media/libogg/src/ogg_framing.c
--- a/media/libogg/CHANGES
+++ b/media/libogg/CHANGES
@@ -1,8 +1,15 @@
+Version 1.2.0 (2010 March 25)
+
+* Alter default flushing behavior to span less often and use larger page 
+  sizes when packet sizes are large.
+* Build fixes for additional compilers
+* Documentation updates
+
 Version 1.1.4 (2009 June 24)
 
 * New async error reporting mechanism. Calls made after a fatal error are 
   now safely handled in the event an error code is ignored
 * Added allocation checks useful to some embedded applications
 * fix possible read past end of buffer when reading 0 bits
 * Updates to API documentation
 * Build fixes
--- a/media/libogg/README_MOZILLA
+++ b/media/libogg/README_MOZILLA
@@ -1,10 +1,10 @@
 The source from this directory was copied from the libogg subversion
 repository 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.
 
-The svn revision number used was r16911.
+The svn revision number used was r17287.
 
 The int-types.patch address a bug that config_types.h generated from
 Linux platform can't be used on OpenSolaris directly see Mozilla bug
 449754
--- a/media/libogg/include/ogg/ogg.h
+++ b/media/libogg/include/ogg/ogg.h
@@ -6,17 +6,17 @@
  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007             *
  * by the Xiph.Org Foundation http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
  function: toplevel libogg include
- last mod: $Id: ogg.h 16051 2009-05-27 05:00:06Z xiphmont $
+ last mod: $Id: ogg.h 17098 2010-03-29 05:35:11Z gmaxwell $
 
  ********************************************************************/
 #ifndef _OGG_H
 #define _OGG_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -154,16 +154,17 @@ extern long  oggpackB_bits(oggpack_buffe
 extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b);
 
 /* Ogg BITSTREAM PRIMITIVES: encoding **************************/
 
 extern int      ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
 extern int      ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov,
                                    int count, long e_o_s, ogg_int64_t granulepos);
 extern int      ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
+extern int      ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill);
 extern int      ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
 
 /* Ogg BITSTREAM PRIMITIVES: decoding **************************/
 
 extern int      ogg_sync_init(ogg_sync_state *oy);
 extern int      ogg_sync_clear(ogg_sync_state *oy);
 extern int      ogg_sync_reset(ogg_sync_state *oy);
 extern int      ogg_sync_destroy(ogg_sync_state *oy);
--- a/media/libogg/include/ogg/os_types.h
+++ b/media/libogg/include/ogg/os_types.h
@@ -6,17 +6,17 @@
  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
  * by the Xiph.Org Foundation http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
  function: #ifdef jail to whip a few platforms into the UNIX ideal.
- last mod: $Id: os_types.h 16649 2009-10-25 00:49:58Z ds $
+ last mod: $Id: os_types.h 17287 2010-06-10 13:42:06Z tterribe $
 
  ********************************************************************/
 #ifndef _OS_TYPES_H
 #define _OS_TYPES_H
 
 /* make it easy on the folks that want to compile the libs with a
    different malloc than stdlib */
 #define _ogg_malloc  malloc
--- a/media/libogg/src/ogg_bitwise.c
+++ b/media/libogg/src/ogg_bitwise.c
@@ -1,30 +1,31 @@
 /********************************************************************
  *                                                                  *
- * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
+ * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE.              *
  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010             *
  * by the Xiph.Org Foundation http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
   function: packing variable sized words into an octet stream
-  last mod: $Id: bitwise.c 16051 2009-05-27 05:00:06Z xiphmont $
+  last mod: $Id: bitwise.c 17287 2010-06-10 13:42:06Z tterribe $
 
  ********************************************************************/
 
 /* We're 'LSb' endian; if we write a word but read individual bits,
    then we'll read the lsb first */
 
 #include <string.h>
 #include <stdlib.h>
+#include <limits.h>
 #include <ogg/ogg.h>
 
 #define BUFFER_INCREMENT 256
 
 static const unsigned long mask[]=
 {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
  0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
  0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
@@ -75,24 +76,23 @@ void oggpackB_writetrunc(oggpack_buffer 
     b->endbit=bits;
     b->endbyte=bytes;
     *b->ptr&=mask8B[bits];
   }
 }
 
 /* Takes only up to 32 bits. */
 void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){
-  if(b->endbyte+4>=b->storage){
+  if(bits<0 || bits>32) goto err;
+  if(b->endbyte>=b->storage-4){
     void *ret;
     if(!b->ptr)return;
+    if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err;
     ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
-    if(!ret){
-      oggpack_writeclear(b);
-      return;
-    }
+    if(!ret) goto err;
     b->buffer=ret;
     b->storage+=BUFFER_INCREMENT;
     b->ptr=b->buffer+b->endbyte;
   }
 
   value&=mask[bits]; 
   bits+=b->endbit;
 
@@ -112,28 +112,30 @@ void oggpack_write(oggpack_buffer *b,uns
         }
       }
     }
   }
 
   b->endbyte+=bits/8;
   b->ptr+=bits/8;
   b->endbit=bits&7;
+  return;
+ err:
+  oggpack_writeclear(b);
 }
 
 /* Takes only up to 32 bits. */
 void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){
-  if(b->endbyte+4>=b->storage){
+  if(bits<0 || bits>32) goto err;
+  if(b->endbyte>=b->storage-4){
     void *ret;
     if(!b->ptr)return;
+    if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err;
     ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
-    if(!ret){
-      oggpack_writeclear(b);
-      return;
-    }
+    if(!ret) goto err;
     b->buffer=ret;
     b->storage+=BUFFER_INCREMENT;
     b->ptr=b->buffer+b->endbyte;
   }
 
   value=(value&mask[bits])<<(32-bits); 
   bits+=b->endbit;
 
@@ -153,16 +155,19 @@ void oggpackB_write(oggpack_buffer *b,un
         }
       }
     }
   }
 
   b->endbyte+=bits/8;
   b->ptr+=bits/8;
   b->endbit=bits&7;
+  return;
+ err:
+  oggpack_writeclear(b);
 }
 
 void oggpack_writealign(oggpack_buffer *b){
   int bits=8-b->endbit;
   if(bits<8)
     oggpack_write(b,0,bits);
 }
 
@@ -188,39 +193,40 @@ static void oggpack_writecopy_helper(ogg
     int i;
     /* unaligned copy.  Do it the hard way. */
     for(i=0;i<bytes;i++)
       w(b,(unsigned long)(ptr[i]),8);    
   }else{
     /* aligned block copy */
     if(b->endbyte+bytes+1>=b->storage){
       void *ret;
-      if(!b->ptr)return;
+      if(!b->ptr) goto err;
+      if(b->endbyte+bytes+BUFFER_INCREMENT>b->storage) goto err;
       b->storage=b->endbyte+bytes+BUFFER_INCREMENT;
       ret=_ogg_realloc(b->buffer,b->storage);
-      if(!ret){
-        oggpack_writeclear(b);
-        return;
-      }
+      if(!ret) goto err;
       b->buffer=ret;
       b->ptr=b->buffer+b->endbyte;
     }
 
     memmove(b->ptr,source,bytes);
     b->ptr+=bytes;
     b->endbyte+=bytes;
     *b->ptr=0;
 
   }
   if(bits){
     if(msb)
       w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits);    
     else
       w(b,(unsigned long)(ptr[bytes]),bits);    
   }
+  return;
+ err:
+  oggpack_writeclear(b);
 }
 
 void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){
   oggpack_writecopy_helper(b,source,bits,oggpack_write,0);
 }
 
 void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits){
   oggpack_writecopy_helper(b,source,bits,oggpackB_write,1);
@@ -254,25 +260,30 @@ void oggpack_readinit(oggpack_buffer *b,
 
 void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
   oggpack_readinit(b,buf,bytes);
 }
 
 /* Read in bits without advancing the bitptr; bits <= 32 */
 long oggpack_look(oggpack_buffer *b,int bits){
   unsigned long ret;
-  unsigned long m=mask[bits];
+  unsigned long m;
 
+  if(bits<0 || bits>32) return -1;
+  m=mask[bits];
   bits+=b->endbit;
 
-  if(b->endbyte+4>=b->storage){
+  if(b->endbyte >= b->storage-4){
     /* not the main path */
-    if(b->endbyte*8+bits>b->storage*8)return(-1);
+    if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
+    /* special case to avoid reading b->ptr[0], which might be past the end of
+        the buffer; also skips some useless accounting */
+    else if(!bits)return(0L);
   }
-  
+
   ret=b->ptr[0]>>b->endbit;
   if(bits>8){
     ret|=b->ptr[1]<<(8-b->endbit);  
     if(bits>16){
       ret|=b->ptr[2]<<(16-b->endbit);  
       if(bits>24){
         ret|=b->ptr[3]<<(24-b->endbit);  
         if(bits>32 && b->endbit)
@@ -283,23 +294,27 @@ long oggpack_look(oggpack_buffer *b,int 
   return(m&ret);
 }
 
 /* Read in bits without advancing the bitptr; bits <= 32 */
 long oggpackB_look(oggpack_buffer *b,int bits){
   unsigned long ret;
   int m=32-bits;
 
+  if(m<0 || m>32) return -1;
   bits+=b->endbit;
 
-  if(b->endbyte+4>=b->storage){
+  if(b->endbyte >= b->storage-4){
     /* not the main path */
-    if(b->endbyte*8+bits>b->storage*8)return(-1);
+    if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
+    /* special case to avoid reading b->ptr[0], which might be past the end of
+        the buffer; also skips some useless accounting */
+    else if(!bits)return(0L);
   }
-  
+
   ret=b->ptr[0]<<(24+b->endbit);
   if(bits>8){
     ret|=b->ptr[1]<<(16+b->endbit);  
     if(bits>16){
       ret|=b->ptr[2]<<(8+b->endbit);  
       if(bits>24){
         ret|=b->ptr[3]<<(b->endbit);  
         if(bits>32 && b->endbit)
@@ -317,19 +332,28 @@ long oggpack_look1(oggpack_buffer *b){
 
 long oggpackB_look1(oggpack_buffer *b){
   if(b->endbyte>=b->storage)return(-1);
   return((b->ptr[0]>>(7-b->endbit))&1);
 }
 
 void oggpack_adv(oggpack_buffer *b,int bits){
   bits+=b->endbit;
+
+  if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
+
   b->ptr+=bits/8;
   b->endbyte+=bits/8;
   b->endbit=bits&7;
+  return;
+
+ overflow:
+  b->ptr=NULL;
+  b->endbyte=b->storage;
+  b->endbit=1;
 }
 
 void oggpackB_adv(oggpack_buffer *b,int bits){
   oggpack_adv(b,bits);
 }
 
 void oggpack_adv1(oggpack_buffer *b){
   if(++(b->endbit)>7){
@@ -341,129 +365,140 @@ void oggpack_adv1(oggpack_buffer *b){
 
 void oggpackB_adv1(oggpack_buffer *b){
   oggpack_adv1(b);
 }
 
 /* bits <= 32 */
 long oggpack_read(oggpack_buffer *b,int bits){
   long ret;
-  unsigned long m=mask[bits];
+  unsigned long m;
 
+  if(bits<0 || bits>32) goto err;
+  m=mask[bits];
   bits+=b->endbit;
 
-  if(b->endbyte+4>=b->storage){
+  if(b->endbyte >= b->storage-4){
     /* not the main path */
-    ret=-1L;
-    if(b->endbyte*8+bits>b->storage*8)goto overflow;
+    if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
+    /* special case to avoid reading b->ptr[0], which might be past the end of
+        the buffer; also skips some useless accounting */
+    else if(!bits)return(0L);
   }
-  
+
   ret=b->ptr[0]>>b->endbit;
   if(bits>8){
     ret|=b->ptr[1]<<(8-b->endbit);  
     if(bits>16){
       ret|=b->ptr[2]<<(16-b->endbit);  
       if(bits>24){
         ret|=b->ptr[3]<<(24-b->endbit);  
         if(bits>32 && b->endbit){
           ret|=b->ptr[4]<<(32-b->endbit);
         }
       }
     }
   }
   ret&=m;
-  
- overflow:
-
   b->ptr+=bits/8;
   b->endbyte+=bits/8;
   b->endbit=bits&7;
-  return(ret);
+  return ret;
+
+ overflow:
+ err:
+  b->ptr=NULL;
+  b->endbyte=b->storage;
+  b->endbit=1;
+  return -1L;
 }
 
 /* bits <= 32 */
 long oggpackB_read(oggpack_buffer *b,int bits){
   long ret;
   long m=32-bits;
-  
+
+  if(m<0 || m>32) goto err;
   bits+=b->endbit;
 
   if(b->endbyte+4>=b->storage){
     /* not the main path */
-    ret=-1L;
-    if(b->endbyte*8+bits>b->storage*8)goto overflow;
+    if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
     /* special case to avoid reading b->ptr[0], which might be past the end of
         the buffer; also skips some useless accounting */
     else if(!bits)return(0L);
   }
-  
+
   ret=b->ptr[0]<<(24+b->endbit);
   if(bits>8){
     ret|=b->ptr[1]<<(16+b->endbit);  
     if(bits>16){
       ret|=b->ptr[2]<<(8+b->endbit);  
       if(bits>24){
         ret|=b->ptr[3]<<(b->endbit);  
         if(bits>32 && b->endbit)
           ret|=b->ptr[4]>>(8-b->endbit);
       }
     }
   }
   ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1);
-  
- overflow:
 
   b->ptr+=bits/8;
   b->endbyte+=bits/8;
   b->endbit=bits&7;
-  return(ret);
+  return ret;
+
+ overflow:
+ err:
+  b->ptr=NULL;
+  b->endbyte=b->storage;
+  b->endbit=1;
+  return -1L;
 }
 
 long oggpack_read1(oggpack_buffer *b){
   long ret;
-  
-  if(b->endbyte>=b->storage){
-    /* not the main path */
-    ret=-1L;
-    goto overflow;
-  }
 
+  if(b->endbyte >= b->storage) goto overflow;
   ret=(b->ptr[0]>>b->endbit)&1;
-  
- overflow:
 
   b->endbit++;
   if(b->endbit>7){
     b->endbit=0;
     b->ptr++;
     b->endbyte++;
   }
-  return(ret);
+  return ret;
+
+ overflow:
+  b->ptr=NULL;
+  b->endbyte=b->storage;
+  b->endbit=1;
+  return -1L;
 }
 
 long oggpackB_read1(oggpack_buffer *b){
   long ret;
-  
-  if(b->endbyte>=b->storage){
-    /* not the main path */
-    ret=-1L;
-    goto overflow;
-  }
 
+  if(b->endbyte >= b->storage) goto overflow;
   ret=(b->ptr[0]>>(7-b->endbit))&1;
-  
- overflow:
 
   b->endbit++;
   if(b->endbit>7){
     b->endbit=0;
     b->ptr++;
     b->endbyte++;
   }
-  return(ret);
+  return ret;
+
+ overflow:
+  b->ptr=NULL;
+  b->endbyte=b->storage;
+  b->endbit=1;
+  return -1L;
 }
 
 long oggpack_bytes(oggpack_buffer *b){
   return(b->endbyte+(b->endbit+7)/8);
 }
 
 long oggpack_bits(oggpack_buffer *b){
   return(b->endbyte*8+b->endbit);
@@ -687,29 +722,29 @@ int main(void){
   cliptest(testbuffer2,test2size,17,five,fivesize);
   fprintf(stderr,"ok.");
 
   fprintf(stderr,"\nSingle bit unclipped packing (LSb): ");
   cliptest(testbuffer3,test3size,1,six,sixsize);
   fprintf(stderr,"ok.");
 
   fprintf(stderr,"\nTesting read past end (LSb): ");
-  oggpack_readinit(&r,"\0\0\0\0\0\0\0\0",8);
+  oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
   for(i=0;i<64;i++){
     if(oggpack_read(&r,1)!=0){
       fprintf(stderr,"failed; got -1 prematurely.\n");
       exit(1);
     }
   }
   if(oggpack_look(&r,1)!=-1 ||
      oggpack_read(&r,1)!=-1){
       fprintf(stderr,"failed; read past end without -1.\n");
       exit(1);
   }
-  oggpack_readinit(&r,"\0\0\0\0\0\0\0\0",8);
+  oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
   if(oggpack_read(&r,30)!=0 || oggpack_read(&r,16)!=0){
       fprintf(stderr,"failed 2; got -1 prematurely.\n");
       exit(1);
   }
 
   if(oggpack_look(&r,18)!=0 ||
      oggpack_look(&r,18)!=0){
     fprintf(stderr,"failed 3; got -1 prematurely.\n");
@@ -773,29 +808,29 @@ int main(void){
   cliptestB(testbuffer2,test2size,17,fiveB,fivesize);
   fprintf(stderr,"ok.");
 
   fprintf(stderr,"\nSingle bit unclipped packing (MSb): ");
   cliptestB(testbuffer3,test3size,1,sixB,sixsize);
   fprintf(stderr,"ok.");
 
   fprintf(stderr,"\nTesting read past end (MSb): ");
-  oggpackB_readinit(&r,"\0\0\0\0\0\0\0\0",8);
+  oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
   for(i=0;i<64;i++){
     if(oggpackB_read(&r,1)!=0){
       fprintf(stderr,"failed; got -1 prematurely.\n");
       exit(1);
     }
   }
   if(oggpackB_look(&r,1)!=-1 ||
      oggpackB_read(&r,1)!=-1){
       fprintf(stderr,"failed; read past end without -1.\n");
       exit(1);
   }
-  oggpackB_readinit(&r,"\0\0\0\0\0\0\0\0",8);
+  oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
   if(oggpackB_read(&r,30)!=0 || oggpackB_read(&r,16)!=0){
       fprintf(stderr,"failed 2; got -1 prematurely.\n");
       exit(1);
   }
 
   if(oggpackB_look(&r,18)!=0 ||
      oggpackB_look(&r,18)!=0){
     fprintf(stderr,"failed 3; got -1 prematurely.\n");
--- a/media/libogg/src/ogg_framing.c
+++ b/media/libogg/src/ogg_framing.c
@@ -1,23 +1,23 @@
 /********************************************************************
  *                                                                  *
- * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
+ * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE.              *
  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010             *
  * by the Xiph.Org Foundation http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
  function: code raw packets into framed OggSquish stream and
            decode Ogg streams back into raw packets
- last mod: $Id: framing.c 16051 2009-05-27 05:00:06Z xiphmont $
+ last mod: $Id: framing.c 17269 2010-06-04 05:39:45Z xiphmont $
 
  note: The CRC code is directly derived from public domain code by
  Ross Williams (ross@guest.adelaide.edu.au).  See docs/framing.html
  for details.
 
  ********************************************************************/
 
 #include <stdlib.h>
@@ -361,69 +361,79 @@ int ogg_stream_iovecin(ogg_stream_state 
 
 int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
   ogg_iovec_t iov;
   iov.iov_base = op->packet;
   iov.iov_len = op->bytes;
   return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos);
 }
 
-/* This will flush remaining packets into a page (returning nonzero),
-   even if there is not enough data to trigger a flush normally
-   (undersized page). If there are no packets or partial packets to
-   flush, ogg_stream_flush returns 0.  Note that ogg_stream_flush will
-   try to flush a normal sized page like ogg_stream_pageout; a call to
-   ogg_stream_flush does not guarantee that all packets have flushed.
-   Only a return value of 0 from ogg_stream_flush indicates all packet
-   data is flushed into pages.
-
-   since ogg_stream_flush will flush the last page in a stream even if
-   it's undersized, you almost certainly want to use ogg_stream_pageout
-   (and *not* ogg_stream_flush) unless you specifically need to flush 
-   an page regardless of size in the middle of a stream. */
-
-int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
+/* Conditionally flush a page; force==0 will only flush nominal-size
+   pages, force==1 forces us to flush a page regardless of page size
+   so long as there's any data available at all. */
+static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){
   int i;
   int vals=0;
   int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
   int bytes=0;
   long acc=0;
   ogg_int64_t granule_pos=-1;
 
-  if(ogg_stream_check(os)) return 0;
-  if(maxvals==0)return 0;
-  
+  if(ogg_stream_check(os)) return(0);
+  if(maxvals==0) return(0);
+
   /* construct a page */
   /* decide how many segments to include */
-  
+
   /* If this is the initial header case, the first page must only include
      the initial header packet */
   if(os->b_o_s==0){  /* 'initial header page' case */
     granule_pos=0;
     for(vals=0;vals<maxvals;vals++){
       if((os->lacing_vals[vals]&0x0ff)<255){
         vals++;
         break;
       }
     }
   }else{
+
+    /* The extra packets_done, packet_just_done logic here attempts to do two things:
+       1) Don't unneccessarily span pages.
+       2) Unless necessary, don't flush pages if there are less than four packets on
+          them; this expands page size to reduce unneccessary overhead if incoming packets
+          are large.
+       These are not necessary behaviors, just 'always better than naive flushing'
+       without requiring an application to explicitly request a specific optimized
+       behavior. We'll want an explicit behavior setup pathway eventually as well. */
+
+    int packets_done=0;
+    int packet_just_done=0;
     for(vals=0;vals<maxvals;vals++){
-      if(acc>4096)break;
+      if(acc>nfill && packet_just_done>=8){
+        force=1;
+        break;
+      }
       acc+=os->lacing_vals[vals]&0x0ff;
-      if((os->lacing_vals[vals]&0xff)<255)
+      if((os->lacing_vals[vals]&0xff)<255){
         granule_pos=os->granule_vals[vals];
+        packet_just_done=++packets_done;
+      }else
+        packet_just_done=0;
     }
+    if(vals==255)force=1;
   }
-  
+
+  if(!force) return(0);
+
   /* construct the header in temp storage */
   memcpy(os->header,"OggS",4);
-  
+
   /* stream structure version */
   os->header[4]=0x00;
-  
+
   /* continued packet flag? */
   os->header[5]=0x00;
   if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
   /* first page flag? */
   if(os->b_o_s==0)os->header[5]|=0x02;
   /* last page flag? */
   if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
   os->b_o_s=1;
@@ -485,34 +495,62 @@ int ogg_stream_flush(ogg_stream_state *o
   /* calculate the checksum */
   
   ogg_page_checksum_set(og);
 
   /* done */
   return(1);
 }
 
+/* This will flush remaining packets into a page (returning nonzero),
+   even if there is not enough data to trigger a flush normally
+   (undersized page). If there are no packets or partial packets to
+   flush, ogg_stream_flush returns 0.  Note that ogg_stream_flush will
+   try to flush a normal sized page like ogg_stream_pageout; a call to
+   ogg_stream_flush does not guarantee that all packets have flushed.
+   Only a return value of 0 from ogg_stream_flush indicates all packet
+   data is flushed into pages.
+
+   since ogg_stream_flush will flush the last page in a stream even if
+   it's undersized, you almost certainly want to use ogg_stream_pageout
+   (and *not* ogg_stream_flush) unless you specifically need to flush
+   an page regardless of size in the middle of a stream. */
+
+int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
+  return ogg_stream_flush_i(os,og,1,4096);
+}
 
 /* This constructs pages from buffered packet segments.  The pointers
 returned are to static buffers; do not free. The returned buffers are
 good only until the next call (using the same ogg_stream_state) */
 
 int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
+  int force=0;
   if(ogg_stream_check(os)) return 0;
 
   if((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
-     os->body_fill-os->body_returned > 4096 ||/* 'page nominal size' case */
-     os->lacing_fill>=255 ||                  /* 'segment table full' case */
-     (os->lacing_fill&&!os->b_o_s)){          /* 'initial header page' case */
-        
-    return(ogg_stream_flush(os,og));
-  }
-  
-  /* not enough data to construct a page and not end of stream */
-  return 0;
+     (os->lacing_fill&&!os->b_o_s))           /* 'initial header page' case */
+    force=1;
+
+  return(ogg_stream_flush_i(os,og,force,4096));
+}
+
+/* Like the above, but an argument is provided to adjust the nominal 
+page size for applications which are smart enough to provide their
+own delay based flushing */
+   
+int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){
+  int force=0;
+  if(ogg_stream_check(os)) return 0;
+
+  if((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
+     (os->lacing_fill&&!os->b_o_s))           /* 'initial header page' case */
+    force=1;
+
+  return(ogg_stream_flush_i(os,og,force,nfill));
 }
 
 int ogg_stream_eos(ogg_stream_state *os){
   if(ogg_stream_check(os)) return 1;
   return os->e_o_s;
 }
 
 /* DECODING PRIMITIVES: packet streaming layer **********************/
@@ -929,17 +967,17 @@ static int _packetout(ogg_stream_state *
 
   if(!op && !adv)return(1); /* just using peek as an inexpensive way
                                to ask if there's a whole packet
                                waiting */
 
   /* Gather the whole packet. We'll have no holes or a partial packet */
   {
     int size=os->lacing_vals[ptr]&0xff;
-    int bytes=size;
+    long bytes=size;
     int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
     int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
 
     while(size==255){
       int val=os->lacing_vals[++ptr];
       size=val&0xff;
       if(val&0x200)eos=0x200;
       bytes+=size;
@@ -979,27 +1017,27 @@ void ogg_packet_clear(ogg_packet *op) {
 }
 
 #ifdef _V_SELFTEST
 #include <stdio.h>
 
 ogg_stream_state os_en, os_de;
 ogg_sync_state oy;
 
-void checkpacket(ogg_packet *op,int len, int no, int pos){
+void checkpacket(ogg_packet *op,long len, int no, long pos){
   long j;
   static int sequence=0;
   static int lastno=0;
 
   if(op->bytes!=len){
-    fprintf(stderr,"incorrect packet length!\n");
+    fprintf(stderr,"incorrect packet length (%ld != %ld)!\n",op->bytes,len);
     exit(1);
   }
   if(op->granulepos!=pos){
-    fprintf(stderr,"incorrect packet position!\n");
+    fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos);
     exit(1);
   }
 
   /* packet number just follows sequence/gap; adjust the input number
      for that */
   if(no==0){
     sequence=0;
   }else{
@@ -1156,28 +1194,83 @@ const int head1_4[] = {0x4f,0x67,0x67,0x
                        0x01,0x02,0x03,0x04,0,0,0,0,
                        0xff,0x7b,0x23,0x17,
                        1,
                        0};
 
 const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
                        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
                        0x01,0x02,0x03,0x04,1,0,0,0,
-                       0x54,0x05,0x51,0xc8,
-                       17,
+                       0xf8,0x3c,0x19,0x79,
+                       255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
                        255,255,255,255,255,255,255,255,
-                       255,255,255,255,255,255,255,255,255};
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255};
 
 const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
                        0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x01,0x02,0x03,0x04,2,0,0,0,
-                       0xc8,0xc3,0xcb,0xed,
-                       5,
-                       10,255,4,255,0};
+                       0x38,0xe6,0xb6,0x28,
+                       6,
+                       255,220,255,4,255,0};
+
+
+/* spill expansion test */
+const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
+                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                        0x01,0x02,0x03,0x04,0,0,0,0,
+                        0xff,0x7b,0x23,0x17,
+                        1,
+                        0};
 
+const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
+                        0x07,0x20,0x00,0x00,0x00,0x00,0x00,0x00,
+                        0x01,0x02,0x03,0x04,1,0,0,0,
+                        0xe6,0x54,0xfe,0x7d,
+                        27,
+                        255,255,255,255,255,255,255,255,
+                        255,255,255,255,255,255,255,255,
+                        255,10,255,4,255,0,0,0,0,0,0};
+
+
+const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
+                        0x07,0x24,0x00,0x00,0x00,0x00,0x00,0x00,
+                        0x01,0x02,0x03,0x04,2,0,0,0,
+                        0x77,0x62,0xe0,0x12,
+                        1,
+                        0};
 
 /* page with the 255 segment limit */
 const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x01,0x02,0x03,0x04,0,0,0,0,
                        0xff,0x7b,0x23,0x17,
                        1,
                        0};
@@ -1234,59 +1327,152 @@ const int head1_6[] = {0x4f,0x67,0x67,0x
                        0x01,0x02,0x03,0x04,0,0,0,0,
                        0xff,0x7b,0x23,0x17,
                        1,
                        0};
 
 const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
                        0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x01,0x02,0x03,0x04,1,0,0,0,
-                       0x3c,0xd9,0x4d,0x3f,
-                       17,
-                       100,255,255,255,255,255,255,255,255,
-                       255,255,255,255,255,255,255,255};
+                       0x68,0x22,0x7c,0x3d,
+                       255,
+                       100,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255};
 
 const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
                        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
                        0x01,0x02,0x03,0x04,2,0,0,0,
-                       0x01,0xd2,0xe5,0xe5,
-                       17,
+                       0xf4,0x87,0xba,0xf3,
+                       255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
                        255,255,255,255,255,255,255,255,
-                       255,255,255,255,255,255,255,255,255};
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255};
 
 const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
                        0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x01,0x02,0x03,0x04,3,0,0,0,
-                       0xef,0xdd,0x88,0xde,
-                       7,
-                       255,255,75,255,4,255,0};
+                       0xf7,0x2f,0x6c,0x60,
+                       5,
+                       254,255,4,255,0};
 
 /* packet that overspans over an entire page */
 const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x01,0x02,0x03,0x04,0,0,0,0,
                        0xff,0x7b,0x23,0x17,
                        1,
                        0};
 
 const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
                        0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x01,0x02,0x03,0x04,1,0,0,0,
-                       0x3c,0xd9,0x4d,0x3f,
-                       17,
-                       100,255,255,255,255,255,255,255,255,
-                       255,255,255,255,255,255,255,255};
+                       0x68,0x22,0x7c,0x3d,
+                       255,
+                       100,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255,255,255,
+                       255,255,255,255,255,255};
 
 const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
                        0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
                        0x01,0x02,0x03,0x04,2,0,0,0,
                        0xd4,0xe0,0x60,0xe5,
-                       1,0};
+                       1,
+                       0};
 
-void test_pack(const int *pl, const int **headers, int byteskip, 
+void test_pack(const int *pl, const int **headers, int byteskip,
                int pageskip, int packetskip){
   unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
   long inptr=0;
   long outptr=0;
   long deptr=0;
   long depacket=0;
   long granule_pos=7,pageno=0;
   int i,j,packets,pageout=pageskip;
@@ -1369,17 +1555,17 @@ void test_pack(const int *pl, const int 
           ogg_sync_wrote(&oy,next-buf);
 
           while(1){
             int ret=ogg_sync_pageout(&oy,&og_de);
             if(ret==0)break;
             if(ret<0)continue;
             /* got a page.  Happy happy.  Verify that it's good. */
             
-            fprintf(stderr,"(%ld), ",pageout);
+            fprintf(stderr,"(%d), ",pageout);
 
             check_page(data+deptr,headers[pageout],&og_de);
             deptr+=og_de.body_len;
             pageout++;
 
             /* submit it to deconstitution */
             ogg_stream_pagein(&os_de,&og_de);
 
@@ -1468,57 +1654,67 @@ int main(void){
 
   /* Exercise each code path in the framing code.  Also verify that
      the checksums are working.  */
 
   {
     /* 17 only */
     const int packets[]={17, -1};
     const int *headret[]={head1_0,NULL};
-    
+
     fprintf(stderr,"testing single page encoding... ");
     test_pack(packets,headret,0,0,0);
   }
 
   {
     /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
     const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
     const int *headret[]={head1_1,head2_1,NULL};
-    
+
     fprintf(stderr,"testing basic page encoding... ");
     test_pack(packets,headret,0,0,0);
   }
 
   {
     /* nil packets; beginning,middle,end */
     const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
     const int *headret[]={head1_2,head2_2,NULL};
-    
+
     fprintf(stderr,"testing basic nil packets... ");
     test_pack(packets,headret,0,0,0);
   }
 
   {
     /* large initial packet */
     const int packets[]={4345,259,255,-1};
     const int *headret[]={head1_3,head2_3,NULL};
-    
+
     fprintf(stderr,"testing initial-packet lacing > 4k... ");
     test_pack(packets,headret,0,0,0);
   }
 
   {
-    /* continuing packet test */
-    const int packets[]={0,4345,259,255,-1};
+    /* continuing packet test; with page spill expansion, we have to
+       overflow the lacing table. */
+    const int packets[]={0,65500,259,255,-1};
     const int *headret[]={head1_4,head2_4,head3_4,NULL};
-    
+
     fprintf(stderr,"testing single packet page span... ");
     test_pack(packets,headret,0,0,0);
   }
 
+  {
+    /* spill expand packet test */
+    const int packets[]={0,4345,259,255,0,0,0,0,0,0,-1};
+    const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
+
+    fprintf(stderr,"testing page spill expansion... ");
+    test_pack(packets,headret,0,0,0);
+  }
+
   /* page with the 255 segment limit */
   {
 
     const int packets[]={0,10,10,10,10,10,10,10,10,
                    10,10,10,10,10,10,10,10,
                    10,10,10,10,10,10,10,10,
                    10,10,10,10,10,10,10,10,
                    10,10,10,10,10,10,10,10,
@@ -1552,48 +1748,48 @@ int main(void){
     const int *headret[]={head1_5,head2_5,head3_5,NULL};
     
     fprintf(stderr,"testing max packet segments... ");
     test_pack(packets,headret,0,0,0);
   }
 
   {
     /* packet that overspans over an entire page */
-    const int packets[]={0,100,9000,259,255,-1};
+    const int packets[]={0,100,130049,259,255,-1};
     const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
     
     fprintf(stderr,"testing very large packets... ");
     test_pack(packets,headret,0,0,0);
   }
 
   {
     /* test for the libogg 1.1.1 resync in large continuation bug
        found by Josh Coalson)  */
-    const int packets[]={0,100,9000,259,255,-1};
+    const int packets[]={0,100,130049,259,255,-1};
     const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
     
     fprintf(stderr,"testing continuation resync in very large packets... ");
     test_pack(packets,headret,100,2,3);
   }
 
   {
     /* term only page.  why not? */
-    const int packets[]={0,100,4080,-1};
+    const int packets[]={0,100,64770,-1};
     const int *headret[]={head1_7,head2_7,head3_7,NULL};
     
     fprintf(stderr,"testing zero data page (1 nil packet)... ");
     test_pack(packets,headret,0,0,0);
   }
 
 
 
   {
     /* build a bunch of pages for testing */
     unsigned char *data=_ogg_malloc(1024*1024);
-    int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1};
+    int pl[]={0, 0,0,0,0,1,1,98,4079, 0,0,0,0,1,1,2954,2057, 0,0,0,0,76,34,912,0,234,1000,1000, 1000,300,-1};
     int inptr=0,i,j;
     ogg_page og[5];
     
     ogg_stream_reset(&os_en);
 
     for(i=0;pl[i]!=-1;i++){
       ogg_packet op;
       int len=pl[i];
@@ -1644,27 +1840,47 @@ int main(void){
       ogg_sync_pageout(&oy,&temp);
       ogg_stream_pagein(&os_de,&temp);
 
       /* do we get the expected results/packets? */
       
       if(ogg_stream_packetout(&os_de,&test)!=1)error();
       checkpacket(&test,0,0,0);
       if(ogg_stream_packetout(&os_de,&test)!=1)error();
-      checkpacket(&test,100,1,-1);
+      checkpacket(&test,0,1,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,0,2,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,0,3,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,0,4,-1);
       if(ogg_stream_packetout(&os_de,&test)!=1)error();
-      checkpacket(&test,4079,2,3000);
+      checkpacket(&test,1,5,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,1,6,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,98,7,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,4079,8,9000);
       if(ogg_stream_packetout(&os_de,&test)!=-1){
         fprintf(stderr,"Error: loss of page did not return error\n");
         exit(1);
       }
       if(ogg_stream_packetout(&os_de,&test)!=1)error();
-      checkpacket(&test,76,5,-1);
+      checkpacket(&test,0,17,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,0,18,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,0,19,-1);
       if(ogg_stream_packetout(&os_de,&test)!=1)error();
-      checkpacket(&test,34,6,-1);
+      checkpacket(&test,0,20,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,76,21,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,34,22,-1);
       fprintf(stderr,"ok.\n");
     }
 
     /* Test lost pages on pagein/packetout: rollback with continuation */
     {
       ogg_page temp;
       ogg_packet test;
 
@@ -1687,81 +1903,107 @@ int main(void){
       ogg_sync_pageout(&oy,&temp);
       ogg_stream_pagein(&os_de,&temp);
       ogg_sync_pageout(&oy,&temp);
       /* skip */
       ogg_sync_pageout(&oy,&temp);
       ogg_stream_pagein(&os_de,&temp);
 
       /* do we get the expected results/packets? */
-      
+
       if(ogg_stream_packetout(&os_de,&test)!=1)error();
       checkpacket(&test,0,0,0);
       if(ogg_stream_packetout(&os_de,&test)!=1)error();
-      checkpacket(&test,100,1,-1);
+      checkpacket(&test,0,1,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,0,2,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,0,3,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,0,4,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,1,5,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,1,6,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,98,7,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,4079,8,9000);
       if(ogg_stream_packetout(&os_de,&test)!=1)error();
-      checkpacket(&test,4079,2,3000);
+      checkpacket(&test,0,9,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,0,10,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,0,11,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,0,12,-1);
       if(ogg_stream_packetout(&os_de,&test)!=1)error();
-      checkpacket(&test,2956,3,4000);
+      checkpacket(&test,1,13,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,1,14,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,2954,15,-1);
+      if(ogg_stream_packetout(&os_de,&test)!=1)error();
+      checkpacket(&test,2057,16,17000);
       if(ogg_stream_packetout(&os_de,&test)!=-1){
         fprintf(stderr,"Error: loss of page did not return error\n");
         exit(1);
       }
       if(ogg_stream_packetout(&os_de,&test)!=1)error();
-      checkpacket(&test,300,13,14000);
+      checkpacket(&test,300,29,30000);
       fprintf(stderr,"ok.\n");
     }
-    
+
     /* the rest only test sync */
     {
       ogg_page og_de;
       /* Test fractional page inputs: incomplete capture */
       fprintf(stderr,"Testing sync on partial inputs... ");
       ogg_sync_reset(&oy);
       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
              3);
       ogg_sync_wrote(&oy,3);
       if(ogg_sync_pageout(&oy,&og_de)>0)error();
-      
+
       /* Test fractional page inputs: incomplete fixed header */
       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
              20);
       ogg_sync_wrote(&oy,20);
       if(ogg_sync_pageout(&oy,&og_de)>0)error();
-      
+
       /* Test fractional page inputs: incomplete header */
       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
              5);
       ogg_sync_wrote(&oy,5);
       if(ogg_sync_pageout(&oy,&og_de)>0)error();
-      
+
       /* Test fractional page inputs: incomplete body */
-      
+
       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
              og[1].header_len-28);
       ogg_sync_wrote(&oy,og[1].header_len-28);
       if(ogg_sync_pageout(&oy,&og_de)>0)error();
-      
+
       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
       ogg_sync_wrote(&oy,1000);
       if(ogg_sync_pageout(&oy,&og_de)>0)error();
-      
+
       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
              og[1].body_len-1000);
       ogg_sync_wrote(&oy,og[1].body_len-1000);
       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
-      
+
       fprintf(stderr,"ok.\n");
     }
 
     /* Test fractional page inputs: page + incomplete capture */
     {
       ogg_page og_de;
       fprintf(stderr,"Testing sync on 1+partial inputs... ");
-      ogg_sync_reset(&oy); 
+      ogg_sync_reset(&oy);
 
       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
              og[1].header_len);
       ogg_sync_wrote(&oy,og[1].header_len);
 
       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
              og[1].body_len);
       ogg_sync_wrote(&oy,og[1].body_len);