changeset 15250:e891ff7a7b6c

update to libogg 1.1.2 (needed for Theora)
author henry
date Sun, 24 Apr 2005 08:37:48 +0000
parents 0deaa53ed5ad
children c39173a67cbb
files tremor/FILES tremor/bitwise.c tremor/framing.c tremor/ogg.h
diffstat 4 files changed, 610 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/tremor/FILES	Sun Apr 24 07:50:18 2005 +0000
+++ b/tremor/FILES	Sun Apr 24 08:37:48 2005 +0000
@@ -8,18 +8,15 @@
 1.0 Release:
 -----------
 backends.h
-bitwise.c
 block.c
 codebook.c
 codebook.h
 codec_internal.h
 config_types.h
-framing.c
 info.c
 ivorbiscodec.h
 lsp_lookup.h
 mapping0.c
-ogg.h
 os.h
 registry.c
 registry.h
@@ -41,5 +38,11 @@
 window.h
 window_lookup.h
 
+libogg 1.1.2:
+------------
+bitwise.c
+framing.c
+ogg.h
+
 Additional MPlayer-specific changes are contained in tremor.diff.
 This file should be updated with each modification of the Tremor code.
--- a/tremor/bitwise.c	Sun Apr 24 07:50:18 2005 +0000
+++ b/tremor/bitwise.c	Sun Apr 24 08:37:48 2005 +0000
@@ -1,14 +1,17 @@
 /********************************************************************
  *                                                                  *
- * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
- * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
- * ALL REDISTRIBUTION RIGHTS RESERVED.                              *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
+ * by the Xiph.Org Foundation http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
   function: packing variable sized words into an octet stream
+  last mod: $Id$
 
  ********************************************************************/
 
@@ -21,7 +24,7 @@
 
 #define BUFFER_INCREMENT 256
 
-static unsigned long mask[]=
+static const unsigned long mask[]=
 {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
  0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
  0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
@@ -30,12 +33,194 @@
  0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
  0x3fffffff,0x7fffffff,0xffffffff };
 
+static const unsigned int mask8B[]=
+{0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};
+
+void oggpack_writeinit(oggpack_buffer *b){
+  memset(b,0,sizeof(*b));
+  b->ptr=b->buffer=_ogg_malloc(BUFFER_INCREMENT);
+  b->buffer[0]='\0';
+  b->storage=BUFFER_INCREMENT;
+}
+
+void oggpackB_writeinit(oggpack_buffer *b){
+  oggpack_writeinit(b);
+}
+
+void oggpack_writetrunc(oggpack_buffer *b,long bits){
+  long bytes=bits>>3;
+  bits-=bytes*8;
+  b->ptr=b->buffer+bytes;
+  b->endbit=bits;
+  b->endbyte=bytes;
+  *b->ptr&=mask[bits];
+}
+
+void oggpackB_writetrunc(oggpack_buffer *b,long bits){
+  long bytes=bits>>3;
+  bits-=bytes*8;
+  b->ptr=b->buffer+bytes;
+  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){
+    b->buffer=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
+    b->storage+=BUFFER_INCREMENT;
+    b->ptr=b->buffer+b->endbyte;
+  }
+
+  value&=mask[bits]; 
+  bits+=b->endbit;
+
+  b->ptr[0]|=value<<b->endbit;  
+  
+  if(bits>=8){
+    b->ptr[1]=(unsigned char)(value>>(8-b->endbit));
+    if(bits>=16){
+      b->ptr[2]=(unsigned char)(value>>(16-b->endbit));
+      if(bits>=24){
+	b->ptr[3]=(unsigned char)(value>>(24-b->endbit));
+	if(bits>=32){
+	  if(b->endbit)
+	    b->ptr[4]=(unsigned char)(value>>(32-b->endbit));
+	  else
+	    b->ptr[4]=0;
+	}
+      }
+    }
+  }
+
+  b->endbyte+=bits/8;
+  b->ptr+=bits/8;
+  b->endbit=bits&7;
+}
+
+/* Takes only up to 32 bits. */
+void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){
+  if(b->endbyte+4>=b->storage){
+    b->buffer=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
+    b->storage+=BUFFER_INCREMENT;
+    b->ptr=b->buffer+b->endbyte;
+  }
+
+  value=(value&mask[bits])<<(32-bits); 
+  bits+=b->endbit;
+
+  b->ptr[0]|=value>>(24+b->endbit);  
+  
+  if(bits>=8){
+    b->ptr[1]=(unsigned char)(value>>(16+b->endbit));
+    if(bits>=16){
+      b->ptr[2]=(unsigned char)(value>>(8+b->endbit));
+      if(bits>=24){
+	b->ptr[3]=(unsigned char)(value>>(b->endbit));
+	if(bits>=32){
+	  if(b->endbit)
+	    b->ptr[4]=(unsigned char)(value<<(8-b->endbit));
+	  else
+	    b->ptr[4]=0;
+	}
+      }
+    }
+  }
+
+  b->endbyte+=bits/8;
+  b->ptr+=bits/8;
+  b->endbit=bits&7;
+}
+
+void oggpack_writealign(oggpack_buffer *b){
+  int bits=8-b->endbit;
+  if(bits<8)
+    oggpack_write(b,0,bits);
+}
+
+void oggpackB_writealign(oggpack_buffer *b){
+  int bits=8-b->endbit;
+  if(bits<8)
+    oggpackB_write(b,0,bits);
+}
+
+static void oggpack_writecopy_helper(oggpack_buffer *b,
+				     void *source,
+				     long bits,
+				     void (*w)(oggpack_buffer *,
+					       unsigned long,
+					       int),
+				     int msb){
+  unsigned char *ptr=(unsigned char *)source;
+
+  long bytes=bits/8;
+  bits-=bytes*8;
+
+  if(b->endbit){
+    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){
+      b->storage=b->endbyte+bytes+BUFFER_INCREMENT;
+      b->buffer=_ogg_realloc(b->buffer,b->storage);
+      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);    
+  }
+}
+
+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);
+}
+
+void oggpack_reset(oggpack_buffer *b){
+  b->ptr=b->buffer;
+  b->buffer[0]=0;
+  b->endbit=b->endbyte=0;
+}
+
+void oggpackB_reset(oggpack_buffer *b){
+  oggpack_reset(b);
+}
+
+void oggpack_writeclear(oggpack_buffer *b){
+  _ogg_free(b->buffer);
+  memset(b,0,sizeof(*b));
+}
+
+void oggpackB_writeclear(oggpack_buffer *b){
+  oggpack_writeclear(b);
+}
+
 void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
   memset(b,0,sizeof(*b));
   b->buffer=b->ptr=buf;
   b->storage=bytes;
 }
 
