framing.c 42 KB

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