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
29int ogg_page_version(const ogg_page *og){
30  return((int)(og->header[4]));
31}
32
33int ogg_page_continued(const ogg_page *og){
34  return((int)(og->header[5]&0x01));
35}
36
37int ogg_page_bos(const ogg_page *og){
38  return((int)(og->header[5]&0x02));
39}
40
41int ogg_page_eos(const ogg_page *og){
42  return((int)(og->header[5]&0x04));
43}
44
45ogg_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
58int 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
65long 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:
79If a page consists of a packet begun on a previous page, and a new
80packet begun (but not completed) on this page, the return will be:
81  ogg_page_packets(page)   ==1,
82  ogg_page_continued(page) !=0
83
84If a page happens to be a single packet that was begun on a
85previous page, and spans to the next page (in the case of a three or
86more page packet), the return will be:
87  ogg_page_packets(page)   ==0,
88  ogg_page_continued(page) !=0
89*/
90
91int 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
103static 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
120static 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
188int 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 */
211int 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 */
217int 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
228int 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
239static 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
254static 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
280void 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 */
304int 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
362int 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. */
372static 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
517int 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
522returned are to static buffers; do not free. The returned buffers are
523good only until the next call (using the same ogg_stream_state) */
524
525int 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
536int 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 */
557int 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 */
566int 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
574int 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
582int ogg_sync_check(ogg_sync_state *oy){
583  if(oy->storage<0) return -1;
584  return 0;
585}
586
587char *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
619int 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
636long 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
734int 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
767int 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 */
896int 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
907int 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
928int 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
935static 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
989int 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
994int 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
999void 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
1007ogg_stream_state os_en, os_de;
1008ogg_sync_state oy;
1009
1010void 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
1049void 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
1076void 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
1101void 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
1111void free_page(ogg_page *og){
1112  _ogg_free (og->header);
1113  _ogg_free (og->body);
1114}
1115
1116void error(void){
1117  fprintf(stderr,"error!\n");
1118  exit(1);
1119}
1120
1121/* 17 only */
1122const 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 */
1130const 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};
1136const 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 */
1145const 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};
1151const 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 */
1160const 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
1168const 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 */
1177const 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
1184const 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
1222const 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 */
1231const 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
1238const 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
1247const 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 */
1255const 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
1262const 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
1300const 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 */
1309const 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
1316const 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
1355const 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
1393const 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 */
1401const 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
1408const 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
1447const 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
1454void 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
1633int main(void){
1634
1635  ogg_stream_init(&os_en,0x04030201);
1636  ogg_stream_init(&os_de,0x04030201);
1637  ogg_sync_init(&oy);
1638
1639  /* Exercise each code path in the framing code.  Also verify that
1640     the checksums are working.  */
1641
1642  {
1643    /* 17 only */
1644    const int packets[]={17, -1};
1645    const int *headret[]={head1_0,NULL};
1646
1647    fprintf(stderr,"testing single page encoding... ");
1648    test_pack(packets,headret,0,0,0);
1649  }
1650
1651  {
1652    /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1653    const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
1654    const int *headret[]={head1_1,head2_1,NULL};
1655
1656    fprintf(stderr,"testing basic page encoding... ");
1657    test_pack(packets,headret,0,0,0);
1658  }
1659
1660  {
1661    /* nil packets; beginning,middle,end */
1662    const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
1663    const int *headret[]={head1_2,head2_2,NULL};
1664
1665    fprintf(stderr,"testing basic nil packets... ");
1666    test_pack(packets,headret,0,0,0);
1667  }
1668
1669  {
1670    /* large initial packet */
1671    const int packets[]={4345,259,255,-1};
1672    const int *headret[]={head1_3,head2_3,NULL};
1673
1674    fprintf(stderr,"testing initial-packet lacing > 4k... ");
1675    test_pack(packets,headret,0,0,0);
1676  }
1677
1678  {
1679    /* continuing packet test; with page spill expansion, we have to
1680       overflow the lacing table. */
1681    const int packets[]={0,65500,259,255,-1};
1682    const int *headret[]={head1_4,head2_4,head3_4,NULL};
1683
1684    fprintf(stderr,"testing single packet page span... ");
1685    test_pack(packets,headret,0,0,0);
1686  }
1687
1688  {
1689    /* spill expand packet test */
1690    const int packets[]={0,4345,259,255,0,0,-1};
1691    const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
1692
1693    fprintf(stderr,"testing page spill expansion... ");
1694    test_pack(packets,headret,0,0,0);
1695  }
1696
1697  /* page with the 255 segment limit */
1698  {
1699
1700    const int packets[]={0,10,10,10,10,10,10,10,10,
1701                   10,10,10,10,10,10,10,10,
1702                   10,10,10,10,10,10,10,10,
1703                   10,10,10,10,10,10,10,10,
1704                   10,10,10,10,10,10,10,10,
1705                   10,10,10,10,10,10,10,10,
1706                   10,10,10,10,10,10,10,10,
1707                   10,10,10,10,10,10,10,10,
1708                   10,10,10,10,10,10,10,10,
1709                   10,10,10,10,10,10,10,10,
1710                   10,10,10,10,10,10,10,10,
1711                   10,10,10,10,10,10,10,10,
1712                   10,10,10,10,10,10,10,10,
1713                   10,10,10,10,10,10,10,10,
1714                   10,10,10,10,10,10,10,10,
1715                   10,10,10,10,10,10,10,10,
1716                   10,10,10,10,10,10,10,10,
1717                   10,10,10,10,10,10,10,10,
1718                   10,10,10,10,10,10,10,10,
1719                   10,10,10,10,10,10,10,10,
1720                   10,10,10,10,10,10,10,10,
1721                   10,10,10,10,10,10,10,10,
1722                   10,10,10,10,10,10,10,10,
1723                   10,10,10,10,10,10,10,10,
1724                   10,10,10,10,10,10,10,10,
1725                   10,10,10,10,10,10,10,10,
1726                   10,10,10,10,10,10,10,10,
1727                   10,10,10,10,10,10,10,10,
1728                   10,10,10,10,10,10,10,10,
1729                   10,10,10,10,10,10,10,10,
1730                   10,10,10,10,10,10,10,10,
1731                   10,10,10,10,10,10,10,50,-1};
1732    const int *headret[]={head1_5,head2_5,head3_5,NULL};
1733
1734    fprintf(stderr,"testing max packet segments... ");
1735    test_pack(packets,headret,0,0,0);
1736  }
1737
1738  {
1739    /* packet that overspans over an entire page */
1740    const int packets[]={0,100,130049,259,255,-1};
1741    const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1742
1743    fprintf(stderr,"testing very large packets... ");
1744    test_pack(packets,headret,0,0,0);
1745  }
1746
1747  {
1748    /* test for the libogg 1.1.1 resync in large continuation bug
1749       found by Josh Coalson)  */
1750    const int packets[]={0,100,130049,259,255,-1};
1751    const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1752
1753    fprintf(stderr,"testing continuation resync in very large packets... ");
1754    test_pack(packets,headret,100,2,3);
1755  }
1756
1757  {
1758    /* term only page.  why not? */
1759    const int packets[]={0,100,64770,-1};
1760    const int *headret[]={head1_7,head2_7,head3_7,NULL};
1761
1762    fprintf(stderr,"testing zero data page (1 nil packet)... ");
1763    test_pack(packets,headret,0,0,0);
1764  }
1765
1766
1767
1768  {
1769    /* build a bunch of pages for testing */
1770    unsigned char *data=_ogg_malloc(1024*1024);
1771    int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
1772    int inptr=0,i,j;
1773    ogg_page og[5];
1774
1775    ogg_stream_reset(&os_en);
1776
1777    for(i=0;pl[i]!=-1;i++){
1778      ogg_packet op;
1779      int len=pl[i];
1780
1781      op.packet=data+inptr;
1782      op.bytes=len;
1783      op.e_o_s=(pl[i+1]<0?1:0);
1784      op.granulepos=(i+1)*1000;
1785
1786      for(j=0;j<len;j++)data[inptr++]=i+j;
1787      ogg_stream_packetin(&os_en,&op);
1788    }
1789
1790    _ogg_free(data);
1791
1792    /* retrieve finished pages */
1793    for(i=0;i<5;i++){
1794      if(ogg_stream_pageout(&os_en,&og[i])==0){
1795        fprintf(stderr,"Too few pages output building sync tests!\n");
1796        exit(1);
1797      }
1798      copy_page(&og[i]);
1799    }
1800
1801    /* Test lost pages on pagein/packetout: no rollback */
1802    {
1803      ogg_page temp;
1804      ogg_packet test;
1805
1806      fprintf(stderr,"Testing loss of pages... ");
1807
1808      ogg_sync_reset(&oy);
1809      ogg_stream_reset(&os_de);
1810      for(i=0;i<5;i++){
1811        memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1812               og[i].header_len);
1813        ogg_sync_wrote(&oy,og[i].header_len);
1814        memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1815        ogg_sync_wrote(&oy,og[i].body_len);
1816      }
1817
1818      ogg_sync_pageout(&oy,&temp);
1819      ogg_stream_pagein(&os_de,&temp);
1820      ogg_sync_pageout(&oy,&temp);
1821      ogg_stream_pagein(&os_de,&temp);
1822      ogg_sync_pageout(&oy,&temp);
1823      /* skip */
1824      ogg_sync_pageout(&oy,&temp);
1825      ogg_stream_pagein(&os_de,&temp);
1826
1827      /* do we get the expected results/packets? */
1828
1829      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1830      checkpacket(&test,0,0,0);
1831      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1832      checkpacket(&test,1,1,-1);
1833      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1834      checkpacket(&test,1,2,-1);
1835      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1836      checkpacket(&test,98,3,-1);
1837      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1838      checkpacket(&test,4079,4,5000);
1839      if(ogg_stream_packetout(&os_de,&test)!=-1){
1840        fprintf(stderr,"Error: loss of page did not return error\n");
1841        exit(1);
1842      }
1843      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1844      checkpacket(&test,76,9,-1);
1845      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1846      checkpacket(&test,34,10,-1);
1847      fprintf(stderr,"ok.\n");
1848    }
1849
1850    /* Test lost pages on pagein/packetout: rollback with continuation */
1851    {
1852      ogg_page temp;
1853      ogg_packet test;
1854
1855      fprintf(stderr,"Testing loss of pages (rollback required)... ");
1856
1857      ogg_sync_reset(&oy);
1858      ogg_stream_reset(&os_de);
1859      for(i=0;i<5;i++){
1860        memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1861               og[i].header_len);
1862        ogg_sync_wrote(&oy,og[i].header_len);
1863        memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1864        ogg_sync_wrote(&oy,og[i].body_len);
1865      }
1866
1867      ogg_sync_pageout(&oy,&temp);
1868      ogg_stream_pagein(&os_de,&temp);
1869      ogg_sync_pageout(&oy,&temp);
1870      ogg_stream_pagein(&os_de,&temp);
1871      ogg_sync_pageout(&oy,&temp);
1872      ogg_stream_pagein(&os_de,&temp);
1873      ogg_sync_pageout(&oy,&temp);
1874      /* skip */
1875      ogg_sync_pageout(&oy,&temp);
1876      ogg_stream_pagein(&os_de,&temp);
1877
1878      /* do we get the expected results/packets? */
1879
1880      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1881      checkpacket(&test,0,0,0);
1882      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1883      checkpacket(&test,1,1,-1);
1884      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1885      checkpacket(&test,1,2,-1);
1886      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1887      checkpacket(&test,98,3,-1);
1888      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1889      checkpacket(&test,4079,4,5000);
1890      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1891      checkpacket(&test,1,5,-1);
1892      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1893      checkpacket(&test,1,6,-1);
1894      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1895      checkpacket(&test,2954,7,-1);
1896      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1897      checkpacket(&test,2057,8,9000);
1898      if(ogg_stream_packetout(&os_de,&test)!=-1){
1899        fprintf(stderr,"Error: loss of page did not return error\n");
1900        exit(1);
1901      }
1902      if(ogg_stream_packetout(&os_de,&test)!=1)error();
1903      checkpacket(&test,300,17,18000);
1904      fprintf(stderr,"ok.\n");
1905    }
1906
1907    /* the rest only test sync */
1908    {
1909      ogg_page og_de;
1910      /* Test fractional page inputs: incomplete capture */
1911      fprintf(stderr,"Testing sync on partial inputs... ");
1912      ogg_sync_reset(&oy);
1913      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1914             3);
1915      ogg_sync_wrote(&oy,3);
1916      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1917
1918      /* Test fractional page inputs: incomplete fixed header */
1919      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
1920             20);
1921      ogg_sync_wrote(&oy,20);
1922      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1923
1924      /* Test fractional page inputs: incomplete header */
1925      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
1926             5);
1927      ogg_sync_wrote(&oy,5);
1928      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1929
1930      /* Test fractional page inputs: incomplete body */
1931
1932      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
1933             og[1].header_len-28);
1934      ogg_sync_wrote(&oy,og[1].header_len-28);
1935      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1936
1937      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
1938      ogg_sync_wrote(&oy,1000);
1939      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1940
1941      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
1942             og[1].body_len-1000);
1943      ogg_sync_wrote(&oy,og[1].body_len-1000);
1944      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1945
1946      fprintf(stderr,"ok.\n");
1947    }
1948
1949    /* Test fractional page inputs: page + incomplete capture */
1950    {
1951      ogg_page og_de;
1952      fprintf(stderr,"Testing sync on 1+partial inputs... ");
1953      ogg_sync_reset(&oy);
1954
1955      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1956             og[1].header_len);
1957      ogg_sync_wrote(&oy,og[1].header_len);
1958
1959      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1960             og[1].body_len);
1961      ogg_sync_wrote(&oy,og[1].body_len);
1962
1963      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1964             20);
1965      ogg_sync_wrote(&oy,20);
1966      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1967      if(ogg_sync_pageout(&oy,&og_de)>0)error();
1968
1969      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
1970             og[1].header_len-20);
1971      ogg_sync_wrote(&oy,og[1].header_len-20);
1972      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1973             og[1].body_len);
1974      ogg_sync_wrote(&oy,og[1].body_len);
1975      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1976
1977      fprintf(stderr,"ok.\n");
1978    }
1979
1980    /* Test recapture: garbage + page */
1981    {
1982      ogg_page og_de;
1983      fprintf(stderr,"Testing search for capture... ");
1984      ogg_sync_reset(&oy);
1985
1986      /* 'garbage' */
1987      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1988             og[1].body_len);
1989      ogg_sync_wrote(&oy,og[1].body_len);
1990
1991      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1992             og[1].header_len);
1993      ogg_sync_wrote(&oy,og[1].header_len);
1994
1995      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1996             og[1].body_len);
1997      ogg_sync_wrote(&oy,og[1].body_len);
1998
1999      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2000             20);
2001      ogg_sync_wrote(&oy,20);
2002      if(ogg_sync_pageout(&oy,&og_de)>0)error();
2003      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2004      if(ogg_sync_pageout(&oy,&og_de)>0)error();
2005
2006      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
2007             og[2].header_len-20);
2008      ogg_sync_wrote(&oy,og[2].header_len-20);
2009      memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2010             og[2].body_len);
2011      ogg_sync_wrote(&oy,og[2].body_len);
2012      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2013
2014      fprintf(stderr,"ok.\n");
2015    }
2016
2017    /* Test recapture: page + garbage + page */
2018    {
2019      ogg_page og_de;
2020      fprintf(stderr,"Testing recapture... ");
2021      ogg_sync_reset(&oy);
2022
2023      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2024             og[1].header_len);
2025      ogg_sync_wrote(&oy,og[1].header_len);
2026
2027      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2028             og[1].body_len);
2029      ogg_sync_wrote(&oy,og[1].body_len);
2030
2031      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2032             og[2].header_len);
2033      ogg_sync_wrote(&oy,og[2].header_len);
2034
2035      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2036             og[2].header_len);
2037      ogg_sync_wrote(&oy,og[2].header_len);
2038
2039      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2040
2041      memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2042             og[2].body_len-5);
2043      ogg_sync_wrote(&oy,og[2].body_len-5);
2044
2045      memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
2046             og[3].header_len);
2047      ogg_sync_wrote(&oy,og[3].header_len);
2048
2049      memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
2050             og[3].body_len);
2051      ogg_sync_wrote(&oy,og[3].body_len);
2052
2053      if(ogg_sync_pageout(&oy,&og_de)>0)error();
2054      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2055
2056      fprintf(stderr,"ok.\n");
2057    }
2058
2059    /* Free page data that was previously copied */
2060    {
2061      for(i=0;i<5;i++){
2062        free_page(&og[i]);
2063      }
2064    }
2065  }
2066
2067  return(0);
2068}
2069
2070#endif
2071
2072
2073
2074
2075