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