doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
framing.c
Go to the documentation of this file.
1 /********************************************************************
2  * *
3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC 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-2002 *
9  * by the Xiph.Org Foundation http://www.xiph.org/ *
10  * *
11  ********************************************************************
12 
13  function: code raw [Vorbis] packets into framed OggSquish stream and
14  decode Ogg streams back into raw packets
15  last mod: $Id: framing.c,v 1.23 2002/09/29 07:10:37 giles Exp $
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 
30  return((int)(og->header[4]));
31 }
32 
34  return((int)(og->header[5]&0x01));
35 }
36 
38  return((int)(og->header[5]&0x02));
39 }
40 
42  return((int)(og->header[5]&0x04));
43 }
44 
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 
59  return(og->header[14] |
60  (og->header[15]<<8) |
61  (og->header[16]<<16) |
62  (og->header[17]<<24));
63 }
64 
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 
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 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  // lowered for DOOM
192  os->body_storage=8*1024;
193  os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
194 
195  os->lacing_storage=1024;
196  os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
197  os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
198 
199  os->serialno=serialno;
200 
201  return(0);
202  }
203  return(-1);
204 }
205 
206 /* _clear does not free os, only the non-flat storage within */
208  if(os){
209  if(os->body_data)_ogg_free(os->body_data);
210  if(os->lacing_vals)_ogg_free(os->lacing_vals);
211  if(os->granule_vals)_ogg_free(os->granule_vals);
212 
213  memset(os,0,sizeof(*os));
214  }
215  return(0);
216 }
217 
219  if(os){
220  ogg_stream_clear(os);
221  _ogg_free(os);
222  }
223  return(0);
224 }
225 
226 /* Helpers for ogg_stream_encode; this keeps the structure and
227  what's happening fairly clear */
228 
229 static void _os_body_expand(ogg_stream_state *os,int needed){
230  if(os->body_storage<=os->body_fill+needed){
231  os->body_storage+=(needed+1024);
232  os->body_data=_ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data));
233  }
234 }
235 
236 static void _os_lacing_expand(ogg_stream_state *os,int needed){
237  if(os->lacing_storage<=os->lacing_fill+needed){
238  os->lacing_storage+=(needed+32);
241  }
242 }
243 
244 /* checksum the page */
245 /* Direct table CRC; note that this will be faster in the future if we
246  perform the checksum silmultaneously with other copies */
247 
249  if(og){
250  ogg_uint32_t crc_reg=0;
251  int i;
252 
253  /* safety; needed for API behavior, but not framing code */
254  og->header[22]=0;
255  og->header[23]=0;
256  og->header[24]=0;
257  og->header[25]=0;
258 
259  for(i=0;i<og->header_len;i++)
260  crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
261  for(i=0;i<og->body_len;i++)
262  crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
263 
264  og->header[22]=crc_reg&0xff;
265  og->header[23]=(crc_reg>>8)&0xff;
266  og->header[24]=(crc_reg>>16)&0xff;
267  og->header[25]=(crc_reg>>24)&0xff;
268  }
269 }
270 
271 /* submit data to the internal buffer of the framing engine */
273  int lacing_vals=op->bytes/255+1,i;
274 
275  if(os->body_returned){
276  /* advance packet data according to the body_returned pointer. We
277  had to keep it around to return a pointer into the buffer last
278  call */
279 
280  os->body_fill-=os->body_returned;
281  if(os->body_fill)
282  memmove(os->body_data,os->body_data+os->body_returned,
283  os->body_fill);
284  os->body_returned=0;
285  }
286 
287  /* make sure we have the buffer storage */
288  _os_body_expand(os,op->bytes);
289  _os_lacing_expand(os,lacing_vals);
290 
291  /* Copy in the submitted packet. Yes, the copy is a waste; this is
292  the liability of overly clean abstraction for the time being. It
293  will actually be fairly easy to eliminate the extra copy in the
294  future */
295 
296  memcpy(os->body_data+os->body_fill,op->packet,op->bytes);
297  os->body_fill+=op->bytes;
298 
299  /* Store lacing vals for this packet */
300  for(i=0;i<lacing_vals-1;i++){
301  os->lacing_vals[os->lacing_fill+i]=255;
302  os->granule_vals[os->lacing_fill+i]=os->granulepos;
303  }
304  os->lacing_vals[os->lacing_fill+i]=(op->bytes)%255;
306 
307  /* flag the first segment as the beginning of the packet */
308  os->lacing_vals[os->lacing_fill]|= 0x100;
309 
310  os->lacing_fill+=lacing_vals;
311 
312  /* for the sake of completeness */
313  os->packetno++;
314 
315  if(op->e_o_s)os->e_o_s=1;
316 
317  return(0);
318 }
319 
320 /* This will flush remaining packets into a page (returning nonzero),
321  even if there is not enough data to trigger a flush normally
322  (undersized page). If there are no packets or partial packets to
323  flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
324  try to flush a normal sized page like ogg_stream_pageout; a call to
325  ogg_stream_flush does not guarantee that all packets have flushed.
326  Only a return value of 0 from ogg_stream_flush indicates all packet
327  data is flushed into pages.
328 
329  since ogg_stream_flush will flush the last page in a stream even if
330  it's undersized, you almost certainly want to use ogg_stream_pageout
331  (and *not* ogg_stream_flush) unless you specifically need to flush
332  an page regardless of size in the middle of a stream. */
333 
335  int i;
336  int vals=0;
337  int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
338  int bytes=0;
339  long acc=0;
340  ogg_int64_t granule_pos=os->granule_vals[0];
341 
342  if(maxvals==0)return(0);
343 
344  /* construct a page */
345  /* decide how many segments to include */
346 
347  /* If this is the initial header case, the first page must only include
348  the initial header packet */
349  if(os->b_o_s==0){ /* 'initial header page' case */
350  granule_pos=0;
351  for(vals=0;vals<maxvals;vals++){
352  if((os->lacing_vals[vals]&0x0ff)<255){
353  vals++;
354  break;
355  }
356  }
357  }else{
358  for(vals=0;vals<maxvals;vals++){
359  if(acc>4096)break;
360  acc+=os->lacing_vals[vals]&0x0ff;
361  granule_pos=os->granule_vals[vals];
362  }
363  }
364 
365  /* construct the header in temp storage */
366  memcpy(os->header,"OggS",4);
367 
368  /* stream structure version */
369  os->header[4]=0x00;
370 
371  /* continued packet flag? */
372  os->header[5]=0x00;
373  if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
374  /* first page flag? */
375  if(os->b_o_s==0)os->header[5]|=0x02;
376  /* last page flag? */
377  if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
378  os->b_o_s=1;
379 
380  /* 64 bits of PCM position */
381  for(i=6;i<14;i++){
382  os->header[i]=(granule_pos&0xff);
383  granule_pos>>=8;
384  }
385 
386  /* 32 bits of stream serial number */
387  {
388  long serialno=os->serialno;
389  for(i=14;i<18;i++){
390  os->header[i]=(serialno&0xff);
391  serialno>>=8;
392  }
393  }
394 
395  /* 32 bits of page counter (we have both counter and page header
396  because this val can roll over) */
397  if(os->pageno==-1)os->pageno=0; /* because someone called
398  stream_reset; this would be a
399  strange thing to do in an
400  encode stream, but it has
401  plausible uses */
402  {
403  long pageno=os->pageno++;
404  for(i=18;i<22;i++){
405  os->header[i]=(pageno&0xff);
406  pageno>>=8;
407  }
408  }
409 
410  /* zero for computation; filled in later */
411  os->header[22]=0;
412  os->header[23]=0;
413  os->header[24]=0;
414  os->header[25]=0;
415 
416  /* segment table */
417  os->header[26]=vals&0xff;
418  for(i=0;i<vals;i++)
419  bytes+=os->header[i+27]=(os->lacing_vals[i]&0xff);
420 
421  /* set pointers in the ogg_page struct */
422  og->header=os->header;
423  og->header_len=os->header_fill=vals+27;
424  og->body=os->body_data+os->body_returned;
425  og->body_len=bytes;
426 
427  /* advance the lacing data and set the body_returned pointer */
428 
429  os->lacing_fill-=vals;
430  memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
431  memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
432  os->body_returned+=bytes;
433 
434  /* calculate the checksum */
435 
437 
438  /* done */
439  return(1);
440 }
441 
442 
443 /* This constructs pages from buffered packet segments. The pointers
444 returned are to static buffers; do not free. The returned buffers are
445 good only until the next call (using the same ogg_stream_state) */
446 
448 
449  if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
450  os->body_fill-os->body_returned > 4096 ||/* 'page nominal size' case */
451  os->lacing_fill>=255 || /* 'segment table full' case */
452  (os->lacing_fill&&!os->b_o_s)){ /* 'initial header page' case */
453 
454  return(ogg_stream_flush(os,og));
455  }
456 
457  /* not enough data to construct a page and not end of stream */
458  return(0);
459 }
460 
462  return os->e_o_s;
463 }
464 
465 /* DECODING PRIMITIVES: packet streaming layer **********************/
466 
467 /* This has two layers to place more of the multi-serialno and paging
468  control in the application's hands. First, we expose a data buffer
469  using ogg_sync_buffer(). The app either copies into the
470  buffer, or passes it directly to read(), etc. We then call
471  ogg_sync_wrote() to tell how many bytes we just added.
472 
473  Pages are returned (pointers into the buffer in ogg_sync_state)
474  by ogg_sync_pageout(). The page is then submitted to
475  ogg_stream_pagein() along with the appropriate
476  ogg_stream_state* (ie, matching serialno). We then get raw
477  packets out calling ogg_stream_packetout() with a
478  ogg_stream_state. See the 'frame-prog.txt' docs for details and
479  example code. */
480 
481 /* initialize the struct to a known state */
483  if(oy){
484  memset(oy,0,sizeof(*oy));
485  }
486  return(0);
487 }
488 
489 /* clear non-flat storage within */
491  if(oy){
492  if(oy->data)_ogg_free(oy->data);
493  ogg_sync_init(oy);
494  }
495  return(0);
496 }
497 
499  if(oy){
500  ogg_sync_clear(oy);
501  _ogg_free(oy);
502  }
503  return(0);
504 }
505 
507 
508  /* first, clear out any space that has been previously returned */
509  if(oy->returned){
510  oy->fill-=oy->returned;
511  if(oy->fill>0)
512  memmove(oy->data,oy->data+oy->returned,oy->fill);
513  oy->returned=0;
514  }
515 
516  if(size>oy->storage-oy->fill){
517  /* We need to extend the internal buffer */
518  long newsize=size+oy->fill+4096; /* an extra page to be nice */
519 
520  if(oy->data)
521  oy->data=_ogg_realloc(oy->data,newsize);
522  else
523  oy->data=_ogg_malloc(newsize);
524  oy->storage=newsize;
525  }
526 
527  /* expose a segment at least as large as requested at the fill mark */
528  return((char *)oy->data+oy->fill);
529 }
530 
531 int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
532  if(oy->fill+bytes>oy->storage)return(-1);
533  oy->fill+=bytes;
534  return(0);
535 }
536 
537 /* sync the stream. This is meant to be useful for finding page
538  boundaries.
539 
540  return values for this:
541  -n) skipped n bytes
542  0) page not ready; more data (no bytes skipped)
543  n) page synced at current location; page length n bytes
544 
545 */
546 
548  unsigned char *page=oy->data+oy->returned;
549  unsigned char *next;
550  long bytes=oy->fill-oy->returned;
551 
552  if(oy->headerbytes==0){
553  int headerbytes,i;
554  if(bytes<27)return(0); /* not enough for a header */
555 
556  /* verify capture pattern */
557  if(memcmp(page,"OggS",4))goto sync_fail;
558 
559  headerbytes=page[26]+27;
560  if(bytes<headerbytes)return(0); /* not enough for header + seg table */
561 
562  /* count up body length in the segment table */
563 
564  for(i=0;i<page[26];i++)
565  oy->bodybytes+=page[27+i];
566  oy->headerbytes=headerbytes;
567  }
568 
569  if(oy->bodybytes+oy->headerbytes>bytes)return(0);
570 
571  /* The whole test page is buffered. Verify the checksum */
572  {
573  /* Grab the checksum bytes, set the header field to zero */
574  char chksum[4];
575  ogg_page log;
576 
577  memcpy(chksum,page+22,4);
578  memset(page+22,0,4);
579 
580  /* set up a temp page struct and recompute the checksum */
581  log.header=page;
582  log.header_len=oy->headerbytes;
583  log.body=page+oy->headerbytes;
584  log.body_len=oy->bodybytes;
585  ogg_page_checksum_set(&log);
586 
587  /* Compare */
588  if(memcmp(chksum,page+22,4)){
589  /* D'oh. Mismatch! Corrupt page (or miscapture and not a page
590  at all) */
591  /* replace the computed checksum with the one actually read in */
592  memcpy(page+22,chksum,4);
593 
594  /* Bad checksum. Lose sync */
595  goto sync_fail;
596  }
597  }
598 
599  /* yes, have a whole page all ready to go */
600  {
601  unsigned char *page=oy->data+oy->returned;
602  long bytes;
603 
604  if(og){
605  og->header=page;
606  og->header_len=oy->headerbytes;
607  og->body=page+oy->headerbytes;
608  og->body_len=oy->bodybytes;
609  }
610 
611  oy->unsynced=0;
612  oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
613  oy->headerbytes=0;
614  oy->bodybytes=0;
615  return(bytes);
616  }
617 
618  sync_fail:
619 
620  oy->headerbytes=0;
621  oy->bodybytes=0;
622 
623  /* search for possible capture */
624  next=memchr(page+1,'O',bytes-1);
625  if(!next)
626  next=oy->data+oy->fill;
627 
628  oy->returned=next-oy->data;
629  return(-(next-page));
630 }
631 
632 /* sync the stream and get a page. Keep trying until we find a page.
633  Supress 'sync errors' after reporting the first.
634 
635  return values:
636  -1) recapture (hole in data)
637  0) need more data
638  1) page returned
639 
640  Returns pointers into buffered data; invalidated by next call to
641  _stream, _clear, _init, or _buffer */
642 
644 
645  /* all we need to do is verify a page at the head of the stream
646  buffer. If it doesn't verify, we look for the next potential
647  frame */
648 
649  while(1){
650  long ret=ogg_sync_pageseek(oy,og);
651  if(ret>0){
652  /* have a page */
653  return(1);
654  }
655  if(ret==0){
656  /* need more data */
657  return(0);
658  }
659 
660  /* head did not start a synced page... skipped some bytes */
661  if(!oy->unsynced){
662  oy->unsynced=1;
663  return(-1);
664  }
665 
666  /* loop. keep looking */
667 
668  }
669 }
670 
671 /* add the incoming page to the stream state; we decompose the page
672  into packet segments here as well. */
673 
675  unsigned char *header=og->header;
676  unsigned char *body=og->body;
677  long bodysize=og->body_len;
678  int segptr=0;
679 
680  int version=ogg_page_version(og);
681  int continued=ogg_page_continued(og);
682  int bos=ogg_page_bos(og);
683  int eos=ogg_page_eos(og);
684  ogg_int64_t granulepos=ogg_page_granulepos(og);
685  int serialno=ogg_page_serialno(og);
686  long pageno=ogg_page_pageno(og);
687  int segments=header[26];
688 
689  /* clean up 'returned data' */
690  {
691  long lr=os->lacing_returned;
692  long br=os->body_returned;
693 
694  /* body data */
695  if(br){
696  os->body_fill-=br;
697  if(os->body_fill)
698  memmove(os->body_data,os->body_data+br,os->body_fill);
699  os->body_returned=0;
700  }
701 
702  if(lr){
703  /* segment table */
704  if(os->lacing_fill-lr){
705  memmove(os->lacing_vals,os->lacing_vals+lr,
706  (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
707  memmove(os->granule_vals,os->granule_vals+lr,
708  (os->lacing_fill-lr)*sizeof(*os->granule_vals));
709  }
710  os->lacing_fill-=lr;
711  os->lacing_packet-=lr;
712  os->lacing_returned=0;
713  }
714  }
715 
716  /* check the serial number */
717  if(serialno!=os->serialno)return(-1);
718  if(version>0)return(-1);
719 
720  _os_lacing_expand(os,segments+1);
721 
722  /* are we in sequence? */
723  if(pageno!=os->pageno){
724  int i;
725 
726  /* unroll previous partial packet (if any) */
727  for(i=os->lacing_packet;i<os->lacing_fill;i++)
728  os->body_fill-=os->lacing_vals[i]&0xff;
729  os->lacing_fill=os->lacing_packet;
730 
731  /* make a note of dropped data in segment table */
732  if(os->pageno!=-1){
733  os->lacing_vals[os->lacing_fill++]=0x400;
734  os->lacing_packet++;
735  }
736 
737  /* are we a 'continued packet' page? If so, we'll need to skip
738  some segments */
739  if(continued){
740  bos=0;
741  for(;segptr<segments;segptr++){
742  int val=header[27+segptr];
743  body+=val;
744  bodysize-=val;
745  if(val<255){
746  segptr++;
747  break;
748  }
749  }
750  }
751  }
752 
753  if(bodysize){
754  _os_body_expand(os,bodysize);
755  memcpy(os->body_data+os->body_fill,body,bodysize);
756  os->body_fill+=bodysize;
757  }
758 
759  {
760  int saved=-1;
761  while(segptr<segments){
762  int val=header[27+segptr];
763  os->lacing_vals[os->lacing_fill]=val;
764  os->granule_vals[os->lacing_fill]=-1;
765 
766  if(bos){
767  os->lacing_vals[os->lacing_fill]|=0x100;
768  bos=0;
769  }
770 
771  if(val<255)saved=os->lacing_fill;
772 
773  os->lacing_fill++;
774  segptr++;
775 
776  if(val<255)os->lacing_packet=os->lacing_fill;
777  }
778 
779  /* set the granulepos on the last granuleval of the last full packet */
780  if(saved!=-1){
781  os->granule_vals[saved]=granulepos;
782  }
783 
784  }
785 
786  if(eos){
787  os->e_o_s=1;
788  if(os->lacing_fill>0)
789  os->lacing_vals[os->lacing_fill-1]|=0x200;
790  }
791 
792  os->pageno=pageno+1;
793 
794  return(0);
795 }
796 
797 /* clear things to an initial state. Good to call, eg, before seeking */
799  oy->fill=0;
800  oy->returned=0;
801  oy->unsynced=0;
802  oy->headerbytes=0;
803  oy->bodybytes=0;
804  return(0);
805 }
806 
808  os->body_fill=0;
809  os->body_returned=0;
810 
811  os->lacing_fill=0;
812  os->lacing_packet=0;
813  os->lacing_returned=0;
814 
815  os->header_fill=0;
816 
817  os->e_o_s=0;
818  os->b_o_s=0;
819  os->pageno=-1;
820  os->packetno=0;
821  os->granulepos=0;
822 
823  return(0);
824 }
825 
827  ogg_stream_reset(os);
828  os->serialno=serialno;
829  return(0);
830 }
831 
832 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
833 
834  /* The last part of decode. We have the stream broken into packet
835  segments. Now we need to group them into packets (or return the
836  out of sync markers) */
837 
838  int ptr=os->lacing_returned;
839 
840  if(os->lacing_packet<=ptr)return(0);
841 
842  if(os->lacing_vals[ptr]&0x400){
843  /* we need to tell the codec there's a gap; it might need to
844  handle previous packet dependencies. */
845  os->lacing_returned++;
846  os->packetno++;
847  return(-1);
848  }
849 
850  if(!op && !adv)return(1); /* just using peek as an inexpensive way
851  to ask if there's a whole packet
852  waiting */
853 
854  /* Gather the whole packet. We'll have no holes or a partial packet */
855  {
856  int size=os->lacing_vals[ptr]&0xff;
857  int bytes=size;
858  int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
859  int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
860 
861  while(size==255){
862  int val=os->lacing_vals[++ptr];
863  size=val&0xff;
864  if(val&0x200)eos=0x200;
865  bytes+=size;
866  }
867 
868  if(op){
869  op->e_o_s=eos;
870  op->b_o_s=bos;
871  op->packet=os->body_data+os->body_returned;
872  op->packetno=os->packetno;
873  op->granulepos=os->granule_vals[ptr];
874  op->bytes=bytes;
875  }
876 
877  if(adv){
878  os->body_returned+=bytes;
879  os->lacing_returned=ptr+1;
880  os->packetno++;
881  }
882  }
883  return(1);
884 }
885 
887  return _packetout(os,op,1);
888 }
889 
891  return _packetout(os,op,0);
892 }
893 
895  _ogg_free(op->packet);
896  memset(op, 0, sizeof(*op));
897 }
898 
899 #ifdef _V_SELFTEST
900 #include <stdio.h>
901 
902 ogg_stream_state os_en, os_de;
903 ogg_sync_state oy;
904 
905 void checkpacket(ogg_packet *op,int len, int no, int pos){
906  long j;
907  static int sequence=0;
908  static int lastno=0;
909 
910  if(op->bytes!=len){
911  fprintf(stderr,"incorrect packet length!\n");
912  exit(1);
913  }
914  if(op->granulepos!=pos){
915  fprintf(stderr,"incorrect packet position!\n");
916  exit(1);
917  }
918 
919  /* packet number just follows sequence/gap; adjust the input number
920  for that */
921  if(no==0){
922  sequence=0;
923  }else{
924  sequence++;
925  if(no>lastno+1)
926  sequence++;
927  }
928  lastno=no;
929  if(op->packetno!=sequence){
930  fprintf(stderr,"incorrect packet sequence %ld != %d\n",
931  (long)(op->packetno),sequence);
932  exit(1);
933  }
934 
935  /* Test data */
936  for(j=0;j<op->bytes;j++)
937  if(op->packet[j]!=((j+no)&0xff)){
938  fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
939  j,op->packet[j],(j+no)&0xff);
940  exit(1);
941  }
942 }
943 
944 void check_page(unsigned char *data,const int *header,ogg_page *og){
945  long j;
946  /* Test data */
947  for(j=0;j<og->body_len;j++)
948  if(og->body[j]!=data[j]){
949  fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
950  j,data[j],og->body[j]);
951  exit(1);
952  }
953 
954  /* Test header */
955  for(j=0;j<og->header_len;j++){
956  if(og->header[j]!=header[j]){
957  fprintf(stderr,"header content mismatch at pos %ld:\n",j);
958  for(j=0;j<header[26]+27;j++)
959  fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
960  fprintf(stderr,"\n");
961  exit(1);
962  }
963  }
964  if(og->header_len!=header[26]+27){
965  fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
966  og->header_len,header[26]+27);
967  exit(1);
968  }
969 }
970 
971 void print_header(ogg_page *og){
972  int j;
973  fprintf(stderr,"\nHEADER:\n");
974  fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n",
975  og->header[0],og->header[1],og->header[2],og->header[3],
976  (int)og->header[4],(int)og->header[5]);
977 
978  fprintf(stderr," granulepos: %d serialno: %d pageno: %ld\n",
979  (og->header[9]<<24)|(og->header[8]<<16)|
980  (og->header[7]<<8)|og->header[6],
981  (og->header[17]<<24)|(og->header[16]<<16)|
982  (og->header[15]<<8)|og->header[14],
983  ((long)(og->header[21])<<24)|(og->header[20]<<16)|
984  (og->header[19]<<8)|og->header[18]);
985 
986  fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (",
987  (int)og->header[22],(int)og->header[23],
988  (int)og->header[24],(int)og->header[25],
989  (int)og->header[26]);
990 
991  for(j=27;j<og->header_len;j++)
992  fprintf(stderr,"%d ",(int)og->header[j]);
993  fprintf(stderr,")\n\n");
994 }
995 
996 void copy_page(ogg_page *og){
997  unsigned char *temp=_ogg_malloc(og->header_len);
998  memcpy(temp,og->header,og->header_len);
999  og->header=temp;
1000 
1001  temp=_ogg_malloc(og->body_len);
1002  memcpy(temp,og->body,og->body_len);
1003  og->body=temp;
1004 }
1005 
1006 void error(void){
1007  fprintf(stderr,"error!\n");
1008  exit(1);
1009 }
1010 
1011 /* 17 only */
1012 const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
1013  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1014  0x01,0x02,0x03,0x04,0,0,0,0,
1015  0x15,0xed,0xec,0x91,
1016  1,
1017  17};
1018 
1019 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1020 const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
1021  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1022  0x01,0x02,0x03,0x04,0,0,0,0,
1023  0x59,0x10,0x6c,0x2c,
1024  1,
1025  17};
1026 const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
1027  0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
1028  0x01,0x02,0x03,0x04,1,0,0,0,
1029  0x89,0x33,0x85,0xce,
1030  13,
1031  254,255,0,255,1,255,245,255,255,0,
1032  255,255,90};
1033 
1034 /* nil packets; beginning,middle,end */
1035 const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
1036  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1037  0x01,0x02,0x03,0x04,0,0,0,0,
1038  0xff,0x7b,0x23,0x17,
1039  1,
1040  0};
1041 const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
1042  0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
1043  0x01,0x02,0x03,0x04,1,0,0,0,
1044  0x5c,0x3f,0x66,0xcb,
1045  17,
1046  17,254,255,0,0,255,1,0,255,245,255,255,0,
1047  255,255,90,0};
1048 
1049 /* large initial packet */
1050 const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
1051  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1052  0x01,0x02,0x03,0x04,0,0,0,0,
1053  0x01,0x27,0x31,0xaa,
1054  18,
1055  255,255,255,255,255,255,255,255,
1056  255,255,255,255,255,255,255,255,255,10};
1057 
1058 const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
1059  0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1060  0x01,0x02,0x03,0x04,1,0,0,0,
1061  0x7f,0x4e,0x8a,0xd2,
1062  4,
1063  255,4,255,0};
1064 
1065 
1066 /* continuing packet test */
1067 const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
1068  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1069  0x01,0x02,0x03,0x04,0,0,0,0,
1070  0xff,0x7b,0x23,0x17,
1071  1,
1072  0};
1073 
1074 const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
1075  0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1076  0x01,0x02,0x03,0x04,1,0,0,0,
1077  0x34,0x24,0xd5,0x29,
1078  17,
1079  255,255,255,255,255,255,255,255,
1080  255,255,255,255,255,255,255,255,255};
1081 
1082 const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
1083  0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
1084  0x01,0x02,0x03,0x04,2,0,0,0,
1085  0xc8,0xc3,0xcb,0xed,
1086  5,
1087  10,255,4,255,0};
1088 
1089 
1090 /* page with the 255 segment limit */
1091 const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
1092  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1093  0x01,0x02,0x03,0x04,0,0,0,0,
1094  0xff,0x7b,0x23,0x17,
1095  1,
1096  0};
1097 
1098 const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
1099  0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
1100  0x01,0x02,0x03,0x04,1,0,0,0,
1101  0xed,0x2a,0x2e,0xa7,
1102  255,
1103  10,10,10,10,10,10,10,10,
1104  10,10,10,10,10,10,10,10,
1105  10,10,10,10,10,10,10,10,
1106  10,10,10,10,10,10,10,10,
1107  10,10,10,10,10,10,10,10,
1108  10,10,10,10,10,10,10,10,
1109  10,10,10,10,10,10,10,10,
1110  10,10,10,10,10,10,10,10,
1111  10,10,10,10,10,10,10,10,
1112  10,10,10,10,10,10,10,10,
1113  10,10,10,10,10,10,10,10,
1114  10,10,10,10,10,10,10,10,
1115  10,10,10,10,10,10,10,10,
1116  10,10,10,10,10,10,10,10,
1117  10,10,10,10,10,10,10,10,
1118  10,10,10,10,10,10,10,10,
1119  10,10,10,10,10,10,10,10,
1120  10,10,10,10,10,10,10,10,
1121  10,10,10,10,10,10,10,10,
1122  10,10,10,10,10,10,10,10,
1123  10,10,10,10,10,10,10,10,
1124  10,10,10,10,10,10,10,10,
1125  10,10,10,10,10,10,10,10,
1126  10,10,10,10,10,10,10,10,
1127  10,10,10,10,10,10,10,10,
1128  10,10,10,10,10,10,10,10,
1129  10,10,10,10,10,10,10,10,
1130  10,10,10,10,10,10,10,10,
1131  10,10,10,10,10,10,10,10,
1132  10,10,10,10,10,10,10,10,
1133  10,10,10,10,10,10,10,10,
1134  10,10,10,10,10,10,10};
1135 
1136 const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
1137  0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
1138  0x01,0x02,0x03,0x04,2,0,0,0,
1139  0x6c,0x3b,0x82,0x3d,
1140  1,
1141  50};
1142 
1143 
1144 /* packet that overspans over an entire page */
1145 const int head1_6[] = {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 
1152 const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
1153  0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1154  0x01,0x02,0x03,0x04,1,0,0,0,
1155  0x3c,0xd9,0x4d,0x3f,
1156  17,
1157  100,255,255,255,255,255,255,255,255,
1158  255,255,255,255,255,255,255,255};
1159 
1160 const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
1161  0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1162  0x01,0x02,0x03,0x04,2,0,0,0,
1163  0xbd,0xd5,0xb5,0x8b,
1164  17,
1165  255,255,255,255,255,255,255,255,
1166  255,255,255,255,255,255,255,255,255};
1167 
1168 const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
1169  0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1170  0x01,0x02,0x03,0x04,3,0,0,0,
1171  0xef,0xdd,0x88,0xde,
1172  7,
1173  255,255,75,255,4,255,0};
1174 
1175 /* packet that overspans over an entire page */
1176 const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
1177  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1178  0x01,0x02,0x03,0x04,0,0,0,0,
1179  0xff,0x7b,0x23,0x17,
1180  1,
1181  0};
1182 
1183 const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
1184  0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1185  0x01,0x02,0x03,0x04,1,0,0,0,
1186  0x3c,0xd9,0x4d,0x3f,
1187  17,
1188  100,255,255,255,255,255,255,255,255,
1189  255,255,255,255,255,255,255,255};
1190 
1191 const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
1192  0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1193  0x01,0x02,0x03,0x04,2,0,0,0,
1194  0xd4,0xe0,0x60,0xe5,
1195  1,0};
1196 
1197 void test_pack(const int *pl, const int **headers){
1198  unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
1199  long inptr=0;
1200  long outptr=0;
1201  long deptr=0;
1202  long depacket=0;
1203  long granule_pos=7,pageno=0;
1204  int i,j,packets,pageout=0;
1205  int eosflag=0;
1206  int bosflag=0;
1207 
1208  ogg_stream_reset(&os_en);
1209  ogg_stream_reset(&os_de);
1210  ogg_sync_reset(&oy);
1211 
1212  for(packets=0;;packets++)if(pl[packets]==-1)break;
1213 
1214  for(i=0;i<packets;i++){
1215  /* construct a test packet */
1216  ogg_packet op;
1217  int len=pl[i];
1218 
1219  op.packet=data+inptr;
1220  op.bytes=len;
1221  op.e_o_s=(pl[i+1]<0?1:0);
1222  op.granulepos=granule_pos;
1223 
1224  granule_pos+=1024;
1225 
1226  for(j=0;j<len;j++)data[inptr++]=i+j;
1227 
1228  /* submit the test packet */
1229  ogg_stream_packetin(&os_en,&op);
1230 
1231  /* retrieve any finished pages */
1232  {
1233  ogg_page og;
1234 
1235  while(ogg_stream_pageout(&os_en,&og)){
1236  /* We have a page. Check it carefully */
1237 
1238  fprintf(stderr,"%ld, ",pageno);
1239 
1240  if(headers[pageno]==NULL){
1241  fprintf(stderr,"coded too many pages!\n");
1242  exit(1);
1243  }
1244 
1245  check_page(data+outptr,headers[pageno],&og);
1246 
1247  outptr+=og.body_len;
1248  pageno++;
1249 
1250  /* have a complete page; submit it to sync/decode */
1251 
1252  {
1253  ogg_page og_de;
1254  ogg_packet op_de,op_de2;
1255  char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
1256  memcpy(buf,og.header,og.header_len);
1257  memcpy(buf+og.header_len,og.body,og.body_len);
1258  ogg_sync_wrote(&oy,og.header_len+og.body_len);
1259 
1260  while(ogg_sync_pageout(&oy,&og_de)>0){
1261  /* got a page. Happy happy. Verify that it's good. */
1262 
1263  check_page(data+deptr,headers[pageout],&og_de);
1264  deptr+=og_de.body_len;
1265  pageout++;
1266 
1267  /* submit it to deconstitution */
1268  ogg_stream_pagein(&os_de,&og_de);
1269 
1270  /* packets out? */
1271  while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
1272  ogg_stream_packetpeek(&os_de,NULL);
1273  ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
1274 
1275  /* verify peek and out match */
1276  if(memcmp(&op_de,&op_de2,sizeof(op_de))){
1277  fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
1278  depacket);
1279  exit(1);
1280  }
1281 
1282  /* verify the packet! */
1283  /* check data */
1284  if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
1285  fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
1286  depacket);
1287  exit(1);
1288  }
1289  /* check bos flag */
1290  if(bosflag==0 && op_de.b_o_s==0){
1291  fprintf(stderr,"b_o_s flag not set on packet!\n");
1292  exit(1);
1293  }
1294  if(bosflag && op_de.b_o_s){
1295  fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
1296  exit(1);
1297  }
1298  bosflag=1;
1299  depacket+=op_de.bytes;
1300 
1301  /* check eos flag */
1302  if(eosflag){
1303  fprintf(stderr,"Multiple decoded packets with eos flag!\n");
1304  exit(1);
1305  }
1306 
1307  if(op_de.e_o_s)eosflag=1;
1308 
1309  /* check granulepos flag */
1310  if(op_de.granulepos!=-1){
1311  fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
1312  }
1313  }
1314  }
1315  }
1316  }
1317  }
1318  }
1319  _ogg_free(data);
1320  if(headers[pageno]!=NULL){
1321  fprintf(stderr,"did not write last page!\n");
1322  exit(1);
1323  }
1324  if(headers[pageout]!=NULL){
1325  fprintf(stderr,"did not decode last page!\n");
1326  exit(1);
1327  }
1328  if(inptr!=outptr){
1329  fprintf(stderr,"encoded page data incomplete!\n");
1330  exit(1);
1331  }
1332  if(inptr!=deptr){
1333  fprintf(stderr,"decoded page data incomplete!\n");
1334  exit(1);
1335  }
1336  if(inptr!=depacket){
1337  fprintf(stderr,"decoded packet data incomplete!\n");
1338  exit(1);
1339  }
1340  if(!eosflag){
1341  fprintf(stderr,"Never got a packet with EOS set!\n");
1342  exit(1);
1343  }
1344  fprintf(stderr,"ok.\n");
1345 }
1346 
1347 int main(void){
1348 
1349  ogg_stream_init(&os_en,0x04030201);
1350  ogg_stream_init(&os_de,0x04030201);
1351  ogg_sync_init(&oy);
1352 
1353  /* Exercise each code path in the framing code. Also verify that
1354  the checksums are working. */
1355 
1356  {
1357  /* 17 only */
1358  const int packets[]={17, -1};
1359  const int *headret[]={head1_0,NULL};
1360 
1361  fprintf(stderr,"testing single page encoding... ");
1362  test_pack(packets,headret);
1363  }
1364 
1365  {
1366  /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1367  const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
1368  const int *headret[]={head1_1,head2_1,NULL};
1369 
1370  fprintf(stderr,"testing basic page encoding... ");
1371  test_pack(packets,headret);
1372  }
1373 
1374  {
1375  /* nil packets; beginning,middle,end */
1376  const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
1377  const int *headret[]={head1_2,head2_2,NULL};
1378 
1379  fprintf(stderr,"testing basic nil packets... ");
1380  test_pack(packets,headret);
1381  }
1382 
1383  {
1384  /* large initial packet */
1385  const int packets[]={4345,259,255,-1};
1386  const int *headret[]={head1_3,head2_3,NULL};
1387 
1388  fprintf(stderr,"testing initial-packet lacing > 4k... ");
1389  test_pack(packets,headret);
1390  }
1391 
1392  {
1393  /* continuing packet test */
1394  const int packets[]={0,4345,259,255,-1};
1395  const int *headret[]={head1_4,head2_4,head3_4,NULL};
1396 
1397  fprintf(stderr,"testing single packet page span... ");
1398  test_pack(packets,headret);
1399  }
1400 
1401  /* page with the 255 segment limit */
1402  {
1403 
1404  const int packets[]={0,10,10,10,10,10,10,10,10,
1405  10,10,10,10,10,10,10,10,
1406  10,10,10,10,10,10,10,10,
1407  10,10,10,10,10,10,10,10,
1408  10,10,10,10,10,10,10,10,
1409  10,10,10,10,10,10,10,10,
1410  10,10,10,10,10,10,10,10,
1411  10,10,10,10,10,10,10,10,
1412  10,10,10,10,10,10,10,10,
1413  10,10,10,10,10,10,10,10,
1414  10,10,10,10,10,10,10,10,
1415  10,10,10,10,10,10,10,10,
1416  10,10,10,10,10,10,10,10,
1417  10,10,10,10,10,10,10,10,
1418  10,10,10,10,10,10,10,10,
1419  10,10,10,10,10,10,10,10,
1420  10,10,10,10,10,10,10,10,
1421  10,10,10,10,10,10,10,10,
1422  10,10,10,10,10,10,10,10,
1423  10,10,10,10,10,10,10,10,
1424  10,10,10,10,10,10,10,10,
1425  10,10,10,10,10,10,10,10,
1426  10,10,10,10,10,10,10,10,
1427  10,10,10,10,10,10,10,10,
1428  10,10,10,10,10,10,10,10,
1429  10,10,10,10,10,10,10,10,
1430  10,10,10,10,10,10,10,10,
1431  10,10,10,10,10,10,10,10,
1432  10,10,10,10,10,10,10,10,
1433  10,10,10,10,10,10,10,10,
1434  10,10,10,10,10,10,10,10,
1435  10,10,10,10,10,10,10,50,-1};
1436  const int *headret[]={head1_5,head2_5,head3_5,NULL};
1437 
1438  fprintf(stderr,"testing max packet segments... ");
1439  test_pack(packets,headret);
1440  }
1441 
1442  {
1443  /* packet that overspans over an entire page */
1444  const int packets[]={0,100,9000,259,255,-1};
1445  const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1446 
1447  fprintf(stderr,"testing very large packets... ");
1448  test_pack(packets,headret);
1449  }
1450 
1451  {
1452  /* term only page. why not? */
1453  const int packets[]={0,100,4080,-1};
1454  const int *headret[]={head1_7,head2_7,head3_7,NULL};
1455 
1456  fprintf(stderr,"testing zero data page (1 nil packet)... ");
1457  test_pack(packets,headret);
1458  }
1459 
1460 
1461 
1462  {
1463  /* build a bunch of pages for testing */
1464  unsigned char *data=_ogg_malloc(1024*1024);
1465  int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1};
1466  int inptr=0,i,j;
1467  ogg_page og[5];
1468 
1469  ogg_stream_reset(&os_en);
1470 
1471  for(i=0;pl[i]!=-1;i++){
1472  ogg_packet op;
1473  int len=pl[i];
1474 
1475  op.packet=data+inptr;
1476  op.bytes=len;
1477  op.e_o_s=(pl[i+1]<0?1:0);
1478  op.granulepos=(i+1)*1000;
1479 
1480  for(j=0;j<len;j++)data[inptr++]=i+j;
1481  ogg_stream_packetin(&os_en,&op);
1482  }
1483 
1484  _ogg_free(data);
1485 
1486  /* retrieve finished pages */
1487  for(i=0;i<5;i++){
1488  if(ogg_stream_pageout(&os_en,&og[i])==0){
1489  fprintf(stderr,"Too few pages output building sync tests!\n");
1490  exit(1);
1491  }
1492  copy_page(&og[i]);
1493  }
1494 
1495  /* Test lost pages on pagein/packetout: no rollback */
1496  {
1497  ogg_page temp;
1498  ogg_packet test;
1499 
1500  fprintf(stderr,"Testing loss of pages... ");
1501 
1502  ogg_sync_reset(&oy);
1503  ogg_stream_reset(&os_de);
1504  for(i=0;i<5;i++){
1505  memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1506  og[i].header_len);
1507  ogg_sync_wrote(&oy,og[i].header_len);
1508  memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1509  ogg_sync_wrote(&oy,og[i].body_len);
1510  }
1511 
1512  ogg_sync_pageout(&oy,&temp);
1513  ogg_stream_pagein(&os_de,&temp);
1514  ogg_sync_pageout(&oy,&temp);
1515  ogg_stream_pagein(&os_de,&temp);
1516  ogg_sync_pageout(&oy,&temp);
1517  /* skip */
1518  ogg_sync_pageout(&oy,&temp);
1519  ogg_stream_pagein(&os_de,&temp);
1520 
1521  /* do we get the expected results/packets? */
1522 
1523  if(ogg_stream_packetout(&os_de,&test)!=1)error();
1524  checkpacket(&test,0,0,0);
1525  if(ogg_stream_packetout(&os_de,&test)!=1)error();
1526  checkpacket(&test,100,1,-1);
1527  if(ogg_stream_packetout(&os_de,&test)!=1)error();
1528  checkpacket(&test,4079,2,3000);
1529  if(ogg_stream_packetout(&os_de,&test)!=-1){
1530  fprintf(stderr,"Error: loss of page did not return error\n");
1531  exit(1);
1532  }
1533  if(ogg_stream_packetout(&os_de,&test)!=1)error();
1534  checkpacket(&test,76,5,-1);
1535  if(ogg_stream_packetout(&os_de,&test)!=1)error();
1536  checkpacket(&test,34,6,-1);
1537  fprintf(stderr,"ok.\n");
1538  }
1539 
1540  /* Test lost pages on pagein/packetout: rollback with continuation */
1541  {
1542  ogg_page temp;
1543  ogg_packet test;
1544 
1545  fprintf(stderr,"Testing loss of pages (rollback required)... ");
1546 
1547  ogg_sync_reset(&oy);
1548  ogg_stream_reset(&os_de);
1549  for(i=0;i<5;i++){
1550  memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1551  og[i].header_len);
1552  ogg_sync_wrote(&oy,og[i].header_len);
1553  memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1554  ogg_sync_wrote(&oy,og[i].body_len);
1555  }
1556 
1557  ogg_sync_pageout(&oy,&temp);
1558  ogg_stream_pagein(&os_de,&temp);
1559  ogg_sync_pageout(&oy,&temp);
1560  ogg_stream_pagein(&os_de,&temp);
1561  ogg_sync_pageout(&oy,&temp);
1562  ogg_stream_pagein(&os_de,&temp);
1563  ogg_sync_pageout(&oy,&temp);
1564  /* skip */
1565  ogg_sync_pageout(&oy,&temp);
1566  ogg_stream_pagein(&os_de,&temp);
1567 
1568  /* do we get the expected results/packets? */
1569 
1570  if(ogg_stream_packetout(&os_de,&test)!=1)error();
1571  checkpacket(&test,0,0,0);
1572  if(ogg_stream_packetout(&os_de,&test)!=1)error();
1573  checkpacket(&test,100,1,-1);
1574  if(ogg_stream_packetout(&os_de,&test)!=1)error();
1575  checkpacket(&test,4079,2,3000);
1576  if(ogg_stream_packetout(&os_de,&test)!=1)error();
1577  checkpacket(&test,2956,3,4000);
1578  if(ogg_stream_packetout(&os_de,&test)!=-1){
1579  fprintf(stderr,"Error: loss of page did not return error\n");
1580  exit(1);
1581  }
1582  if(ogg_stream_packetout(&os_de,&test)!=1)error();
1583  checkpacket(&test,300,13,14000);
1584  fprintf(stderr,"ok.\n");
1585  }
1586 
1587  /* the rest only test sync */
1588  {
1589  ogg_page og_de;
1590  /* Test fractional page inputs: incomplete capture */
1591  fprintf(stderr,"Testing sync on partial inputs... ");
1592  ogg_sync_reset(&oy);
1593  memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1594  3);
1595  ogg_sync_wrote(&oy,3);
1596  if(ogg_sync_pageout(&oy,&og_de)>0)error();
1597 
1598  /* Test fractional page inputs: incomplete fixed header */
1599  memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
1600  20);
1601  ogg_sync_wrote(&oy,20);
1602  if(ogg_sync_pageout(&oy,&og_de)>0)error();
1603 
1604  /* Test fractional page inputs: incomplete header */
1605  memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
1606  5);
1607  ogg_sync_wrote(&oy,5);
1608  if(ogg_sync_pageout(&oy,&og_de)>0)error();
1609 
1610  /* Test fractional page inputs: incomplete body */
1611 
1612  memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
1613  og[1].header_len-28);
1614  ogg_sync_wrote(&oy,og[1].header_len-28);
1615  if(ogg_sync_pageout(&oy,&og_de)>0)error();
1616 
1617  memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
1618  ogg_sync_wrote(&oy,1000);
1619  if(ogg_sync_pageout(&oy,&og_de)>0)error();
1620 
1621  memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
1622  og[1].body_len-1000);
1623  ogg_sync_wrote(&oy,og[1].body_len-1000);
1624  if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1625 
1626  fprintf(stderr,"ok.\n");
1627  }
1628 
1629  /* Test fractional page inputs: page + incomplete capture */
1630  {
1631  ogg_page og_de;
1632  fprintf(stderr,"Testing sync on 1+partial inputs... ");
1633  ogg_sync_reset(&oy);
1634 
1635  memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1636  og[1].header_len);
1637  ogg_sync_wrote(&oy,og[1].header_len);
1638 
1639  memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1640  og[1].body_len);
1641  ogg_sync_wrote(&oy,og[1].body_len);
1642 
1643  memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1644  20);
1645  ogg_sync_wrote(&oy,20);
1646  if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1647  if(ogg_sync_pageout(&oy,&og_de)>0)error();
1648 
1649  memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
1650  og[1].header_len-20);
1651  ogg_sync_wrote(&oy,og[1].header_len-20);
1652  memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1653  og[1].body_len);
1654  ogg_sync_wrote(&oy,og[1].body_len);
1655  if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1656 
1657  fprintf(stderr,"ok.\n");
1658  }
1659 
1660  /* Test recapture: garbage + page */
1661  {
1662  ogg_page og_de;
1663  fprintf(stderr,"Testing search for capture... ");
1664  ogg_sync_reset(&oy);
1665 
1666  /* 'garbage' */
1667  memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1668  og[1].body_len);
1669  ogg_sync_wrote(&oy,og[1].body_len);
1670 
1671  memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1672  og[1].header_len);
1673  ogg_sync_wrote(&oy,og[1].header_len);
1674 
1675  memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1676  og[1].body_len);
1677  ogg_sync_wrote(&oy,og[1].body_len);
1678 
1679  memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
1680  20);
1681  ogg_sync_wrote(&oy,20);
1682  if(ogg_sync_pageout(&oy,&og_de)>0)error();
1683  if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1684  if(ogg_sync_pageout(&oy,&og_de)>0)error();
1685 
1686  memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
1687  og[2].header_len-20);
1688  ogg_sync_wrote(&oy,og[2].header_len-20);
1689  memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
1690  og[2].body_len);
1691  ogg_sync_wrote(&oy,og[2].body_len);
1692  if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1693 
1694  fprintf(stderr,"ok.\n");
1695  }
1696 
1697  /* Test recapture: page + garbage + page */
1698  {
1699  ogg_page og_de;
1700  fprintf(stderr,"Testing recapture... ");
1701  ogg_sync_reset(&oy);
1702 
1703  memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1704  og[1].header_len);
1705  ogg_sync_wrote(&oy,og[1].header_len);
1706 
1707  memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1708  og[1].body_len);
1709  ogg_sync_wrote(&oy,og[1].body_len);
1710 
1711  memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
1712  og[2].header_len);
1713  ogg_sync_wrote(&oy,og[2].header_len);
1714 
1715  memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
1716  og[2].header_len);
1717  ogg_sync_wrote(&oy,og[2].header_len);
1718 
1719  if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1720 
1721  memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
1722  og[2].body_len-5);
1723  ogg_sync_wrote(&oy,og[2].body_len-5);
1724 
1725  memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
1726  og[3].header_len);
1727  ogg_sync_wrote(&oy,og[3].header_len);
1728 
1729  memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
1730  og[3].body_len);
1731  ogg_sync_wrote(&oy,og[3].body_len);
1732 
1733  if(ogg_sync_pageout(&oy,&og_de)>0)error();
1734  if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1735 
1736  fprintf(stderr,"ok.\n");
1737  }
1738  }
1739 
1740  return(0);
1741 }
1742 
1743 #endif
1744 
1745 
1746 
1747 
int ogg_stream_eos(ogg_stream_state *os)
Definition: framing.c:461
long lacing_storage
Definition: ogg.h:58
int b_o_s
Definition: ogg.h:68
int ogg_page_serialno(ogg_page *og)
Definition: framing.c:58
int fill
Definition: ogg.h:102
Definition: ogg.h:37
unsigned char * body
Definition: ogg.h:40
u_int32_t ogg_uint32_t
Definition: os_types.h:139
long ogg_page_pageno(ogg_page *og)
Definition: framing.c:65
int ogg_page_packets(ogg_page *og)
Definition: framing.c:91
#define main(x, y)
Definition: config-mac.h:9
int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og)
Definition: framing.c:643
long body_fill
Definition: ogg.h:50
long lacing_fill
Definition: ogg.h:59
Definition: ogg.h:84
unsigned char * data
Definition: ogg.h:100
unsigned char * body_data
Definition: ogg.h:48
GLenum GLsizei n
Definition: glext.h:3705
long header_len
Definition: ogg.h:39
long body_returned
Definition: ogg.h:51
#define _ogg_free
Definition: os_types.h:41
int bodybytes
Definition: ogg.h:107
GLenum GLsizei len
Definition: glext.h:3472
int ogg_sync_wrote(ogg_sync_state *oy, long bytes)
Definition: framing.c:531
int unsynced
Definition: ogg.h:105
ogg_int64_t * granule_vals
Definition: ogg.h:55
int i
Definition: process.py:33
int ogg_sync_destroy(ogg_sync_state *oy)
Definition: framing.c:498
int test(char *url)
Definition: lib500.c:3
int ogg_page_version(ogg_page *og)
Definition: framing.c:29
int ogg_sync_reset(ogg_sync_state *oy)
Definition: framing.c:798
long serialno
Definition: ogg.h:70
unsigned char header[282]
Definition: ogg.h:63
int ogg_sync_clear(ogg_sync_state *oy)
Definition: framing.c:490
int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og)
Definition: framing.c:447
struct version_s version
GLuint GLuint GLsizei count
Definition: glext.h:2845
GLuint index
Definition: glext.h:3476
int ogg_page_continued(ogg_page *og)
Definition: framing.c:33
long pageno
Definition: ogg.h:71
int storage
Definition: ogg.h:101
long bytes
Definition: ogg.h:86
int * lacing_vals
Definition: ogg.h:54
int ogg_stream_clear(ogg_stream_state *os)
Definition: framing.c:207
#define NULL
Definition: Lib.h:88
int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og)
Definition: framing.c:674
int ogg_stream_init(ogg_stream_state *os, int serialno)
Definition: framing.c:188
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:2853
void ogg_page_checksum_set(ogg_page *og)
Definition: framing.c:248
int ogg_stream_destroy(ogg_stream_state *os)
Definition: framing.c:218
unsigned char * packet
Definition: ogg.h:85
int ogg_stream_flush(ogg_stream_state *os, ogg_page *og)
Definition: framing.c:334
unsigned char * header
Definition: ogg.h:38
long b_o_s
Definition: ogg.h:87
#define _ogg_realloc
Definition: os_types.h:40
int ogg_stream_reset(ogg_stream_state *os)
Definition: framing.c:807
int ogg_sync_init(ogg_sync_state *oy)
Definition: framing.c:482
long lacing_returned
Definition: ogg.h:61
int ogg_page_bos(ogg_page *og)
Definition: framing.c:37
GLdouble GLdouble GLdouble r
Definition: glext.h:2951
char * ogg_sync_buffer(ogg_sync_state *oy, long size)
Definition: framing.c:506
int ogg_stream_packetout(ogg_stream_state *os, ogg_packet *op)
Definition: framing.c:886
int ogg_page_eos(ogg_page *og)
Definition: framing.c:41
ogg_int64_t packetno
Definition: ogg.h:72
int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op)
Definition: framing.c:272
GLsizeiptr size
Definition: glext.h:3112
ogg_int64_t granulepos
Definition: ogg.h:90
int ogg_stream_packetpeek(ogg_stream_state *os, ogg_packet *op)
Definition: framing.c:890
void ogg_packet_clear(ogg_packet *op)
Definition: framing.c:894
ogg_int64_t ogg_page_granulepos(ogg_page *og)
Definition: framing.c:45
int e_o_s
Definition: ogg.h:66
GLint j
Definition: qgl.h:264
int returned
Definition: ogg.h:103
int header_fill
Definition: ogg.h:64
long body_len
Definition: ogg.h:41
int64_t ogg_int64_t
Definition: os_types.h:140
long lacing_packet
Definition: ogg.h:60
int ogg_stream_reset_serialno(ogg_stream_state *os, int serialno)
Definition: framing.c:826
long e_o_s
Definition: ogg.h:88
int headerbytes
Definition: ogg.h:106
ogg_int64_t granulepos
Definition: ogg.h:77
long ogg_sync_pageseek(ogg_sync_state *oy, ogg_page *og)
Definition: framing.c:547
ogg_int64_t packetno
Definition: ogg.h:92
long body_storage
Definition: ogg.h:49
#define _ogg_malloc
Definition: os_types.h:38