media/libogg/src/ogg_framing.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     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  ********************************************************************
    13  function: code raw packets into framed OggSquish stream and
    14            decode Ogg streams back into raw packets
    15  last mod: $Id: framing.c 18052 2011-08-04 17:57:02Z giles $
    17  note: The CRC code is directly derived from public domain code by
    18  Ross Williams (ross@guest.adelaide.edu.au).  See docs/framing.html
    19  for details.
    21  ********************************************************************/
    23 #include <stdlib.h>
    24 #include <string.h>
    25 #include <ogg/ogg.h>
    27 /* A complete description of Ogg framing exists in docs/framing.html */
    29 int ogg_page_version(const ogg_page *og){
    30   return((int)(og->header[4]));
    31 }
    33 int ogg_page_continued(const ogg_page *og){
    34   return((int)(og->header[5]&0x01));
    35 }
    37 int ogg_page_bos(const ogg_page *og){
    38   return((int)(og->header[5]&0x02));
    39 }
    41 int ogg_page_eos(const ogg_page *og){
    42   return((int)(og->header[5]&0x04));
    43 }
    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 }
    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 }
    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 }
    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 */
    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
    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 */
    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 }
    99 #if 0
   100 /* helper to initialize lookup for direct-table CRC (illustrative; we
   101    use the static init below) */
   103 static ogg_uint32_t _ogg_crc_entry(unsigned long index){
   104   int           i;
   105   unsigned long r;
   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
   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};
   186 /* init the encode/decode logical stream state */
   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;
   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));
   198     if(!os->body_data || !os->lacing_vals || !os->granule_vals){
   199       ogg_stream_clear(os);
   200       return -1;
   201     }
   203     os->serialno=serialno;
   205     return(0);
   206   }
   207   return(-1);
   208 }
   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 }
   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);
   223     memset(os,0,sizeof(*os));
   224   }
   225   return(0);
   226 }
   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 }
   236 /* Helpers for ogg_stream_encode; this keeps the structure and
   237    what's happening fairly clear */
   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 }
   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 }
   276 /* checksum the page */
   277 /* Direct table CRC; note that this will be faster in the future if we
   278    perform the checksum simultaneously with other copies */
   280 void ogg_page_checksum_set(ogg_page *og){
   281   if(og){
   282     ogg_uint32_t crc_reg=0;
   283     int i;
   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;
   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]];
   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 }
   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){
   307   int bytes = 0, lacing_vals, i;
   309   if(ogg_stream_check(os)) return -1;
   310   if(!iov) return 0;
   312   for (i = 0; i < count; ++i) bytes += (int)iov[i].iov_len;
   313   lacing_vals=bytes/255+1;
   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 */
   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   }
   327   /* make sure we have the buffer storage */
   328   if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals))
   329     return -1;
   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 */
   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   }
   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;
   349   /* flag the first segment as the beginning of the packet */
   350   os->lacing_vals[os->lacing_fill]|= 0x100;
   352   os->lacing_fill+=lacing_vals;
   354   /* for the sake of completeness */
   355   os->packetno++;
   357   if(e_o_s)os->e_o_s=1;
   359   return(0);
   360 }
   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 }
   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, int nfill){
   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;
   380   if(ogg_stream_check(os)) return(0);
   381   if(maxvals==0) return(0);
   383   /* construct a page */
   384   /* decide how many segments to include */
   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{
   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. */
   407     int packets_done=0;
   408     int packet_just_done=0;
   409     for(vals=0;vals<maxvals;vals++){
   410       if(acc>nfill && 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   }
   424   if(!force) return(0);
   426   /* construct the header in temp storage */
   427   memcpy(os->header,"OggS",4);
   429   /* stream structure version */
   430   os->header[4]=0x00;
   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;
   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   }
   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   }
   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   }
   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;
   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);
   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;
   488   /* advance the lacing data and set the body_returned pointer */
   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;
   495   /* calculate the checksum */
   497   ogg_page_checksum_set(og);
   499   /* done */
   500   return(1);
   501 }
   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.
   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    a page regardless of size in the middle of a stream. */
   517 int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
   518   return ogg_stream_flush_i(os,og,1,4096);
   519 }
   521 /* Like the above, but an argument is provided to adjust the nominal
   522    page size for applications which are smart enough to provide their
   523    own delay based flushing */
   525 int ogg_stream_flush_fill(ogg_stream_state *os,ogg_page *og, int nfill){
   526   return ogg_stream_flush_i(os,og,1,nfill);
   527 }
   529 /* This constructs pages from buffered packet segments.  The pointers
   530 returned are to static buffers; do not free. The returned buffers are
   531 good only until the next call (using the same ogg_stream_state) */
   533 int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
   534   int force=0;
   535   if(ogg_stream_check(os)) return 0;
   537   if((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
   538      (os->lacing_fill&&!os->b_o_s))           /* 'initial header page' case */
   539     force=1;
   541   return(ogg_stream_flush_i(os,og,force,4096));
   542 }
   544 /* Like the above, but an argument is provided to adjust the nominal
   545 page size for applications which are smart enough to provide their
   546 own delay based flushing */
   548 int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){
   549   int force=0;
   550   if(ogg_stream_check(os)) return 0;
   552   if((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
   553      (os->lacing_fill&&!os->b_o_s))           /* 'initial header page' case */
   554     force=1;
   556   return(ogg_stream_flush_i(os,og,force,nfill));
   557 }
   559 int ogg_stream_eos(ogg_stream_state *os){
   560   if(ogg_stream_check(os)) return 1;
   561   return os->e_o_s;
   562 }
   564 /* DECODING PRIMITIVES: packet streaming layer **********************/
   566 /* This has two layers to place more of the multi-serialno and paging
   567    control in the application's hands.  First, we expose a data buffer
   568    using ogg_sync_buffer().  The app either copies into the
   569    buffer, or passes it directly to read(), etc.  We then call
   570    ogg_sync_wrote() to tell how many bytes we just added.
   572    Pages are returned (pointers into the buffer in ogg_sync_state)
   573    by ogg_sync_pageout().  The page is then submitted to
   574    ogg_stream_pagein() along with the appropriate
   575    ogg_stream_state* (ie, matching serialno).  We then get raw
   576    packets out calling ogg_stream_packetout() with a
   577    ogg_stream_state. */
   579 /* initialize the struct to a known state */
   580 int ogg_sync_init(ogg_sync_state *oy){
   581   if(oy){
   582     oy->storage = -1; /* used as a readiness flag */
   583     memset(oy,0,sizeof(*oy));
   584   }
   585   return(0);
   586 }
   588 /* clear non-flat storage within */
   589 int ogg_sync_clear(ogg_sync_state *oy){
   590   if(oy){
   591     if(oy->data)_ogg_free(oy->data);
   592     memset(oy,0,sizeof(*oy));
   593   }
   594   return(0);
   595 }
   597 int ogg_sync_destroy(ogg_sync_state *oy){
   598   if(oy){
   599     ogg_sync_clear(oy);
   600     _ogg_free(oy);
   601   }
   602   return(0);
   603 }
   605 int ogg_sync_check(ogg_sync_state *oy){
   606   if(oy->storage<0) return -1;
   607   return 0;
   608 }
   610 char *ogg_sync_buffer(ogg_sync_state *oy, long size){
   611   if(ogg_sync_check(oy)) return NULL;
   613   /* first, clear out any space that has been previously returned */
   614   if(oy->returned){
   615     oy->fill-=oy->returned;
   616     if(oy->fill>0)
   617       memmove(oy->data,oy->data+oy->returned,oy->fill);
   618     oy->returned=0;
   619   }
   621   if(size>oy->storage-oy->fill){
   622     /* We need to extend the internal buffer */
   623     long newsize=size+oy->fill+4096; /* an extra page to be nice */
   624     void *ret;
   626     if(oy->data)
   627       ret=_ogg_realloc(oy->data,newsize);
   628     else
   629       ret=_ogg_malloc(newsize);
   630     if(!ret){
   631       ogg_sync_clear(oy);
   632       return NULL;
   633     }
   634     oy->data=ret;
   635     oy->storage=newsize;
   636   }
   638   /* expose a segment at least as large as requested at the fill mark */
   639   return((char *)oy->data+oy->fill);
   640 }
   642 int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
   643   if(ogg_sync_check(oy))return -1;
   644   if(oy->fill+bytes>oy->storage)return -1;
   645   oy->fill+=bytes;
   646   return(0);
   647 }
   649 /* sync the stream.  This is meant to be useful for finding page
   650    boundaries.
   652    return values for this:
   653   -n) skipped n bytes
   654    0) page not ready; more data (no bytes skipped)
   655    n) page synced at current location; page length n bytes
   657 */
   659 long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
   660   unsigned char *page=oy->data+oy->returned;
   661   unsigned char *next;
   662   long bytes=oy->fill-oy->returned;
   664   if(ogg_sync_check(oy))return 0;
   666   if(oy->headerbytes==0){
   667     int headerbytes,i;
   668     if(bytes<27)return(0); /* not enough for a header */
   670     /* verify capture pattern */
   671     if(memcmp(page,"OggS",4))goto sync_fail;
   673     headerbytes=page[26]+27;
   674     if(bytes<headerbytes)return(0); /* not enough for header + seg table */
   676     /* count up body length in the segment table */
   678     for(i=0;i<page[26];i++)
   679       oy->bodybytes+=page[27+i];
   680     oy->headerbytes=headerbytes;
   681   }
   683   if(oy->bodybytes+oy->headerbytes>bytes)return(0);
   685   /* The whole test page is buffered.  Verify the checksum */
   686   {
   687     /* Grab the checksum bytes, set the header field to zero */
   688     char chksum[4];
   689     ogg_page log;
   691     memcpy(chksum,page+22,4);
   692     memset(page+22,0,4);
   694     /* set up a temp page struct and recompute the checksum */
   695     log.header=page;
   696     log.header_len=oy->headerbytes;
   697     log.body=page+oy->headerbytes;
   698     log.body_len=oy->bodybytes;
   699     ogg_page_checksum_set(&log);
   701     /* Compare */
   702     if(memcmp(chksum,page+22,4)){
   703       /* D'oh.  Mismatch! Corrupt page (or miscapture and not a page
   704          at all) */
   705       /* replace the computed checksum with the one actually read in */
   706       memcpy(page+22,chksum,4);
   708       /* Bad checksum. Lose sync */
   709       goto sync_fail;
   710     }
   711   }
   713   /* yes, have a whole page all ready to go */
   714   {
   715     unsigned char *page=oy->data+oy->returned;
   716     long bytes;
   718     if(og){
   719       og->header=page;
   720       og->header_len=oy->headerbytes;
   721       og->body=page+oy->headerbytes;
   722       og->body_len=oy->bodybytes;
   723     }
   725     oy->unsynced=0;
   726     oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
   727     oy->headerbytes=0;
   728     oy->bodybytes=0;
   729     return(bytes);
   730   }
   732  sync_fail:
   734   oy->headerbytes=0;
   735   oy->bodybytes=0;
   737   /* search for possible capture */
   738   next=memchr(page+1,'O',bytes-1);
   739   if(!next)
   740     next=oy->data+oy->fill;
   742   oy->returned=(int)(next-oy->data);
   743   return((long)-(next-page));
   744 }
   746 /* sync the stream and get a page.  Keep trying until we find a page.
   747    Suppress 'sync errors' after reporting the first.
   749    return values:
   750    -1) recapture (hole in data)
   751     0) need more data
   752     1) page returned
   754    Returns pointers into buffered data; invalidated by next call to
   755    _stream, _clear, _init, or _buffer */
   757 int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
   759   if(ogg_sync_check(oy))return 0;
   761   /* all we need to do is verify a page at the head of the stream
   762      buffer.  If it doesn't verify, we look for the next potential
   763      frame */
   765   for(;;){
   766     long ret=ogg_sync_pageseek(oy,og);
   767     if(ret>0){
   768       /* have a page */
   769       return(1);
   770     }
   771     if(ret==0){
   772       /* need more data */
   773       return(0);
   774     }
   776     /* head did not start a synced page... skipped some bytes */
   777     if(!oy->unsynced){
   778       oy->unsynced=1;
   779       return(-1);
   780     }
   782     /* loop. keep looking */
   784   }
   785 }
   787 /* add the incoming page to the stream state; we decompose the page
   788    into packet segments here as well. */
   790 int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
   791   unsigned char *header=og->header;
   792   unsigned char *body=og->body;
   793   long           bodysize=og->body_len;
   794   int            segptr=0;
   796   int version=ogg_page_version(og);
   797   int continued=ogg_page_continued(og);
   798   int bos=ogg_page_bos(og);
   799   int eos=ogg_page_eos(og);
   800   ogg_int64_t granulepos=ogg_page_granulepos(og);
   801   int serialno=ogg_page_serialno(og);
   802   long pageno=ogg_page_pageno(og);
   803   int segments=header[26];
   805   if(ogg_stream_check(os)) return -1;
   807   /* clean up 'returned data' */
   808   {
   809     long lr=os->lacing_returned;
   810     long br=os->body_returned;
   812     /* body data */
   813     if(br){
   814       os->body_fill-=br;
   815       if(os->body_fill)
   816         memmove(os->body_data,os->body_data+br,os->body_fill);
   817       os->body_returned=0;
   818     }
   820     if(lr){
   821       /* segment table */
   822       if(os->lacing_fill-lr){
   823         memmove(os->lacing_vals,os->lacing_vals+lr,
   824                 (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
   825         memmove(os->granule_vals,os->granule_vals+lr,
   826                 (os->lacing_fill-lr)*sizeof(*os->granule_vals));
   827       }
   828       os->lacing_fill-=lr;
   829       os->lacing_packet-=lr;
   830       os->lacing_returned=0;
   831     }
   832   }
   834   /* check the serial number */
   835   if(serialno!=os->serialno)return(-1);
   836   if(version>0)return(-1);
   838   if(_os_lacing_expand(os,segments+1)) return -1;
   840   /* are we in sequence? */
   841   if(pageno!=os->pageno){
   842     int i;
   844     /* unroll previous partial packet (if any) */
   845     for(i=os->lacing_packet;i<os->lacing_fill;i++)
   846       os->body_fill-=os->lacing_vals[i]&0xff;
   847     os->lacing_fill=os->lacing_packet;
   849     /* make a note of dropped data in segment table */
   850     if(os->pageno!=-1){
   851       os->lacing_vals[os->lacing_fill++]=0x400;
   852       os->lacing_packet++;
   853     }
   854   }
   856   /* are we a 'continued packet' page?  If so, we may need to skip
   857      some segments */
   858   if(continued){
   859     if(os->lacing_fill<1 ||
   860        os->lacing_vals[os->lacing_fill-1]==0x400){
   861       bos=0;
   862       for(;segptr<segments;segptr++){
   863         int val=header[27+segptr];
   864         body+=val;
   865         bodysize-=val;
   866         if(val<255){
   867           segptr++;
   868           break;
   869         }
   870       }
   871     }
   872   }
   874   if(bodysize){
   875     if(_os_body_expand(os,bodysize)) return -1;
   876     memcpy(os->body_data+os->body_fill,body,bodysize);
   877     os->body_fill+=bodysize;
   878   }
   880   {
   881     int saved=-1;
   882     while(segptr<segments){
   883       int val=header[27+segptr];
   884       os->lacing_vals[os->lacing_fill]=val;
   885       os->granule_vals[os->lacing_fill]=-1;
   887       if(bos){
   888         os->lacing_vals[os->lacing_fill]|=0x100;
   889         bos=0;
   890       }
   892       if(val<255)saved=os->lacing_fill;
   894       os->lacing_fill++;
   895       segptr++;
   897       if(val<255)os->lacing_packet=os->lacing_fill;
   898     }
   900     /* set the granulepos on the last granuleval of the last full packet */
   901     if(saved!=-1){
   902       os->granule_vals[saved]=granulepos;
   903     }
   905   }
   907   if(eos){
   908     os->e_o_s=1;
   909     if(os->lacing_fill>0)
   910       os->lacing_vals[os->lacing_fill-1]|=0x200;
   911   }
   913   os->pageno=pageno+1;
   915   return(0);
   916 }
   918 /* clear things to an initial state.  Good to call, eg, before seeking */
   919 int ogg_sync_reset(ogg_sync_state *oy){
   920   if(ogg_sync_check(oy))return -1;
   922   oy->fill=0;
   923   oy->returned=0;
   924   oy->unsynced=0;
   925   oy->headerbytes=0;
   926   oy->bodybytes=0;
   927   return(0);
   928 }
   930 int ogg_stream_reset(ogg_stream_state *os){
   931   if(ogg_stream_check(os)) return -1;
   933   os->body_fill=0;
   934   os->body_returned=0;
   936   os->lacing_fill=0;
   937   os->lacing_packet=0;
   938   os->lacing_returned=0;
   940   os->header_fill=0;
   942   os->e_o_s=0;
   943   os->b_o_s=0;
   944   os->pageno=-1;
   945   os->packetno=0;
   946   os->granulepos=0;
   948   return(0);
   949 }
   951 int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
   952   if(ogg_stream_check(os)) return -1;
   953   ogg_stream_reset(os);
   954   os->serialno=serialno;
   955   return(0);
   956 }
   958 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
   960   /* The last part of decode. We have the stream broken into packet
   961      segments.  Now we need to group them into packets (or return the
   962      out of sync markers) */
   964   int ptr=os->lacing_returned;
   966   if(os->lacing_packet<=ptr)return(0);
   968   if(os->lacing_vals[ptr]&0x400){
   969     /* we need to tell the codec there's a gap; it might need to
   970        handle previous packet dependencies. */
   971     os->lacing_returned++;
   972     os->packetno++;
   973     return(-1);
   974   }
   976   if(!op && !adv)return(1); /* just using peek as an inexpensive way
   977                                to ask if there's a whole packet
   978                                waiting */
   980   /* Gather the whole packet. We'll have no holes or a partial packet */
   981   {
   982     int size=os->lacing_vals[ptr]&0xff;
   983     long bytes=size;
   984     int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
   985     int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
   987     while(size==255){
   988       int val=os->lacing_vals[++ptr];
   989       size=val&0xff;
   990       if(val&0x200)eos=0x200;
   991       bytes+=size;
   992     }
   994     if(op){
   995       op->e_o_s=eos;
   996       op->b_o_s=bos;
   997       op->packet=os->body_data+os->body_returned;
   998       op->packetno=os->packetno;
   999       op->granulepos=os->granule_vals[ptr];
  1000       op->bytes=bytes;
  1003     if(adv){
  1004       os->body_returned+=bytes;
  1005       os->lacing_returned=ptr+1;
  1006       os->packetno++;
  1009   return(1);
  1012 int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
  1013   if(ogg_stream_check(os)) return 0;
  1014   return _packetout(os,op,1);
  1017 int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
  1018   if(ogg_stream_check(os)) return 0;
  1019   return _packetout(os,op,0);
  1022 void ogg_packet_clear(ogg_packet *op) {
  1023   _ogg_free(op->packet);
  1024   memset(op, 0, sizeof(*op));
  1027 #ifdef _V_SELFTEST
  1028 #include <stdio.h>
  1030 ogg_stream_state os_en, os_de;
  1031 ogg_sync_state oy;
  1033 void checkpacket(ogg_packet *op,long len, int no, long pos){
  1034   long j;
  1035   static int sequence=0;
  1036   static int lastno=0;
  1038   if(op->bytes!=len){
  1039     fprintf(stderr,"incorrect packet length (%ld != %ld)!\n",op->bytes,len);
  1040     exit(1);
  1042   if(op->granulepos!=pos){
  1043     fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos);
  1044     exit(1);
  1047   /* packet number just follows sequence/gap; adjust the input number
  1048      for that */
  1049   if(no==0){
  1050     sequence=0;
  1051   }else{
  1052     sequence++;
  1053     if(no>lastno+1)
  1054       sequence++;
  1056   lastno=no;
  1057   if(op->packetno!=sequence){
  1058     fprintf(stderr,"incorrect packet sequence %ld != %d\n",
  1059             (long)(op->packetno),sequence);
  1060     exit(1);
  1063   /* Test data */
  1064   for(j=0;j<op->bytes;j++)
  1065     if(op->packet[j]!=((j+no)&0xff)){
  1066       fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
  1067               j,op->packet[j],(j+no)&0xff);
  1068       exit(1);
  1072 void check_page(unsigned char *data,const int *header,ogg_page *og){
  1073   long j;
  1074   /* Test data */
  1075   for(j=0;j<og->body_len;j++)
  1076     if(og->body[j]!=data[j]){
  1077       fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
  1078               j,data[j],og->body[j]);
  1079       exit(1);
  1082   /* Test header */
  1083   for(j=0;j<og->header_len;j++){
  1084     if(og->header[j]!=header[j]){
  1085       fprintf(stderr,"header content mismatch at pos %ld:\n",j);
  1086       for(j=0;j<header[26]+27;j++)
  1087         fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
  1088       fprintf(stderr,"\n");
  1089       exit(1);
  1092   if(og->header_len!=header[26]+27){
  1093     fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
  1094             og->header_len,header[26]+27);
  1095     exit(1);
  1099 void print_header(ogg_page *og){
  1100   int j;
  1101   fprintf(stderr,"\nHEADER:\n");
  1102   fprintf(stderr,"  capture: %c %c %c %c  version: %d  flags: %x\n",
  1103           og->header[0],og->header[1],og->header[2],og->header[3],
  1104           (int)og->header[4],(int)og->header[5]);
  1106   fprintf(stderr,"  granulepos: %d  serialno: %d  pageno: %ld\n",
  1107           (og->header[9]<<24)|(og->header[8]<<16)|
  1108           (og->header[7]<<8)|og->header[6],
  1109           (og->header[17]<<24)|(og->header[16]<<16)|
  1110           (og->header[15]<<8)|og->header[14],
  1111           ((long)(og->header[21])<<24)|(og->header[20]<<16)|
  1112           (og->header[19]<<8)|og->header[18]);
  1114   fprintf(stderr,"  checksum: %02x:%02x:%02x:%02x\n  segments: %d (",
  1115           (int)og->header[22],(int)og->header[23],
  1116           (int)og->header[24],(int)og->header[25],
  1117           (int)og->header[26]);
  1119   for(j=27;j<og->header_len;j++)
  1120     fprintf(stderr,"%d ",(int)og->header[j]);
  1121   fprintf(stderr,")\n\n");
  1124 void copy_page(ogg_page *og){
  1125   unsigned char *temp=_ogg_malloc(og->header_len);
  1126   memcpy(temp,og->header,og->header_len);
  1127   og->header=temp;
  1129   temp=_ogg_malloc(og->body_len);
  1130   memcpy(temp,og->body,og->body_len);
  1131   og->body=temp;
  1134 void free_page(ogg_page *og){
  1135   _ogg_free (og->header);
  1136   _ogg_free (og->body);
  1139 void error(void){
  1140   fprintf(stderr,"error!\n");
  1141   exit(1);
  1144 /* 17 only */
  1145 const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
  1146                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  1147                        0x01,0x02,0x03,0x04,0,0,0,0,
  1148                        0x15,0xed,0xec,0x91,
  1149                        1,
  1150                        17};
  1152 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
  1153 const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
  1154                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  1155                        0x01,0x02,0x03,0x04,0,0,0,0,
  1156                        0x59,0x10,0x6c,0x2c,
  1157                        1,
  1158                        17};
  1159 const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
  1160                        0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
  1161                        0x01,0x02,0x03,0x04,1,0,0,0,
  1162                        0x89,0x33,0x85,0xce,
  1163                        13,
  1164                        254,255,0,255,1,255,245,255,255,0,
  1165                        255,255,90};
  1167 /* nil packets; beginning,middle,end */
  1168 const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
  1169                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  1170                        0x01,0x02,0x03,0x04,0,0,0,0,
  1171                        0xff,0x7b,0x23,0x17,
  1172                        1,
  1173                        0};
  1174 const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
  1175                        0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
  1176                        0x01,0x02,0x03,0x04,1,0,0,0,
  1177                        0x5c,0x3f,0x66,0xcb,
  1178                        17,
  1179                        17,254,255,0,0,255,1,0,255,245,255,255,0,
  1180                        255,255,90,0};
  1182 /* large initial packet */
  1183 const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
  1184                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  1185                        0x01,0x02,0x03,0x04,0,0,0,0,
  1186                        0x01,0x27,0x31,0xaa,
  1187                        18,
  1188                        255,255,255,255,255,255,255,255,
  1189                        255,255,255,255,255,255,255,255,255,10};
  1191 const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
  1192                        0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
  1193                        0x01,0x02,0x03,0x04,1,0,0,0,
  1194                        0x7f,0x4e,0x8a,0xd2,
  1195                        4,
  1196                        255,4,255,0};
  1199 /* continuing packet test */
  1200 const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
  1201                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  1202                        0x01,0x02,0x03,0x04,0,0,0,0,
  1203                        0xff,0x7b,0x23,0x17,
  1204                        1,
  1205                        0};
  1207 const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
  1208                        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  1209                        0x01,0x02,0x03,0x04,1,0,0,0,
  1210                        0xf8,0x3c,0x19,0x79,
  1211                        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,255,
  1237                        255,255,255,255,255,255,255,255,
  1238                        255,255,255,255,255,255,255,255,
  1239                        255,255,255,255,255,255,255,255,
  1240                        255,255,255,255,255,255,255,255,
  1241                        255,255,255,255,255,255,255,255,
  1242                        255,255,255,255,255,255,255,255,
  1243                        255,255,255,255,255,255,255};
  1245 const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
  1246                        0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
  1247                        0x01,0x02,0x03,0x04,2,0,0,0,
  1248                        0x38,0xe6,0xb6,0x28,
  1249                        6,
  1250                        255,220,255,4,255,0};
  1253 /* spill expansion test */
  1254 const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
  1255                         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  1256                         0x01,0x02,0x03,0x04,0,0,0,0,
  1257                         0xff,0x7b,0x23,0x17,
  1258                         1,
  1259                         0};
  1261 const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
  1262                         0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
  1263                         0x01,0x02,0x03,0x04,1,0,0,0,
  1264                         0xce,0x8f,0x17,0x1a,
  1265                         23,
  1266                         255,255,255,255,255,255,255,255,
  1267                         255,255,255,255,255,255,255,255,255,10,255,4,255,0,0};
  1270 const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
  1271                         0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
  1272                         0x01,0x02,0x03,0x04,2,0,0,0,
  1273                         0x9b,0xb2,0x50,0xa1,
  1274                         1,
  1275                         0};
  1277 /* page with the 255 segment limit */
  1278 const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
  1279                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  1280                        0x01,0x02,0x03,0x04,0,0,0,0,
  1281                        0xff,0x7b,0x23,0x17,
  1282                        1,
  1283                        0};
  1285 const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
  1286                        0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
  1287                        0x01,0x02,0x03,0x04,1,0,0,0,
  1288                        0xed,0x2a,0x2e,0xa7,
  1289                        255,
  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,10,
  1315                        10,10,10,10,10,10,10,10,
  1316                        10,10,10,10,10,10,10,10,
  1317                        10,10,10,10,10,10,10,10,
  1318                        10,10,10,10,10,10,10,10,
  1319                        10,10,10,10,10,10,10,10,
  1320                        10,10,10,10,10,10,10,10,
  1321                        10,10,10,10,10,10,10};
  1323 const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
  1324                        0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
  1325                        0x01,0x02,0x03,0x04,2,0,0,0,
  1326                        0x6c,0x3b,0x82,0x3d,
  1327                        1,
  1328                        50};
  1331 /* packet that overspans over an entire page */
  1332 const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
  1333                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  1334                        0x01,0x02,0x03,0x04,0,0,0,0,
  1335                        0xff,0x7b,0x23,0x17,
  1336                        1,
  1337                        0};
  1339 const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
  1340                        0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
  1341                        0x01,0x02,0x03,0x04,1,0,0,0,
  1342                        0x68,0x22,0x7c,0x3d,
  1343                        255,
  1344                        100,
  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,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};
  1378 const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
  1379                        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  1380                        0x01,0x02,0x03,0x04,2,0,0,0,
  1381                        0xf4,0x87,0xba,0xf3,
  1382                        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,255,
  1408                        255,255,255,255,255,255,255,255,
  1409                        255,255,255,255,255,255,255,255,
  1410                        255,255,255,255,255,255,255,255,
  1411                        255,255,255,255,255,255,255,255,
  1412                        255,255,255,255,255,255,255,255,
  1413                        255,255,255,255,255,255,255,255,
  1414                        255,255,255,255,255,255,255};
  1416 const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
  1417                        0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
  1418                        0x01,0x02,0x03,0x04,3,0,0,0,
  1419                        0xf7,0x2f,0x6c,0x60,
  1420                        5,
  1421                        254,255,4,255,0};
  1423 /* packet that overspans over an entire page */
  1424 const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
  1425                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  1426                        0x01,0x02,0x03,0x04,0,0,0,0,
  1427                        0xff,0x7b,0x23,0x17,
  1428                        1,
  1429                        0};
  1431 const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
  1432                        0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
  1433                        0x01,0x02,0x03,0x04,1,0,0,0,
  1434                        0x68,0x22,0x7c,0x3d,
  1435                        255,
  1436                        100,
  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,255,255,
  1462                        255,255,255,255,255,255,255,255,
  1463                        255,255,255,255,255,255,255,255,
  1464                        255,255,255,255,255,255,255,255,
  1465                        255,255,255,255,255,255,255,255,
  1466                        255,255,255,255,255,255,255,255,
  1467                        255,255,255,255,255,255,255,255,
  1468                        255,255,255,255,255,255};
  1470 const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
  1471                        0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
  1472                        0x01,0x02,0x03,0x04,2,0,0,0,
  1473                        0xd4,0xe0,0x60,0xe5,
  1474                        1,
  1475                        0};
  1477 void test_pack(const int *pl, const int **headers, int byteskip,
  1478                int pageskip, int packetskip){
  1479   unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
  1480   long inptr=0;
  1481   long outptr=0;
  1482   long deptr=0;
  1483   long depacket=0;
  1484   long granule_pos=7,pageno=0;
  1485   int i,j,packets,pageout=pageskip;
  1486   int eosflag=0;
  1487   int bosflag=0;
  1489   int byteskipcount=0;
  1491   ogg_stream_reset(&os_en);
  1492   ogg_stream_reset(&os_de);
  1493   ogg_sync_reset(&oy);
  1495   for(packets=0;packets<packetskip;packets++)
  1496     depacket+=pl[packets];
  1498   for(packets=0;;packets++)if(pl[packets]==-1)break;
  1500   for(i=0;i<packets;i++){
  1501     /* construct a test packet */
  1502     ogg_packet op;
  1503     int len=pl[i];
  1505     op.packet=data+inptr;
  1506     op.bytes=len;
  1507     op.e_o_s=(pl[i+1]<0?1:0);
  1508     op.granulepos=granule_pos;
  1510     granule_pos+=1024;
  1512     for(j=0;j<len;j++)data[inptr++]=i+j;
  1514     /* submit the test packet */
  1515     ogg_stream_packetin(&os_en,&op);
  1517     /* retrieve any finished pages */
  1519       ogg_page og;
  1521       while(ogg_stream_pageout(&os_en,&og)){
  1522         /* We have a page.  Check it carefully */
  1524         fprintf(stderr,"%ld, ",pageno);
  1526         if(headers[pageno]==NULL){
  1527           fprintf(stderr,"coded too many pages!\n");
  1528           exit(1);
  1531         check_page(data+outptr,headers[pageno],&og);
  1533         outptr+=og.body_len;
  1534         pageno++;
  1535         if(pageskip){
  1536           bosflag=1;
  1537           pageskip--;
  1538           deptr+=og.body_len;
  1541         /* have a complete page; submit it to sync/decode */
  1544           ogg_page og_de;
  1545           ogg_packet op_de,op_de2;
  1546           char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
  1547           char *next=buf;
  1548           byteskipcount+=og.header_len;
  1549           if(byteskipcount>byteskip){
  1550             memcpy(next,og.header,byteskipcount-byteskip);
  1551             next+=byteskipcount-byteskip;
  1552             byteskipcount=byteskip;
  1555           byteskipcount+=og.body_len;
  1556           if(byteskipcount>byteskip){
  1557             memcpy(next,og.body,byteskipcount-byteskip);
  1558             next+=byteskipcount-byteskip;
  1559             byteskipcount=byteskip;
  1562           ogg_sync_wrote(&oy,next-buf);
  1564           while(1){
  1565             int ret=ogg_sync_pageout(&oy,&og_de);
  1566             if(ret==0)break;
  1567             if(ret<0)continue;
  1568             /* got a page.  Happy happy.  Verify that it's good. */
  1570             fprintf(stderr,"(%d), ",pageout);
  1572             check_page(data+deptr,headers[pageout],&og_de);
  1573             deptr+=og_de.body_len;
  1574             pageout++;
  1576             /* submit it to deconstitution */
  1577             ogg_stream_pagein(&os_de,&og_de);
  1579             /* packets out? */
  1580             while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
  1581               ogg_stream_packetpeek(&os_de,NULL);
  1582               ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
  1584               /* verify peek and out match */
  1585               if(memcmp(&op_de,&op_de2,sizeof(op_de))){
  1586                 fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
  1587                         depacket);
  1588                 exit(1);
  1591               /* verify the packet! */
  1592               /* check data */
  1593               if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
  1594                 fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
  1595                         depacket);
  1596                 exit(1);
  1598               /* check bos flag */
  1599               if(bosflag==0 && op_de.b_o_s==0){
  1600                 fprintf(stderr,"b_o_s flag not set on packet!\n");
  1601                 exit(1);
  1603               if(bosflag && op_de.b_o_s){
  1604                 fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
  1605                 exit(1);
  1607               bosflag=1;
  1608               depacket+=op_de.bytes;
  1610               /* check eos flag */
  1611               if(eosflag){
  1612                 fprintf(stderr,"Multiple decoded packets with eos flag!\n");
  1613                 exit(1);
  1616               if(op_de.e_o_s)eosflag=1;
  1618               /* check granulepos flag */
  1619               if(op_de.granulepos!=-1){
  1620                 fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
  1628   _ogg_free(data);
  1629   if(headers[pageno]!=NULL){
  1630     fprintf(stderr,"did not write last page!\n");
  1631     exit(1);
  1633   if(headers[pageout]!=NULL){
  1634     fprintf(stderr,"did not decode last page!\n");
  1635     exit(1);
  1637   if(inptr!=outptr){
  1638     fprintf(stderr,"encoded page data incomplete!\n");
  1639     exit(1);
  1641   if(inptr!=deptr){
  1642     fprintf(stderr,"decoded page data incomplete!\n");
  1643     exit(1);
  1645   if(inptr!=depacket){
  1646     fprintf(stderr,"decoded packet data incomplete!\n");
  1647     exit(1);
  1649   if(!eosflag){
  1650     fprintf(stderr,"Never got a packet with EOS set!\n");
  1651     exit(1);
  1653   fprintf(stderr,"ok.\n");
  1656 int main(void){
  1658   ogg_stream_init(&os_en,0x04030201);
  1659   ogg_stream_init(&os_de,0x04030201);
  1660   ogg_sync_init(&oy);
  1662   /* Exercise each code path in the framing code.  Also verify that
  1663      the checksums are working.  */
  1666     /* 17 only */
  1667     const int packets[]={17, -1};
  1668     const int *headret[]={head1_0,NULL};
  1670     fprintf(stderr,"testing single page encoding... ");
  1671     test_pack(packets,headret,0,0,0);
  1675     /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
  1676     const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
  1677     const int *headret[]={head1_1,head2_1,NULL};
  1679     fprintf(stderr,"testing basic page encoding... ");
  1680     test_pack(packets,headret,0,0,0);
  1684     /* nil packets; beginning,middle,end */
  1685     const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
  1686     const int *headret[]={head1_2,head2_2,NULL};
  1688     fprintf(stderr,"testing basic nil packets... ");
  1689     test_pack(packets,headret,0,0,0);
  1693     /* large initial packet */
  1694     const int packets[]={4345,259,255,-1};
  1695     const int *headret[]={head1_3,head2_3,NULL};
  1697     fprintf(stderr,"testing initial-packet lacing > 4k... ");
  1698     test_pack(packets,headret,0,0,0);
  1702     /* continuing packet test; with page spill expansion, we have to
  1703        overflow the lacing table. */
  1704     const int packets[]={0,65500,259,255,-1};
  1705     const int *headret[]={head1_4,head2_4,head3_4,NULL};
  1707     fprintf(stderr,"testing single packet page span... ");
  1708     test_pack(packets,headret,0,0,0);
  1712     /* spill expand packet test */
  1713     const int packets[]={0,4345,259,255,0,0,-1};
  1714     const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
  1716     fprintf(stderr,"testing page spill expansion... ");
  1717     test_pack(packets,headret,0,0,0);
  1720   /* page with the 255 segment limit */
  1723     const int packets[]={0,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,10,
  1732                    10,10,10,10,10,10,10,10,
  1733                    10,10,10,10,10,10,10,10,
  1734                    10,10,10,10,10,10,10,10,
  1735                    10,10,10,10,10,10,10,10,
  1736                    10,10,10,10,10,10,10,10,
  1737                    10,10,10,10,10,10,10,10,
  1738                    10,10,10,10,10,10,10,10,
  1739                    10,10,10,10,10,10,10,10,
  1740                    10,10,10,10,10,10,10,10,
  1741                    10,10,10,10,10,10,10,10,
  1742                    10,10,10,10,10,10,10,10,
  1743                    10,10,10,10,10,10,10,10,
  1744                    10,10,10,10,10,10,10,10,
  1745                    10,10,10,10,10,10,10,10,
  1746                    10,10,10,10,10,10,10,10,
  1747                    10,10,10,10,10,10,10,10,
  1748                    10,10,10,10,10,10,10,10,
  1749                    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,50,-1};
  1755     const int *headret[]={head1_5,head2_5,head3_5,NULL};
  1757     fprintf(stderr,"testing max packet segments... ");
  1758     test_pack(packets,headret,0,0,0);
  1762     /* packet that overspans over an entire page */
  1763     const int packets[]={0,100,130049,259,255,-1};
  1764     const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
  1766     fprintf(stderr,"testing very large packets... ");
  1767     test_pack(packets,headret,0,0,0);
  1771     /* test for the libogg 1.1.1 resync in large continuation bug
  1772        found by Josh Coalson)  */
  1773     const int packets[]={0,100,130049,259,255,-1};
  1774     const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
  1776     fprintf(stderr,"testing continuation resync in very large packets... ");
  1777     test_pack(packets,headret,100,2,3);
  1781     /* term only page.  why not? */
  1782     const int packets[]={0,100,64770,-1};
  1783     const int *headret[]={head1_7,head2_7,head3_7,NULL};
  1785     fprintf(stderr,"testing zero data page (1 nil packet)... ");
  1786     test_pack(packets,headret,0,0,0);
  1792     /* build a bunch of pages for testing */
  1793     unsigned char *data=_ogg_malloc(1024*1024);
  1794     int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
  1795     int inptr=0,i,j;
  1796     ogg_page og[5];
  1798     ogg_stream_reset(&os_en);
  1800     for(i=0;pl[i]!=-1;i++){
  1801       ogg_packet op;
  1802       int len=pl[i];
  1804       op.packet=data+inptr;
  1805       op.bytes=len;
  1806       op.e_o_s=(pl[i+1]<0?1:0);
  1807       op.granulepos=(i+1)*1000;
  1809       for(j=0;j<len;j++)data[inptr++]=i+j;
  1810       ogg_stream_packetin(&os_en,&op);
  1813     _ogg_free(data);
  1815     /* retrieve finished pages */
  1816     for(i=0;i<5;i++){
  1817       if(ogg_stream_pageout(&os_en,&og[i])==0){
  1818         fprintf(stderr,"Too few pages output building sync tests!\n");
  1819         exit(1);
  1821       copy_page(&og[i]);
  1824     /* Test lost pages on pagein/packetout: no rollback */
  1826       ogg_page temp;
  1827       ogg_packet test;
  1829       fprintf(stderr,"Testing loss of pages... ");
  1831       ogg_sync_reset(&oy);
  1832       ogg_stream_reset(&os_de);
  1833       for(i=0;i<5;i++){
  1834         memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
  1835                og[i].header_len);
  1836         ogg_sync_wrote(&oy,og[i].header_len);
  1837         memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
  1838         ogg_sync_wrote(&oy,og[i].body_len);
  1841       ogg_sync_pageout(&oy,&temp);
  1842       ogg_stream_pagein(&os_de,&temp);
  1843       ogg_sync_pageout(&oy,&temp);
  1844       ogg_stream_pagein(&os_de,&temp);
  1845       ogg_sync_pageout(&oy,&temp);
  1846       /* skip */
  1847       ogg_sync_pageout(&oy,&temp);
  1848       ogg_stream_pagein(&os_de,&temp);
  1850       /* do we get the expected results/packets? */
  1852       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1853       checkpacket(&test,0,0,0);
  1854       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1855       checkpacket(&test,1,1,-1);
  1856       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1857       checkpacket(&test,1,2,-1);
  1858       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1859       checkpacket(&test,98,3,-1);
  1860       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1861       checkpacket(&test,4079,4,5000);
  1862       if(ogg_stream_packetout(&os_de,&test)!=-1){
  1863         fprintf(stderr,"Error: loss of page did not return error\n");
  1864         exit(1);
  1866       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1867       checkpacket(&test,76,9,-1);
  1868       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1869       checkpacket(&test,34,10,-1);
  1870       fprintf(stderr,"ok.\n");
  1873     /* Test lost pages on pagein/packetout: rollback with continuation */
  1875       ogg_page temp;
  1876       ogg_packet test;
  1878       fprintf(stderr,"Testing loss of pages (rollback required)... ");
  1880       ogg_sync_reset(&oy);
  1881       ogg_stream_reset(&os_de);
  1882       for(i=0;i<5;i++){
  1883         memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
  1884                og[i].header_len);
  1885         ogg_sync_wrote(&oy,og[i].header_len);
  1886         memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
  1887         ogg_sync_wrote(&oy,og[i].body_len);
  1890       ogg_sync_pageout(&oy,&temp);
  1891       ogg_stream_pagein(&os_de,&temp);
  1892       ogg_sync_pageout(&oy,&temp);
  1893       ogg_stream_pagein(&os_de,&temp);
  1894       ogg_sync_pageout(&oy,&temp);
  1895       ogg_stream_pagein(&os_de,&temp);
  1896       ogg_sync_pageout(&oy,&temp);
  1897       /* skip */
  1898       ogg_sync_pageout(&oy,&temp);
  1899       ogg_stream_pagein(&os_de,&temp);
  1901       /* do we get the expected results/packets? */
  1903       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1904       checkpacket(&test,0,0,0);
  1905       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1906       checkpacket(&test,1,1,-1);
  1907       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1908       checkpacket(&test,1,2,-1);
  1909       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1910       checkpacket(&test,98,3,-1);
  1911       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1912       checkpacket(&test,4079,4,5000);
  1913       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1914       checkpacket(&test,1,5,-1);
  1915       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1916       checkpacket(&test,1,6,-1);
  1917       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1918       checkpacket(&test,2954,7,-1);
  1919       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1920       checkpacket(&test,2057,8,9000);
  1921       if(ogg_stream_packetout(&os_de,&test)!=-1){
  1922         fprintf(stderr,"Error: loss of page did not return error\n");
  1923         exit(1);
  1925       if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1926       checkpacket(&test,300,17,18000);
  1927       fprintf(stderr,"ok.\n");
  1930     /* the rest only test sync */
  1932       ogg_page og_de;
  1933       /* Test fractional page inputs: incomplete capture */
  1934       fprintf(stderr,"Testing sync on partial inputs... ");
  1935       ogg_sync_reset(&oy);
  1936       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1937              3);
  1938       ogg_sync_wrote(&oy,3);
  1939       if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1941       /* Test fractional page inputs: incomplete fixed header */
  1942       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
  1943              20);
  1944       ogg_sync_wrote(&oy,20);
  1945       if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1947       /* Test fractional page inputs: incomplete header */
  1948       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
  1949              5);
  1950       ogg_sync_wrote(&oy,5);
  1951       if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1953       /* Test fractional page inputs: incomplete body */
  1955       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
  1956              og[1].header_len-28);
  1957       ogg_sync_wrote(&oy,og[1].header_len-28);
  1958       if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1960       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
  1961       ogg_sync_wrote(&oy,1000);
  1962       if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1964       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
  1965              og[1].body_len-1000);
  1966       ogg_sync_wrote(&oy,og[1].body_len-1000);
  1967       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1969       fprintf(stderr,"ok.\n");
  1972     /* Test fractional page inputs: page + incomplete capture */
  1974       ogg_page og_de;
  1975       fprintf(stderr,"Testing sync on 1+partial inputs... ");
  1976       ogg_sync_reset(&oy);
  1978       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1979              og[1].header_len);
  1980       ogg_sync_wrote(&oy,og[1].header_len);
  1982       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1983              og[1].body_len);
  1984       ogg_sync_wrote(&oy,og[1].body_len);
  1986       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1987              20);
  1988       ogg_sync_wrote(&oy,20);
  1989       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1990       if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1992       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
  1993              og[1].header_len-20);
  1994       ogg_sync_wrote(&oy,og[1].header_len-20);
  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       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  2000       fprintf(stderr,"ok.\n");
  2003     /* Test recapture: garbage + page */
  2005       ogg_page og_de;
  2006       fprintf(stderr,"Testing search for capture... ");
  2007       ogg_sync_reset(&oy);
  2009       /* 'garbage' */
  2010       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  2011              og[1].body_len);
  2012       ogg_sync_wrote(&oy,og[1].body_len);
  2014       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  2015              og[1].header_len);
  2016       ogg_sync_wrote(&oy,og[1].header_len);
  2018       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  2019              og[1].body_len);
  2020       ogg_sync_wrote(&oy,og[1].body_len);
  2022       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
  2023              20);
  2024       ogg_sync_wrote(&oy,20);
  2025       if(ogg_sync_pageout(&oy,&og_de)>0)error();
  2026       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  2027       if(ogg_sync_pageout(&oy,&og_de)>0)error();
  2029       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
  2030              og[2].header_len-20);
  2031       ogg_sync_wrote(&oy,og[2].header_len-20);
  2032       memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
  2033              og[2].body_len);
  2034       ogg_sync_wrote(&oy,og[2].body_len);
  2035       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  2037       fprintf(stderr,"ok.\n");
  2040     /* Test recapture: page + garbage + page */
  2042       ogg_page og_de;
  2043       fprintf(stderr,"Testing recapture... ");
  2044       ogg_sync_reset(&oy);
  2046       memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  2047              og[1].header_len);
  2048       ogg_sync_wrote(&oy,og[1].header_len);
  2050       memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  2051              og[1].body_len);
  2052       ogg_sync_wrote(&oy,og[1].body_len);
  2054       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
  2055              og[2].header_len);
  2056       ogg_sync_wrote(&oy,og[2].header_len);
  2058       memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
  2059              og[2].header_len);
  2060       ogg_sync_wrote(&oy,og[2].header_len);
  2062       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  2064       memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
  2065              og[2].body_len-5);
  2066       ogg_sync_wrote(&oy,og[2].body_len-5);
  2068       memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
  2069              og[3].header_len);
  2070       ogg_sync_wrote(&oy,og[3].header_len);
  2072       memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
  2073              og[3].body_len);
  2074       ogg_sync_wrote(&oy,og[3].body_len);
  2076       if(ogg_sync_pageout(&oy,&og_de)>0)error();
  2077       if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  2079       fprintf(stderr,"ok.\n");
  2082     /* Free page data that was previously copied */
  2084       for(i=0;i<5;i++){
  2085         free_page(&og[i]);
  2090   return(0);
  2093 #endif

mercurial