vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

framing.c (49564B)


      1 /********************************************************************
      2  *                                                                  *
      3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
      4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
      5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
      6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
      7  *                                                                  *
      8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
      9  * by the Xiph.Org Foundation http://www.xiph.org/                  *
     10  *                                                                  *
     11  ********************************************************************
     12 
     13  function: code raw [Vorbis] packets into framed OggSquish stream and
     14            decode Ogg streams back into raw packets
     15  last mod: $Id: framing.c 1919 2005-07-24 14:18:04Z baford $
     16 
     17  note: The CRC code is directly derived from public domain code by
     18  Ross Williams (ross@guest.adelaide.edu.au).  See docs/framing.html
     19  for details.
     20 
     21  ********************************************************************/
     22 
     23 #include <stdlib.h>
     24 #include <string.h>
     25 #include <ogg/ogg.h>
     26 
     27 /* A complete description of Ogg framing exists in docs/framing.html */
     28 
     29 int ogg_page_version(ogg_page *og){
     30   return((int)(og->header[4]));
     31 }
     32 
     33 int ogg_page_continued(ogg_page *og){
     34   return((int)(og->header[5]&0x01));
     35 }
     36 
     37 int ogg_page_bos(ogg_page *og){
     38   return((int)(og->header[5]&0x02));
     39 }
     40 
     41 int ogg_page_eos(ogg_page *og){
     42   return((int)(og->header[5]&0x04));
     43 }
     44 
     45 ogg_int64_t ogg_page_granulepos(ogg_page *og){
     46   unsigned char *page=og->header;
     47   ogg_int64_t granulepos=page[13]&(0xff);
     48   granulepos= (granulepos<<8)|(page[12]&0xff);
     49   granulepos= (granulepos<<8)|(page[11]&0xff);
     50   granulepos= (granulepos<<8)|(page[10]&0xff);
     51   granulepos= (granulepos<<8)|(page[9]&0xff);
     52   granulepos= (granulepos<<8)|(page[8]&0xff);
     53   granulepos= (granulepos<<8)|(page[7]&0xff);
     54   granulepos= (granulepos<<8)|(page[6]&0xff);
     55   return(granulepos);
     56 }
     57 
     58 int ogg_page_serialno(ogg_page *og){
     59   return(og->header[14] |
     60 	 (og->header[15]<<8) |
     61 	 (og->header[16]<<16) |
     62 	 (og->header[17]<<24));
     63 }
     64  
     65 long ogg_page_pageno(ogg_page *og){
     66   return(og->header[18] |
     67 	 (og->header[19]<<8) |
     68 	 (og->header[20]<<16) |
     69 	 (og->header[21]<<24));
     70 }
     71 
     72 
     73 
     74 /* returns the number of packets that are completed on this page (if
     75    the leading packet is begun on a previous page, but ends on this
     76    page, it's counted */
     77 
     78 /* NOTE:
     79 If a page consists of a packet begun on a previous page, and a new
     80 packet begun (but not completed) on this page, the return will be:
     81   ogg_page_packets(page)   ==1, 
     82   ogg_page_continued(page) !=0
     83 
     84 If a page happens to be a single packet that was begun on a
     85 previous page, and spans to the next page (in the case of a three or
     86 more page packet), the return will be: 
     87   ogg_page_packets(page)   ==0, 
     88   ogg_page_continued(page) !=0
     89 */
     90 
     91 int ogg_page_packets(ogg_page *og){
     92   int i,n=og->header[26],count=0;
     93   for(i=0;i<n;i++)
     94     if(og->header[27+i]<255)count++;
     95   return(count);
     96 }
     97 
     98 
     99 #if 0
    100 /* helper to initialize lookup for direct-table CRC (illustrative; we
    101    use the static init below) */
    102 
    103 static ogg_uint32_t _ogg_crc_entry(unsigned long index){
    104   int           i;
    105   unsigned long r;
    106 
    107   r = index << 24;
    108   for (i=0; i<8; i++)
    109     if (r & 0x80000000UL)
    110       r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
    111 				    polynomial, although we use an
    112 				    unreflected alg and an init/final
    113 				    of 0, not 0xffffffff */
    114     else
    115        r<<=1;
    116  return (r & 0xffffffffUL);
    117 }
    118 #endif
    119 
    120 static ogg_uint32_t crc_lookup[256]={
    121   0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
    122   0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
    123   0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
    124   0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
    125   0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
    126   0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
    127   0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
    128   0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
    129   0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
    130   0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
    131   0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
    132   0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
    133   0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
    134   0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
    135   0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
    136   0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
    137   0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
    138   0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
    139   0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
    140   0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
    141   0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
    142   0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
    143   0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
    144   0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
    145   0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
    146   0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
    147   0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
    148   0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
    149   0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
    150   0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
    151   0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
    152   0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
    153   0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
    154   0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
    155   0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
    156   0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
    157   0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
    158   0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
    159   0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
    160   0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
    161   0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
    162   0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
    163   0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
    164   0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
    165   0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
    166   0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
    167   0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
    168   0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
    169   0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
    170   0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
    171   0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
    172   0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
    173   0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
    174   0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
    175   0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
    176   0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
    177   0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
    178   0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
    179   0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
    180   0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
    181   0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
    182   0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
    183   0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
    184   0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4};
    185 
    186 /* init the encode/decode logical stream state */
    187 
    188 int ogg_stream_init(ogg_stream_state *os,int serialno){
    189   if(os){
    190     memset(os,0,sizeof(*os));
    191     os->body_storage=16*1024;
    192     os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
    193 
    194     os->lacing_storage=1024;
    195     os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
    196     os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
    197 
    198     os->serialno=serialno;
    199 
    200     return(0);
    201   }
    202   return(-1);
    203 } 
    204 
    205 /* _clear does not free os, only the non-flat storage within */
    206 int ogg_stream_clear(ogg_stream_state *os){
    207   if(os){
    208     if(os->body_data)_ogg_free(os->body_data);
    209     if(os->lacing_vals)_ogg_free(os->lacing_vals);
    210     if(os->granule_vals)_ogg_free(os->granule_vals);
    211 
    212     memset(os,0,sizeof(*os));    
    213   }
    214   return(0);
    215 } 
    216 
    217 int ogg_stream_destroy(ogg_stream_state *os){
    218   if(os){
    219     ogg_stream_clear(os);
    220     _ogg_free(os);
    221   }
    222   return(0);
    223 } 
    224 
    225 /* Helpers for ogg_stream_encode; this keeps the structure and
    226    what's happening fairly clear */
    227 
    228 static void _os_body_expand(ogg_stream_state *os,int needed){
    229   if(os->body_storage<=os->body_fill+needed){
    230     os->body_storage+=(needed+1024);
    231     os->body_data=_ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data));
    232   }
    233 }
    234 
    235 static void _os_lacing_expand(ogg_stream_state *os,int needed){
    236   if(os->lacing_storage<=os->lacing_fill+needed){
    237     os->lacing_storage+=(needed+32);
    238     os->lacing_vals=_ogg_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals));
    239     os->granule_vals=_ogg_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals));
    240   }
    241 }
    242 
    243 /* checksum the page */
    244 /* Direct table CRC; note that this will be faster in the future if we
    245    perform the checksum silmultaneously with other copies */
    246 
    247 void ogg_page_checksum_set(ogg_page *og){
    248   if(og){
    249     ogg_uint32_t crc_reg=0;
    250     int i;
    251 
    252     /* safety; needed for API behavior, but not framing code */
    253     og->header[22]=0;
    254     og->header[23]=0;
    255     og->header[24]=0;
    256     og->header[25]=0;
    257     
    258     for(i=0;i<og->header_len;i++)
    259       crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
    260     for(i=0;i<og->body_len;i++)
    261       crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
    262     
    263     og->header[22]=crc_reg&0xff;
    264     og->header[23]=(crc_reg>>8)&0xff;
    265     og->header[24]=(crc_reg>>16)&0xff;
    266     og->header[25]=(crc_reg>>24)&0xff;
    267   }
    268 }
    269 
    270 /* submit data to the internal buffer of the framing engine */
    271 int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
    272   int lacing_vals=op->bytes/255+1,i;
    273 
    274   if(os->body_returned){
    275     /* advance packet data according to the body_returned pointer. We
    276        had to keep it around to return a pointer into the buffer last
    277        call */
    278     
    279     os->body_fill-=os->body_returned;
    280     if(os->body_fill)
    281       memmove(os->body_data,os->body_data+os->body_returned,
    282 	      os->body_fill);
    283     os->body_returned=0;
    284   }
    285  
    286   /* make sure we have the buffer storage */
    287   _os_body_expand(os,op->bytes);
    288   _os_lacing_expand(os,lacing_vals);
    289 
    290   /* Copy in the submitted packet.  Yes, the copy is a waste; this is
    291      the liability of overly clean abstraction for the time being.  It
    292      will actually be fairly easy to eliminate the extra copy in the
    293      future */
    294 
    295   memcpy(os->body_data+os->body_fill,op->packet,op->bytes);
    296   os->body_fill+=op->bytes;
    297 
    298   /* Store lacing vals for this packet */
    299   for(i=0;i<lacing_vals-1;i++){
    300     os->lacing_vals[os->lacing_fill+i]=255;
    301     os->granule_vals[os->lacing_fill+i]=os->granulepos;
    302   }
    303   os->lacing_vals[os->lacing_fill+i]=(op->bytes)%255;
    304   os->granulepos=os->granule_vals[os->lacing_fill+i]=op->granulepos;
    305 
    306   /* flag the first segment as the beginning of the packet */
    307   os->lacing_vals[os->lacing_fill]|= 0x100;
    308 
    309   os->lacing_fill+=lacing_vals;
    310 
    311   /* for the sake of completeness */
    312   os->packetno++;
    313 
    314   if(op->e_o_s)os->e_o_s=1;
    315 
    316   return(0);
    317 }
    318 
    319 /* This will flush remaining packets into a page (returning nonzero),
    320    even if there is not enough data to trigger a flush normally
    321    (undersized page). If there are no packets or partial packets to
    322    flush, ogg_stream_flush returns 0.  Note that ogg_stream_flush will
    323    try to flush a normal sized page like ogg_stream_pageout; a call to
    324    ogg_stream_flush does not guarantee that all packets have flushed.
    325    Only a return value of 0 from ogg_stream_flush indicates all packet
    326    data is flushed into pages.
    327 
    328    since ogg_stream_flush will flush the last page in a stream even if
    329    it's undersized, you almost certainly want to use ogg_stream_pageout
    330    (and *not* ogg_stream_flush) unless you specifically need to flush 
    331    an page regardless of size in the middle of a stream. */
    332 
    333 int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
    334   int i;
    335   int vals=0;
    336   int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
    337   int bytes=0;
    338   long acc=0;
    339   ogg_int64_t granule_pos=os->granule_vals[0];
    340 
    341   if(maxvals==0)return(0);
    342   
    343   /* construct a page */
    344   /* decide how many segments to include */
    345   
    346   /* If this is the initial header case, the first page must only include
    347      the initial header packet */
    348   if(os->b_o_s==0){  /* 'initial header page' case */
    349     granule_pos=0;
    350     for(vals=0;vals<maxvals;vals++){
    351       if((os->lacing_vals[vals]&0x0ff)<255){
    352 	vals++;
    353 	break;
    354       }
    355     }
    356   }else{
    357     for(vals=0;vals<maxvals;vals++){
    358       if(acc>4096)break;
    359       acc+=os->lacing_vals[vals]&0x0ff;
    360       granule_pos=os->granule_vals[vals];
    361     }
    362   }
    363   
    364   /* construct the header in temp storage */
    365   memcpy(os->header,"OggS",4);
    366   
    367   /* stream structure version */
    368   os->header[4]=0x00;
    369   
    370   /* continued packet flag? */
    371   os->header[5]=0x00;
    372   if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
    373   /* first page flag? */
    374   if(os->b_o_s==0)os->header[5]|=0x02;
    375   /* last page flag? */
    376   if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
    377   os->b_o_s=1;
    378 
    379   /* 64 bits of PCM position */
    380   for(i=6;i<14;i++){
    381     os->header[i]=(granule_pos&0xff);
    382     granule_pos>>=8;
    383   }
    384 
    385   /* 32 bits of stream serial number */
    386   {
    387     long serialno=os->serialno;
    388     for(i=14;i<18;i++){
    389       os->header[i]=(serialno&0xff);
    390       serialno>>=8;
    391     }
    392   }
    393 
    394   /* 32 bits of page counter (we have both counter and page header
    395      because this val can roll over) */
    396   if(os->pageno==-1)os->pageno=0; /* because someone called
    397 				     stream_reset; this would be a
    398 				     strange thing to do in an
    399 				     encode stream, but it has
    400 				     plausible uses */
    401   {
    402     long pageno=os->pageno++;
    403     for(i=18;i<22;i++){
    404       os->header[i]=(pageno&0xff);
    405       pageno>>=8;
    406     }
    407   }
    408   
    409   /* zero for computation; filled in later */
    410   os->header[22]=0;
    411   os->header[23]=0;
    412   os->header[24]=0;
    413   os->header[25]=0;
    414   
    415   /* segment table */
    416   os->header[26]=vals&0xff;
    417   for(i=0;i<vals;i++)
    418     bytes+=os->header[i+27]=(os->lacing_vals[i]&0xff);
    419   
    420   /* set pointers in the ogg_page struct */
    421   og->header=os->header;
    422   og->header_len=os->header_fill=vals+27;
    423   og->body=os->body_data+os->body_returned;
    424   og->body_len=bytes;
    425   
    426   /* advance the lacing data and set the body_returned pointer */
    427   
    428   os->lacing_fill-=vals;
    429   memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
    430   memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
    431   os->body_returned+=bytes;
    432   
    433   /* calculate the checksum */
    434   
    435   ogg_page_checksum_set(og);
    436 
    437   /* done */
    438   return(1);
    439 }
    440 
    441 
    442 /* This constructs pages from buffered packet segments.  The pointers
    443 returned are to static buffers; do not free. The returned buffers are
    444 good only until the next call (using the same ogg_stream_state) */
    445 
    446 int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
    447 
    448   if((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
    449      os->body_fill-os->body_returned > 4096 ||/* 'page nominal size' case */
    450      os->lacing_fill>=255 ||                  /* 'segment table full' case */
    451      (os->lacing_fill&&!os->b_o_s)){          /* 'initial header page' case */
    452         
    453     return(ogg_stream_flush(os,og));
    454   }
    455   
    456   /* not enough data to construct a page and not end of stream */
    457   return(0);
    458 }
    459 
    460 int ogg_stream_eos(ogg_stream_state *os){
    461   return os->e_o_s;
    462 }
    463 
    464 /* DECODING PRIMITIVES: packet streaming layer **********************/
    465 
    466 /* This has two layers to place more of the multi-serialno and paging
    467    control in the application's hands.  First, we expose a data buffer
    468    using ogg_sync_buffer().  The app either copies into the
    469    buffer, or passes it directly to read(), etc.  We then call
    470    ogg_sync_wrote() to tell how many bytes we just added.
    471 
    472    Pages are returned (pointers into the buffer in ogg_sync_state)
    473    by ogg_sync_pageout().  The page is then submitted to
    474    ogg_stream_pagein() along with the appropriate
    475    ogg_stream_state* (ie, matching serialno).  We then get raw
    476    packets out calling ogg_stream_packetout() with a
    477    ogg_stream_state.  See the 'frame-prog.txt' docs for details and
    478    example code. */
    479 
    480 /* initialize the struct to a known state */
    481 int ogg_sync_init(ogg_sync_state *oy){
    482   if(oy){
    483     memset(oy,0,sizeof(*oy));
    484   }
    485   return(0);
    486 }
    487 
    488 /* clear non-flat storage within */
    489 int ogg_sync_clear(ogg_sync_state *oy){
    490   if(oy){
    491     if(oy->data)_ogg_free(oy->data);
    492     ogg_sync_init(oy);
    493   }
    494   return(0);
    495 }
    496 
    497 int ogg_sync_destroy(ogg_sync_state *oy){
    498   if(oy){
    499     ogg_sync_clear(oy);
    500     _ogg_free(oy);
    501   }
    502   return(0);
    503 }
    504 
    505 char *ogg_sync_buffer(ogg_sync_state *oy, long size){
    506 
    507   /* first, clear out any space that has been previously returned */
    508   if(oy->returned){
    509     oy->fill-=oy->returned;
    510     if(oy->fill>0)
    511       memmove(oy->data,oy->data+oy->returned,oy->fill);
    512     oy->returned=0;
    513   }
    514 
    515   if(size>oy->storage-oy->fill){
    516     /* We need to extend the internal buffer */
    517     long newsize=size+oy->fill+4096; /* an extra page to be nice */
    518 
    519     if(oy->data)
    520       oy->data=_ogg_realloc(oy->data,newsize);
    521     else
    522       oy->data=_ogg_malloc(newsize);
    523     oy->storage=newsize;
    524   }
    525 
    526   /* expose a segment at least as large as requested at the fill mark */
    527   return((char *)oy->data+oy->fill);
    528 }
    529 
    530 int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
    531   if(oy->fill+bytes>oy->storage)return(-1);
    532   oy->fill+=bytes;
    533   return(0);
    534 }
    535 
    536 /* sync the stream.  This is meant to be useful for finding page
    537    boundaries.
    538 
    539    return values for this:
    540   -n) skipped n bytes
    541    0) page not ready; more data (no bytes skipped)
    542    n) page synced at current location; page length n bytes
    543    
    544 */
    545 
    546 long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
    547   unsigned char *page=oy->data+oy->returned;
    548   unsigned char *next;
    549   long bytes=oy->fill-oy->returned;
    550   
    551   if(oy->headerbytes==0){
    552     int headerbytes,i;
    553     if(bytes<27)return(0); /* not enough for a header */
    554     
    555     /* verify capture pattern */
    556     if(memcmp(page,"OggS",4))goto sync_fail;
    557     
    558     headerbytes=page[26]+27;
    559     if(bytes<headerbytes)return(0); /* not enough for header + seg table */
    560     
    561     /* count up body length in the segment table */
    562     
    563     for(i=0;i<page[26];i++)
    564       oy->bodybytes+=page[27+i];
    565     oy->headerbytes=headerbytes;
    566   }
    567   
    568   if(oy->bodybytes+oy->headerbytes>bytes)return(0);
    569   
    570   /* The whole test page is buffered.  Verify the checksum */
    571   {
    572     /* Grab the checksum bytes, set the header field to zero */
    573     char chksum[4];
    574     ogg_page log;
    575     
    576     memcpy(chksum,page+22,4);
    577     memset(page+22,0,4);
    578     
    579     /* set up a temp page struct and recompute the checksum */
    580     log.header=page;
    581     log.header_len=oy->headerbytes;
    582     log.body=page+oy->headerbytes;
    583     log.body_len=oy->bodybytes;
    584     ogg_page_checksum_set(&log);
    585     
    586     /* Compare */
    587     if(memcmp(chksum,page+22,4)){
    588       /* D'oh.  Mismatch! Corrupt page (or miscapture and not a page
    589 	 at all) */
    590       /* replace the computed checksum with the one actually read in */
    591       memcpy(page+22,chksum,4);
    592       
    593       /* Bad checksum. Lose sync */
    594       goto sync_fail;
    595     }
    596   }
    597   
    598   /* yes, have a whole page all ready to go */
    599   {
    600     unsigned char *page=oy->data+oy->returned;
    601     long bytes;
    602 
    603     if(og){
    604       og->header=page;
    605       og->header_len=oy->headerbytes;
    606       og->body=page+oy->headerbytes;
    607       og->body_len=oy->bodybytes;
    608     }
    609 
    610     oy->unsynced=0;
    611     oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
    612     oy->headerbytes=0;
    613     oy->bodybytes=0;
    614     return(bytes);
    615   }
    616   
    617  sync_fail:
    618   
    619   oy->headerbytes=0;
    620   oy->bodybytes=0;
    621   
    622   /* search for possible capture */
    623   next=memchr(page+1,'O',bytes-1);
    624   if(!next)
    625     next=oy->data+oy->fill;
    626 
    627   oy->returned=next-oy->data;
    628   return(-(next-page));
    629 }
    630 
    631 /* sync the stream and get a page.  Keep trying until we find a page.
    632    Supress 'sync errors' after reporting the first.
    633 
    634    return values:
    635    -1) recapture (hole in data)
    636     0) need more data
    637     1) page returned
    638 
    639    Returns pointers into buffered data; invalidated by next call to
    640    _stream, _clear, _init, or _buffer */
    641 
    642 int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
    643 
    644   /* all we need to do is verify a page at the head of the stream
    645      buffer.  If it doesn't verify, we look for the next potential
    646      frame */
    647 
    648   while(1){
    649     long ret=ogg_sync_pageseek(oy,og);
    650     if(ret>0){
    651       /* have a page */
    652       return(1);
    653     }
    654     if(ret==0){
    655       /* need more data */
    656       return(0);
    657     }
    658     
    659     /* head did not start a synced page... skipped some bytes */
    660     if(!oy->unsynced){
    661       oy->unsynced=1;
    662       return(-1);
    663     }
    664 
    665     /* loop. keep looking */
    666 
    667   }
    668 }
    669 
    670 /* add the incoming page to the stream state; we decompose the page
    671    into packet segments here as well. */
    672 
    673 int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
    674   unsigned char *header=og->header;
    675   unsigned char *body=og->body;
    676   long           bodysize=og->body_len;
    677   int            segptr=0;
    678 
    679   int version=ogg_page_version(og);
    680   int continued=ogg_page_continued(og);
    681   int bos=ogg_page_bos(og);
    682   int eos=ogg_page_eos(og);
    683   ogg_int64_t granulepos=ogg_page_granulepos(og);
    684   int serialno=ogg_page_serialno(og);
    685   long pageno=ogg_page_pageno(og);
    686   int segments=header[26];
    687   
    688   /* clean up 'returned data' */
    689   {
    690     long lr=os->lacing_returned;
    691     long br=os->body_returned;
    692 
    693     /* body data */
    694     if(br){
    695       os->body_fill-=br;
    696       if(os->body_fill)
    697 	memmove(os->body_data,os->body_data+br,os->body_fill);
    698       os->body_returned=0;
    699     }
    700 
    701     if(lr){
    702       /* segment table */
    703       if(os->lacing_fill-lr){
    704 	memmove(os->lacing_vals,os->lacing_vals+lr,
    705 		(os->lacing_fill-lr)*sizeof(*os->lacing_vals));
    706 	memmove(os->granule_vals,os->granule_vals+lr,
    707 		(os->lacing_fill-lr)*sizeof(*os->granule_vals));
    708       }
    709       os->lacing_fill-=lr;
    710       os->lacing_packet-=lr;
    711       os->lacing_returned=0;
    712     }
    713   }
    714 
    715   /* check the serial number */
    716   if(serialno!=os->serialno)return(-1);
    717   if(version>0)return(-1);
    718 
    719   _os_lacing_expand(os,segments+1);
    720 
    721   /* are we in sequence? */
    722   if(pageno!=os->pageno){
    723     int i;
    724 
    725     /* unroll previous partial packet (if any) */
    726     for(i=os->lacing_packet;i<os->lacing_fill;i++)
    727       os->body_fill-=os->lacing_vals[i]&0xff;
    728     os->lacing_fill=os->lacing_packet;
    729 
    730     /* make a note of dropped data in segment table */
    731     if(os->pageno!=-1){
    732       os->lacing_vals[os->lacing_fill++]=0x400;
    733       os->lacing_packet++;
    734     }
    735 
    736     /* are we a 'continued packet' page?  If so, we'll need to skip
    737        some segments */
    738     if(continued){
    739       bos=0;
    740       for(;segptr<segments;segptr++){
    741 	int val=header[27+segptr];
    742 	body+=val;
    743 	bodysize-=val;
    744 	if(val<255){
    745 	  segptr++;
    746 	  break;
    747 	}
    748       }
    749     }
    750   }
    751   
    752   if(bodysize){
    753     _os_body_expand(os,bodysize);
    754     memcpy(os->body_data+os->body_fill,body,bodysize);
    755     os->body_fill+=bodysize;
    756   }
    757 
    758   {
    759     int saved=-1;
    760     while(segptr<segments){
    761       int val=header[27+segptr];
    762       os->lacing_vals[os->lacing_fill]=val;
    763       os->granule_vals[os->lacing_fill]=-1;
    764       
    765       if(bos){
    766 	os->lacing_vals[os->lacing_fill]|=0x100;
    767 	bos=0;
    768       }
    769       
    770       if(val<255)saved=os->lacing_fill;
    771       
    772       os->lacing_fill++;
    773       segptr++;
    774       
    775       if(val<255)os->lacing_packet=os->lacing_fill;
    776     }
    777   
    778     /* set the granulepos on the last granuleval of the last full packet */
    779     if(saved!=-1){
    780       os->granule_vals[saved]=granulepos;
    781     }
    782 
    783   }
    784 
    785   if(eos){
    786     os->e_o_s=1;
    787     if(os->lacing_fill>0)
    788       os->lacing_vals[os->lacing_fill-1]|=0x200;
    789   }
    790 
    791   os->pageno=pageno+1;
    792 
    793   return(0);
    794 }
    795 
    796 /* clear things to an initial state.  Good to call, eg, before seeking */
    797 int ogg_sync_reset(ogg_sync_state *oy){
    798   oy->fill=0;
    799   oy->returned=0;
    800   oy->unsynced=0;
    801   oy->headerbytes=0;
    802   oy->bodybytes=0;
    803   return(0);
    804 }
    805 
    806 int ogg_stream_reset(ogg_stream_state *os){
    807   os->body_fill=0;
    808   os->body_returned=0;
    809 
    810   os->lacing_fill=0;
    811   os->lacing_packet=0;
    812   os->lacing_returned=0;
    813 
    814   os->header_fill=0;
    815 
    816   os->e_o_s=0;
    817   os->b_o_s=0;
    818   os->pageno=-1;
    819   os->packetno=0;
    820   os->granulepos=0;
    821 
    822   return(0);
    823 }
    824 
    825 int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
    826   ogg_stream_reset(os);
    827   os->serialno=serialno;
    828   return(0);
    829 }
    830 
    831 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
    832 
    833   /* The last part of decode. We have the stream broken into packet
    834      segments.  Now we need to group them into packets (or return the
    835      out of sync markers) */
    836 
    837   int ptr=os->lacing_returned;
    838 
    839   if(os->lacing_packet<=ptr)return(0);
    840 
    841   if(os->lacing_vals[ptr]&0x400){
    842     /* we need to tell the codec there's a gap; it might need to
    843        handle previous packet dependencies. */
    844     os->lacing_returned++;
    845     os->packetno++;
    846     return(-1);
    847   }
    848 
    849   if(!op && !adv)return(1); /* just using peek as an inexpensive way
    850                                to ask if there's a whole packet
    851                                waiting */
    852 
    853   /* Gather the whole packet. We'll have no holes or a partial packet */
    854   {
    855     int size=os->lacing_vals[ptr]&0xff;
    856     int bytes=size;
    857     int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
    858     int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
    859 
    860     while(size==255){
    861       int val=os->lacing_vals[++ptr];
    862       size=val&0xff;
    863       if(val&0x200)eos=0x200;
    864       bytes+=size;
    865     }
    866 
    867     if(op){
    868       op->e_o_s=eos;
    869       op->b_o_s=bos;
    870       op->packet=os->body_data+os->body_returned;
    871       op->packetno=os->packetno;
    872       op->granulepos=os->granule_vals[ptr];
    873       op->bytes=bytes;
    874     }
    875 
    876     if(adv){
    877       os->body_returned+=bytes;
    878       os->lacing_returned=ptr+1;
    879       os->packetno++;
    880     }
    881   }
    882   return(1);
    883 }
    884 
    885 int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
    886   return _packetout(os,op,1);
    887 }
    888 
    889 int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
    890   return _packetout(os,op,0);
    891 }
    892 
    893 void ogg_packet_clear(ogg_packet *op) {
    894   _ogg_free(op->packet);
    895   memset(op, 0, sizeof(*op));
    896 }
    897 
    898 #ifdef _V_SELFTEST
    899 #include <stdio.h>
    900 
    901 ogg_stream_state os_en, os_de;
    902 ogg_sync_state oy;
    903 
    904 void checkpacket(ogg_packet *op,int len, int no, int pos){
    905   long j;
    906   static int sequence=0;
    907   static int lastno=0;
    908 
    909   if(op->bytes!=len){
    910     fprintf(stderr,"incorrect packet length!\n");
    911     exit(1);
    912   }
    913   if(op->granulepos!=pos){
    914     fprintf(stderr,"incorrect packet position!\n");
    915     exit(1);
    916   }
    917 
    918   /* packet number just follows sequence/gap; adjust the input number
    919      for that */
    920   if(no==0){
    921     sequence=0;
    922   }else{
    923     sequence++;
    924     if(no>lastno+1)
    925       sequence++;
    926   }
    927   lastno=no;
    928   if(op->packetno!=sequence){
    929     fprintf(stderr,"incorrect packet sequence %ld != %d\n",
    930 	    (long)(op->packetno),sequence);
    931     exit(1);
    932   }
    933 
    934   /* Test data */
    935   for(j=0;j<op->bytes;j++)
    936     if(op->packet[j]!=((j+no)&0xff)){
    937       fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
    938 	      j,op->packet[j],(j+no)&0xff);
    939       exit(1);
    940     }
    941 }
    942 
    943 void check_page(unsigned char *data,const int *header,ogg_page *og){
    944   long j;
    945   /* Test data */
    946   for(j=0;j<og->body_len;j++)
    947     if(og->body[j]!=data[j]){
    948       fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
    949 	      j,data[j],og->body[j]);
    950       exit(1);
    951     }
    952 
    953   /* Test header */
    954   for(j=0;j<og->header_len;j++){
    955     if(og->header[j]!=header[j]){
    956       fprintf(stderr,"header content mismatch at pos %ld:\n",j);
    957       for(j=0;j<header[26]+27;j++)
    958 	fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
    959       fprintf(stderr,"\n");
    960       exit(1);
    961     }
    962   }
    963   if(og->header_len!=header[26]+27){
    964     fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
    965 	    og->header_len,header[26]+27);
    966     exit(1);
    967   }
    968 }
    969 
    970 void print_header(ogg_page *og){
    971   int j;
    972   fprintf(stderr,"\nHEADER:\n");
    973   fprintf(stderr,"  capture: %c %c %c %c  version: %d  flags: %x\n",
    974 	  og->header[0],og->header[1],og->header[2],og->header[3],
    975 	  (int)og->header[4],(int)og->header[5]);
    976 
    977   fprintf(stderr,"  granulepos: %d  serialno: %d  pageno: %ld\n",
    978 	  (og->header[9]<<24)|(og->header[8]<<16)|
    979 	  (og->header[7]<<8)|og->header[6],
    980 	  (og->header[17]<<24)|(og->header[16]<<16)|
    981 	  (og->header[15]<<8)|og->header[14],
    982 	  ((long)(og->header[21])<<24)|(og->header[20]<<16)|
    983 	  (og->header[19]<<8)|og->header[18]);
    984 
    985   fprintf(stderr,"  checksum: %02x:%02x:%02x:%02x\n  segments: %d (",
    986 	  (int)og->header[22],(int)og->header[23],
    987 	  (int)og->header[24],(int)og->header[25],
    988 	  (int)og->header[26]);
    989 
    990   for(j=27;j<og->header_len;j++)
    991     fprintf(stderr,"%d ",(int)og->header[j]);
    992   fprintf(stderr,")\n\n");
    993 }
    994 
    995 void copy_page(ogg_page *og){
    996   unsigned char *temp=_ogg_malloc(og->header_len);
    997   memcpy(temp,og->header,og->header_len);
    998   og->header=temp;
    999 
   1000   temp=_ogg_malloc(og->body_len);
   1001   memcpy(temp,og->body,og->body_len);
   1002   og->body=temp;
   1003 }
   1004 
   1005 void error(void){
   1006   fprintf(stderr,"error!\n");
   1007   exit(1);
   1008 }
   1009 
   1010 /* 17 only */
   1011 const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
   1012 		       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1013 		       0x01,0x02,0x03,0x04,0,0,0,0,
   1014 		       0x15,0xed,0xec,0x91,
   1015 		       1,
   1016 		       17};
   1017 
   1018 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
   1019 const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1020 		       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1021 		       0x01,0x02,0x03,0x04,0,0,0,0,
   1022 		       0x59,0x10,0x6c,0x2c,
   1023 		       1,
   1024 		       17};
   1025 const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
   1026 		       0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
   1027 		       0x01,0x02,0x03,0x04,1,0,0,0,
   1028 		       0x89,0x33,0x85,0xce,
   1029 		       13,
   1030 		       254,255,0,255,1,255,245,255,255,0,
   1031 		       255,255,90};
   1032 
   1033 /* nil packets; beginning,middle,end */
   1034 const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1035 		       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1036 		       0x01,0x02,0x03,0x04,0,0,0,0,
   1037 		       0xff,0x7b,0x23,0x17,
   1038 		       1,
   1039 		       0};
   1040 const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
   1041 		       0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
   1042 		       0x01,0x02,0x03,0x04,1,0,0,0,
   1043 		       0x5c,0x3f,0x66,0xcb,
   1044 		       17,
   1045 		       17,254,255,0,0,255,1,0,255,245,255,255,0,
   1046 		       255,255,90,0};
   1047 
   1048 /* large initial packet */
   1049 const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1050 		       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1051 		       0x01,0x02,0x03,0x04,0,0,0,0,
   1052 		       0x01,0x27,0x31,0xaa,
   1053 		       18,
   1054 		       255,255,255,255,255,255,255,255,
   1055 		       255,255,255,255,255,255,255,255,255,10};
   1056 
   1057 const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
   1058 		       0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
   1059 		       0x01,0x02,0x03,0x04,1,0,0,0,
   1060 		       0x7f,0x4e,0x8a,0xd2,
   1061 		       4,
   1062 		       255,4,255,0};
   1063 
   1064 
   1065 /* continuing packet test */
   1066 const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1067 		       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1068 		       0x01,0x02,0x03,0x04,0,0,0,0,
   1069 		       0xff,0x7b,0x23,0x17,
   1070 		       1,
   1071 		       0};
   1072 
   1073 const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
   1074 		       0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1075 		       0x01,0x02,0x03,0x04,1,0,0,0,
   1076 		       0x34,0x24,0xd5,0x29,
   1077 		       17,
   1078 		       255,255,255,255,255,255,255,255,
   1079 		       255,255,255,255,255,255,255,255,255};
   1080 
   1081 const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
   1082 		       0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
   1083 		       0x01,0x02,0x03,0x04,2,0,0,0,
   1084 		       0xc8,0xc3,0xcb,0xed,
   1085 		       5,
   1086 		       10,255,4,255,0};
   1087 
   1088 
   1089 /* page with the 255 segment limit */
   1090 const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1091 		       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1092 		       0x01,0x02,0x03,0x04,0,0,0,0,
   1093 		       0xff,0x7b,0x23,0x17,
   1094 		       1,
   1095 		       0};
   1096 
   1097 const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
   1098 		       0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
   1099 		       0x01,0x02,0x03,0x04,1,0,0,0,
   1100 		       0xed,0x2a,0x2e,0xa7,
   1101 		       255,
   1102 		       10,10,10,10,10,10,10,10,
   1103 		       10,10,10,10,10,10,10,10,
   1104 		       10,10,10,10,10,10,10,10,
   1105 		       10,10,10,10,10,10,10,10,
   1106 		       10,10,10,10,10,10,10,10,
   1107 		       10,10,10,10,10,10,10,10,
   1108 		       10,10,10,10,10,10,10,10,
   1109 		       10,10,10,10,10,10,10,10,
   1110 		       10,10,10,10,10,10,10,10,
   1111 		       10,10,10,10,10,10,10,10,
   1112 		       10,10,10,10,10,10,10,10,
   1113 		       10,10,10,10,10,10,10,10,
   1114 		       10,10,10,10,10,10,10,10,
   1115 		       10,10,10,10,10,10,10,10,
   1116 		       10,10,10,10,10,10,10,10,
   1117 		       10,10,10,10,10,10,10,10,
   1118 		       10,10,10,10,10,10,10,10,
   1119 		       10,10,10,10,10,10,10,10,
   1120 		       10,10,10,10,10,10,10,10,
   1121 		       10,10,10,10,10,10,10,10,
   1122 		       10,10,10,10,10,10,10,10,
   1123 		       10,10,10,10,10,10,10,10,
   1124 		       10,10,10,10,10,10,10,10,
   1125 		       10,10,10,10,10,10,10,10,
   1126 		       10,10,10,10,10,10,10,10,
   1127 		       10,10,10,10,10,10,10,10,
   1128 		       10,10,10,10,10,10,10,10,
   1129 		       10,10,10,10,10,10,10,10,
   1130 		       10,10,10,10,10,10,10,10,
   1131 		       10,10,10,10,10,10,10,10,
   1132 		       10,10,10,10,10,10,10,10,
   1133 		       10,10,10,10,10,10,10};
   1134 
   1135 const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
   1136 		       0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
   1137 		       0x01,0x02,0x03,0x04,2,0,0,0,
   1138 		       0x6c,0x3b,0x82,0x3d,
   1139 		       1,
   1140 		       50};
   1141 
   1142 
   1143 /* packet that overspans over an entire page */
   1144 const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1145 		       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1146 		       0x01,0x02,0x03,0x04,0,0,0,0,
   1147 		       0xff,0x7b,0x23,0x17,
   1148 		       1,
   1149 		       0};
   1150 
   1151 const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
   1152 		       0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
   1153 		       0x01,0x02,0x03,0x04,1,0,0,0,
   1154 		       0x3c,0xd9,0x4d,0x3f,
   1155 		       17,
   1156 		       100,255,255,255,255,255,255,255,255,
   1157 		       255,255,255,255,255,255,255,255};
   1158 
   1159 const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
   1160 		       0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
   1161 		       0x01,0x02,0x03,0x04,2,0,0,0,
   1162 		       0xbd,0xd5,0xb5,0x8b,
   1163 		       17,
   1164 		       255,255,255,255,255,255,255,255,
   1165 		       255,255,255,255,255,255,255,255,255};
   1166 
   1167 const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
   1168 		       0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
   1169 		       0x01,0x02,0x03,0x04,3,0,0,0,
   1170 		       0xef,0xdd,0x88,0xde,
   1171 		       7,
   1172 		       255,255,75,255,4,255,0};
   1173 
   1174 /* packet that overspans over an entire page */
   1175 const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1176 		       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1177 		       0x01,0x02,0x03,0x04,0,0,0,0,
   1178 		       0xff,0x7b,0x23,0x17,
   1179 		       1,
   1180 		       0};
   1181 
   1182 const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
   1183 		       0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
   1184 		       0x01,0x02,0x03,0x04,1,0,0,0,
   1185 		       0x3c,0xd9,0x4d,0x3f,
   1186 		       17,
   1187 		       100,255,255,255,255,255,255,255,255,
   1188 		       255,255,255,255,255,255,255,255};
   1189 
   1190 const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
   1191 		       0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
   1192 		       0x01,0x02,0x03,0x04,2,0,0,0,
   1193 		       0xd4,0xe0,0x60,0xe5,
   1194 		       1,0};
   1195 
   1196 void test_pack(const int *pl, const int **headers){
   1197   unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
   1198   long inptr=0;
   1199   long outptr=0;
   1200   long deptr=0;
   1201   long depacket=0;
   1202   long granule_pos=7,pageno=0;
   1203   int i,j,packets,pageout=0;
   1204   int eosflag=0;
   1205   int bosflag=0;
   1206 
   1207   ogg_stream_reset(&os_en);
   1208   ogg_stream_reset(&os_de);
   1209   ogg_sync_reset(&oy);
   1210 
   1211   for(packets=0;;packets++)if(pl[packets]==-1)break;
   1212 
   1213   for(i=0;i<packets;i++){
   1214     /* construct a test packet */
   1215     ogg_packet op;
   1216     int len=pl[i];
   1217     
   1218     op.packet=data+inptr;
   1219     op.bytes=len;
   1220     op.e_o_s=(pl[i+1]<0?1:0);
   1221     op.granulepos=granule_pos;
   1222 
   1223     granule_pos+=1024;
   1224 
   1225     for(j=0;j<len;j++)data[inptr++]=i+j;
   1226 
   1227     /* submit the test packet */
   1228     ogg_stream_packetin(&os_en,&op);
   1229 
   1230     /* retrieve any finished pages */
   1231     {
   1232       ogg_page og;
   1233       
   1234       while(ogg_stream_pageout(&os_en,&og)){
   1235 	/* We have a page.  Check it carefully */
   1236 
   1237 	fprintf(stderr,"%ld, ",pageno);
   1238 
   1239 	if(headers[pageno]==NULL){
   1240 	  fprintf(stderr,"coded too many pages!\n");
   1241 	  exit(1);
   1242 	}
   1243 
   1244 	check_page(data+outptr,headers[pageno],&og);
   1245 
   1246 	outptr+=og.body_len;
   1247 	pageno++;
   1248 
   1249 	/* have a complete page; submit it to sync/decode */
   1250 
   1251 	{
   1252 	  ogg_page og_de;
   1253 	  ogg_packet op_de,op_de2;
   1254 	  char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
   1255 	  memcpy(buf,og.header,og.header_len);
   1256 	  memcpy(buf+og.header_len,og.body,og.body_len);
   1257 	  ogg_sync_wrote(&oy,og.header_len+og.body_len);
   1258 
   1259 	  while(ogg_sync_pageout(&oy,&og_de)>0){
   1260 	    /* got a page.  Happy happy.  Verify that it's good. */
   1261 	    
   1262 	    check_page(data+deptr,headers[pageout],&og_de);
   1263 	    deptr+=og_de.body_len;
   1264 	    pageout++;
   1265 
   1266 	    /* submit it to deconstitution */
   1267 	    ogg_stream_pagein(&os_de,&og_de);
   1268 
   1269 	    /* packets out? */
   1270 	    while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
   1271 	      ogg_stream_packetpeek(&os_de,NULL);
   1272 	      ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
   1273 	      
   1274 	      /* verify peek and out match */
   1275 	      if(memcmp(&op_de,&op_de2,sizeof(op_de))){
   1276 		fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
   1277 			depacket);
   1278 		exit(1);
   1279 	      }
   1280 
   1281 	      /* verify the packet! */
   1282 	      /* check data */
   1283 	      if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
   1284 		fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
   1285 			depacket);
   1286 		exit(1);
   1287 	      }
   1288 	      /* check bos flag */
   1289 	      if(bosflag==0 && op_de.b_o_s==0){
   1290 		fprintf(stderr,"b_o_s flag not set on packet!\n");
   1291 		exit(1);
   1292 	      }
   1293 	      if(bosflag && op_de.b_o_s){
   1294 		fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
   1295 		exit(1);
   1296 	      }
   1297 	      bosflag=1;
   1298 	      depacket+=op_de.bytes;
   1299 	      
   1300 	      /* check eos flag */
   1301 	      if(eosflag){
   1302 		fprintf(stderr,"Multiple decoded packets with eos flag!\n");
   1303 		exit(1);
   1304 	      }
   1305 
   1306 	      if(op_de.e_o_s)eosflag=1;
   1307 
   1308 	      /* check granulepos flag */
   1309 	      if(op_de.granulepos!=-1){
   1310 		fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
   1311 	      }
   1312 	    }
   1313 	  }
   1314 	}
   1315       }
   1316     }
   1317   }
   1318   _ogg_free(data);
   1319   if(headers[pageno]!=NULL){
   1320     fprintf(stderr,"did not write last page!\n");
   1321     exit(1);
   1322   }
   1323   if(headers[pageout]!=NULL){
   1324     fprintf(stderr,"did not decode last page!\n");
   1325     exit(1);
   1326   }
   1327   if(inptr!=outptr){
   1328     fprintf(stderr,"encoded page data incomplete!\n");
   1329     exit(1);
   1330   }
   1331   if(inptr!=deptr){
   1332     fprintf(stderr,"decoded page data incomplete!\n");
   1333     exit(1);
   1334   }
   1335   if(inptr!=depacket){
   1336     fprintf(stderr,"decoded packet data incomplete!\n");
   1337     exit(1);
   1338   }
   1339   if(!eosflag){
   1340     fprintf(stderr,"Never got a packet with EOS set!\n");
   1341     exit(1);
   1342   }
   1343   fprintf(stderr,"ok.\n");
   1344 }
   1345 
   1346 int main(void){
   1347 
   1348   ogg_stream_init(&os_en,0x04030201);
   1349   ogg_stream_init(&os_de,0x04030201);
   1350   ogg_sync_init(&oy);
   1351 
   1352   /* Exercise each code path in the framing code.  Also verify that
   1353      the checksums are working.  */
   1354 
   1355   {
   1356     /* 17 only */
   1357     const int packets[]={17, -1};
   1358     const int *headret[]={head1_0,NULL};
   1359     
   1360     fprintf(stderr,"testing single page encoding... ");
   1361     test_pack(packets,headret);
   1362   }
   1363 
   1364   {
   1365     /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
   1366     const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
   1367     const int *headret[]={head1_1,head2_1,NULL};
   1368     
   1369     fprintf(stderr,"testing basic page encoding... ");
   1370     test_pack(packets,headret);
   1371   }
   1372 
   1373   {
   1374     /* nil packets; beginning,middle,end */
   1375     const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
   1376     const int *headret[]={head1_2,head2_2,NULL};
   1377     
   1378     fprintf(stderr,"testing basic nil packets... ");
   1379     test_pack(packets,headret);
   1380   }
   1381 
   1382   {
   1383     /* large initial packet */
   1384     const int packets[]={4345,259,255,-1};
   1385     const int *headret[]={head1_3,head2_3,NULL};
   1386     
   1387     fprintf(stderr,"testing initial-packet lacing > 4k... ");
   1388     test_pack(packets,headret);
   1389   }
   1390 
   1391   {
   1392     /* continuing packet test */
   1393     const int packets[]={0,4345,259,255,-1};
   1394     const int *headret[]={head1_4,head2_4,head3_4,NULL};
   1395     
   1396     fprintf(stderr,"testing single packet page span... ");
   1397     test_pack(packets,headret);
   1398   }
   1399 
   1400   /* page with the 255 segment limit */
   1401   {
   1402 
   1403     const int packets[]={0,10,10,10,10,10,10,10,10,
   1404 		   10,10,10,10,10,10,10,10,
   1405 		   10,10,10,10,10,10,10,10,
   1406 		   10,10,10,10,10,10,10,10,
   1407 		   10,10,10,10,10,10,10,10,
   1408 		   10,10,10,10,10,10,10,10,
   1409 		   10,10,10,10,10,10,10,10,
   1410 		   10,10,10,10,10,10,10,10,
   1411 		   10,10,10,10,10,10,10,10,
   1412 		   10,10,10,10,10,10,10,10,
   1413 		   10,10,10,10,10,10,10,10,
   1414 		   10,10,10,10,10,10,10,10,
   1415 		   10,10,10,10,10,10,10,10,
   1416 		   10,10,10,10,10,10,10,10,
   1417 		   10,10,10,10,10,10,10,10,
   1418 		   10,10,10,10,10,10,10,10,
   1419 		   10,10,10,10,10,10,10,10,
   1420 		   10,10,10,10,10,10,10,10,
   1421 		   10,10,10,10,10,10,10,10,
   1422 		   10,10,10,10,10,10,10,10,
   1423 		   10,10,10,10,10,10,10,10,
   1424 		   10,10,10,10,10,10,10,10,
   1425 		   10,10,10,10,10,10,10,10,
   1426 		   10,10,10,10,10,10,10,10,
   1427 		   10,10,10,10,10,10,10,10,
   1428 		   10,10,10,10,10,10,10,10,
   1429 		   10,10,10,10,10,10,10,10,
   1430 		   10,10,10,10,10,10,10,10,
   1431 		   10,10,10,10,10,10,10,10,
   1432 		   10,10,10,10,10,10,10,10,
   1433 		   10,10,10,10,10,10,10,10,
   1434 		   10,10,10,10,10,10,10,50,-1};
   1435     const int *headret[]={head1_5,head2_5,head3_5,NULL};
   1436     
   1437     fprintf(stderr,"testing max packet segments... ");
   1438     test_pack(packets,headret);
   1439   }
   1440 
   1441   {
   1442     /* packet that overspans over an entire page */
   1443     const int packets[]={0,100,9000,259,255,-1};
   1444     const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
   1445     
   1446     fprintf(stderr,"testing very large packets... ");
   1447     test_pack(packets,headret);
   1448   }
   1449 
   1450   {
   1451     /* term only page.  why not? */
   1452     const int packets[]={0,100,4080,-1};
   1453     const int *headret[]={head1_7,head2_7,head3_7,NULL};
   1454     
   1455     fprintf(stderr,"testing zero data page (1 nil packet)... ");
   1456     test_pack(packets,headret);
   1457   }
   1458 
   1459 
   1460 
   1461   {
   1462     /* build a bunch of pages for testing */
   1463     unsigned char *data=_ogg_malloc(1024*1024);
   1464     int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1};
   1465     int inptr=0,i,j;
   1466     ogg_page og[5];
   1467     
   1468     ogg_stream_reset(&os_en);
   1469 
   1470     for(i=0;pl[i]!=-1;i++){
   1471       ogg_packet op;
   1472       int len=pl[i];
   1473       
   1474       op.packet=data+inptr;
   1475       op.bytes=len;
   1476       op.e_o_s=(pl[i+1]<0?1:0);
   1477       op.granulepos=(i+1)*1000;
   1478 
   1479       for(j=0;j<len;j++)data[inptr++]=i+j;
   1480       ogg_stream_packetin(&os_en,&op);
   1481     }
   1482 
   1483     _ogg_free(data);
   1484 
   1485     /* retrieve finished pages */
   1486     for(i=0;i<5;i++){
   1487       if(ogg_stream_pageout(&os_en,&og[i])==0){
   1488 	fprintf(stderr,"Too few pages output building sync tests!\n");
   1489 	exit(1);
   1490       }
   1491       copy_page(&og[i]);
   1492     }
   1493 
   1494     /* Test lost pages on pagein/packetout: no rollback */
   1495     {
   1496       ogg_page temp;
   1497       ogg_packet test;
   1498 
   1499       fprintf(stderr,"Testing loss of pages... ");
   1500 
   1501       ogg_sync_reset(&oy);
   1502       ogg_stream_reset(&os_de);
   1503       for(i=0;i<5;i++){
   1504 	memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
   1505 	       og[i].header_len);
   1506 	ogg_sync_wrote(&oy,og[i].header_len);
   1507 	memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
   1508 	ogg_sync_wrote(&oy,og[i].body_len);
   1509       }
   1510 
   1511       ogg_sync_pageout(&oy,&temp);
   1512       ogg_stream_pagein(&os_de,&temp);
   1513       ogg_sync_pageout(&oy,&temp);
   1514       ogg_stream_pagein(&os_de,&temp);
   1515       ogg_sync_pageout(&oy,&temp);
   1516       /* skip */
   1517       ogg_sync_pageout(&oy,&temp);
   1518       ogg_stream_pagein(&os_de,&temp);
   1519 
   1520       /* do we get the expected results/packets? */
   1521       
   1522       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1523       checkpacket(&test,0,0,0);
   1524       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1525       checkpacket(&test,100,1,-1);
   1526       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1527       checkpacket(&test,4079,2,3000);
   1528       if(ogg_stream_packetout(&os_de,&test)!=-1){
   1529 	fprintf(stderr,"Error: loss of page did not return error\n");
   1530 	exit(1);
   1531       }
   1532       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1533       checkpacket(&test,76,5,-1);
   1534       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1535       checkpacket(&test,34,6,-1);
   1536       fprintf(stderr,"ok.\n");
   1537     }
   1538 
   1539     /* Test lost pages on pagein/packetout: rollback with continuation */
   1540     {
   1541       ogg_page temp;
   1542       ogg_packet test;
   1543 
   1544       fprintf(stderr,"Testing loss of pages (rollback required)... ");
   1545 
   1546       ogg_sync_reset(&oy);
   1547       ogg_stream_reset(&os_de);
   1548       for(i=0;i<5;i++){
   1549 	memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
   1550 	       og[i].header_len);
   1551 	ogg_sync_wrote(&oy,og[i].header_len);
   1552 	memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
   1553 	ogg_sync_wrote(&oy,og[i].body_len);
   1554       }
   1555 
   1556       ogg_sync_pageout(&oy,&temp);
   1557       ogg_stream_pagein(&os_de,&temp);
   1558       ogg_sync_pageout(&oy,&temp);
   1559       ogg_stream_pagein(&os_de,&temp);
   1560       ogg_sync_pageout(&oy,&temp);
   1561       ogg_stream_pagein(&os_de,&temp);
   1562       ogg_sync_pageout(&oy,&temp);
   1563       /* skip */
   1564       ogg_sync_pageout(&oy,&temp);
   1565       ogg_stream_pagein(&os_de,&temp);
   1566 
   1567       /* do we get the expected results/packets? */
   1568       
   1569       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1570       checkpacket(&test,0,0,0);
   1571       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1572       checkpacket(&test,100,1,-1);
   1573       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1574       checkpacket(&test,4079,2,3000);
   1575       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1576       checkpacket(&test,2956,3,4000);
   1577       if(ogg_stream_packetout(&os_de,&test)!=-1){
   1578 	fprintf(stderr,"Error: loss of page did not return error\n");
   1579 	exit(1);
   1580       }
   1581       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1582       checkpacket(&test,300,13,14000);
   1583       fprintf(stderr,"ok.\n");
   1584     }
   1585     
   1586     /* the rest only test sync */
   1587     {
   1588       ogg_page og_de;
   1589       /* Test fractional page inputs: incomplete capture */
   1590       fprintf(stderr,"Testing sync on partial inputs... ");
   1591       ogg_sync_reset(&oy);
   1592       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
   1593 	     3);
   1594       ogg_sync_wrote(&oy,3);
   1595       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1596       
   1597       /* Test fractional page inputs: incomplete fixed header */
   1598       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
   1599 	     20);
   1600       ogg_sync_wrote(&oy,20);
   1601       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1602       
   1603       /* Test fractional page inputs: incomplete header */
   1604       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
   1605 	     5);
   1606       ogg_sync_wrote(&oy,5);
   1607       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1608       
   1609       /* Test fractional page inputs: incomplete body */
   1610       
   1611       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
   1612 	     og[1].header_len-28);
   1613       ogg_sync_wrote(&oy,og[1].header_len-28);
   1614       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1615       
   1616       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
   1617       ogg_sync_wrote(&oy,1000);
   1618       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1619       
   1620       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
   1621 	     og[1].body_len-1000);
   1622       ogg_sync_wrote(&oy,og[1].body_len-1000);
   1623       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   1624       
   1625       fprintf(stderr,"ok.\n");
   1626     }
   1627 
   1628     /* Test fractional page inputs: page + incomplete capture */
   1629     {
   1630       ogg_page og_de;
   1631       fprintf(stderr,"Testing sync on 1+partial inputs... ");
   1632       ogg_sync_reset(&oy); 
   1633 
   1634       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
   1635 	     og[1].header_len);
   1636       ogg_sync_wrote(&oy,og[1].header_len);
   1637 
   1638       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
   1639 	     og[1].body_len);
   1640       ogg_sync_wrote(&oy,og[1].body_len);
   1641 
   1642       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
   1643 	     20);
   1644       ogg_sync_wrote(&oy,20);
   1645       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   1646       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1647 
   1648       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
   1649 	     og[1].header_len-20);
   1650       ogg_sync_wrote(&oy,og[1].header_len-20);
   1651       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
   1652 	     og[1].body_len);
   1653       ogg_sync_wrote(&oy,og[1].body_len);
   1654       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   1655 
   1656       fprintf(stderr,"ok.\n");
   1657     }
   1658     
   1659     /* Test recapture: garbage + page */
   1660     {
   1661       ogg_page og_de;
   1662       fprintf(stderr,"Testing search for capture... ");
   1663       ogg_sync_reset(&oy); 
   1664       
   1665       /* 'garbage' */
   1666       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
   1667 	     og[1].body_len);
   1668       ogg_sync_wrote(&oy,og[1].body_len);
   1669 
   1670       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
   1671 	     og[1].header_len);
   1672       ogg_sync_wrote(&oy,og[1].header_len);
   1673 
   1674       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
   1675 	     og[1].body_len);
   1676       ogg_sync_wrote(&oy,og[1].body_len);
   1677 
   1678       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
   1679 	     20);
   1680       ogg_sync_wrote(&oy,20);
   1681       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1682       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   1683       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1684 
   1685       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
   1686 	     og[2].header_len-20);
   1687       ogg_sync_wrote(&oy,og[2].header_len-20);
   1688       memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
   1689 	     og[2].body_len);
   1690       ogg_sync_wrote(&oy,og[2].body_len);
   1691       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   1692 
   1693       fprintf(stderr,"ok.\n");
   1694     }
   1695 
   1696     /* Test recapture: page + garbage + page */
   1697     {
   1698       ogg_page og_de;
   1699       fprintf(stderr,"Testing recapture... ");
   1700       ogg_sync_reset(&oy); 
   1701 
   1702       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
   1703 	     og[1].header_len);
   1704       ogg_sync_wrote(&oy,og[1].header_len);
   1705 
   1706       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
   1707 	     og[1].body_len);
   1708       ogg_sync_wrote(&oy,og[1].body_len);
   1709 
   1710       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
   1711 	     og[2].header_len);
   1712       ogg_sync_wrote(&oy,og[2].header_len);
   1713 
   1714       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
   1715 	     og[2].header_len);
   1716       ogg_sync_wrote(&oy,og[2].header_len);
   1717 
   1718       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   1719 
   1720       memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
   1721 	     og[2].body_len-5);
   1722       ogg_sync_wrote(&oy,og[2].body_len-5);
   1723 
   1724       memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
   1725 	     og[3].header_len);
   1726       ogg_sync_wrote(&oy,og[3].header_len);
   1727 
   1728       memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
   1729 	     og[3].body_len);
   1730       ogg_sync_wrote(&oy,og[3].body_len);
   1731 
   1732       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1733       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   1734 
   1735       fprintf(stderr,"ok.\n");
   1736     }
   1737   }    
   1738 
   1739   return(0);
   1740 }
   1741 
   1742 #endif
   1743 
   1744 
   1745 
   1746