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