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