PageRenderTime 75ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/cdex1/tags/CDEX130B2A1/cdexos/vorbis/lib/framing.c

#
C | 1623 lines | 1118 code | 285 blank | 220 comment | 144 complexity | 873e05e9d5dfaf599c1f83df1a94cd62 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, LGPL-2.0, BSD-3-Clause, AGPL-1.0, CC-BY-SA-3.0, GPL-3.0
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
  5. * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
  6. * PLEASE READ THESE TERMS DISTRIBUTING. *
  7. * *
  8. * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 *
  9. * by Monty <monty@xiph.org> and the XIPHOPHORUS Company *
  10. * http://www.xiph.org/ *
  11. * *
  12. ********************************************************************
  13. function: code raw [Vorbis] packets into framed OggSquish stream and
  14. decode Ogg streams back into raw packets
  15. last mod: $Id: framing.c 97 2000-08-07 23:58:05Z afaber $
  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. #include <stdlib.h>
  21. #include <string.h>
  22. #include "vorbis/codec.h"
  23. #include "misc.h"
  24. /* A complete description of Ogg framing exists in docs/framing.html */
  25. int ogg_page_version(ogg_page *og){
  26. return((int)(og->header[4]));
  27. }
  28. int ogg_page_continued(ogg_page *og){
  29. return((int)(og->header[5]&0x01));
  30. }
  31. int ogg_page_bos(ogg_page *og){
  32. return((int)(og->header[5]&0x02));
  33. }
  34. int ogg_page_eos(ogg_page *og){
  35. return((int)(og->header[5]&0x04));
  36. }
  37. int64_t ogg_page_frameno(ogg_page *og){
  38. unsigned char *page=og->header;
  39. int64_t pcmpos=page[13]&(0xff);
  40. pcmpos= (pcmpos<<8)|(page[12]&0xff);
  41. pcmpos= (pcmpos<<8)|(page[11]&0xff);
  42. pcmpos= (pcmpos<<8)|(page[10]&0xff);
  43. pcmpos= (pcmpos<<8)|(page[9]&0xff);
  44. pcmpos= (pcmpos<<8)|(page[8]&0xff);
  45. pcmpos= (pcmpos<<8)|(page[7]&0xff);
  46. pcmpos= (pcmpos<<8)|(page[6]&0xff);
  47. return(pcmpos);
  48. }
  49. int ogg_page_serialno(ogg_page *og){
  50. return(og->header[14] |
  51. (og->header[15]<<8) |
  52. (og->header[16]<<16) |
  53. (og->header[17]<<24));
  54. }
  55. int ogg_page_pageno(ogg_page *og){
  56. return(og->header[18] |
  57. (og->header[19]<<8) |
  58. (og->header[20]<<16) |
  59. (og->header[21]<<24));
  60. }
  61. /* helper to initialize lookup for direct-table CRC */
  62. static unsigned vorbis_size32_t crc_lookup[256];
  63. static int crc_ready=0;
  64. static unsigned vorbis_size32_t _ogg_crc_entry(unsigned long index){
  65. int i;
  66. unsigned long r;
  67. r = index << 24;
  68. for (i=0; i<8; i++)
  69. if (r & 0x80000000UL)
  70. r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
  71. polynomial, although we use an
  72. unreflected alg and an init/final
  73. of 0, not 0xffffffff */
  74. else
  75. r<<=1;
  76. return (r & 0xffffffffUL);
  77. }
  78. /* mind this in threaded code; sync_init and stream_init call it.
  79. It's thread safe only after the first time it returns */
  80. static void _ogg_crc_init(void){
  81. if(!crc_ready){
  82. /* initialize the crc_lookup table */
  83. int i;
  84. for (i=0;i<256;i++)
  85. crc_lookup[i]=_ogg_crc_entry((unsigned long)i);
  86. crc_ready=0;
  87. }
  88. }
  89. /* init the encode/decode logical stream state */
  90. int ogg_stream_init(ogg_stream_state *os,int serialno){
  91. if(os){
  92. memset(os,0,sizeof(ogg_stream_state));
  93. os->body_storage=16*1024;
  94. os->body_data=malloc(os->body_storage*sizeof(char));
  95. os->lacing_storage=1024;
  96. os->lacing_vals=malloc(os->lacing_storage*sizeof(int));
  97. os->pcm_vals=malloc(os->lacing_storage*sizeof(int64_t));
  98. /* initialize the crc_lookup table if not done */
  99. _ogg_crc_init();
  100. os->serialno=serialno;
  101. return(0);
  102. }
  103. return(-1);
  104. }
  105. /* _clear does not free os, only the non-flat storage within */
  106. int ogg_stream_clear(ogg_stream_state *os){
  107. if(os){
  108. if(os->body_data)free(os->body_data);
  109. if(os->lacing_vals)free(os->lacing_vals);
  110. if(os->pcm_vals)free(os->pcm_vals);
  111. memset(os,0,sizeof(ogg_stream_state));
  112. }
  113. return(0);
  114. }
  115. int ogg_stream_destroy(ogg_stream_state *os){
  116. if(os){
  117. ogg_stream_clear(os);
  118. free(os);
  119. }
  120. return(0);
  121. }
  122. /* Helpers for ogg_stream_encode; this keeps the structure and
  123. what's happening fairly clear */
  124. static void _os_body_expand(ogg_stream_state *os,int needed){
  125. if(os->body_storage<=os->body_fill+needed){
  126. os->body_storage+=(needed+1024);
  127. os->body_data=realloc(os->body_data,os->body_storage);
  128. }
  129. }
  130. static void _os_lacing_expand(ogg_stream_state *os,int needed){
  131. if(os->lacing_storage<=os->lacing_fill+needed){
  132. os->lacing_storage+=(needed+32);
  133. os->lacing_vals=realloc(os->lacing_vals,os->lacing_storage*sizeof(int));
  134. os->pcm_vals=realloc(os->pcm_vals,os->lacing_storage*sizeof(int64_t));
  135. }
  136. }
  137. /* checksum the page */
  138. /* Direct table CRC; note that this will be faster in the future if we
  139. perform the checksum silmultaneously with other copies */
  140. static void _os_checksum(ogg_page *og){
  141. unsigned vorbis_size32_t crc_reg=0;
  142. int i;
  143. for(i=0;i<og->header_len;i++)
  144. crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
  145. for(i=0;i<og->body_len;i++)
  146. crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
  147. og->header[22]=crc_reg&0xff;
  148. og->header[23]=(crc_reg>>8)&0xff;
  149. og->header[24]=(crc_reg>>16)&0xff;
  150. og->header[25]=(crc_reg>>24)&0xff;
  151. }
  152. /* submit data to the internal buffer of the framing engine */
  153. int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
  154. int lacing_vals=op->bytes/255+1,i;
  155. if(os->body_returned){
  156. /* advance packet data according to the body_returned pointer. We
  157. had to keep it around to return a pointer into the buffer last
  158. call */
  159. os->body_fill-=os->body_returned;
  160. if(os->body_fill)
  161. memmove(os->body_data,os->body_data+os->body_returned,
  162. os->body_fill*sizeof(char));
  163. os->body_returned=0;
  164. }
  165. /* make sure we have the buffer storage */
  166. _os_body_expand(os,op->bytes);
  167. _os_lacing_expand(os,lacing_vals);
  168. /* Copy in the submitted packet. Yes, the copy is a waste; this is
  169. the liability of overly clean abstraction for the time being. It
  170. will actually be fairly easy to eliminate the extra copy in the
  171. future */
  172. memcpy(os->body_data+os->body_fill,op->packet,op->bytes);
  173. os->body_fill+=op->bytes;
  174. /* Store lacing vals for this packet */
  175. for(i=0;i<lacing_vals-1;i++){
  176. os->lacing_vals[os->lacing_fill+i]=255;
  177. os->pcm_vals[os->lacing_fill+i]=os->pcmpos;
  178. }
  179. os->lacing_vals[os->lacing_fill+i]=(op->bytes)%255;
  180. os->pcmpos=os->pcm_vals[os->lacing_fill+i]=op->frameno;
  181. /* flag the first segment as the beginning of the packet */
  182. os->lacing_vals[os->lacing_fill]|= 0x100;
  183. os->lacing_fill+=lacing_vals;
  184. /* for the sake of completeness */
  185. os->packetno++;
  186. if(op->e_o_s)os->e_o_s=1;
  187. return(0);
  188. }
  189. /* This will flush remaining packets into a page (returning nonzero),
  190. even if there is not enough data to trigger a flush normally
  191. (undersized page). If there are no packets or partial packets to
  192. flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
  193. try to flush a normal sized page like ogg_stream_pageout; a call to
  194. ogg_stream_flush does not gurantee that all packets have flushed.
  195. Only a return value of 0 from ogg_stream_flush indicates all packet
  196. data is flushed into pages.
  197. ogg_stream_page will flush the last page in a stream even if it's
  198. undersized; you almost certainly want to use ogg_stream_pageout
  199. (and *not* ogg_stream_flush) unless you need to flush an undersized
  200. page in the middle of a stream for some reason. */
  201. int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
  202. int i;
  203. int vals=0;
  204. int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
  205. int bytes=0;
  206. long acc=0;
  207. int64_t pcm_pos=os->pcm_vals[0];
  208. if(maxvals==0)return(0);
  209. /* construct a page */
  210. /* decide how many segments to include */
  211. /* If this is the initial header case, the first page must only include
  212. the initial header packet */
  213. if(os->b_o_s==0){ /* 'initial header page' case */
  214. pcm_pos=0;
  215. for(vals=0;vals<maxvals;vals++){
  216. if((os->lacing_vals[vals]&0x0ff)<255){
  217. vals++;
  218. break;
  219. }
  220. }
  221. }else{
  222. for(vals=0;vals<maxvals;vals++){
  223. if(acc>4096)break;
  224. acc+=os->lacing_vals[vals]&0x0ff;
  225. pcm_pos=os->pcm_vals[vals];
  226. }
  227. }
  228. /* construct the header in temp storage */
  229. memcpy(os->header,"OggS",4);
  230. /* stream structure version */
  231. os->header[4]=0x00;
  232. /* continued packet flag? */
  233. os->header[5]=0x00;
  234. if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
  235. /* first page flag? */
  236. if(os->b_o_s==0)os->header[5]|=0x02;
  237. /* last page flag? */
  238. if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
  239. os->b_o_s=1;
  240. /* 64 bits of PCM position */
  241. for(i=6;i<14;i++){
  242. os->header[i]=(pcm_pos&0xff);
  243. pcm_pos>>=8;
  244. }
  245. /* 32 bits of stream serial number */
  246. {
  247. long serialno=os->serialno;
  248. for(i=14;i<18;i++){
  249. os->header[i]=(serialno&0xff);
  250. serialno>>=8;
  251. }
  252. }
  253. /* 32 bits of page counter (we have both counter and page header
  254. because this val can roll over) */
  255. if(os->pageno==-1)os->pageno=0; /* because someone called
  256. stream_reset; this would be a
  257. strange thing to do in an
  258. encode stream, but it has
  259. plausible uses */
  260. {
  261. long pageno=os->pageno++;
  262. for(i=18;i<22;i++){
  263. os->header[i]=(pageno&0xff);
  264. pageno>>=8;
  265. }
  266. }
  267. /* zero for computation; filled in later */
  268. os->header[22]=0;
  269. os->header[23]=0;
  270. os->header[24]=0;
  271. os->header[25]=0;
  272. /* segment table */
  273. os->header[26]=vals&0xff;
  274. for(i=0;i<vals;i++)
  275. bytes+=os->header[i+27]=(os->lacing_vals[i]&0xff);
  276. /* set pointers in the ogg_page struct */
  277. og->header=os->header;
  278. og->header_len=os->header_fill=vals+27;
  279. og->body=os->body_data+os->body_returned;
  280. og->body_len=bytes;
  281. /* advance the lacing data and set the body_returned pointer */
  282. os->lacing_fill-=vals;
  283. memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(int));
  284. memmove(os->pcm_vals,os->pcm_vals+vals,os->lacing_fill*sizeof(int64_t));
  285. os->body_returned+=bytes;
  286. /* calculate the checksum */
  287. _os_checksum(og);
  288. /* done */
  289. return(1);
  290. }
  291. /* This constructs pages from buffered packet segments. The pointers
  292. returned are to static buffers; do not free. The returned buffers are
  293. good only until the next call (using the same ogg_stream_state) */
  294. int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
  295. if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
  296. os->body_fill-os->body_returned > 4096 ||/* 'page nominal size' case */
  297. os->lacing_fill>=255 || /* 'segment table full' case */
  298. (os->lacing_fill&&!os->b_o_s)){ /* 'initial header page' case */
  299. return(ogg_stream_flush(os,og));
  300. }
  301. /* not enough data to construct a page and not end of stream */
  302. return(0);
  303. }
  304. int ogg_stream_eof(ogg_stream_state *os){
  305. return os->e_o_s;
  306. }
  307. /* DECODING PRIMITIVES: packet streaming layer **********************/
  308. /* This has two layers to place more of the multi-serialno and paging
  309. control in the application's hands. First, we expose a data buffer
  310. using ogg_sync_buffer(). The app either copies into the
  311. buffer, or passes it directly to read(), etc. We then call
  312. ogg_sync_wrote() to tell how many bytes we just added.
  313. Pages are returned (pointers into the buffer in ogg_sync_state)
  314. by ogg_sync_pageout(). The page is then submitted to
  315. ogg_stream_pagein() along with the appropriate
  316. ogg_stream_state* (ie, matching serialno). We then get raw
  317. packets out calling ogg_stream_packetout() with a
  318. ogg_stream_state. See the 'frame-prog.txt' docs for details and
  319. example code. */
  320. /* initialize the struct to a known state */
  321. int ogg_sync_init(ogg_sync_state *oy){
  322. if(oy){
  323. memset(oy,0,sizeof(ogg_sync_state));
  324. _ogg_crc_init();
  325. }
  326. return(0);
  327. }
  328. /* clear non-flat storage within */
  329. int ogg_sync_clear(ogg_sync_state *oy){
  330. if(oy){
  331. if(oy->data)free(oy->data);
  332. ogg_sync_init(oy);
  333. }
  334. return(0);
  335. }
  336. char *ogg_sync_buffer(ogg_sync_state *oy, long size){
  337. /* first, clear out any space that has been previously returned */
  338. if(oy->returned){
  339. oy->fill-=oy->returned;
  340. if(oy->fill>0)
  341. memmove(oy->data,oy->data+oy->returned,
  342. (oy->fill)*sizeof(char));
  343. oy->returned=0;
  344. }
  345. if(size>oy->storage-oy->fill){
  346. /* We need to extend the internal buffer */
  347. long newsize=size+oy->fill+4096; /* an extra page to be nice */
  348. if(oy->data)
  349. oy->data=realloc(oy->data,newsize);
  350. else
  351. oy->data=malloc(newsize);
  352. oy->storage=newsize;
  353. }
  354. /* expose a segment at least as large as requested at the fill mark */
  355. return((char *)oy->data+oy->fill);
  356. }
  357. int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
  358. if(oy->fill+bytes>oy->storage)return(-1);
  359. oy->fill+=bytes;
  360. return(0);
  361. }
  362. /* sync the stream. This is meant to be useful for finding page
  363. boundaries.
  364. return values for this:
  365. -n) skipped n bytes
  366. 0) page not ready; more data (no bytes skipped)
  367. n) page synced at current location; page length n bytes
  368. */
  369. long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
  370. unsigned char *page=oy->data+oy->returned;
  371. unsigned char *next;
  372. long bytes=oy->fill-oy->returned;
  373. if(oy->headerbytes==0){
  374. int headerbytes,i;
  375. if(bytes<27)return(0); /* not enough for a header */
  376. /* verify capture pattern */
  377. if(memcmp(page,"OggS",4))goto sync_fail;
  378. headerbytes=page[26]+27;
  379. if(bytes<headerbytes)return(0); /* not enough for header + seg table */
  380. /* count up body length in the segment table */
  381. for(i=0;i<page[26];i++)
  382. oy->bodybytes+=page[27+i];
  383. oy->headerbytes=headerbytes;
  384. }
  385. if(oy->bodybytes+oy->headerbytes>bytes)return(0);
  386. /* The whole test page is buffered. Verify the checksum */
  387. {
  388. /* Grab the checksum bytes, set the header field to zero */
  389. char chksum[4];
  390. ogg_page log;
  391. memcpy(chksum,page+22,4);
  392. memset(page+22,0,4);
  393. /* set up a temp page struct and recompute the checksum */
  394. log.header=page;
  395. log.header_len=oy->headerbytes;
  396. log.body=page+oy->headerbytes;
  397. log.body_len=oy->bodybytes;
  398. _os_checksum(&log);
  399. /* Compare */
  400. if(memcmp(chksum,page+22,4)){
  401. /* D'oh. Mismatch! Corrupt page (or miscapture and not a page
  402. at all) */
  403. /* replace the computed checksum with the one actually read in */
  404. memcpy(page+22,chksum,4);
  405. /* Bad checksum. Lose sync */
  406. goto sync_fail;
  407. }
  408. }
  409. /* yes, have a whole page all ready to go */
  410. {
  411. unsigned char *page=oy->data+oy->returned;
  412. long bytes;
  413. if(og){
  414. og->header=page;
  415. og->header_len=oy->headerbytes;
  416. og->body=page+oy->headerbytes;
  417. og->body_len=oy->bodybytes;
  418. }
  419. oy->unsynced=0;
  420. oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
  421. oy->headerbytes=0;
  422. oy->bodybytes=0;
  423. return(bytes);
  424. }
  425. sync_fail:
  426. oy->headerbytes=0;
  427. oy->bodybytes=0;
  428. /* search for possible capture */
  429. next=memchr(page+1,'O',bytes-1);
  430. if(!next)
  431. next=oy->data+oy->fill;
  432. oy->returned=next-oy->data;
  433. return(-(next-page));
  434. }
  435. /* sync the stream and get a page. Keep trying until we find a page.
  436. Supress 'sync errors' after reporting the first.
  437. return values:
  438. -1) recapture (hole in data)
  439. 0) need more data
  440. 1) page returned
  441. Returns pointers into buffered data; invalidated by next call to
  442. _stream, _clear, _init, or _buffer */
  443. int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
  444. /* all we need to do is verify a page at the head of the stream
  445. buffer. If it doesn't verify, we look for the next potential
  446. frame */
  447. while(1){
  448. long ret=ogg_sync_pageseek(oy,og);
  449. if(ret>0){
  450. /* have a page */
  451. return(1);
  452. }
  453. if(ret==0){
  454. /* need more data */
  455. return(0);
  456. }
  457. /* head did not start a synced page... skipped some bytes */
  458. if(!oy->unsynced){
  459. oy->unsynced=1;
  460. return(-1);
  461. }
  462. /* loop. keep looking */
  463. }
  464. }
  465. /* add the incoming page to the stream state; we decompose the page
  466. into packet segments here as well. */
  467. int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
  468. unsigned char *header=og->header;
  469. unsigned char *body=og->body;
  470. long bodysize=og->body_len;
  471. int segptr=0;
  472. int version=ogg_page_version(og);
  473. int continued=ogg_page_continued(og);
  474. int bos=ogg_page_bos(og);
  475. int eos=ogg_page_eos(og);
  476. int64_t pcmpos=ogg_page_frameno(og);
  477. int serialno=ogg_page_serialno(og);
  478. int pageno=ogg_page_pageno(og);
  479. int segments=header[26];
  480. /* clean up 'returned data' */
  481. {
  482. long lr=os->lacing_returned;
  483. long br=os->body_returned;
  484. /* body data */
  485. if(br){
  486. os->body_fill-=br;
  487. if(os->body_fill)
  488. memmove(os->body_data,os->body_data+br,os->body_fill);
  489. os->body_returned=0;
  490. }
  491. if(lr){
  492. /* segment table */
  493. if(os->lacing_fill-lr){
  494. memmove(os->lacing_vals,os->lacing_vals+lr,
  495. (os->lacing_fill-lr)*sizeof(int));
  496. memmove(os->pcm_vals,os->pcm_vals+lr,
  497. (os->lacing_fill-lr)*sizeof(int64_t));
  498. }
  499. os->lacing_fill-=lr;
  500. os->lacing_packet-=lr;
  501. os->lacing_returned=0;
  502. }
  503. }
  504. /* check the serial number */
  505. if(serialno!=os->serialno)return(-1);
  506. if(version>0)return(-1);
  507. _os_lacing_expand(os,segments+1);
  508. /* are we in sequence? */
  509. if(pageno!=os->pageno){
  510. int i;
  511. /* unroll previous partial packet (if any) */
  512. for(i=os->lacing_packet;i<os->lacing_fill;i++)
  513. os->body_fill-=os->lacing_vals[i]&0xff;
  514. os->lacing_fill=os->lacing_packet;
  515. /* make a note of dropped data in segment table */
  516. if(os->pageno!=-1){
  517. os->lacing_vals[os->lacing_fill++]=0x400;
  518. os->lacing_packet++;
  519. }
  520. /* are we a 'continued packet' page? If so, we'll need to skip
  521. some segments */
  522. if(continued){
  523. bos=0;
  524. for(;segptr<segments;segptr++){
  525. int val=header[27+segptr];
  526. body+=val;
  527. bodysize-=val;
  528. if(val<255){
  529. segptr++;
  530. break;
  531. }
  532. }
  533. }
  534. }
  535. if(bodysize){
  536. _os_body_expand(os,bodysize);
  537. memcpy(os->body_data+os->body_fill,body,bodysize);
  538. os->body_fill+=bodysize;
  539. }
  540. {
  541. int saved=-1;
  542. while(segptr<segments){
  543. int val=header[27+segptr];
  544. os->lacing_vals[os->lacing_fill]=val;
  545. os->pcm_vals[os->lacing_fill]=-1;
  546. if(bos){
  547. os->lacing_vals[os->lacing_fill]|=0x100;
  548. bos=0;
  549. }
  550. if(val<255)saved=os->lacing_fill;
  551. os->lacing_fill++;
  552. segptr++;
  553. if(val<255)os->lacing_packet=os->lacing_fill;
  554. }
  555. /* set the pcmpos on the last pcmval of the last full packet */
  556. if(saved!=-1){
  557. os->pcm_vals[saved]=pcmpos;
  558. }
  559. }
  560. if(eos){
  561. os->e_o_s=1;
  562. if(os->lacing_fill>0)
  563. os->lacing_vals[os->lacing_fill-1]|=0x200;
  564. }
  565. os->pageno=pageno+1;
  566. return(0);
  567. }
  568. /* clear things to an initial state. Good to call, eg, before seeking */
  569. int ogg_sync_reset(ogg_sync_state *oy){
  570. oy->fill=0;
  571. oy->returned=0;
  572. oy->unsynced=0;
  573. oy->headerbytes=0;
  574. oy->bodybytes=0;
  575. return(0);
  576. }
  577. int ogg_stream_reset(ogg_stream_state *os){
  578. os->body_fill=0;
  579. os->body_returned=0;
  580. os->lacing_fill=0;
  581. os->lacing_packet=0;
  582. os->lacing_returned=0;
  583. os->header_fill=0;
  584. os->e_o_s=0;
  585. os->b_o_s=0;
  586. os->pageno=-1;
  587. os->packetno=0;
  588. os->pcmpos=0;
  589. return(0);
  590. }
  591. int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
  592. /* The last part of decode. We have the stream broken into packet
  593. segments. Now we need to group them into packets (or return the
  594. out of sync markers) */
  595. int ptr=os->lacing_returned;
  596. if(os->lacing_packet<=ptr)return(0);
  597. if(os->lacing_vals[ptr]&0x400){
  598. /* We lost sync here; let the app know */
  599. os->lacing_returned++;
  600. /* we need to tell the codec there's a gap; it might need to
  601. handle previous packet dependencies. */
  602. os->packetno++;
  603. return(-1);
  604. }
  605. /* Gather the whole packet. We'll have no holes or a partial packet */
  606. {
  607. int size=os->lacing_vals[ptr]&0xff;
  608. int bytes=0;
  609. op->packet=os->body_data+os->body_returned;
  610. op->e_o_s=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
  611. op->b_o_s=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
  612. bytes+=size;
  613. while(size==255){
  614. int val=os->lacing_vals[++ptr];
  615. size=val&0xff;
  616. if(val&0x200)op->e_o_s=0x200;
  617. bytes+=size;
  618. }
  619. op->packetno=os->packetno;
  620. op->frameno=os->pcm_vals[ptr];
  621. op->bytes=bytes;
  622. os->body_returned+=bytes;
  623. os->lacing_returned=ptr+1;
  624. }
  625. os->packetno++;
  626. return(1);
  627. }
  628. #ifdef _V_SELFTEST
  629. #include <stdio.h>
  630. ogg_stream_state os_en, os_de;
  631. ogg_sync_state oy;
  632. void checkpacket(ogg_packet *op,int len, int no, int pos){
  633. long j;
  634. static int sequence=0;
  635. static int lastno=0;
  636. if(op->bytes!=len){
  637. fprintf(stderr,"incorrect packet length!\n");
  638. exit(1);
  639. }
  640. if(op->frameno!=pos){
  641. fprintf(stderr,"incorrect packet position!\n");
  642. exit(1);
  643. }
  644. /* packet number just follows sequence/gap; adjust the input number
  645. for that */
  646. if(no==0){
  647. sequence=0;
  648. }else{
  649. sequence++;
  650. if(no>lastno+1)
  651. sequence++;
  652. }
  653. lastno=no;
  654. if(op->packetno!=sequence){
  655. fprintf(stderr,"incorrect packet sequence %ld != %d\n",
  656. (long)(op->packetno),sequence);
  657. exit(1);
  658. }
  659. /* Test data */
  660. for(j=0;j<op->bytes;j++)
  661. if(op->packet[j]!=((j+no)&0xff)){
  662. fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
  663. j,op->packet[j],(j+no)&0xff);
  664. exit(1);
  665. }
  666. }
  667. void check_page(unsigned char *data,const int *header,ogg_page *og){
  668. long j;
  669. /* Test data */
  670. for(j=0;j<og->body_len;j++)
  671. if(og->body[j]!=data[j]){
  672. fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
  673. j,data[j],og->body[j]);
  674. exit(1);
  675. }
  676. /* Test header */
  677. for(j=0;j<og->header_len;j++){
  678. if(og->header[j]!=header[j]){
  679. fprintf(stderr,"header content mismatch at pos %ld:\n",j);
  680. for(j=0;j<header[26]+27;j++)
  681. fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
  682. fprintf(stderr,"\n");
  683. exit(1);
  684. }
  685. }
  686. if(og->header_len!=header[26]+27){
  687. fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
  688. og->header_len,header[26]+27);
  689. exit(1);
  690. }
  691. }
  692. void print_header(ogg_page *og){
  693. int j;
  694. fprintf(stderr,"\nHEADER:\n");
  695. fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n",
  696. og->header[0],og->header[1],og->header[2],og->header[3],
  697. (int)og->header[4],(int)og->header[5]);
  698. fprintf(stderr," pcmpos: %d serialno: %d pageno: %d\n",
  699. (og->header[9]<<24)|(og->header[8]<<16)|
  700. (og->header[7]<<8)|og->header[6],
  701. (og->header[17]<<24)|(og->header[16]<<16)|
  702. (og->header[15]<<8)|og->header[14],
  703. (og->header[21]<<24)|(og->header[20]<<16)|
  704. (og->header[19]<<8)|og->header[18]);
  705. fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (",
  706. (int)og->header[22],(int)og->header[23],
  707. (int)og->header[24],(int)og->header[25],
  708. (int)og->header[26]);
  709. for(j=27;j<og->header_len;j++)
  710. fprintf(stderr,"%d ",(int)og->header[j]);
  711. fprintf(stderr,")\n\n");
  712. }
  713. void copy_page(ogg_page *og){
  714. unsigned char *temp=malloc(og->header_len);
  715. memcpy(temp,og->header,og->header_len);
  716. og->header=temp;
  717. temp=malloc(og->body_len);
  718. memcpy(temp,og->body,og->body_len);
  719. og->body=temp;
  720. }
  721. void error(void){
  722. fprintf(stderr,"error!\n");
  723. exit(1);
  724. }
  725. /* 17 only */
  726. const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
  727. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  728. 0x01,0x02,0x03,0x04,0,0,0,0,
  729. 0x15,0xed,0xec,0x91,
  730. 1,
  731. 17};
  732. /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
  733. const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
  734. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  735. 0x01,0x02,0x03,0x04,0,0,0,0,
  736. 0x59,0x10,0x6c,0x2c,
  737. 1,
  738. 17};
  739. const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
  740. 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
  741. 0x01,0x02,0x03,0x04,1,0,0,0,
  742. 0x89,0x33,0x85,0xce,
  743. 13,
  744. 254,255,0,255,1,255,245,255,255,0,
  745. 255,255,90};
  746. /* nil packets; beginning,middle,end */
  747. const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
  748. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  749. 0x01,0x02,0x03,0x04,0,0,0,0,
  750. 0xff,0x7b,0x23,0x17,
  751. 1,
  752. 0};
  753. const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
  754. 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
  755. 0x01,0x02,0x03,0x04,1,0,0,0,
  756. 0x5c,0x3f,0x66,0xcb,
  757. 17,
  758. 17,254,255,0,0,255,1,0,255,245,255,255,0,
  759. 255,255,90,0};
  760. /* large initial packet */
  761. const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
  762. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  763. 0x01,0x02,0x03,0x04,0,0,0,0,
  764. 0x01,0x27,0x31,0xaa,
  765. 18,
  766. 255,255,255,255,255,255,255,255,
  767. 255,255,255,255,255,255,255,255,255,10};
  768. const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
  769. 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
  770. 0x01,0x02,0x03,0x04,1,0,0,0,
  771. 0x7f,0x4e,0x8a,0xd2,
  772. 4,
  773. 255,4,255,0};
  774. /* continuing packet test */
  775. const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
  776. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  777. 0x01,0x02,0x03,0x04,0,0,0,0,
  778. 0xff,0x7b,0x23,0x17,
  779. 1,
  780. 0};
  781. const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
  782. 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  783. 0x01,0x02,0x03,0x04,1,0,0,0,
  784. 0x34,0x24,0xd5,0x29,
  785. 17,
  786. 255,255,255,255,255,255,255,255,
  787. 255,255,255,255,255,255,255,255,255};
  788. const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
  789. 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
  790. 0x01,0x02,0x03,0x04,2,0,0,0,
  791. 0xc8,0xc3,0xcb,0xed,
  792. 5,
  793. 10,255,4,255,0};
  794. /* page with the 255 segment limit */
  795. const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
  796. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  797. 0x01,0x02,0x03,0x04,0,0,0,0,
  798. 0xff,0x7b,0x23,0x17,
  799. 1,
  800. 0};
  801. const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
  802. 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
  803. 0x01,0x02,0x03,0x04,1,0,0,0,
  804. 0xed,0x2a,0x2e,0xa7,
  805. 255,
  806. 10,10,10,10,10,10,10,10,
  807. 10,10,10,10,10,10,10,10,
  808. 10,10,10,10,10,10,10,10,
  809. 10,10,10,10,10,10,10,10,
  810. 10,10,10,10,10,10,10,10,
  811. 10,10,10,10,10,10,10,10,
  812. 10,10,10,10,10,10,10,10,
  813. 10,10,10,10,10,10,10,10,
  814. 10,10,10,10,10,10,10,10,
  815. 10,10,10,10,10,10,10,10,
  816. 10,10,10,10,10,10,10,10,
  817. 10,10,10,10,10,10,10,10,
  818. 10,10,10,10,10,10,10,10,
  819. 10,10,10,10,10,10,10,10,
  820. 10,10,10,10,10,10,10,10,
  821. 10,10,10,10,10,10,10,10,
  822. 10,10,10,10,10,10,10,10,
  823. 10,10,10,10,10,10,10,10,
  824. 10,10,10,10,10,10,10,10,
  825. 10,10,10,10,10,10,10,10,
  826. 10,10,10,10,10,10,10,10,
  827. 10,10,10,10,10,10,10,10,
  828. 10,10,10,10,10,10,10,10,
  829. 10,10,10,10,10,10,10,10,
  830. 10,10,10,10,10,10,10,10,
  831. 10,10,10,10,10,10,10,10,
  832. 10,10,10,10,10,10,10,10,
  833. 10,10,10,10,10,10,10,10,
  834. 10,10,10,10,10,10,10,10,
  835. 10,10,10,10,10,10,10,10,
  836. 10,10,10,10,10,10,10,10,
  837. 10,10,10,10,10,10,10};
  838. const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
  839. 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
  840. 0x01,0x02,0x03,0x04,2,0,0,0,
  841. 0x6c,0x3b,0x82,0x3d,
  842. 1,
  843. 50};
  844. /* packet that overspans over an entire page */
  845. const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
  846. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  847. 0x01,0x02,0x03,0x04,0,0,0,0,
  848. 0xff,0x7b,0x23,0x17,
  849. 1,
  850. 0};
  851. const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
  852. 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
  853. 0x01,0x02,0x03,0x04,1,0,0,0,
  854. 0x3c,0xd9,0x4d,0x3f,
  855. 17,
  856. 100,255,255,255,255,255,255,255,255,
  857. 255,255,255,255,255,255,255,255};
  858. const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
  859. 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
  860. 0x01,0x02,0x03,0x04,2,0,0,0,
  861. 0xbd,0xd5,0xb5,0x8b,
  862. 17,
  863. 255,255,255,255,255,255,255,255,
  864. 255,255,255,255,255,255,255,255,255};
  865. const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
  866. 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
  867. 0x01,0x02,0x03,0x04,3,0,0,0,
  868. 0xef,0xdd,0x88,0xde,
  869. 7,
  870. 255,255,75,255,4,255,0};
  871. /* packet that overspans over an entire page */
  872. const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
  873. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  874. 0x01,0x02,0x03,0x04,0,0,0,0,
  875. 0xff,0x7b,0x23,0x17,
  876. 1,
  877. 0};
  878. const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
  879. 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
  880. 0x01,0x02,0x03,0x04,1,0,0,0,
  881. 0x3c,0xd9,0x4d,0x3f,
  882. 17,
  883. 100,255,255,255,255,255,255,255,255,
  884. 255,255,255,255,255,255,255,255};
  885. const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
  886. 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
  887. 0x01,0x02,0x03,0x04,2,0,0,0,
  888. 0xd4,0xe0,0x60,0xe5,
  889. 1,0};
  890. void test_pack(const int *pl, const int **headers){
  891. unsigned char *data=malloc(1024*1024); /* for scripted test cases only */
  892. long inptr=0;
  893. long outptr=0;
  894. long deptr=0;
  895. long depacket=0;
  896. long pcm_pos=7;
  897. int i,j,packets,pageno=0,pageout=0;
  898. int eosflag=0;
  899. int bosflag=0;
  900. ogg_stream_reset(&os_en);
  901. ogg_stream_reset(&os_de);
  902. ogg_sync_reset(&oy);
  903. for(packets=0;;packets++)if(pl[packets]==-1)break;
  904. for(i=0;i<packets;i++){
  905. /* construct a test packet */
  906. ogg_packet op;
  907. int len=pl[i];
  908. op.packet=data+inptr;
  909. op.bytes=len;
  910. op.e_o_s=(pl[i+1]<0?1:0);
  911. op.frameno=pcm_pos;
  912. pcm_pos+=1024;
  913. for(j=0;j<len;j++)data[inptr++]=i+j;
  914. /* submit the test packet */
  915. ogg_stream_packetin(&os_en,&op);
  916. /* retrieve any finished pages */
  917. {
  918. ogg_page og;
  919. while(ogg_stream_pageout(&os_en,&og)){
  920. /* We have a page. Check it carefully */
  921. fprintf(stderr,"%d, ",pageno);
  922. if(headers[pageno]==NULL){
  923. fprintf(stderr,"coded too many pages!\n");
  924. exit(1);
  925. }
  926. check_page(data+outptr,headers[pageno],&og);
  927. outptr+=og.body_len;
  928. pageno++;
  929. /* have a complete page; submit it to sync/decode */
  930. {
  931. ogg_page og_de;
  932. ogg_packet op_de;
  933. char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
  934. memcpy(buf,og.header,og.header_len);
  935. memcpy(buf+og.header_len,og.body,og.body_len);
  936. ogg_sync_wrote(&oy,og.header_len+og.body_len);
  937. while(ogg_sync_pageout(&oy,&og_de)>0){
  938. /* got a page. Happy happy. Verify that it's good. */
  939. check_page(data+deptr,headers[pageout],&og_de);
  940. deptr+=og_de.body_len;
  941. pageout++;
  942. /* submit it to deconstitution */
  943. ogg_stream_pagein(&os_de,&og_de);
  944. /* packets out? */
  945. while(ogg_stream_packetout(&os_de,&op_de)>0){
  946. /* verify the packet! */
  947. /* check data */
  948. if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
  949. fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
  950. depacket);
  951. exit(1);
  952. }
  953. /* check bos flag */
  954. if(bosflag==0 && op_de.b_o_s==0){
  955. fprintf(stderr,"b_o_s flag not set on packet!\n");
  956. exit(1);
  957. }
  958. if(bosflag && op_de.b_o_s){
  959. fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
  960. exit(1);
  961. }
  962. bosflag=1;
  963. depacket+=op_de.bytes;
  964. /* check eos flag */
  965. if(eosflag){
  966. fprintf(stderr,"Multiple decoded packets with eos flag!\n");
  967. exit(1);
  968. }
  969. if(op_de.e_o_s)eosflag=1;
  970. /* check pcmpos flag */
  971. if(op_de.frameno!=-1){
  972. fprintf(stderr," pcm:%ld ",(long)op_de.frameno);
  973. }
  974. }
  975. }
  976. }
  977. }
  978. }
  979. }
  980. free(data);
  981. if(headers[pageno]!=NULL){
  982. fprintf(stderr,"did not write last page!\n");
  983. exit(1);
  984. }
  985. if(headers[pageout]!=NULL){
  986. fprintf(stderr,"did not decode last page!\n");
  987. exit(1);
  988. }
  989. if(inptr!=outptr){
  990. fprintf(stderr,"encoded page data incomplete!\n");
  991. exit(1);
  992. }
  993. if(inptr!=deptr){
  994. fprintf(stderr,"decoded page data incomplete!\n");
  995. exit(1);
  996. }
  997. if(inptr!=depacket){
  998. fprintf(stderr,"decoded packet data incomplete!\n");
  999. exit(1);
  1000. }
  1001. if(!eosflag){
  1002. fprintf(stderr,"Never got a packet with EOS set!\n");
  1003. exit(1);
  1004. }
  1005. fprintf(stderr,"ok.\n");
  1006. }
  1007. int main(void){
  1008. ogg_stream_init(&os_en,0x04030201);
  1009. ogg_stream_init(&os_de,0x04030201);
  1010. ogg_sync_init(&oy);
  1011. /* Exercise each code path in the framing code. Also verify that
  1012. the checksums are working. */
  1013. {
  1014. /* 17 only */
  1015. const int packets[]={17, -1};
  1016. const int *headret[]={head1_0,NULL};
  1017. fprintf(stderr,"testing single page encoding... ");
  1018. test_pack(packets,headret);
  1019. }
  1020. {
  1021. /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
  1022. const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
  1023. const int *headret[]={head1_1,head2_1,NULL};
  1024. fprintf(stderr,"testing basic page encoding... ");
  1025. test_pack(packets,headret);
  1026. }
  1027. {
  1028. /* nil packets; beginning,middle,end */
  1029. const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
  1030. const int *headret[]={head1_2,head2_2,NULL};
  1031. fprintf(stderr,"testing basic nil packets... ");
  1032. test_pack(packets,headret);
  1033. }
  1034. {
  1035. /* large initial packet */
  1036. const int packets[]={4345,259,255,-1};
  1037. const int *headret[]={head1_3,head2_3,NULL};
  1038. fprintf(stderr,"testing initial-packet lacing > 4k... ");
  1039. test_pack(packets,headret);
  1040. }
  1041. {
  1042. /* continuing packet test */
  1043. const int packets[]={0,4345,259,255,-1};
  1044. const int *headret[]={head1_4,head2_4,head3_4,NULL};
  1045. fprintf(stderr,"testing single packet page span... ");
  1046. test_pack(packets,headret);
  1047. }
  1048. /* page with the 255 segment limit */
  1049. {
  1050. const int packets[]={0,10,10,10,10,10,10,10,10,
  1051. 10,10,10,10,10,10,10,10,
  1052. 10,10,10,10,10,10,10,10,
  1053. 10,10,10,10,10,10,10,10,
  1054. 10,10,10,10,10,10,10,10,
  1055. 10,10,10,10,10,10,10,10,
  1056. 10,10,10,10,10,10,10,10,
  1057. 10,10,10,10,10,10,10,10,
  1058. 10,10,10,10,10,10,10,10,
  1059. 10,10,10,10,10,10,10,10,
  1060. 10,10,10,10,10,10,10,10,
  1061. 10,10,10,10,10,10,10,10,
  1062. 10,10,10,10,10,10,10,10,
  1063. 10,10,10,10,10,10,10,10,
  1064. 10,10,10,10,10,10,10,10,
  1065. 10,10,10,10,10,10,10,10,
  1066. 10,10,10,10,10,10,10,10,
  1067. 10,10,10,10,10,10,10,10,
  1068. 10,10,10,10,10,10,10,10,
  1069. 10,10,10,10,10,10,10,10,
  1070. 10,10,10,10,10,10,10,10,
  1071. 10,10,10,10,10,10,10,10,
  1072. 10,10,10,10,10,10,10,10,
  1073. 10,10,10,10,10,10,10,10,
  1074. 10,10,10,10,10,10,10,10,
  1075. 10,10,10,10,10,10,10,10,
  1076. 10,10,10,10,10,10,10,10,
  1077. 10,10,10,10,10,10,10,10,
  1078. 10,10,10,10,10,10,10,10,
  1079. 10,10,10,10,10,10,10,10,
  1080. 10,10,10,10,10,10,10,10,
  1081. 10,10,10,10,10,10,10,50,-1};
  1082. const int *headret[]={head1_5,head2_5,head3_5,NULL};
  1083. fprintf(stderr,"testing max packet segments... ");
  1084. test_pack(packets,headret);
  1085. }
  1086. {
  1087. /* packet that overspans over an entire page */
  1088. const int packets[]={0,100,9000,259,255,-1};
  1089. const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
  1090. fprintf(stderr,"testing very large packets... ");
  1091. test_pack(packets,headret);
  1092. }
  1093. {
  1094. /* term only page. why not? */
  1095. const int packets[]={0,100,4080,-1};
  1096. const int *headret[]={head1_7,head2_7,head3_7,NULL};
  1097. fprintf(stderr,"testing zero data page (1 nil packet)... ");
  1098. test_pack(packets,headret);
  1099. }
  1100. {
  1101. /* build a bunch of pages for testing */
  1102. unsigned char *data=malloc(1024*1024);
  1103. int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1};
  1104. int inptr=0,i,j;
  1105. ogg_page og[5];
  1106. ogg_stream_reset(&os_en);
  1107. for(i=0;pl[i]!=-1;i++){
  1108. ogg_packet op;
  1109. int len=pl[i];
  1110. op.packet=data+inptr;
  1111. op.bytes=len;
  1112. op.e_o_s=(pl[i+1]<0?1:0);
  1113. op.frameno=(i+1)*1000;
  1114. for(j=0;j<len;j++)data[inptr++]=i+j;
  1115. ogg_stream_packetin(&os_en,&op);
  1116. }
  1117. free(data);
  1118. /* retrieve finished pages */
  1119. for(i=0;i<5;i++){
  1120. if(ogg_stream_pageout(&os_en,&og[i])==0){
  1121. fprintf(stderr,"Too few pages output building sync tests!\n");
  1122. exit(1);
  1123. }
  1124. copy_page(&og[i]);
  1125. }
  1126. /* Test lost pages on pagein/packetout: no rollback */
  1127. {
  1128. ogg_page temp;
  1129. ogg_packet test;
  1130. fprintf(stderr,"Testing loss of pages... ");
  1131. ogg_sync_reset(&oy);
  1132. ogg_stream_reset(&os_de);
  1133. for(i=0;i<5;i++){
  1134. memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
  1135. og[i].header_len);
  1136. ogg_sync_wrote(&oy,og[i].header_len);
  1137. memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
  1138. ogg_sync_wrote(&oy,og[i].body_len);
  1139. }
  1140. ogg_sync_pageout(&oy,&temp);
  1141. ogg_stream_pagein(&os_de,&temp);
  1142. ogg_sync_pageout(&oy,&temp);
  1143. ogg_stream_pagein(&os_de,&temp);
  1144. ogg_sync_pageout(&oy,&temp);
  1145. /* skip */
  1146. ogg_sync_pageout(&oy,&temp);
  1147. ogg_stream_pagein(&os_de,&temp);
  1148. /* do we get the expected results/packets? */
  1149. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1150. checkpacket(&test,0,0,0);
  1151. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1152. checkpacket(&test,100,1,-1);
  1153. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1154. checkpacket(&test,4079,2,3000);
  1155. if(ogg_stream_packetout(&os_de,&test)!=-1){
  1156. fprintf(stderr,"Error: loss of page did not return error\n");
  1157. exit(1);
  1158. }
  1159. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1160. checkpacket(&test,76,5,-1);
  1161. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1162. checkpacket(&test,34,6,-1);
  1163. fprintf(stderr,"ok.\n");
  1164. }
  1165. /* Test lost pages on pagein/packetout: rollback with continuation */
  1166. {
  1167. ogg_page temp;
  1168. ogg_packet test;
  1169. fprintf(stderr,"Testing loss of pages (rollback required)... ");
  1170. ogg_sync_reset(&oy);
  1171. ogg_stream_reset(&os_de);
  1172. for(i=0;i<5;i++){
  1173. memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
  1174. og[i].header_len);
  1175. ogg_sync_wrote(&oy,og[i].header_len);
  1176. memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
  1177. ogg_sync_wrote(&oy,og[i].body_len);
  1178. }
  1179. ogg_sync_pageout(&oy,&temp);
  1180. ogg_stream_pagein(&os_de,&temp);
  1181. ogg_sync_pageout(&oy,&temp);
  1182. ogg_stream_pagein(&os_de,&temp);
  1183. ogg_sync_pageout(&oy,&temp);
  1184. ogg_stream_pagein(&os_de,&temp);
  1185. ogg_sync_pageout(&oy,&temp);
  1186. /* skip */
  1187. ogg_sync_pageout(&oy,&temp);
  1188. ogg_stream_pagein(&os_de,&temp);
  1189. /* do we get the expected results/packets? */
  1190. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1191. checkpacket(&test,0,0,0);
  1192. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1193. checkpacket(&test,100,1,-1);
  1194. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1195. checkpacket(&test,4079,2,3000);
  1196. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1197. checkpacket(&test,2956,3,4000);
  1198. if(ogg_stream_packetout(&os_de,&test)!=-1){
  1199. fprintf(stderr,"Error: loss of page did not return error\n");
  1200. exit(1);
  1201. }
  1202. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1203. checkpacket(&test,300,13,14000);
  1204. fprintf(stderr,"ok.\n");
  1205. }
  1206. /* the rest only test sync */
  1207. {
  1208. ogg_page og_de;
  1209. /* Test fractional page inputs: incomplete capture */
  1210. fprintf(stderr,"Testing sync on partial inputs... ");
  1211. ogg_sync_reset(&oy);
  1212. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1213. 3);
  1214. ogg_sync_wrote(&oy,3);
  1215. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1216. /* Test fractional page inputs: incomplete fixed header */
  1217. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
  1218. 20);
  1219. ogg_sync_wrote(&oy,20);
  1220. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1221. /* Test fractional page inputs: incomplete header */
  1222. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
  1223. 5);
  1224. ogg_sync_wrote(&oy,5);
  1225. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1226. /* Test fractional page inputs: incomplete body */
  1227. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
  1228. og[1].header_len-28);
  1229. ogg_sync_wrote(&oy,og[1].header_len-28);
  1230. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1231. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
  1232. ogg_sync_wrote(&oy,1000);
  1233. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1234. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
  1235. og[1].body_len-1000);
  1236. ogg_sync_wrote(&oy,og[1].body_len-1000);
  1237. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1238. fprintf(stderr,"ok.\n");
  1239. }
  1240. /* Test fractional page inputs: page + incomplete capture */
  1241. {
  1242. ogg_page og_de;
  1243. fprintf(stderr,"Testing sync on 1+partial inputs... ");
  1244. ogg_sync_reset(&oy);
  1245. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1246. og[1].header_len);
  1247. ogg_sync_wrote(&oy,og[1].header_len);
  1248. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1249. og[1].body_len);
  1250. ogg_sync_wrote(&oy,og[1].body_len);
  1251. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1252. 20);
  1253. ogg_sync_wrote(&oy,20);
  1254. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1255. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1256. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
  1257. og[1].header_len-20);
  1258. ogg_sync_wrote(&oy,og[1].header_len-20);
  1259. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1260. og[1].body_len);
  1261. ogg_sync_wrote(&oy,og[1].body_len);
  1262. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1263. fprintf(stderr,"ok.\n");
  1264. }
  1265. /* Test recapture: garbage + page */
  1266. {
  1267. ogg_page og_de;
  1268. fprintf(stderr,"Testing search for capture... ");
  1269. ogg_sync_reset(&oy);
  1270. /* 'garbage' */
  1271. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1272. og[1].body_len);
  1273. ogg_sync_wrote(&oy,og[1].body_len);
  1274. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1275. og[1].header_len);
  1276. ogg_sync_wrote(&oy,og[1].header_len);
  1277. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1278. og[1].body_len);
  1279. ogg_sync_wrote(&oy,og[1].body_len);
  1280. memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
  1281. 20);
  1282. ogg_sync_wrote(&oy,20);
  1283. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1284. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1285. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1286. memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
  1287. og[2].header_len-20);
  1288. ogg_sync_wrote(&oy,og[2].header_len-20);
  1289. memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
  1290. og[2].body_len);
  1291. ogg_sync_wrote(&oy,og[2].body_len);
  1292. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1293. fprintf(stderr,"ok.\n");
  1294. }
  1295. /* Test recapture: page + garbage + page */
  1296. {
  1297. ogg_page og_de;
  1298. fprintf(stderr,"Testing recapture... ");
  1299. ogg_sync_reset(&oy);
  1300. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1301. og[1].header_len);
  1302. ogg_sync_wrote(&oy,og[1].header_len);
  1303. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1304. og[1].body_len);
  1305. ogg_sync_wrote(&oy,og[1].body_len);
  1306. memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
  1307. og[2].header_len);
  1308. ogg_sync_wrote(&oy,og[2].header_len);
  1309. memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
  1310. og[2].header_len);
  1311. ogg_sync_wrote(&oy,og[2].header_len);
  1312. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1313. memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
  1314. og[2].body_len-5);
  1315. ogg_sync_wrote(&oy,og[2].body_len-5);
  1316. memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
  1317. og[3].header_len);
  1318. ogg_sync_wrote(&oy,og[3].header_len);
  1319. memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
  1320. og[3].body_len);
  1321. ogg_sync_wrote(&oy,og[3].body_len);
  1322. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1323. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1324. fprintf(stderr,"ok.\n");
  1325. }
  1326. }
  1327. return(0);
  1328. }
  1329. #endif