+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;
@@ -63,11 +248,43 @@
   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;
+
+  bits+=b->endbit;
+
+  if(b->endbyte+4>=b->storage){
+    /* not the main path */
+    if(b->endbyte*8+bits>b->storage*8)return(-1);
+  }
+  
+  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);
+      }
+    }
+  }
+  return ((ret&0xffffffff)>>(m>>1))>>((m+1)>>1);
+}
+
 long oggpack_look1(oggpack_buffer *b){
   if(b->endbyte>=b->storage)return(-1);
   return((b->ptr[0]>>b->endbit)&1);
 }
 
+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;
   b->ptr+=bits/8;
@@ -75,6 +292,10 @@
   b->endbit=bits&7;
 }
 
+void oggpackB_adv(oggpack_buffer *b,int bits){
+  oggpack_adv(b,bits);
+}
+
 void oggpack_adv1(oggpack_buffer *b){
   if(++(b->endbit)>7){
     b->endbit=0;
@@ -83,16 +304,20 @@
   }
 }
 
+void oggpackB_adv1(oggpack_buffer *b){
+  oggpack_adv1(b);
+}
+
 /* bits <= 32 */
 long oggpack_read(oggpack_buffer *b,int bits){
-  unsigned long ret;
+  long ret;
   unsigned long m=mask[bits];
 
   bits+=b->endbit;
 
   if(b->endbyte+4>=b->storage){
     /* not the main path */
-    ret=-1UL;
+    ret=-1L;
     if(b->endbyte*8+bits>b->storage*8)goto overflow;
   }
   
@@ -119,12 +344,47 @@
   return(ret);
 }
 
+/* bits <= 32 */
+long oggpackB_read(oggpack_buffer *b,int bits){
+  long ret;
+  long m=32-bits;
+  
+  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;
+  }
+  
+  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);
+}
+
 long oggpack_read1(oggpack_buffer *b){
-  unsigned long ret;
+  long ret;
   
   if(b->endbyte>=b->storage){
     /* not the main path */
-    ret=-1UL;
+    ret=-1L;
     goto overflow;
   }
 
@@ -141,4 +401,50 @@
   return(ret);
 }
 
