Home | History | Annotate | Download | only in src
      1 /********************************************************************
      2  *                                                                  *
      3  * THIS FILE IS PART OF THE Ogg CONTAINER 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-2010             *
      9  * by the Xiph.Org Foundation http://www.xiph.org/                  *
     10  *                                                                  *
     11  ********************************************************************
     12 
     13  function: code raw packets into framed OggSquish stream and
     14            decode Ogg streams back into raw packets
     15  last mod: $Id: framing.c 17039 2010-03-26 00:34:54Z xiphmont $
     16 
     17  note: The CRC code is directly derived from public domain code by
     18  Ross Williams (ross (at) 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(const ogg_page *og){
     30   return((int)(og->header[4]));
     31 }
     32 
     33 int ogg_page_continued(const ogg_page *og){
     34   return((int)(og->header[5]&0x01));
     35 }
     36 
     37 int ogg_page_bos(const ogg_page *og){
     38   return((int)(og->header[5]&0x02));
     39 }
     40 
     41 int ogg_page_eos(const ogg_page *og){
     42   return((int)(og->header[5]&0x04));
     43 }
     44 
     45 ogg_int64_t ogg_page_granulepos(const 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(const 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(const 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(const 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 const 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->lacing_storage=1024;
    193 
    194     os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
    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     if(!os->body_data || !os->lacing_vals || !os->granule_vals){
    199       ogg_stream_clear(os);
    200       return -1;
    201     }
    202 
    203     os->serialno=serialno;
    204 
    205     return(0);
    206   }
    207   return(-1);
    208 }
    209 
    210 /* async/delayed error detection for the ogg_stream_state */
    211 int ogg_stream_check(ogg_stream_state *os){
    212   if(!os || !os->body_data) return -1;
    213   return 0;
    214 }
    215 
    216 /* _clear does not free os, only the non-flat storage within */
    217 int ogg_stream_clear(ogg_stream_state *os){
    218   if(os){
    219     if(os->body_data)_ogg_free(os->body_data);
    220     if(os->lacing_vals)_ogg_free(os->lacing_vals);
    221     if(os->granule_vals)_ogg_free(os->granule_vals);
    222 
    223     memset(os,0,sizeof(*os));
    224   }
    225   return(0);
    226 }
    227 
    228 int ogg_stream_destroy(ogg_stream_state *os){
    229   if(os){
    230     ogg_stream_clear(os);
    231     _ogg_free(os);
    232   }
    233   return(0);
    234 }
    235 
    236 /* Helpers for ogg_stream_encode; this keeps the structure and
    237    what's happening fairly clear */
    238 
    239 static int _os_body_expand(ogg_stream_state *os,int needed){
    240   if(os->body_storage<=os->body_fill+needed){
    241     void *ret;
    242     ret=_ogg_realloc(os->body_data,(os->body_storage+needed+1024)*
    243                      sizeof(*os->body_data));
    244     if(!ret){
    245       ogg_stream_clear(os);
    246       return -1;
    247     }
    248     os->body_storage+=(needed+1024);
    249     os->body_data=ret;
    250   }
    251   return 0;
    252 }
    253 
    254 static int _os_lacing_expand(ogg_stream_state *os,int needed){
    255   if(os->lacing_storage<=os->lacing_fill+needed){
    256     void *ret;
    257     ret=_ogg_realloc(os->lacing_vals,(os->lacing_storage+needed+32)*
    258                      sizeof(*os->lacing_vals));
    259     if(!ret){
    260       ogg_stream_clear(os);
    261       return -1;
    262     }
    263     os->lacing_vals=ret;
    264     ret=_ogg_realloc(os->granule_vals,(os->lacing_storage+needed+32)*
    265                      sizeof(*os->granule_vals));
    266     if(!ret){
    267       ogg_stream_clear(os);
    268       return -1;
    269     }
    270     os->granule_vals=ret;
    271     os->lacing_storage+=(needed+32);
    272   }
    273   return 0;
    274 }
    275 
    276 /* checksum the page */
    277 /* Direct table CRC; note that this will be faster in the future if we
    278    perform the checksum silmultaneously with other copies */
    279 
    280 void ogg_page_checksum_set(ogg_page *og){
    281   if(og){
    282     ogg_uint32_t crc_reg=0;
    283     int i;
    284 
    285     /* safety; needed for API behavior, but not framing code */
    286     og->header[22]=0;
    287     og->header[23]=0;
    288     og->header[24]=0;
    289     og->header[25]=0;
    290 
    291     for(i=0;i<og->header_len;i++)
    292       crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
    293     for(i=0;i<og->body_len;i++)
    294       crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
    295 
    296     og->header[22]=(unsigned char)(crc_reg&0xff);
    297     og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
    298     og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
    299     og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
    300   }
    301 }
    302 
    303 /* submit data to the internal buffer of the framing engine */
    304 int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count,
    305                        long e_o_s, ogg_int64_t granulepos){
    306 
    307   int bytes = 0, lacing_vals, i;
    308 
    309   if(ogg_stream_check(os)) return -1;
    310   if(!iov) return 0;
    311 
    312   for (i = 0; i < count; ++i) bytes += (int)iov[i].iov_len;
    313   lacing_vals=bytes/255+1;
    314 
    315   if(os->body_returned){
    316     /* advance packet data according to the body_returned pointer. We
    317        had to keep it around to return a pointer into the buffer last
    318        call */
    319 
    320     os->body_fill-=os->body_returned;
    321     if(os->body_fill)
    322       memmove(os->body_data,os->body_data+os->body_returned,
    323               os->body_fill);
    324     os->body_returned=0;
    325   }
    326 
    327   /* make sure we have the buffer storage */
    328   if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals))
    329     return -1;
    330 
    331   /* Copy in the submitted packet.  Yes, the copy is a waste; this is
    332      the liability of overly clean abstraction for the time being.  It
    333      will actually be fairly easy to eliminate the extra copy in the
    334      future */
    335 
    336   for (i = 0; i < count; ++i) {
    337     memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len);
    338     os->body_fill += (int)iov[i].iov_len;
    339   }
    340 
    341   /* Store lacing vals for this packet */
    342   for(i=0;i<lacing_vals-1;i++){
    343     os->lacing_vals[os->lacing_fill+i]=255;
    344     os->granule_vals[os->lacing_fill+i]=os->granulepos;
    345   }
    346   os->lacing_vals[os->lacing_fill+i]=bytes%255;
    347   os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos;
    348 
    349   /* flag the first segment as the beginning of the packet */
    350   os->lacing_vals[os->lacing_fill]|= 0x100;
    351 
    352   os->lacing_fill+=lacing_vals;
    353 
    354   /* for the sake of completeness */
    355   os->packetno++;
    356 
    357   if(e_o_s)os->e_o_s=1;
    358 
    359   return(0);
    360 }
    361 
    362 int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
    363   ogg_iovec_t iov;
    364   iov.iov_base = op->packet;
    365   iov.iov_len = op->bytes;
    366   return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos);
    367 }
    368 
    369 /* Conditionally flush a page; force==0 will only flush nominal-size
    370    pages, force==1 forces us to flush a page regardless of page size
    371    so long as there's any data available at all. */
    372 static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force){
    373   int i;
    374   int vals=0;
    375   int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
    376   int bytes=0;
    377   long acc=0;
    378   ogg_int64_t granule_pos=-1;
    379 
    380   if(ogg_stream_check(os)) return(0);
    381   if(maxvals==0) return(0);
    382 
    383   /* construct a page */
    384   /* decide how many segments to include */
    385 
    386   /* If this is the initial header case, the first page must only include
    387      the initial header packet */
    388   if(os->b_o_s==0){  /* 'initial header page' case */
    389     granule_pos=0;
    390     for(vals=0;vals<maxvals;vals++){
    391       if((os->lacing_vals[vals]&0x0ff)<255){
    392         vals++;
    393         break;
    394       }
    395     }
    396   }else{
    397 
    398     /* The extra packets_done, packet_just_done logic here attempts to do two things:
    399        1) Don't unneccessarily span pages.
    400        2) Unless necessary, don't flush pages if there are less than four packets on
    401           them; this expands page size to reduce unneccessary overhead if incoming packets
    402           are large.
    403        These are not necessary behaviors, just 'always better than naive flushing'
    404        without requiring an application to explicitly request a specific optimized
    405        behavior. We'll want an explicit behavior setup pathway eventually as well. */
    406 
    407     int packets_done=0;
    408     int packet_just_done=0;
    409     for(vals=0;vals<maxvals;vals++){
    410       if(acc>4096 && packet_just_done>=4){
    411         force=1;
    412         break;
    413       }
    414       acc+=os->lacing_vals[vals]&0x0ff;
    415       if((os->lacing_vals[vals]&0xff)<255){
    416         granule_pos=os->granule_vals[vals];
    417         packet_just_done=++packets_done;
    418       }else
    419         packet_just_done=0;
    420     }
    421     if(vals==255)force=1;
    422   }
    423 
    424   if(!force) return(0);
    425 
    426   /* construct the header in temp storage */
    427   memcpy(os->header,"OggS",4);
    428 
    429   /* stream structure version */
    430   os->header[4]=0x00;
    431 
    432   /* continued packet flag? */
    433   os->header[5]=0x00;
    434   if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
    435   /* first page flag? */
    436   if(os->b_o_s==0)os->header[5]|=0x02;
    437   /* last page flag? */
    438   if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
    439   os->b_o_s=1;
    440 
    441   /* 64 bits of PCM position */
    442   for(i=6;i<14;i++){
    443     os->header[i]=(unsigned char)(granule_pos&0xff);
    444     granule_pos>>=8;
    445   }
    446 
    447   /* 32 bits of stream serial number */
    448   {
    449     long serialno=os->serialno;
    450     for(i=14;i<18;i++){
    451       os->header[i]=(unsigned char)(serialno&0xff);
    452       serialno>>=8;
    453     }
    454   }
    455 
    456   /* 32 bits of page counter (we have both counter and page header
    457      because this val can roll over) */
    458   if(os->pageno==-1)os->pageno=0; /* because someone called
    459                                      stream_reset; this would be a
    460                                      strange thing to do in an
    461                                      encode stream, but it has
    462                                      plausible uses */
    463   {
    464     long pageno=os->pageno++;
    465     for(i=18;i<22;i++){
    466       os->header[i]=(unsigned char)(pageno&0xff);
    467       pageno>>=8;
    468     }
    469   }
    470 
    471   /* zero for computation; filled in later */
    472   os->header[22]=0;
    473   os->header[23]=0;
    474   os->header[24]=0;
    475   os->header[25]=0;
    476 
    477   /* segment table */
    478   os->header[26]=(unsigned char)(vals&0xff);
    479   for(i=0;i<vals;i++)
    480     bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
    481 
    482   /* set pointers in the ogg_page struct */
    483   og->header=os->header;
    484   og->header_len=os->header_fill=vals+27;
    485   og->body=os->body_data+os->body_returned;
    486   og->body_len=bytes;
    487 
    488   /* advance the lacing data and set the body_returned pointer */
    489 
    490   os->lacing_fill-=vals;
    491   memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
    492   memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
    493   os->body_returned+=bytes;
    494 
    495   /* calculate the checksum */
    496 
    497   ogg_page_checksum_set(og);
    498 
    499   /* done */
    500   return(1);
    501 }
    502 
    503 /* This will flush remaining packets into a page (returning nonzero),
    504    even if there is not enough data to trigger a flush normally
    505    (undersized page). If there are no packets or partial packets to
    506    flush, ogg_stream_flush returns 0.  Note that ogg_stream_flush will
    507    try to flush a normal sized page like ogg_stream_pageout; a call to
    508    ogg_stream_flush does not guarantee that all packets have flushed.
    509    Only a return value of 0 from ogg_stream_flush indicates all packet
    510    data is flushed into pages.
    511 
    512    since ogg_stream_flush will flush the last page in a stream even if
    513    it's undersized, you almost certainly want to use ogg_stream_pageout
    514    (and *not* ogg_stream_flush) unless you specifically need to flush
    515    an page regardless of size in the middle of a stream. */
    516 
    517 int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
    518   return ogg_stream_flush_i(os,og,1);
    519 }
    520 
    521 /* This constructs pages from buffered packet segments.  The pointers
    522 returned are to static buffers; do not free. The returned buffers are
    523 good only until the next call (using the same ogg_stream_state) */
    524 
    525 int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
    526   int force=0;
    527   if(ogg_stream_check(os)) return 0;
    528 
    529   if((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
    530      (os->lacing_fill&&!os->b_o_s))           /* 'initial header page' case */
    531     force=1;
    532 
    533   return(ogg_stream_flush_i(os,og,force));
    534 }
    535 
    536 int ogg_stream_eos(ogg_stream_state *os){
    537   if(ogg_stream_check(os)) return 1;
    538   return os->e_o_s;
    539 }
    540 
    541 /* DECODING PRIMITIVES: packet streaming layer **********************/
    542 
    543 /* This has two layers to place more of the multi-serialno and paging
    544    control in the application's hands.  First, we expose a data buffer
    545    using ogg_sync_buffer().  The app either copies into the
    546    buffer, or passes it directly to read(), etc.  We then call
    547    ogg_sync_wrote() to tell how many bytes we just added.
    548 
    549    Pages are returned (pointers into the buffer in ogg_sync_state)
    550    by ogg_sync_pageout().  The page is then submitted to
    551    ogg_stream_pagein() along with the appropriate
    552    ogg_stream_state* (ie, matching serialno).  We then get raw
    553    packets out calling ogg_stream_packetout() with a
    554    ogg_stream_state. */
    555 
    556 /* initialize the struct to a known state */
    557 int ogg_sync_init(ogg_sync_state *oy){
    558   if(oy){
    559     oy->storage = -1; /* used as a readiness flag */
    560     memset(oy,0,sizeof(*oy));
    561   }
    562   return(0);
    563 }
    564 
    565 /* clear non-flat storage within */
    566 int ogg_sync_clear(ogg_sync_state *oy){
    567   if(oy){
    568     if(oy->data)_ogg_free(oy->data);
    569     memset(oy,0,sizeof(*oy));
    570   }
    571   return(0);
    572 }
    573 
    574 int ogg_sync_destroy(ogg_sync_state *oy){
    575   if(oy){
    576     ogg_sync_clear(oy);
    577     _ogg_free(oy);
    578   }
    579   return(0);
    580 }
    581 
    582 int ogg_sync_check(ogg_sync_state *oy){
    583   if(oy->storage<0) return -1;
    584   return 0;
    585 }
    586 
    587 char *ogg_sync_buffer(ogg_sync_state *oy, long size){
    588   if(ogg_sync_check(oy)) return NULL;
    589 
    590   /* first, clear out any space that has been previously returned */
    591   if(oy->returned){
    592     oy->fill-=oy->returned;
    593     if(oy->fill>0)
    594       memmove(oy->data,oy->data+oy->returned,oy->fill);
    595     oy->returned=0;
    596   }
    597 
    598   if(size>oy->storage-oy->fill){
    599     /* We need to extend the internal buffer */
    600     long newsize=size+oy->fill+4096; /* an extra page to be nice */
    601     void *ret;
    602 
    603     if(oy->data)
    604       ret=_ogg_realloc(oy->data,newsize);
    605     else
    606       ret=_ogg_malloc(newsize);
    607     if(!ret){
    608       ogg_sync_clear(oy);
    609       return NULL;
    610     }
    611     oy->data=ret;
    612     oy->storage=newsize;
    613   }
    614 
    615   /* expose a segment at least as large as requested at the fill mark */
    616   return((char *)oy->data+oy->fill);
    617 }
    618 
    619 int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
    620   if(ogg_sync_check(oy))return -1;
    621   if(oy->fill+bytes>oy->storage)return -1;
    622   oy->fill+=bytes;
    623   return(0);
    624 }
    625 
    626 /* sync the stream.  This is meant to be useful for finding page
    627    boundaries.
    628 
    629    return values for this:
    630   -n) skipped n bytes
    631    0) page not ready; more data (no bytes skipped)
    632    n) page synced at current location; page length n bytes
    633 
    634 */
    635 
    636 long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
    637   unsigned char *page=oy->data+oy->returned;
    638   unsigned char *next;
    639   long bytes=oy->fill-oy->returned;
    640 
    641   if(ogg_sync_check(oy))return 0;
    642 
    643   if(oy->headerbytes==0){
    644     int headerbytes,i;
    645     if(bytes<27)return(0); /* not enough for a header */
    646 
    647     /* verify capture pattern */
    648     if(memcmp(page,"OggS",4))goto sync_fail;
    649 
    650     headerbytes=page[26]+27;
    651     if(bytes<headerbytes)return(0); /* not enough for header + seg table */
    652 
    653     /* count up body length in the segment table */
    654 
    655     for(i=0;i<page[26];i++)
    656       oy->bodybytes+=page[27+i];
    657     oy->headerbytes=headerbytes;
    658   }
    659 
    660   if(oy->bodybytes+oy->headerbytes>bytes)return(0);
    661 
    662   /* The whole test page is buffered.  Verify the checksum */
    663   {
    664     /* Grab the checksum bytes, set the header field to zero */
    665     char chksum[4];
    666     ogg_page log;
    667 
    668     memcpy(chksum,page+22,4);
    669     memset(page+22,0,4);
    670 
    671     /* set up a temp page struct and recompute the checksum */
    672     log.header=page;
    673     log.header_len=oy->headerbytes;
    674     log.body=page+oy->headerbytes;
    675     log.body_len=oy->bodybytes;
    676     ogg_page_checksum_set(&log);
    677 
    678     /* Compare */
    679     if(memcmp(chksum,page+22,4)){
    680       /* D'oh.  Mismatch! Corrupt page (or miscapture and not a page
    681          at all) */
    682       /* replace the computed checksum with the one actually read in */
    683       memcpy(page+22,chksum,4);
    684 
    685       /* Bad checksum. Lose sync */
    686       goto sync_fail;
    687     }
    688   }
    689 
    690   /* yes, have a whole page all ready to go */
    691   {
    692     unsigned char *page=oy->data+oy->returned;
    693     long bytes;
    694 
    695     if(og){
    696       og->header=page;
    697       og->header_len=oy->headerbytes;
    698       og->body=page+oy->headerbytes;
    699       og->body_len=oy->bodybytes;
    700     }
    701 
    702     oy->unsynced=0;
    703     oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
    704     oy->headerbytes=0;
    705     oy->bodybytes=0;
    706     return(bytes);
    707   }
    708 
    709  sync_fail:
    710 
    711   oy->headerbytes=0;
    712   oy->bodybytes=0;
    713 
    714   /* search for possible capture */
    715   next=memchr(page+1,'O',bytes-1);
    716   if(!next)
    717     next=oy->data+oy->fill;
    718 
    719   oy->returned=(int)(next-oy->data);
    720   return((long)-(next-page));
    721 }
    722 
    723 /* sync the stream and get a page.  Keep trying until we find a page.
    724    Supress 'sync errors' after reporting the first.
    725 
    726    return values:
    727    -1) recapture (hole in data)
    728     0) need more data
    729     1) page returned
    730 
    731    Returns pointers into buffered data; invalidated by next call to
    732    _stream, _clear, _init, or _buffer */
    733 
    734 int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
    735 
    736   if(ogg_sync_check(oy))return 0;
    737 
    738   /* all we need to do is verify a page at the head of the stream
    739      buffer.  If it doesn't verify, we look for the next potential
    740      frame */
    741 
    742   for(;;){
    743     long ret=ogg_sync_pageseek(oy,og);
    744     if(ret>0){
    745       /* have a page */
    746       return(1);
    747     }
    748     if(ret==0){
    749       /* need more data */
    750       return(0);
    751     }
    752 
    753     /* head did not start a synced page... skipped some bytes */
    754     if(!oy->unsynced){
    755       oy->unsynced=1;
    756       return(-1);
    757     }
    758 
    759     /* loop. keep looking */
    760 
    761   }
    762 }
    763 
    764 /* add the incoming page to the stream state; we decompose the page
    765    into packet segments here as well. */
    766 
    767 int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
    768   unsigned char *header=og->header;
    769   unsigned char *body=og->body;
    770   long           bodysize=og->body_len;
    771   int            segptr=0;
    772 
    773   int version=ogg_page_version(og);
    774   int continued=ogg_page_continued(og);
    775   int bos=ogg_page_bos(og);
    776   int eos=ogg_page_eos(og);
    777   ogg_int64_t granulepos=ogg_page_granulepos(og);
    778   int serialno=ogg_page_serialno(og);
    779   long pageno=ogg_page_pageno(og);
    780   int segments=header[26];
    781 
    782   if(ogg_stream_check(os)) return -1;
    783 
    784   /* clean up 'returned data' */
    785   {
    786     long lr=os->lacing_returned;
    787     long br=os->body_returned;
    788 
    789     /* body data */
    790     if(br){
    791       os->body_fill-=br;
    792       if(os->body_fill)
    793         memmove(os->body_data,os->body_data+br,os->body_fill);
    794       os->body_returned=0;
    795     }
    796 
    797     if(lr){
    798       /* segment table */
    799       if(os->lacing_fill-lr){
    800         memmove(os->lacing_vals,os->lacing_vals+lr,
    801                 (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
    802         memmove(os->granule_vals,os->granule_vals+lr,
    803                 (os->lacing_fill-lr)*sizeof(*os->granule_vals));
    804       }
    805       os->lacing_fill-=lr;
    806       os->lacing_packet-=lr;
    807       os->lacing_returned=0;
    808     }
    809   }
    810 
    811   /* check the serial number */
    812   if(serialno!=os->serialno)return(-1);
    813   if(version>0)return(-1);
    814 
    815   if(_os_lacing_expand(os,segments+1)) return -1;
    816 
    817   /* are we in sequence? */
    818   if(pageno!=os->pageno){
    819     int i;
    820 
    821     /* unroll previous partial packet (if any) */
    822     for(i=os->lacing_packet;i<os->lacing_fill;i++)
    823       os->body_fill-=os->lacing_vals[i]&0xff;
    824     os->lacing_fill=os->lacing_packet;
    825 
    826     /* make a note of dropped data in segment table */
    827     if(os->pageno!=-1){
    828       os->lacing_vals[os->lacing_fill++]=0x400;
    829       os->lacing_packet++;
    830     }
    831   }
    832 
    833   /* are we a 'continued packet' page?  If so, we may need to skip
    834      some segments */
    835   if(continued){
    836     if(os->lacing_fill<1 ||
    837        os->lacing_vals[os->lacing_fill-1]==0x400){
    838       bos=0;
    839       for(;segptr<segments;segptr++){
    840         int val=header[27+segptr];
    841         body+=val;
    842         bodysize-=val;
    843         if(val<255){
    844           segptr++;
    845           break;
    846         }
    847       }
    848     }
    849   }
    850 
    851   if(bodysize){
    852     if(_os_body_expand(os,bodysize)) return -1;
    853     memcpy(os->body_data+os->body_fill,body,bodysize);
    854     os->body_fill+=bodysize;
    855   }
    856 
    857   {
    858     int saved=-1;
    859     while(segptr<segments){
    860       int val=header[27+segptr];
    861       os->lacing_vals[os->lacing_fill]=val;
    862       os->granule_vals[os->lacing_fill]=-1;
    863 
    864       if(bos){
    865         os->lacing_vals[os->lacing_fill]|=0x100;
    866         bos=0;
    867       }
    868 
    869       if(val<255)saved=os->lacing_fill;
    870 
    871       os->lacing_fill++;
    872       segptr++;
    873 
    874       if(val<255)os->lacing_packet=os->lacing_fill;
    875     }
    876 
    877     /* set the granulepos on the last granuleval of the last full packet */
    878     if(saved!=-1){
    879       os->granule_vals[saved]=granulepos;
    880     }
    881 
    882   }
    883 
    884   if(eos){
    885     os->e_o_s=1;
    886     if(os->lacing_fill>0)
    887       os->lacing_vals[os->lacing_fill-1]|=0x200;
    888   }
    889 
    890   os->pageno=pageno+1;
    891 
    892   return(0);
    893 }
    894 
    895 /* clear things to an initial state.  Good to call, eg, before seeking */
    896 int ogg_sync_reset(ogg_sync_state *oy){
    897   if(ogg_sync_check(oy))return -1;
    898 
    899   oy->fill=0;
    900   oy->returned=0;
    901   oy->unsynced=0;
    902   oy->headerbytes=0;
    903   oy->bodybytes=0;
    904   return(0);
    905 }
    906 
    907 int ogg_stream_reset(ogg_stream_state *os){
    908   if(ogg_stream_check(os)) return -1;
    909 
    910   os->body_fill=0;
    911   os->body_returned=0;
    912 
    913   os->lacing_fill=0;
    914   os->lacing_packet=0;
    915   os->lacing_returned=0;
    916 
    917   os->header_fill=0;
    918 
    919   os->e_o_s=0;
    920   os->b_o_s=0;
    921   os->pageno=-1;
    922   os->packetno=0;
    923   os->granulepos=0;
    924 
    925   return(0);
    926 }
    927 
    928 int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
    929   if(ogg_stream_check(os)) return -1;
    930   ogg_stream_reset(os);
    931   os->serialno=serialno;
    932   return(0);
    933 }
    934 
    935 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
    936 
    937   /* The last part of decode. We have the stream broken into packet
    938      segments.  Now we need to group them into packets (or return the
    939      out of sync markers) */
    940 
    941   int ptr=os->lacing_returned;
    942 
    943   if(os->lacing_packet<=ptr)return(0);
    944 
    945   if(os->lacing_vals[ptr]&0x400){
    946     /* we need to tell the codec there's a gap; it might need to
    947        handle previous packet dependencies. */
    948     os->lacing_returned++;
    949     os->packetno++;
    950     return(-1);
    951   }
    952 
    953   if(!op && !adv)return(1); /* just using peek as an inexpensive way
    954                                to ask if there's a whole packet
    955                                waiting */
    956 
    957   /* Gather the whole packet. We'll have no holes or a partial packet */
    958   {
    959     int size=os->lacing_vals[ptr]&0xff;
    960     int bytes=size;
    961     int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
    962     int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
    963 
    964     while(size==255){
    965       int val=os->lacing_vals[++ptr];
    966       size=val&0xff;
    967       if(val&0x200)eos=0x200;
    968       bytes+=size;
    969     }
    970 
    971     if(op){
    972       op->e_o_s=eos;
    973       op->b_o_s=bos;
    974       op->packet=os->body_data+os->body_returned;
    975       op->packetno=os->packetno;
    976       op->granulepos=os->granule_vals[ptr];
    977       op->bytes=bytes;
    978     }
    979 
    980     if(adv){
    981       os->body_returned+=bytes;
    982       os->lacing_returned=ptr+1;
    983       os->packetno++;
    984     }
    985   }
    986   return(1);
    987 }
    988 
    989 int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
    990   if(ogg_stream_check(os)) return 0;
    991   return _packetout(os,op,1);
    992 }
    993 
    994 int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
    995   if(ogg_stream_check(os)) return 0;
    996   return _packetout(os,op,0);
    997 }
    998 
    999 void ogg_packet_clear(ogg_packet *op) {
   1000   _ogg_free(op->packet);
   1001   memset(op, 0, sizeof(*op));
   1002 }
   1003 
   1004 #ifdef _V_SELFTEST
   1005 #include <stdio.h>
   1006 
   1007 ogg_stream_state os_en, os_de;
   1008 ogg_sync_state oy;
   1009 
   1010 void checkpacket(ogg_packet *op,int len, int no, int pos){
   1011   long j;
   1012   static int sequence=0;
   1013   static int lastno=0;
   1014 
   1015   if(op->bytes!=len){
   1016     fprintf(stderr,"incorrect packet length (%d != %d)!\n",op->bytes,len);
   1017     exit(1);
   1018   }
   1019   if(op->granulepos!=pos){
   1020     fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos);
   1021     exit(1);
   1022   }
   1023 
   1024   /* packet number just follows sequence/gap; adjust the input number
   1025      for that */
   1026   if(no==0){
   1027     sequence=0;
   1028   }else{
   1029     sequence++;
   1030     if(no>lastno+1)
   1031       sequence++;
   1032   }
   1033   lastno=no;
   1034   if(op->packetno!=sequence){
   1035     fprintf(stderr,"incorrect packet sequence %ld != %d\n",
   1036             (long)(op->packetno),sequence);
   1037     exit(1);
   1038   }
   1039 
   1040   /* Test data */
   1041   for(j=0;j<op->bytes;j++)
   1042     if(op->packet[j]!=((j+no)&0xff)){
   1043       fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
   1044               j,op->packet[j],(j+no)&0xff);
   1045       exit(1);
   1046     }
   1047 }
   1048 
   1049 void check_page(unsigned char *data,const int *header,ogg_page *og){
   1050   long j;
   1051   /* Test data */
   1052   for(j=0;j<og->body_len;j++)
   1053     if(og->body[j]!=data[j]){
   1054       fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
   1055               j,data[j],og->body[j]);
   1056       exit(1);
   1057     }
   1058 
   1059   /* Test header */
   1060   for(j=0;j<og->header_len;j++){
   1061     if(og->header[j]!=header[j]){
   1062       fprintf(stderr,"header content mismatch at pos %ld:\n",j);
   1063       for(j=0;j<header[26]+27;j++)
   1064         fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
   1065       fprintf(stderr,"\n");
   1066       exit(1);
   1067     }
   1068   }
   1069   if(og->header_len!=header[26]+27){
   1070     fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
   1071             og->header_len,header[26]+27);
   1072     exit(1);
   1073   }
   1074 }
   1075 
   1076 void print_header(ogg_page *og){
   1077   int j;
   1078   fprintf(stderr,"\nHEADER:\n");
   1079   fprintf(stderr,"  capture: %c %c %c %c  version: %d  flags: %x\n",
   1080           og->header[0],og->header[1],og->header[2],og->header[3],
   1081           (int)og->header[4],(int)og->header[5]);
   1082 
   1083   fprintf(stderr,"  granulepos: %d  serialno: %d  pageno: %ld\n",
   1084           (og->header[9]<<24)|(og->header[8]<<16)|
   1085           (og->header[7]<<8)|og->header[6],
   1086           (og->header[17]<<24)|(og->header[16]<<16)|
   1087           (og->header[15]<<8)|og->header[14],
   1088           ((long)(og->header[21])<<24)|(og->header[20]<<16)|
   1089           (og->header[19]<<8)|og->header[18]);
   1090 
   1091   fprintf(stderr,"  checksum: %02x:%02x:%02x:%02x\n  segments: %d (",
   1092           (int)og->header[22],(int)og->header[23],
   1093           (int)og->header[24],(int)og->header[25],
   1094           (int)og->header[26]);
   1095 
   1096   for(j=27;j<og->header_len;j++)
   1097     fprintf(stderr,"%d ",(int)og->header[j]);
   1098   fprintf(stderr,")\n\n");
   1099 }
   1100 
   1101 void copy_page(ogg_page *og){
   1102   unsigned char *temp=_ogg_malloc(og->header_len);
   1103   memcpy(temp,og->header,og->header_len);
   1104   og->header=temp;
   1105 
   1106   temp=_ogg_malloc(og->body_len);
   1107   memcpy(temp,og->body,og->body_len);
   1108   og->body=temp;
   1109 }
   1110 
   1111 void free_page(ogg_page *og){
   1112   _ogg_free (og->header);
   1113   _ogg_free (og->body);
   1114 }
   1115 
   1116 void error(void){
   1117   fprintf(stderr,"error!\n");
   1118   exit(1);
   1119 }
   1120 
   1121 /* 17 only */
   1122 const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
   1123                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1124                        0x01,0x02,0x03,0x04,0,0,0,0,
   1125                        0x15,0xed,0xec,0x91,
   1126                        1,
   1127                        17};
   1128 
   1129 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
   1130 const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1131                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1132                        0x01,0x02,0x03,0x04,0,0,0,0,
   1133                        0x59,0x10,0x6c,0x2c,
   1134                        1,
   1135                        17};
   1136 const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
   1137                        0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
   1138                        0x01,0x02,0x03,0x04,1,0,0,0,
   1139                        0x89,0x33,0x85,0xce,
   1140                        13,
   1141                        254,255,0,255,1,255,245,255,255,0,
   1142                        255,255,90};
   1143 
   1144 /* nil packets; beginning,middle,end */
   1145 const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1146                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1147                        0x01,0x02,0x03,0x04,0,0,0,0,
   1148                        0xff,0x7b,0x23,0x17,
   1149                        1,
   1150                        0};
   1151 const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
   1152                        0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
   1153                        0x01,0x02,0x03,0x04,1,0,0,0,
   1154                        0x5c,0x3f,0x66,0xcb,
   1155                        17,
   1156                        17,254,255,0,0,255,1,0,255,245,255,255,0,
   1157                        255,255,90,0};
   1158 
   1159 /* large initial packet */
   1160 const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1161                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1162                        0x01,0x02,0x03,0x04,0,0,0,0,
   1163                        0x01,0x27,0x31,0xaa,
   1164                        18,
   1165                        255,255,255,255,255,255,255,255,
   1166                        255,255,255,255,255,255,255,255,255,10};
   1167 
   1168 const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
   1169                        0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
   1170                        0x01,0x02,0x03,0x04,1,0,0,0,
   1171                        0x7f,0x4e,0x8a,0xd2,
   1172                        4,
   1173                        255,4,255,0};
   1174 
   1175 
   1176 /* continuing packet test */
   1177 const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1178                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1179                        0x01,0x02,0x03,0x04,0,0,0,0,
   1180                        0xff,0x7b,0x23,0x17,
   1181                        1,
   1182                        0};
   1183 
   1184 const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
   1185                        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
   1186                        0x01,0x02,0x03,0x04,1,0,0,0,
   1187                        0xf8,0x3c,0x19,0x79,
   1188                        255,
   1189                        255,255,255,255,255,255,255,255,
   1190                        255,255,255,255,255,255,255,255,
   1191                        255,255,255,255,255,255,255,255,
   1192                        255,255,255,255,255,255,255,255,
   1193                        255,255,255,255,255,255,255,255,
   1194                        255,255,255,255,255,255,255,255,
   1195                        255,255,255,255,255,255,255,255,
   1196                        255,255,255,255,255,255,255,255,
   1197                        255,255,255,255,255,255,255,255,
   1198                        255,255,255,255,255,255,255,255,
   1199                        255,255,255,255,255,255,255,255,
   1200                        255,255,255,255,255,255,255,255,
   1201                        255,255,255,255,255,255,255,255,
   1202                        255,255,255,255,255,255,255,255,
   1203                        255,255,255,255,255,255,255,255,
   1204                        255,255,255,255,255,255,255,255,
   1205                        255,255,255,255,255,255,255,255,
   1206                        255,255,255,255,255,255,255,255,
   1207                        255,255,255,255,255,255,255,255,
   1208                        255,255,255,255,255,255,255,255,
   1209                        255,255,255,255,255,255,255,255,
   1210                        255,255,255,255,255,255,255,255,
   1211                        255,255,255,255,255,255,255,255,
   1212                        255,255,255,255,255,255,255,255,
   1213                        255,255,255,255,255,255,255,255,
   1214                        255,255,255,255,255,255,255,255,
   1215                        255,255,255,255,255,255,255,255,
   1216                        255,255,255,255,255,255,255,255,
   1217                        255,255,255,255,255,255,255,255,
   1218                        255,255,255,255,255,255,255,255,
   1219                        255,255,255,255,255,255,255,255,
   1220                        255,255,255,255,255,255,255};
   1221 
   1222 const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
   1223                        0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
   1224                        0x01,0x02,0x03,0x04,2,0,0,0,
   1225                        0x38,0xe6,0xb6,0x28,
   1226                        6,
   1227                        255,220,255,4,255,0};
   1228 
   1229 
   1230 /* spill expansion test */
   1231 const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1232                         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1233                         0x01,0x02,0x03,0x04,0,0,0,0,
   1234                         0xff,0x7b,0x23,0x17,
   1235                         1,
   1236                         0};
   1237 
   1238 const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
   1239                         0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
   1240                         0x01,0x02,0x03,0x04,1,0,0,0,
   1241                         0xce,0x8f,0x17,0x1a,
   1242                         23,
   1243                         255,255,255,255,255,255,255,255,
   1244                         255,255,255,255,255,255,255,255,255,10,255,4,255,0,0};
   1245 
   1246 
   1247 const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
   1248                         0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
   1249                         0x01,0x02,0x03,0x04,2,0,0,0,
   1250                         0x9b,0xb2,0x50,0xa1,
   1251                         1,
   1252                         0};
   1253 
   1254 /* page with the 255 segment limit */
   1255 const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1256                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1257                        0x01,0x02,0x03,0x04,0,0,0,0,
   1258                        0xff,0x7b,0x23,0x17,
   1259                        1,
   1260                        0};
   1261 
   1262 const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
   1263                        0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
   1264                        0x01,0x02,0x03,0x04,1,0,0,0,
   1265                        0xed,0x2a,0x2e,0xa7,
   1266                        255,
   1267                        10,10,10,10,10,10,10,10,
   1268                        10,10,10,10,10,10,10,10,
   1269                        10,10,10,10,10,10,10,10,
   1270                        10,10,10,10,10,10,10,10,
   1271                        10,10,10,10,10,10,10,10,
   1272                        10,10,10,10,10,10,10,10,
   1273                        10,10,10,10,10,10,10,10,
   1274                        10,10,10,10,10,10,10,10,
   1275                        10,10,10,10,10,10,10,10,
   1276                        10,10,10,10,10,10,10,10,
   1277                        10,10,10,10,10,10,10,10,
   1278                        10,10,10,10,10,10,10,10,
   1279                        10,10,10,10,10,10,10,10,
   1280                        10,10,10,10,10,10,10,10,
   1281                        10,10,10,10,10,10,10,10,
   1282                        10,10,10,10,10,10,10,10,
   1283                        10,10,10,10,10,10,10,10,
   1284                        10,10,10,10,10,10,10,10,
   1285                        10,10,10,10,10,10,10,10,
   1286                        10,10,10,10,10,10,10,10,
   1287                        10,10,10,10,10,10,10,10,
   1288                        10,10,10,10,10,10,10,10,
   1289                        10,10,10,10,10,10,10,10,
   1290                        10,10,10,10,10,10,10,10,
   1291                        10,10,10,10,10,10,10,10,
   1292                        10,10,10,10,10,10,10,10,
   1293                        10,10,10,10,10,10,10,10,
   1294                        10,10,10,10,10,10,10,10,
   1295                        10,10,10,10,10,10,10,10,
   1296                        10,10,10,10,10,10,10,10,
   1297                        10,10,10,10,10,10,10,10,
   1298                        10,10,10,10,10,10,10};
   1299 
   1300 const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
   1301                        0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
   1302                        0x01,0x02,0x03,0x04,2,0,0,0,
   1303                        0x6c,0x3b,0x82,0x3d,
   1304                        1,
   1305                        50};
   1306 
   1307 
   1308 /* packet that overspans over an entire page */
   1309 const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1310                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1311                        0x01,0x02,0x03,0x04,0,0,0,0,
   1312                        0xff,0x7b,0x23,0x17,
   1313                        1,
   1314                        0};
   1315 
   1316 const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
   1317                        0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
   1318                        0x01,0x02,0x03,0x04,1,0,0,0,
   1319                        0x68,0x22,0x7c,0x3d,
   1320                        255,
   1321                        100,
   1322                        255,255,255,255,255,255,255,255,
   1323                        255,255,255,255,255,255,255,255,
   1324                        255,255,255,255,255,255,255,255,
   1325                        255,255,255,255,255,255,255,255,
   1326                        255,255,255,255,255,255,255,255,
   1327                        255,255,255,255,255,255,255,255,
   1328                        255,255,255,255,255,255,255,255,
   1329                        255,255,255,255,255,255,255,255,
   1330                        255,255,255,255,255,255,255,255,
   1331                        255,255,255,255,255,255,255,255,
   1332                        255,255,255,255,255,255,255,255,
   1333                        255,255,255,255,255,255,255,255,
   1334                        255,255,255,255,255,255,255,255,
   1335                        255,255,255,255,255,255,255,255,
   1336                        255,255,255,255,255,255,255,255,
   1337                        255,255,255,255,255,255,255,255,
   1338                        255,255,255,255,255,255,255,255,
   1339                        255,255,255,255,255,255,255,255,
   1340                        255,255,255,255,255,255,255,255,
   1341                        255,255,255,255,255,255,255,255,
   1342                        255,255,255,255,255,255,255,255,
   1343                        255,255,255,255,255,255,255,255,
   1344                        255,255,255,255,255,255,255,255,
   1345                        255,255,255,255,255,255,255,255,
   1346                        255,255,255,255,255,255,255,255,
   1347                        255,255,255,255,255,255,255,255,
   1348                        255,255,255,255,255,255,255,255,
   1349                        255,255,255,255,255,255,255,255,
   1350                        255,255,255,255,255,255,255,255,
   1351                        255,255,255,255,255,255,255,255,
   1352                        255,255,255,255,255,255,255,255,
   1353                        255,255,255,255,255,255};
   1354 
   1355 const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
   1356                        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
   1357                        0x01,0x02,0x03,0x04,2,0,0,0,
   1358                        0xf4,0x87,0xba,0xf3,
   1359                        255,
   1360                        255,255,255,255,255,255,255,255,
   1361                        255,255,255,255,255,255,255,255,
   1362                        255,255,255,255,255,255,255,255,
   1363                        255,255,255,255,255,255,255,255,
   1364                        255,255,255,255,255,255,255,255,
   1365                        255,255,255,255,255,255,255,255,
   1366                        255,255,255,255,255,255,255,255,
   1367                        255,255,255,255,255,255,255,255,
   1368                        255,255,255,255,255,255,255,255,
   1369                        255,255,255,255,255,255,255,255,
   1370                        255,255,255,255,255,255,255,255,
   1371                        255,255,255,255,255,255,255,255,
   1372                        255,255,255,255,255,255,255,255,
   1373                        255,255,255,255,255,255,255,255,
   1374                        255,255,255,255,255,255,255,255,
   1375                        255,255,255,255,255,255,255,255,
   1376                        255,255,255,255,255,255,255,255,
   1377                        255,255,255,255,255,255,255,255,
   1378                        255,255,255,255,255,255,255,255,
   1379                        255,255,255,255,255,255,255,255,
   1380                        255,255,255,255,255,255,255,255,
   1381                        255,255,255,255,255,255,255,255,
   1382                        255,255,255,255,255,255,255,255,
   1383                        255,255,255,255,255,255,255,255,
   1384                        255,255,255,255,255,255,255,255,
   1385                        255,255,255,255,255,255,255,255,
   1386                        255,255,255,255,255,255,255,255,
   1387                        255,255,255,255,255,255,255,255,
   1388                        255,255,255,255,255,255,255,255,
   1389                        255,255,255,255,255,255,255,255,
   1390                        255,255,255,255,255,255,255,255,
   1391                        255,255,255,255,255,255,255};
   1392 
   1393 const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
   1394                        0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
   1395                        0x01,0x02,0x03,0x04,3,0,0,0,
   1396                        0xf7,0x2f,0x6c,0x60,
   1397                        5,
   1398                        254,255,4,255,0};
   1399 
   1400 /* packet that overspans over an entire page */
   1401 const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
   1402                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
   1403                        0x01,0x02,0x03,0x04,0,0,0,0,
   1404                        0xff,0x7b,0x23,0x17,
   1405                        1,
   1406                        0};
   1407 
   1408 const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
   1409                        0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
   1410                        0x01,0x02,0x03,0x04,1,0,0,0,
   1411                        0x68,0x22,0x7c,0x3d,
   1412                        255,
   1413                        100,
   1414                        255,255,255,255,255,255,255,255,
   1415                        255,255,255,255,255,255,255,255,
   1416                        255,255,255,255,255,255,255,255,
   1417                        255,255,255,255,255,255,255,255,
   1418                        255,255,255,255,255,255,255,255,
   1419                        255,255,255,255,255,255,255,255,
   1420                        255,255,255,255,255,255,255,255,
   1421                        255,255,255,255,255,255,255,255,
   1422                        255,255,255,255,255,255,255,255,
   1423                        255,255,255,255,255,255,255,255,
   1424                        255,255,255,255,255,255,255,255,
   1425                        255,255,255,255,255,255,255,255,
   1426                        255,255,255,255,255,255,255,255,
   1427                        255,255,255,255,255,255,255,255,
   1428                        255,255,255,255,255,255,255,255,
   1429                        255,255,255,255,255,255,255,255,
   1430                        255,255,255,255,255,255,255,255,
   1431                        255,255,255,255,255,255,255,255,
   1432                        255,255,255,255,255,255,255,255,
   1433                        255,255,255,255,255,255,255,255,
   1434                        255,255,255,255,255,255,255,255,
   1435                        255,255,255,255,255,255,255,255,
   1436                        255,255,255,255,255,255,255,255,
   1437                        255,255,255,255,255,255,255,255,
   1438                        255,255,255,255,255,255,255,255,
   1439                        255,255,255,255,255,255,255,255,
   1440                        255,255,255,255,255,255,255,255,
   1441                        255,255,255,255,255,255,255,255,
   1442                        255,255,255,255,255,255,255,255,
   1443                        255,255,255,255,255,255,255,255,
   1444                        255,255,255,255,255,255,255,255,
   1445                        255,255,255,255,255,255};
   1446 
   1447 const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
   1448                        0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
   1449                        0x01,0x02,0x03,0x04,2,0,0,0,
   1450                        0xd4,0xe0,0x60,0xe5,
   1451                        1,
   1452                        0};
   1453 
   1454 void test_pack(const int *pl, const int **headers, int byteskip,
   1455                int pageskip, int packetskip){
   1456   unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
   1457   long inptr=0;
   1458   long outptr=0;
   1459   long deptr=0;
   1460   long depacket=0;
   1461   long granule_pos=7,pageno=0;
   1462   int i,j,packets,pageout=pageskip;
   1463   int eosflag=0;
   1464   int bosflag=0;
   1465 
   1466   int byteskipcount=0;
   1467 
   1468   ogg_stream_reset(&os_en);
   1469   ogg_stream_reset(&os_de);
   1470   ogg_sync_reset(&oy);
   1471 
   1472   for(packets=0;packets<packetskip;packets++)
   1473     depacket+=pl[packets];
   1474 
   1475   for(packets=0;;packets++)if(pl[packets]==-1)break;
   1476 
   1477   for(i=0;i<packets;i++){
   1478     /* construct a test packet */
   1479     ogg_packet op;
   1480     int len=pl[i];
   1481 
   1482     op.packet=data+inptr;
   1483     op.bytes=len;
   1484     op.e_o_s=(pl[i+1]<0?1:0);
   1485     op.granulepos=granule_pos;
   1486 
   1487     granule_pos+=1024;
   1488 
   1489     for(j=0;j<len;j++)data[inptr++]=i+j;
   1490 
   1491     /* submit the test packet */
   1492     ogg_stream_packetin(&os_en,&op);
   1493 
   1494     /* retrieve any finished pages */
   1495     {
   1496       ogg_page og;
   1497 
   1498       while(ogg_stream_pageout(&os_en,&og)){
   1499         /* We have a page.  Check it carefully */
   1500 
   1501         fprintf(stderr,"%ld, ",pageno);
   1502 
   1503         if(headers[pageno]==NULL){
   1504           fprintf(stderr,"coded too many pages!\n");
   1505           exit(1);
   1506         }
   1507 
   1508         check_page(data+outptr,headers[pageno],&og);
   1509 
   1510         outptr+=og.body_len;
   1511         pageno++;
   1512         if(pageskip){
   1513           bosflag=1;
   1514           pageskip--;
   1515           deptr+=og.body_len;
   1516         }
   1517 
   1518         /* have a complete page; submit it to sync/decode */
   1519 
   1520         {
   1521           ogg_page og_de;
   1522           ogg_packet op_de,op_de2;
   1523           char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
   1524           char *next=buf;
   1525           byteskipcount+=og.header_len;
   1526           if(byteskipcount>byteskip){
   1527             memcpy(next,og.header,byteskipcount-byteskip);
   1528             next+=byteskipcount-byteskip;
   1529             byteskipcount=byteskip;
   1530           }
   1531 
   1532           byteskipcount+=og.body_len;
   1533           if(byteskipcount>byteskip){
   1534             memcpy(next,og.body,byteskipcount-byteskip);
   1535             next+=byteskipcount-byteskip;
   1536             byteskipcount=byteskip;
   1537           }
   1538 
   1539           ogg_sync_wrote(&oy,next-buf);
   1540 
   1541           while(1){
   1542             int ret=ogg_sync_pageout(&oy,&og_de);
   1543             if(ret==0)break;
   1544             if(ret<0)continue;
   1545             /* got a page.  Happy happy.  Verify that it's good. */
   1546 
   1547             fprintf(stderr,"(%ld), ",pageout);
   1548 
   1549             check_page(data+deptr,headers[pageout],&og_de);
   1550             deptr+=og_de.body_len;
   1551             pageout++;
   1552 
   1553             /* submit it to deconstitution */
   1554             ogg_stream_pagein(&os_de,&og_de);
   1555 
   1556             /* packets out? */
   1557             while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
   1558               ogg_stream_packetpeek(&os_de,NULL);
   1559               ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
   1560 
   1561               /* verify peek and out match */
   1562               if(memcmp(&op_de,&op_de2,sizeof(op_de))){
   1563                 fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
   1564                         depacket);
   1565                 exit(1);
   1566               }
   1567 
   1568               /* verify the packet! */
   1569               /* check data */
   1570               if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
   1571                 fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
   1572                         depacket);
   1573                 exit(1);
   1574               }
   1575               /* check bos flag */
   1576               if(bosflag==0 && op_de.b_o_s==0){
   1577                 fprintf(stderr,"b_o_s flag not set on packet!\n");
   1578                 exit(1);
   1579               }
   1580               if(bosflag && op_de.b_o_s){
   1581                 fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
   1582                 exit(1);
   1583               }
   1584               bosflag=1;
   1585               depacket+=op_de.bytes;
   1586 
   1587               /* check eos flag */
   1588               if(eosflag){
   1589                 fprintf(stderr,"Multiple decoded packets with eos flag!\n");
   1590                 exit(1);
   1591               }
   1592 
   1593               if(op_de.e_o_s)eosflag=1;
   1594 
   1595               /* check granulepos flag */
   1596               if(op_de.granulepos!=-1){
   1597                 fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
   1598               }
   1599             }
   1600           }
   1601         }
   1602       }
   1603     }
   1604   }
   1605   _ogg_free(data);
   1606   if(headers[pageno]!=NULL){
   1607     fprintf(stderr,"did not write last page!\n");
   1608     exit(1);
   1609   }
   1610   if(headers[pageout]!=NULL){
   1611     fprintf(stderr,"did not decode last page!\n");
   1612     exit(1);
   1613   }
   1614   if(inptr!=outptr){
   1615     fprintf(stderr,"encoded page data incomplete!\n");
   1616     exit(1);
   1617   }
   1618   if(inptr!=deptr){
   1619     fprintf(stderr,"decoded page data incomplete!\n");
   1620     exit(1);
   1621   }
   1622   if(inptr!=depacket){
   1623     fprintf(stderr,"decoded packet data incomplete!\n");
   1624     exit(1);
   1625   }
   1626   if(!eosflag){
   1627     fprintf(stderr,"Never got a packet with EOS set!\n");
   1628     exit(1);
   1629   }
   1630   fprintf(stderr,"ok.\n");
   1631 }
   1632 
   1633 int main(void){
   1634 
   1635   ogg_stream_init(&os_en,0x04030201);
   1636   ogg_stream_init(&os_de,0x04030201);
   1637   ogg_sync_init(&oy);
   1638 
   1639   /* Exercise each code path in the framing code.  Also verify that
   1640      the checksums are working.  */
   1641 
   1642   {
   1643     /* 17 only */
   1644     const int packets[]={17, -1};
   1645     const int *headret[]={head1_0,NULL};
   1646 
   1647     fprintf(stderr,"testing single page encoding... ");
   1648     test_pack(packets,headret,0,0,0);
   1649   }
   1650 
   1651   {
   1652     /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
   1653     const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
   1654     const int *headret[]={head1_1,head2_1,NULL};
   1655 
   1656     fprintf(stderr,"testing basic page encoding... ");
   1657     test_pack(packets,headret,0,0,0);
   1658   }
   1659 
   1660   {
   1661     /* nil packets; beginning,middle,end */
   1662     const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
   1663     const int *headret[]={head1_2,head2_2,NULL};
   1664 
   1665     fprintf(stderr,"testing basic nil packets... ");
   1666     test_pack(packets,headret,0,0,0);
   1667   }
   1668 
   1669   {
   1670     /* large initial packet */
   1671     const int packets[]={4345,259,255,-1};
   1672     const int *headret[]={head1_3,head2_3,NULL};
   1673 
   1674     fprintf(stderr,"testing initial-packet lacing > 4k... ");
   1675     test_pack(packets,headret,0,0,0);
   1676   }
   1677 
   1678   {
   1679     /* continuing packet test; with page spill expansion, we have to
   1680        overflow the lacing table. */
   1681     const int packets[]={0,65500,259,255,-1};
   1682     const int *headret[]={head1_4,head2_4,head3_4,NULL};
   1683 
   1684     fprintf(stderr,"testing single packet page span... ");
   1685     test_pack(packets,headret,0,0,0);
   1686   }
   1687 
   1688   {
   1689     /* spill expand packet test */
   1690     const int packets[]={0,4345,259,255,0,0,-1};
   1691     const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
   1692 
   1693     fprintf(stderr,"testing page spill expansion... ");
   1694     test_pack(packets,headret,0,0,0);
   1695   }
   1696 
   1697   /* page with the 255 segment limit */
   1698   {
   1699 
   1700     const int packets[]={0,10,10,10,10,10,10,10,10,
   1701                    10,10,10,10,10,10,10,10,
   1702                    10,10,10,10,10,10,10,10,
   1703                    10,10,10,10,10,10,10,10,
   1704                    10,10,10,10,10,10,10,10,
   1705                    10,10,10,10,10,10,10,10,
   1706                    10,10,10,10,10,10,10,10,
   1707                    10,10,10,10,10,10,10,10,
   1708                    10,10,10,10,10,10,10,10,
   1709                    10,10,10,10,10,10,10,10,
   1710                    10,10,10,10,10,10,10,10,
   1711                    10,10,10,10,10,10,10,10,
   1712                    10,10,10,10,10,10,10,10,
   1713                    10,10,10,10,10,10,10,10,
   1714                    10,10,10,10,10,10,10,10,
   1715                    10,10,10,10,10,10,10,10,
   1716                    10,10,10,10,10,10,10,10,
   1717                    10,10,10,10,10,10,10,10,
   1718                    10,10,10,10,10,10,10,10,
   1719                    10,10,10,10,10,10,10,10,
   1720                    10,10,10,10,10,10,10,10,
   1721                    10,10,10,10,10,10,10,10,
   1722                    10,10,10,10,10,10,10,10,
   1723                    10,10,10,10,10,10,10,10,
   1724                    10,10,10,10,10,10,10,10,
   1725                    10,10,10,10,10,10,10,10,
   1726                    10,10,10,10,10,10,10,10,
   1727                    10,10,10,10,10,10,10,10,
   1728                    10,10,10,10,10,10,10,10,
   1729                    10,10,10,10,10,10,10,10,
   1730                    10,10,10,10,10,10,10,10,
   1731                    10,10,10,10,10,10,10,50,-1};
   1732     const int *headret[]={head1_5,head2_5,head3_5,NULL};
   1733 
   1734     fprintf(stderr,"testing max packet segments... ");
   1735     test_pack(packets,headret,0,0,0);
   1736   }
   1737 
   1738   {
   1739     /* packet that overspans over an entire page */
   1740     const int packets[]={0,100,130049,259,255,-1};
   1741     const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
   1742 
   1743     fprintf(stderr,"testing very large packets... ");
   1744     test_pack(packets,headret,0,0,0);
   1745   }
   1746 
   1747   {
   1748     /* test for the libogg 1.1.1 resync in large continuation bug
   1749        found by Josh Coalson)  */
   1750     const int packets[]={0,100,130049,259,255,-1};
   1751     const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
   1752 
   1753     fprintf(stderr,"testing continuation resync in very large packets... ");
   1754     test_pack(packets,headret,100,2,3);
   1755   }
   1756 
   1757   {
   1758     /* term only page.  why not? */
   1759     const int packets[]={0,100,64770,-1};
   1760     const int *headret[]={head1_7,head2_7,head3_7,NULL};
   1761 
   1762     fprintf(stderr,"testing zero data page (1 nil packet)... ");
   1763     test_pack(packets,headret,0,0,0);
   1764   }
   1765 
   1766 
   1767 
   1768   {
   1769     /* build a bunch of pages for testing */
   1770     unsigned char *data=_ogg_malloc(1024*1024);
   1771     int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
   1772     int inptr=0,i,j;
   1773     ogg_page og[5];
   1774 
   1775     ogg_stream_reset(&os_en);
   1776 
   1777     for(i=0;pl[i]!=-1;i++){
   1778       ogg_packet op;
   1779       int len=pl[i];
   1780 
   1781       op.packet=data+inptr;
   1782       op.bytes=len;
   1783       op.e_o_s=(pl[i+1]<0?1:0);
   1784       op.granulepos=(i+1)*1000;
   1785 
   1786       for(j=0;j<len;j++)data[inptr++]=i+j;
   1787       ogg_stream_packetin(&os_en,&op);
   1788     }
   1789 
   1790     _ogg_free(data);
   1791 
   1792     /* retrieve finished pages */
   1793     for(i=0;i<5;i++){
   1794       if(ogg_stream_pageout(&os_en,&og[i])==0){
   1795         fprintf(stderr,"Too few pages output building sync tests!\n");
   1796         exit(1);
   1797       }
   1798       copy_page(&og[i]);
   1799     }
   1800 
   1801     /* Test lost pages on pagein/packetout: no rollback */
   1802     {
   1803       ogg_page temp;
   1804       ogg_packet test;
   1805 
   1806       fprintf(stderr,"Testing loss of pages... ");
   1807 
   1808       ogg_sync_reset(&oy);
   1809       ogg_stream_reset(&os_de);
   1810       for(i=0;i<5;i++){
   1811         memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
   1812                og[i].header_len);
   1813         ogg_sync_wrote(&oy,og[i].header_len);
   1814         memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
   1815         ogg_sync_wrote(&oy,og[i].body_len);
   1816       }
   1817 
   1818       ogg_sync_pageout(&oy,&temp);
   1819       ogg_stream_pagein(&os_de,&temp);
   1820       ogg_sync_pageout(&oy,&temp);
   1821       ogg_stream_pagein(&os_de,&temp);
   1822       ogg_sync_pageout(&oy,&temp);
   1823       /* skip */
   1824       ogg_sync_pageout(&oy,&temp);
   1825       ogg_stream_pagein(&os_de,&temp);
   1826 
   1827       /* do we get the expected results/packets? */
   1828 
   1829       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1830       checkpacket(&test,0,0,0);
   1831       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1832       checkpacket(&test,1,1,-1);
   1833       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1834       checkpacket(&test,1,2,-1);
   1835       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1836       checkpacket(&test,98,3,-1);
   1837       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1838       checkpacket(&test,4079,4,5000);
   1839       if(ogg_stream_packetout(&os_de,&test)!=-1){
   1840         fprintf(stderr,"Error: loss of page did not return error\n");
   1841         exit(1);
   1842       }
   1843       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1844       checkpacket(&test,76,9,-1);
   1845       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1846       checkpacket(&test,34,10,-1);
   1847       fprintf(stderr,"ok.\n");
   1848     }
   1849 
   1850     /* Test lost pages on pagein/packetout: rollback with continuation */
   1851     {
   1852       ogg_page temp;
   1853       ogg_packet test;
   1854 
   1855       fprintf(stderr,"Testing loss of pages (rollback required)... ");
   1856 
   1857       ogg_sync_reset(&oy);
   1858       ogg_stream_reset(&os_de);
   1859       for(i=0;i<5;i++){
   1860         memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
   1861                og[i].header_len);
   1862         ogg_sync_wrote(&oy,og[i].header_len);
   1863         memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
   1864         ogg_sync_wrote(&oy,og[i].body_len);
   1865       }
   1866 
   1867       ogg_sync_pageout(&oy,&temp);
   1868       ogg_stream_pagein(&os_de,&temp);
   1869       ogg_sync_pageout(&oy,&temp);
   1870       ogg_stream_pagein(&os_de,&temp);
   1871       ogg_sync_pageout(&oy,&temp);
   1872       ogg_stream_pagein(&os_de,&temp);
   1873       ogg_sync_pageout(&oy,&temp);
   1874       /* skip */
   1875       ogg_sync_pageout(&oy,&temp);
   1876       ogg_stream_pagein(&os_de,&temp);
   1877 
   1878       /* do we get the expected results/packets? */
   1879 
   1880       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1881       checkpacket(&test,0,0,0);
   1882       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1883       checkpacket(&test,1,1,-1);
   1884       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1885       checkpacket(&test,1,2,-1);
   1886       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1887       checkpacket(&test,98,3,-1);
   1888       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1889       checkpacket(&test,4079,4,5000);
   1890       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1891       checkpacket(&test,1,5,-1);
   1892       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1893       checkpacket(&test,1,6,-1);
   1894       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1895       checkpacket(&test,2954,7,-1);
   1896       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1897       checkpacket(&test,2057,8,9000);
   1898       if(ogg_stream_packetout(&os_de,&test)!=-1){
   1899         fprintf(stderr,"Error: loss of page did not return error\n");
   1900         exit(1);
   1901       }
   1902       if(ogg_stream_packetout(&os_de,&test)!=1)error();
   1903       checkpacket(&test,300,17,18000);
   1904       fprintf(stderr,"ok.\n");
   1905     }
   1906 
   1907     /* the rest only test sync */
   1908     {
   1909       ogg_page og_de;
   1910       /* Test fractional page inputs: incomplete capture */
   1911       fprintf(stderr,"Testing sync on partial inputs... ");
   1912       ogg_sync_reset(&oy);
   1913       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
   1914              3);
   1915       ogg_sync_wrote(&oy,3);
   1916       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1917 
   1918       /* Test fractional page inputs: incomplete fixed header */
   1919       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
   1920              20);
   1921       ogg_sync_wrote(&oy,20);
   1922       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1923 
   1924       /* Test fractional page inputs: incomplete header */
   1925       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
   1926              5);
   1927       ogg_sync_wrote(&oy,5);
   1928       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1929 
   1930       /* Test fractional page inputs: incomplete body */
   1931 
   1932       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
   1933              og[1].header_len-28);
   1934       ogg_sync_wrote(&oy,og[1].header_len-28);
   1935       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1936 
   1937       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
   1938       ogg_sync_wrote(&oy,1000);
   1939       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1940 
   1941       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
   1942              og[1].body_len-1000);
   1943       ogg_sync_wrote(&oy,og[1].body_len-1000);
   1944       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   1945 
   1946       fprintf(stderr,"ok.\n");
   1947     }
   1948 
   1949     /* Test fractional page inputs: page + incomplete capture */
   1950     {
   1951       ogg_page og_de;
   1952       fprintf(stderr,"Testing sync on 1+partial inputs... ");
   1953       ogg_sync_reset(&oy);
   1954 
   1955       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
   1956              og[1].header_len);
   1957       ogg_sync_wrote(&oy,og[1].header_len);
   1958 
   1959       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
   1960              og[1].body_len);
   1961       ogg_sync_wrote(&oy,og[1].body_len);
   1962 
   1963       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
   1964              20);
   1965       ogg_sync_wrote(&oy,20);
   1966       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   1967       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   1968 
   1969       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
   1970              og[1].header_len-20);
   1971       ogg_sync_wrote(&oy,og[1].header_len-20);
   1972       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
   1973              og[1].body_len);
   1974       ogg_sync_wrote(&oy,og[1].body_len);
   1975       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   1976 
   1977       fprintf(stderr,"ok.\n");
   1978     }
   1979 
   1980     /* Test recapture: garbage + page */
   1981     {
   1982       ogg_page og_de;
   1983       fprintf(stderr,"Testing search for capture... ");
   1984       ogg_sync_reset(&oy);
   1985 
   1986       /* 'garbage' */
   1987       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
   1988              og[1].body_len);
   1989       ogg_sync_wrote(&oy,og[1].body_len);
   1990 
   1991       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
   1992              og[1].header_len);
   1993       ogg_sync_wrote(&oy,og[1].header_len);
   1994 
   1995       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
   1996              og[1].body_len);
   1997       ogg_sync_wrote(&oy,og[1].body_len);
   1998 
   1999       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
   2000              20);
   2001       ogg_sync_wrote(&oy,20);
   2002       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   2003       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   2004       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   2005 
   2006       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
   2007              og[2].header_len-20);
   2008       ogg_sync_wrote(&oy,og[2].header_len-20);
   2009       memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
   2010              og[2].body_len);
   2011       ogg_sync_wrote(&oy,og[2].body_len);
   2012       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   2013 
   2014       fprintf(stderr,"ok.\n");
   2015     }
   2016 
   2017     /* Test recapture: page + garbage + page */
   2018     {
   2019       ogg_page og_de;
   2020       fprintf(stderr,"Testing recapture... ");
   2021       ogg_sync_reset(&oy);
   2022 
   2023       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
   2024              og[1].header_len);
   2025       ogg_sync_wrote(&oy,og[1].header_len);
   2026 
   2027       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
   2028              og[1].body_len);
   2029       ogg_sync_wrote(&oy,og[1].body_len);
   2030 
   2031       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
   2032              og[2].header_len);
   2033       ogg_sync_wrote(&oy,og[2].header_len);
   2034 
   2035       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
   2036              og[2].header_len);
   2037       ogg_sync_wrote(&oy,og[2].header_len);
   2038 
   2039       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   2040 
   2041       memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
   2042              og[2].body_len-5);
   2043       ogg_sync_wrote(&oy,og[2].body_len-5);
   2044 
   2045       memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
   2046              og[3].header_len);
   2047       ogg_sync_wrote(&oy,og[3].header_len);
   2048 
   2049       memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
   2050              og[3].body_len);
   2051       ogg_sync_wrote(&oy,og[3].body_len);
   2052 
   2053       if(ogg_sync_pageout(&oy,&og_de)>0)error();
   2054       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
   2055 
   2056       fprintf(stderr,"ok.\n");
   2057     }
   2058 
   2059     /* Free page data that was previously copied */
   2060     {
   2061       for(i=0;i<5;i++){
   2062         free_page(&og[i]);
   2063       }
   2064     }
   2065   }
   2066 
   2067   return(0);
   2068 }
   2069 
   2070 #endif
   2071 
   2072 
   2073 
   2074 
   2075