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