+long oggpackB_read1(oggpack_buffer *b){
+  long ret;
+  
+  if(b->endbyte>=b->storage){
+    /* not the main path */
+    ret=-1L;
+    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);
+}
+
+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);
+}
+
+long oggpackB_bytes(oggpack_buffer *b){
+  return oggpack_bytes(b);
+}
+
+long oggpackB_bits(oggpack_buffer *b){
+  return oggpack_bits(b);
+}
+  
+unsigned char *oggpack_get_buffer(oggpack_buffer *b){
+  return(b->buffer);
+}
+
+unsigned char *oggpackB_get_buffer(oggpack_buffer *b){
+  return oggpack_get_buffer(b);
+}
+
 #undef BUFFER_INCREMENT
--- a/tremor/framing.c	Sun Apr 24 07:50:18 2005 +0000
+++ b/tremor/framing.c	Sun Apr 24 08:37:48 2005 +0000
@@ -1,15 +1,18 @@
 /********************************************************************
  *                                                                  *
- * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
- * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
- * ALL REDISTRIBUTION RIGHTS RESERVED.                              *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
+ * by the Xiph.Org Foundation http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
  function: code raw [Vorbis] packets into framed OggSquish stream and
            decode Ogg streams back into raw packets
+ last mod: $Id$
 
  note: The CRC code is directly derived from public domain code by
  Ross Williams (ross@guest.adelaide.edu.au).  See docs/framing.html
@@ -92,7 +95,29 @@
   return(count);
 }
 
-static ogg_uint32_t crc_lookup[256]={
+
+#if 0
+/* helper to initialize lookup for direct-table CRC (illustrative; we
+   use the static init below) */
+
+static ogg_uint32_t _ogg_crc_entry(unsigned long index){
+  int           i;
+  unsigned long r;
+
+  r = index << 24;
+  for (i=0; i<8; i++)
+    if (r & 0x80000000UL)
+      r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
+				    polynomial, although we use an
+				    unreflected alg and an init/final
+				    of 0, not 0xffffffff */
+    else
+       r<<=1;
+ return (r & 0xffffffffUL);
+}
+#endif
+
+static const ogg_uint32_t crc_lookup[256]={
   0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
   0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
   0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
@@ -164,11 +189,11 @@
   if(os){
     memset(os,0,sizeof(*os));
     os->body_storage=16*1024;
-    os->body_data=(unsigned char *)_ogg_malloc(os->body_storage*sizeof(*os->body_data));
+    os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
 
     os->lacing_storage=1024;
-    os->lacing_vals=(int *)_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
-    os->granule_vals=(ogg_int64_t *)_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
+    os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
+    os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
 
     os->serialno=serialno;
 
@@ -203,15 +228,15 @@
 static void _os_body_expand(ogg_stream_state *os,int needed){
   if(os->body_storage<=os->body_fill+needed){
     os->body_storage+=(needed+1024);
-    os->body_data=(unsigned char *)_ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data));
+    os->body_data=_ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data));
   }
 }
 
 static void _os_lacing_expand(ogg_stream_state *os,int needed){
   if(os->lacing_storage<=os->lacing_fill+needed){
     os->lacing_storage+=(needed+32);
-    os->lacing_vals=(int *)_ogg_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals));
-    os->granule_vals=(ogg_int64_t *)_ogg_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals));
+    os->lacing_vals=_ogg_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals));
+    os->granule_vals=_ogg_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals));
   }
 }
 
@@ -235,11 +260,205 @@
     for(i=0;i<og->body_len;i++)
       crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
     
