tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ogg_framing.c (66904B)


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