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