-    og->header[22]=crc_reg&0xff;
-    og->header[23]=(crc_reg>>8)&0xff;
-    og->header[24]=(crc_reg>>16)&0xff;
-    og->header[25]=(crc_reg>>24)&0xff;
+    og->header[22]=(unsigned char)(crc_reg&0xff);
+    og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
+    og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
+    og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
+  }
+}
+
+/* submit data to the internal buffer of the framing engine */
+int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
+  int lacing_vals=op->bytes/255+1,i;
+
+  if(os->body_returned){
+    /* advance packet data according to the body_returned pointer. We
+       had to keep it around to return a pointer into the buffer last
+       call */
+    
+    os->body_fill-=os->body_returned;
+    if(os->body_fill)
+      memmove(os->body_data,os->body_data+os->body_returned,
+	      os->body_fill);
+    os->body_returned=0;
+  }
+ 
+  /* make sure we have the buffer storage */
+  _os_body_expand(os,op->bytes);
+  _os_lacing_expand(os,lacing_vals);
+
+  /* Copy in the submitted packet.  Yes, the copy is a waste; this is
+     the liability of overly clean abstraction for the time being.  It
+     will actually be fairly easy to eliminate the extra copy in the
+     future */
+
+  memcpy(os->body_data+os->body_fill,op->packet,op->bytes);
+  os->body_fill+=op->bytes;
+
+  /* Store lacing vals for this packet */
+  for(i=0;i<lacing_vals-1;i++){
+    os->lacing_vals[os->lacing_fill+i]=255;
+    os->granule_vals[os->lacing_fill+i]=os->granulepos;
+  }
+  os->lacing_vals[os->lacing_fill+i]=(op->bytes)%255;
+  os->granulepos=os->granule_vals[os->lacing_fill+i]=op->granulepos;
+
+  /* flag the first segment as the beginning of the packet */
+  os->lacing_vals[os->lacing_fill]|= 0x100;
+
+  os->lacing_fill+=lacing_vals;
+
+  /* for the sake of completeness */
+  os->packetno++;
+
+  if(op->e_o_s)os->e_o_s=1;
+
+  return(0);
+}
+
+/* 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){
+  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=os->granule_vals[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{
+    for(vals=0;vals<maxvals;vals++){
+      if(acc>4096)break;
+      acc+=os->lacing_vals[vals]&0x0ff;
+      granule_pos=os->granule_vals[vals];
+    }
   }
+  
+  /* 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;
+
+  /* 64 bits of PCM position */
+  for(i=6;i<14;i++){
+    os->header[i]=(unsigned char)(granule_pos&0xff);
+    granule_pos>>=8;
+  }
+
+  /* 32 bits of stream serial number */
+  {
+    long serialno=os->serialno;
+    for(i=14;i<18;i++){
+      os->header[i]=(unsigned char)(serialno&0xff);
+      serialno>>=8;
+    }
+  }
+
+  /* 32 bits of page counter (we have both counter and page header
+     because this val can roll over) */
+  if(os->pageno==-1)os->pageno=0; /* because someone called
+				     stream_reset; this would be a
+				     strange thing to do in an
+				     encode stream, but it has
+				     plausible uses */
+  {
+    long pageno=os->pageno++;
+    for(i=18;i<22;i++){
+      os->header[i]=(unsigned char)(pageno&0xff);
+      pageno>>=8;
+    }
+  }
+  
+  /* zero for computation; filled in later */
+  os->header[22]=0;
+  os->header[23]=0;
+  os->header[24]=0;
+  os->header[25]=0;
+  
+  /* segment table */
+  os->header[26]=(unsigned char)(vals&0xff);
+  for(i=0;i<vals;i++)
+    bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
+  
+  /* set pointers in the ogg_page struct */
+  og->header=os->header;
+  og->header_len=os->header_fill=vals+27;
+  og->body=os->body_data+os->body_returned;
+  og->body_len=bytes;
+  
+  /* advance the lacing data and set the body_returned pointer */
+  
+  os->lacing_fill-=vals;
+  memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
+  memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
+  os->body_returned+=bytes;
+  
+  /* calculate the checksum */
+  
+  ogg_page_checksum_set(og);
+
+  /* done */
+  return(1);
+}
+
+
+/* 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){
+
+  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);
+}
+
+int ogg_stream_eos(ogg_stream_state *os){
+  return os->e_o_s;
 }
 
 /* DECODING PRIMITIVES: packet streaming layer **********************/
@@ -286,7 +505,7 @@
 char *ogg_sync_buffer(ogg_sync_state *oy, long size){
 
   /* first, clear out any space that has been previously returned */
-  if(oy->returned>8192){
+  if(oy->returned){
     oy->fill-=oy->returned;
     if(oy->fill>0)
       memmove(oy->data,oy->data+oy->returned,oy->fill);
@@ -298,9 +517,9 @@
     long newsize=size+oy->fill+4096; /* an extra page to be nice */
 
     if(oy->data)
-      oy->data=(unsigned char *)_ogg_realloc(oy->data,newsize);
+      oy->data=_ogg_realloc(oy->data,newsize);
     else
-      oy->data=(unsigned char *)_ogg_malloc(newsize);
+      oy->data=_ogg_malloc(newsize);
     oy->storage=newsize;
   }
 
@@ -401,7 +620,7 @@
   oy->bodybytes=0;
   
   /* search for possible capture */
-  next=(unsigned char *)memchr(page+1,'O',bytes-1);
+  next=memchr(page+1,'O',bytes-1);
   if(!next)
     next=oy->data+oy->fill;
 
@@ -426,7 +645,7 @@
      buffer.  If it doesn't verify, we look for the next potential
      frame */
 
-  while(1){
+  for(;;){
     long ret=ogg_sync_pageseek(oy,og);
     if(ret>0){
       /* have a page */
@@ -472,14 +691,14 @@
     long br=os->body_returned;
 
     /* body data */
-    if(br>8192){
+    if(br){
       os->body_fill-=br;
       if(os->body_fill)
 	memmove(os->body_data,os->body_data+br,os->body_fill);
       os->body_returned=0;
     }
 
-    if(lr>8192){
+    if(lr){
       /* segment table */
       if(os->lacing_fill-lr){
 	memmove(os->lacing_vals,os->lacing_vals+lr,
@@ -513,10 +732,13 @@
       os->lacing_vals[os->lacing_fill++]=0x400;
       os->lacing_packet++;
     }
+  }
 
-    /* are we a 'continued packet' page?  If so, we'll need to skip
-       some segments */
-    if(continued){
+  /* are we a 'continued packet' page?  If so, we may need to skip
+     some segments */
+  if(continued){
+    if(os->lacing_fill<1 || 
+       os->lacing_vals[os->lacing_fill-1]==0x400){
       bos=0;
       for(;segptr<segments;segptr++){
 	int val=header[27+segptr];
@@ -603,6 +825,12 @@
   return(0);
 }
 
+int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
+  ogg_stream_reset(os);
+  os->serialno=serialno;
+  return(0);
+}
+
 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
 
   /* The last part of decode. We have the stream broken into packet
--- a/tremor/ogg.h	Sun Apr 24 07:50:18 2005 +0000
+++ b/tremor/ogg.h	Sun Apr 24 08:37:48 2005 +0000
@@ -1,14 +1,17 @@
 /********************************************************************
  *                                                                  *
- * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
- * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
- * ALL REDISTRIBUTION RIGHTS RESERVED.                              *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
+ * by the Xiph.Org Foundation http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
- function: subsumed libogg includes
+ function: toplevel libogg include
+ last mod: $Id$
 
  ********************************************************************/
 #ifndef _OGG_H
@@ -107,15 +110,16 @@
 /* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
 
 extern void  oggpack_writeinit(oggpack_buffer *b);
+extern void  oggpack_writetrunc(oggpack_buffer *b,long bits);
+extern void  oggpack_writealign(oggpack_buffer *b);
+extern void  oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
 extern void  oggpack_reset(oggpack_buffer *b);
 extern void  oggpack_writeclear(oggpack_buffer *b);
 extern void  oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
 extern void  oggpack_write(oggpack_buffer *b,unsigned long value,int bits);
 extern long  oggpack_look(oggpack_buffer *b,int bits);
-extern long  oggpack_look_huff(oggpack_buffer *b,int bits);
 extern long  oggpack_look1(oggpack_buffer *b);
 extern void  oggpack_adv(oggpack_buffer *b,int bits);
-extern int   oggpack_adv_huff(oggpack_buffer *b,int bits);
 extern void  oggpack_adv1(oggpack_buffer *b);
 extern long  oggpack_read(oggpack_buffer *b,int bits);
 extern long  oggpack_read1(oggpack_buffer *b);
@@ -123,6 +127,30 @@
 extern long  oggpack_bits(oggpack_buffer *b);
 extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);
 
+extern void  oggpackB_writeinit(oggpack_buffer *b);
+extern void  oggpackB_writetrunc(oggpack_buffer *b,long bits);
+extern void  oggpackB_writealign(oggpack_buffer *b);
+extern void  oggpackB_writecopy(oggpack_buffer *b,void *source,long bits);
+extern void  oggpackB_reset(oggpack_buffer *b);
+extern void  oggpackB_writeclear(oggpack_buffer *b);
+extern void  oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
+extern void  oggpackB_write(oggpack_buffer *b,unsigned long value,int bits);
+extern long  oggpackB_look(oggpack_buffer *b,int bits);
+extern long  oggpackB_look1(oggpack_buffer *b);
+extern void  oggpackB_adv(oggpack_buffer *b,int bits);
+extern void  oggpackB_adv1(oggpack_buffer *b);
+extern long  oggpackB_read(oggpack_buffer *b,int bits);
+extern long  oggpackB_read1(oggpack_buffer *b);
+extern long  oggpackB_bytes(oggpack_buffer *b);
+extern long  oggpackB_bits(oggpack_buffer *b);
+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_pageout(ogg_stream_state *os, ogg_page *og);
+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);
@@ -143,6 +171,7 @@
 extern int      ogg_stream_init(ogg_stream_state *os,int serialno);
 extern int      ogg_stream_clear(ogg_stream_state *os);
 extern int      ogg_stream_reset(ogg_stream_state *os);
+extern int      ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
 extern int      ogg_stream_destroy(ogg_stream_state *os);
 extern int      ogg_stream_eos(ogg_stream_state *os);