The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1797 lines
51KB

  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
  5. * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  6. * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
  7. * *
  8. * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
  9. * by the Xiph.Org Foundation http://www.xiph.org/ *
  10. * *
  11. ********************************************************************
  12. function: code raw [Vorbis] packets into framed OggSquish stream and
  13. decode Ogg streams back into raw packets
  14. last mod: $Id: framing.c,v 1.1 2007/06/07 17:48:18 jules_rms Exp $
  15. note: The CRC code is directly derived from public domain code by
  16. Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html
  17. for details.
  18. ********************************************************************/
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "ogg.h"
  22. /* A complete description of Ogg framing exists in docs/framing.html */
  23. int ogg_page_version(ogg_page *og){
  24. return((int)(og->header[4]));
  25. }
  26. int ogg_page_continued(ogg_page *og){
  27. return((int)(og->header[5]&0x01));
  28. }
  29. int ogg_page_bos(ogg_page *og){
  30. return((int)(og->header[5]&0x02));
  31. }
  32. int ogg_page_eos(ogg_page *og){
  33. return((int)(og->header[5]&0x04));
  34. }
  35. ogg_int64_t ogg_page_granulepos(ogg_page *og){
  36. unsigned char *page=og->header;
  37. ogg_int64_t granulepos=page[13]&(0xff);
  38. granulepos= (granulepos<<8)|(page[12]&0xff);
  39. granulepos= (granulepos<<8)|(page[11]&0xff);
  40. granulepos= (granulepos<<8)|(page[10]&0xff);
  41. granulepos= (granulepos<<8)|(page[9]&0xff);
  42. granulepos= (granulepos<<8)|(page[8]&0xff);
  43. granulepos= (granulepos<<8)|(page[7]&0xff);
  44. granulepos= (granulepos<<8)|(page[6]&0xff);
  45. return(granulepos);
  46. }
  47. int ogg_page_serialno(ogg_page *og){
  48. return(og->header[14] |
  49. (og->header[15]<<8) |
  50. (og->header[16]<<16) |
  51. (og->header[17]<<24));
  52. }
  53. long ogg_page_pageno(ogg_page *og){
  54. return(og->header[18] |
  55. (og->header[19]<<8) |
  56. (og->header[20]<<16) |
  57. (og->header[21]<<24));
  58. }
  59. /* returns the number of packets that are completed on this page (if
  60. the leading packet is begun on a previous page, but ends on this
  61. page, it's counted */
  62. /* NOTE:
  63. If a page consists of a packet begun on a previous page, and a new
  64. packet begun (but not completed) on this page, the return will be:
  65. ogg_page_packets(page) ==1,
  66. ogg_page_continued(page) !=0
  67. If a page happens to be a single packet that was begun on a
  68. previous page, and spans to the next page (in the case of a three or
  69. more page packet), the return will be:
  70. ogg_page_packets(page) ==0,
  71. ogg_page_continued(page) !=0
  72. */
  73. int ogg_page_packets(ogg_page *og){
  74. int i,n=og->header[26],count=0;
  75. for(i=0;i<n;i++)
  76. if(og->header[27+i]<255)count++;
  77. return(count);
  78. }
  79. #if 0
  80. /* helper to initialize lookup for direct-table CRC (illustrative; we
  81. use the static init below) */
  82. static ogg_uint32_t _ogg_crc_entry(unsigned long index){
  83. int i;
  84. unsigned long r;
  85. r = index << 24;
  86. for (i=0; i<8; i++)
  87. if (r & 0x80000000UL)
  88. r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
  89. polynomial, although we use an
  90. unreflected alg and an init/final
  91. of 0, not 0xffffffff */
  92. else
  93. r<<=1;
  94. return (r & 0xffffffffUL);
  95. }
  96. #endif
  97. static const ogg_uint32_t crc_lookup[256]={
  98. 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
  99. 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
  100. 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
  101. 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
  102. 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
  103. 0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
  104. 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
  105. 0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
  106. 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
  107. 0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
  108. 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
  109. 0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
  110. 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
  111. 0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
  112. 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
  113. 0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
  114. 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
  115. 0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
  116. 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
  117. 0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
  118. 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
  119. 0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
  120. 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
  121. 0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
  122. 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
  123. 0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
  124. 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
  125. 0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
  126. 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
  127. 0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
  128. 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
  129. 0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
  130. 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
  131. 0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
  132. 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
  133. 0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
  134. 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
  135. 0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
  136. 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
  137. 0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
  138. 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
  139. 0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
  140. 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
  141. 0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
  142. 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
  143. 0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
  144. 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
  145. 0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
  146. 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
  147. 0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
  148. 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
  149. 0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
  150. 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
  151. 0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
  152. 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
  153. 0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
  154. 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
  155. 0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
  156. 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
  157. 0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
  158. 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
  159. 0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
  160. 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
  161. 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4};
  162. /* init the encode/decode logical stream state */
  163. int ogg_stream_init(ogg_stream_state *os,int serialno){
  164. if(os){
  165. memset(os,0,sizeof(*os));
  166. os->body_storage=16*1024;
  167. os->body_data=(unsigned char*) _ogg_malloc(os->body_storage*sizeof(*os->body_data));
  168. os->lacing_storage=1024;
  169. os->lacing_vals=(int*) _ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
  170. os->granule_vals=(ogg_int64_t*) _ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
  171. os->serialno=serialno;
  172. return(0);
  173. }
  174. return(-1);
  175. }
  176. /* _clear does not free os, only the non-flat storage within */
  177. int ogg_stream_clear(ogg_stream_state *os){
  178. if(os){
  179. if(os->body_data)_ogg_free(os->body_data);
  180. if(os->lacing_vals)_ogg_free(os->lacing_vals);
  181. if(os->granule_vals)_ogg_free(os->granule_vals);
  182. memset(os,0,sizeof(*os));
  183. }
  184. return(0);
  185. }
  186. int ogg_stream_destroy(ogg_stream_state *os){
  187. if(os){
  188. ogg_stream_clear(os);
  189. _ogg_free(os);
  190. }
  191. return(0);
  192. }
  193. /* Helpers for ogg_stream_encode; this keeps the structure and
  194. what's happening fairly clear */
  195. static void _os_body_expand(ogg_stream_state *os,int needed){
  196. if(os->body_storage<=os->body_fill+needed){
  197. os->body_storage+=(needed+1024);
  198. os->body_data=(unsigned char*) _ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data));
  199. }
  200. }
  201. static void _os_lacing_expand(ogg_stream_state *os,int needed){
  202. if(os->lacing_storage<=os->lacing_fill+needed){
  203. os->lacing_storage+=(needed+32);
  204. os->lacing_vals=(int*)_ogg_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals));
  205. os->granule_vals=(ogg_int64_t*)_ogg_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals));
  206. }
  207. }
  208. /* checksum the page */
  209. /* Direct table CRC; note that this will be faster in the future if we
  210. perform the checksum silmultaneously with other copies */
  211. void ogg_page_checksum_set(ogg_page *og){
  212. if(og){
  213. ogg_uint32_t crc_reg=0;
  214. int i;
  215. /* safety; needed for API behavior, but not framing code */
  216. og->header[22]=0;
  217. og->header[23]=0;
  218. og->header[24]=0;
  219. og->header[25]=0;
  220. for(i=0;i<og->header_len;i++)
  221. crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
  222. for(i=0;i<og->body_len;i++)
  223. crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
  224. og->header[22]=(unsigned char)(crc_reg&0xff);
  225. og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
  226. og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
  227. og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
  228. }
  229. }
  230. /* submit data to the internal buffer of the framing engine */
  231. int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
  232. int lacing_vals=op->bytes/255+1,i;
  233. if(os->body_returned){
  234. /* advance packet data according to the body_returned pointer. We
  235. had to keep it around to return a pointer into the buffer last
  236. call */
  237. os->body_fill-=os->body_returned;
  238. if(os->body_fill)
  239. memmove(os->body_data,os->body_data+os->body_returned,
  240. os->body_fill);
  241. os->body_returned=0;
  242. }
  243. /* make sure we have the buffer storage */
  244. _os_body_expand(os,op->bytes);
  245. _os_lacing_expand(os,lacing_vals);
  246. /* Copy in the submitted packet. Yes, the copy is a waste; this is
  247. the liability of overly clean abstraction for the time being. It
  248. will actually be fairly easy to eliminate the extra copy in the
  249. future */
  250. memcpy(os->body_data+os->body_fill,op->packet,op->bytes);
  251. os->body_fill+=op->bytes;
  252. /* Store lacing vals for this packet */
  253. for(i=0;i<lacing_vals-1;i++){
  254. os->lacing_vals[os->lacing_fill+i]=255;
  255. os->granule_vals[os->lacing_fill+i]=os->granulepos;
  256. }
  257. os->lacing_vals[os->lacing_fill+i]=(op->bytes)%255;
  258. os->granulepos=os->granule_vals[os->lacing_fill+i]=op->granulepos;
  259. /* flag the first segment as the beginning of the packet */
  260. os->lacing_vals[os->lacing_fill]|= 0x100;
  261. os->lacing_fill+=lacing_vals;
  262. /* for the sake of completeness */
  263. os->packetno++;
  264. if(op->e_o_s)os->e_o_s=1;
  265. return(0);
  266. }
  267. /* This will flush remaining packets into a page (returning nonzero),
  268. even if there is not enough data to trigger a flush normally
  269. (undersized page). If there are no packets or partial packets to
  270. flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
  271. try to flush a normal sized page like ogg_stream_pageout; a call to
  272. ogg_stream_flush does not guarantee that all packets have flushed.
  273. Only a return value of 0 from ogg_stream_flush indicates all packet
  274. data is flushed into pages.
  275. since ogg_stream_flush will flush the last page in a stream even if
  276. it's undersized, you almost certainly want to use ogg_stream_pageout
  277. (and *not* ogg_stream_flush) unless you specifically need to flush
  278. an page regardless of size in the middle of a stream. */
  279. int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
  280. int i;
  281. int vals=0;
  282. int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
  283. int bytes=0;
  284. long acc=0;
  285. ogg_int64_t granule_pos=-1;
  286. if(maxvals==0)return(0);
  287. /* construct a page */
  288. /* decide how many segments to include */
  289. /* If this is the initial header case, the first page must only include
  290. the initial header packet */
  291. if(os->b_o_s==0){ /* 'initial header page' case */
  292. granule_pos=0;
  293. for(vals=0;vals<maxvals;vals++){
  294. if((os->lacing_vals[vals]&0x0ff)<255){
  295. vals++;
  296. break;
  297. }
  298. }
  299. }else{
  300. for(vals=0;vals<maxvals;vals++){
  301. if(acc>4096)break;
  302. acc+=os->lacing_vals[vals]&0x0ff;
  303. if((os->lacing_vals[vals]&0xff)<255)
  304. granule_pos=os->granule_vals[vals];
  305. }
  306. }
  307. /* construct the header in temp storage */
  308. memcpy(os->header,"OggS",4);
  309. /* stream structure version */
  310. os->header[4]=0x00;
  311. /* continued packet flag? */
  312. os->header[5]=0x00;
  313. if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
  314. /* first page flag? */
  315. if(os->b_o_s==0)os->header[5]|=0x02;
  316. /* last page flag? */
  317. if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
  318. os->b_o_s=1;
  319. /* 64 bits of PCM position */
  320. for(i=6;i<14;i++){
  321. os->header[i]=(unsigned char)(granule_pos&0xff);
  322. granule_pos>>=8;
  323. }
  324. /* 32 bits of stream serial number */
  325. {
  326. long serialno=os->serialno;
  327. for(i=14;i<18;i++){
  328. os->header[i]=(unsigned char)(serialno&0xff);
  329. serialno>>=8;
  330. }
  331. }
  332. /* 32 bits of page counter (we have both counter and page header
  333. because this val can roll over) */
  334. if(os->pageno==-1)os->pageno=0; /* because someone called
  335. stream_reset; this would be a
  336. strange thing to do in an
  337. encode stream, but it has
  338. plausible uses */
  339. {
  340. long pageno=os->pageno++;
  341. for(i=18;i<22;i++){
  342. os->header[i]=(unsigned char)(pageno&0xff);
  343. pageno>>=8;
  344. }
  345. }
  346. /* zero for computation; filled in later */
  347. os->header[22]=0;
  348. os->header[23]=0;
  349. os->header[24]=0;
  350. os->header[25]=0;
  351. /* segment table */
  352. os->header[26]=(unsigned char)(vals&0xff);
  353. for(i=0;i<vals;i++)
  354. bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
  355. /* set pointers in the ogg_page struct */
  356. og->header=os->header;
  357. og->header_len=os->header_fill=vals+27;
  358. og->body=os->body_data+os->body_returned;
  359. og->body_len=bytes;
  360. /* advance the lacing data and set the body_returned pointer */
  361. os->lacing_fill-=vals;
  362. memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
  363. memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
  364. os->body_returned+=bytes;
  365. /* calculate the checksum */
  366. ogg_page_checksum_set(og);
  367. /* done */
  368. return(1);
  369. }
  370. /* This constructs pages from buffered packet segments. The pointers
  371. returned are to static buffers; do not free. The returned buffers are
  372. good only until the next call (using the same ogg_stream_state) */
  373. int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
  374. if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
  375. os->body_fill-os->body_returned > 4096 ||/* 'page nominal size' case */
  376. os->lacing_fill>=255 || /* 'segment table full' case */
  377. (os->lacing_fill&&!os->b_o_s)){ /* 'initial header page' case */
  378. return(ogg_stream_flush(os,og));
  379. }
  380. /* not enough data to construct a page and not end of stream */
  381. return(0);
  382. }
  383. int ogg_stream_eos(ogg_stream_state *os){
  384. return os->e_o_s;
  385. }
  386. /* DECODING PRIMITIVES: packet streaming layer **********************/
  387. /* This has two layers to place more of the multi-serialno and paging
  388. control in the application's hands. First, we expose a data buffer
  389. using ogg_sync_buffer(). The app either copies into the
  390. buffer, or passes it directly to read(), etc. We then call
  391. ogg_sync_wrote() to tell how many bytes we just added.
  392. Pages are returned (pointers into the buffer in ogg_sync_state)
  393. by ogg_sync_pageout(). The page is then submitted to
  394. ogg_stream_pagein() along with the appropriate
  395. ogg_stream_state* (ie, matching serialno). We then get raw
  396. packets out calling ogg_stream_packetout() with a
  397. ogg_stream_state. */
  398. /* initialize the struct to a known state */
  399. int ogg_sync_init(ogg_sync_state *oy){
  400. if(oy){
  401. memset(oy,0,sizeof(*oy));
  402. }
  403. return(0);
  404. }
  405. /* clear non-flat storage within */
  406. int ogg_sync_clear(ogg_sync_state *oy){
  407. if(oy){
  408. if(oy->data)_ogg_free(oy->data);
  409. ogg_sync_init(oy);
  410. }
  411. return(0);
  412. }
  413. int ogg_sync_destroy(ogg_sync_state *oy){
  414. if(oy){
  415. ogg_sync_clear(oy);
  416. _ogg_free(oy);
  417. }
  418. return(0);
  419. }
  420. char *ogg_sync_buffer(ogg_sync_state *oy, long size){
  421. /* first, clear out any space that has been previously returned */
  422. if(oy->returned){
  423. oy->fill-=oy->returned;
  424. if(oy->fill>0)
  425. memmove(oy->data,oy->data+oy->returned,oy->fill);
  426. oy->returned=0;
  427. }
  428. if(size>oy->storage-oy->fill){
  429. /* We need to extend the internal buffer */
  430. long newsize=size+oy->fill+4096; /* an extra page to be nice */
  431. if(oy->data)
  432. oy->data=(unsigned char*) _ogg_realloc(oy->data,newsize);
  433. else
  434. oy->data=(unsigned char*) _ogg_malloc(newsize);
  435. oy->storage=newsize;
  436. }
  437. /* expose a segment at least as large as requested at the fill mark */
  438. return((char *)oy->data+oy->fill);
  439. }
  440. int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
  441. if(oy->fill+bytes>oy->storage)return(-1);
  442. oy->fill+=bytes;
  443. return(0);
  444. }
  445. /* sync the stream. This is meant to be useful for finding page
  446. boundaries.
  447. return values for this:
  448. -n) skipped n bytes
  449. 0) page not ready; more data (no bytes skipped)
  450. n) page synced at current location; page length n bytes
  451. */
  452. long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
  453. unsigned char *page=oy->data+oy->returned;
  454. unsigned char *next;
  455. long bytes=oy->fill-oy->returned;
  456. if(oy->headerbytes==0){
  457. int headerbytes,i;
  458. if(bytes<27)return(0); /* not enough for a header */
  459. /* verify capture pattern */
  460. if(memcmp(page,"OggS",4))goto sync_fail;
  461. headerbytes=page[26]+27;
  462. if(bytes<headerbytes)return(0); /* not enough for header + seg table */
  463. /* count up body length in the segment table */
  464. for(i=0;i<page[26];i++)
  465. oy->bodybytes+=page[27+i];
  466. oy->headerbytes=headerbytes;
  467. }
  468. if(oy->bodybytes+oy->headerbytes>bytes)return(0);
  469. /* The whole test page is buffered. Verify the checksum */
  470. {
  471. /* Grab the checksum bytes, set the header field to zero */
  472. char chksum[4];
  473. ogg_page log;
  474. memcpy(chksum,page+22,4);
  475. memset(page+22,0,4);
  476. /* set up a temp page struct and recompute the checksum */
  477. log.header=page;
  478. log.header_len=oy->headerbytes;
  479. log.body=page+oy->headerbytes;
  480. log.body_len=oy->bodybytes;
  481. ogg_page_checksum_set(&log);
  482. /* Compare */
  483. if(memcmp(chksum,page+22,4)){
  484. /* D'oh. Mismatch! Corrupt page (or miscapture and not a page
  485. at all) */
  486. /* replace the computed checksum with the one actually read in */
  487. memcpy(page+22,chksum,4);
  488. /* Bad checksum. Lose sync */
  489. goto sync_fail;
  490. }
  491. }
  492. /* yes, have a whole page all ready to go */
  493. {
  494. unsigned char *page=oy->data+oy->returned;
  495. long bytes;
  496. if(og){
  497. og->header=page;
  498. og->header_len=oy->headerbytes;
  499. og->body=page+oy->headerbytes;
  500. og->body_len=oy->bodybytes;
  501. }
  502. oy->unsynced=0;
  503. oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
  504. oy->headerbytes=0;
  505. oy->bodybytes=0;
  506. return(bytes);
  507. }
  508. sync_fail:
  509. oy->headerbytes=0;
  510. oy->bodybytes=0;
  511. /* search for possible capture */
  512. next=(unsigned char*)memchr(page+1,'O',bytes-1);
  513. if(!next)
  514. next=oy->data+oy->fill;
  515. oy->returned=next-oy->data;
  516. return(-(next-page));
  517. }
  518. /* sync the stream and get a page. Keep trying until we find a page.
  519. Supress 'sync errors' after reporting the first.
  520. return values:
  521. -1) recapture (hole in data)
  522. 0) need more data
  523. 1) page returned
  524. Returns pointers into buffered data; invalidated by next call to
  525. _stream, _clear, _init, or _buffer */
  526. int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
  527. /* all we need to do is verify a page at the head of the stream
  528. buffer. If it doesn't verify, we look for the next potential
  529. frame */
  530. for(;;){
  531. long ret=ogg_sync_pageseek(oy,og);
  532. if(ret>0){
  533. /* have a page */
  534. return(1);
  535. }
  536. if(ret==0){
  537. /* need more data */
  538. return(0);
  539. }
  540. /* head did not start a synced page... skipped some bytes */
  541. if(!oy->unsynced){
  542. oy->unsynced=1;
  543. return(-1);
  544. }
  545. /* loop. keep looking */
  546. }
  547. }
  548. /* add the incoming page to the stream state; we decompose the page
  549. into packet segments here as well. */
  550. int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
  551. unsigned char *header=og->header;
  552. unsigned char *body=og->body;
  553. long bodysize=og->body_len;
  554. int segptr=0;
  555. int version=ogg_page_version(og);
  556. int continued=ogg_page_continued(og);
  557. int bos=ogg_page_bos(og);
  558. int eos=ogg_page_eos(og);
  559. ogg_int64_t granulepos=ogg_page_granulepos(og);
  560. int serialno=ogg_page_serialno(og);
  561. long pageno=ogg_page_pageno(og);
  562. int segments=header[26];
  563. /* clean up 'returned data' */
  564. {
  565. long lr=os->lacing_returned;
  566. long br=os->body_returned;
  567. /* body data */
  568. if(br){
  569. os->body_fill-=br;
  570. if(os->body_fill)
  571. memmove(os->body_data,os->body_data+br,os->body_fill);
  572. os->body_returned=0;
  573. }
  574. if(lr){
  575. /* segment table */
  576. if(os->lacing_fill-lr){
  577. memmove(os->lacing_vals,os->lacing_vals+lr,
  578. (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
  579. memmove(os->granule_vals,os->granule_vals+lr,
  580. (os->lacing_fill-lr)*sizeof(*os->granule_vals));
  581. }
  582. os->lacing_fill-=lr;
  583. os->lacing_packet-=lr;
  584. os->lacing_returned=0;
  585. }
  586. }
  587. /* check the serial number */
  588. if(serialno!=os->serialno)return(-1);
  589. if(version>0)return(-1);
  590. _os_lacing_expand(os,segments+1);
  591. /* are we in sequence? */
  592. if(pageno!=os->pageno){
  593. int i;
  594. /* unroll previous partial packet (if any) */
  595. for(i=os->lacing_packet;i<os->lacing_fill;i++)
  596. os->body_fill-=os->lacing_vals[i]&0xff;
  597. os->lacing_fill=os->lacing_packet;
  598. /* make a note of dropped data in segment table */
  599. if(os->pageno!=-1){
  600. os->lacing_vals[os->lacing_fill++]=0x400;
  601. os->lacing_packet++;
  602. }
  603. }
  604. /* are we a 'continued packet' page? If so, we may need to skip
  605. some segments */
  606. if(continued){
  607. if(os->lacing_fill<1 ||
  608. os->lacing_vals[os->lacing_fill-1]==0x400){
  609. bos=0;
  610. for(;segptr<segments;segptr++){
  611. int val=header[27+segptr];
  612. body+=val;
  613. bodysize-=val;
  614. if(val<255){
  615. segptr++;
  616. break;
  617. }
  618. }
  619. }
  620. }
  621. if(bodysize){
  622. _os_body_expand(os,bodysize);
  623. memcpy(os->body_data+os->body_fill,body,bodysize);
  624. os->body_fill+=bodysize;
  625. }
  626. {
  627. int saved=-1;
  628. while(segptr<segments){
  629. int val=header[27+segptr];
  630. os->lacing_vals[os->lacing_fill]=val;
  631. os->granule_vals[os->lacing_fill]=-1;
  632. if(bos){
  633. os->lacing_vals[os->lacing_fill]|=0x100;
  634. bos=0;
  635. }
  636. if(val<255)saved=os->lacing_fill;
  637. os->lacing_fill++;
  638. segptr++;
  639. if(val<255)os->lacing_packet=os->lacing_fill;
  640. }
  641. /* set the granulepos on the last granuleval of the last full packet */
  642. if(saved!=-1){
  643. os->granule_vals[saved]=granulepos;
  644. }
  645. }
  646. if(eos){
  647. os->e_o_s=1;
  648. if(os->lacing_fill>0)
  649. os->lacing_vals[os->lacing_fill-1]|=0x200;
  650. }
  651. os->pageno=pageno+1;
  652. return(0);
  653. }
  654. /* clear things to an initial state. Good to call, eg, before seeking */
  655. int ogg_sync_reset(ogg_sync_state *oy){
  656. oy->fill=0;
  657. oy->returned=0;
  658. oy->unsynced=0;
  659. oy->headerbytes=0;
  660. oy->bodybytes=0;
  661. return(0);
  662. }
  663. int ogg_stream_reset(ogg_stream_state *os){
  664. os->body_fill=0;
  665. os->body_returned=0;
  666. os->lacing_fill=0;
  667. os->lacing_packet=0;
  668. os->lacing_returned=0;
  669. os->header_fill=0;
  670. os->e_o_s=0;
  671. os->b_o_s=0;
  672. os->pageno=-1;
  673. os->packetno=0;
  674. os->granulepos=0;
  675. return(0);
  676. }
  677. int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
  678. ogg_stream_reset(os);
  679. os->serialno=serialno;
  680. return(0);
  681. }
  682. static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
  683. /* The last part of decode. We have the stream broken into packet
  684. segments. Now we need to group them into packets (or return the
  685. out of sync markers) */
  686. int ptr=os->lacing_returned;
  687. if(os->lacing_packet<=ptr)return(0);
  688. if(os->lacing_vals[ptr]&0x400){
  689. /* we need to tell the codec there's a gap; it might need to
  690. handle previous packet dependencies. */
  691. os->lacing_returned++;
  692. os->packetno++;
  693. return(-1);
  694. }
  695. if(!op && !adv)return(1); /* just using peek as an inexpensive way
  696. to ask if there's a whole packet
  697. waiting */
  698. /* Gather the whole packet. We'll have no holes or a partial packet */
  699. {
  700. int size=os->lacing_vals[ptr]&0xff;
  701. int bytes=size;
  702. int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
  703. int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
  704. while(size==255){
  705. int val=os->lacing_vals[++ptr];
  706. size=val&0xff;
  707. if(val&0x200)eos=0x200;
  708. bytes+=size;
  709. }
  710. if(op){
  711. op->e_o_s=eos;
  712. op->b_o_s=bos;
  713. op->packet=os->body_data+os->body_returned;
  714. op->packetno=os->packetno;
  715. op->granulepos=os->granule_vals[ptr];
  716. op->bytes=bytes;
  717. }
  718. if(adv){
  719. os->body_returned+=bytes;
  720. os->lacing_returned=ptr+1;
  721. os->packetno++;
  722. }
  723. }
  724. return(1);
  725. }
  726. int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
  727. return _packetout(os,op,1);
  728. }
  729. int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
  730. return _packetout(os,op,0);
  731. }
  732. void ogg_packet_clear(ogg_packet *op) {
  733. _ogg_free(op->packet);
  734. memset(op, 0, sizeof(*op));
  735. }
  736. #ifdef _V_SELFTEST
  737. #include <stdio.h>
  738. ogg_stream_state os_en, os_de;
  739. ogg_sync_state oy;
  740. void checkpacket(ogg_packet *op,int len, int no, int pos){
  741. long j;
  742. static int sequence=0;
  743. static int lastno=0;
  744. if(op->bytes!=len){
  745. fprintf(stderr,"incorrect packet length!\n");
  746. exit(1);
  747. }
  748. if(op->granulepos!=pos){
  749. fprintf(stderr,"incorrect packet position!\n");
  750. exit(1);
  751. }
  752. /* packet number just follows sequence/gap; adjust the input number
  753. for that */
  754. if(no==0){
  755. sequence=0;
  756. }else{
  757. sequence++;
  758. if(no>lastno+1)
  759. sequence++;
  760. }
  761. lastno=no;
  762. if(op->packetno!=sequence){
  763. fprintf(stderr,"incorrect packet sequence %ld != %d\n",
  764. (long)(op->packetno),sequence);
  765. exit(1);
  766. }
  767. /* Test data */
  768. for(j=0;j<op->bytes;j++)
  769. if(op->packet[j]!=((j+no)&0xff)){
  770. fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
  771. j,op->packet[j],(j+no)&0xff);
  772. exit(1);
  773. }
  774. }
  775. void check_page(unsigned char *data,const int *header,ogg_page *og){
  776. long j;
  777. /* Test data */
  778. for(j=0;j<og->body_len;j++)
  779. if(og->body[j]!=data[j]){
  780. fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
  781. j,data[j],og->body[j]);
  782. exit(1);
  783. }
  784. /* Test header */
  785. for(j=0;j<og->header_len;j++){
  786. if(og->header[j]!=header[j]){
  787. fprintf(stderr,"header content mismatch at pos %ld:\n",j);
  788. for(j=0;j<header[26]+27;j++)
  789. fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
  790. fprintf(stderr,"\n");
  791. exit(1);
  792. }
  793. }
  794. if(og->header_len!=header[26]+27){
  795. fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
  796. og->header_len,header[26]+27);
  797. exit(1);
  798. }
  799. }
  800. void print_header(ogg_page *og){
  801. int j;
  802. fprintf(stderr,"\nHEADER:\n");
  803. fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n",
  804. og->header[0],og->header[1],og->header[2],og->header[3],
  805. (int)og->header[4],(int)og->header[5]);
  806. fprintf(stderr," granulepos: %d serialno: %d pageno: %ld\n",
  807. (og->header[9]<<24)|(og->header[8]<<16)|
  808. (og->header[7]<<8)|og->header[6],
  809. (og->header[17]<<24)|(og->header[16]<<16)|
  810. (og->header[15]<<8)|og->header[14],
  811. ((long)(og->header[21])<<24)|(og->header[20]<<16)|
  812. (og->header[19]<<8)|og->header[18]);
  813. fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (",
  814. (int)og->header[22],(int)og->header[23],
  815. (int)og->header[24],(int)og->header[25],
  816. (int)og->header[26]);
  817. for(j=27;j<og->header_len;j++)
  818. fprintf(stderr,"%d ",(int)og->header[j]);
  819. fprintf(stderr,")\n\n");
  820. }
  821. void copy_page(ogg_page *og){
  822. unsigned char *temp=_ogg_malloc(og->header_len);
  823. memcpy(temp,og->header,og->header_len);
  824. og->header=temp;
  825. temp=_ogg_malloc(og->body_len);
  826. memcpy(temp,og->body,og->body_len);
  827. og->body=temp;
  828. }
  829. void free_page(ogg_page *og){
  830. _ogg_free (og->header);
  831. _ogg_free (og->body);
  832. }
  833. void error(void){
  834. fprintf(stderr,"error!\n");
  835. exit(1);
  836. }
  837. /* 17 only */
  838. const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
  839. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  840. 0x01,0x02,0x03,0x04,0,0,0,0,
  841. 0x15,0xed,0xec,0x91,
  842. 1,
  843. 17};
  844. /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
  845. const int head1_1[] = {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. const int head2_1[] = {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. /* nil packets; beginning,middle,end */
  859. const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
  860. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  861. 0x01,0x02,0x03,0x04,0,0,0,0,
  862. 0xff,0x7b,0x23,0x17,
  863. 1,
  864. 0};
  865. const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
  866. 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
  867. 0x01,0x02,0x03,0x04,1,0,0,0,
  868. 0x5c,0x3f,0x66,0xcb,
  869. 17,
  870. 17,254,255,0,0,255,1,0,255,245,255,255,0,
  871. 255,255,90,0};
  872. /* large initial packet */
  873. const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
  874. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  875. 0x01,0x02,0x03,0x04,0,0,0,0,
  876. 0x01,0x27,0x31,0xaa,
  877. 18,
  878. 255,255,255,255,255,255,255,255,
  879. 255,255,255,255,255,255,255,255,255,10};
  880. const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
  881. 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
  882. 0x01,0x02,0x03,0x04,1,0,0,0,
  883. 0x7f,0x4e,0x8a,0xd2,
  884. 4,
  885. 255,4,255,0};
  886. /* continuing packet test */
  887. const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
  888. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  889. 0x01,0x02,0x03,0x04,0,0,0,0,
  890. 0xff,0x7b,0x23,0x17,
  891. 1,
  892. 0};
  893. const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
  894. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  895. 0x01,0x02,0x03,0x04,1,0,0,0,
  896. 0x54,0x05,0x51,0xc8,
  897. 17,
  898. 255,255,255,255,255,255,255,255,
  899. 255,255,255,255,255,255,255,255,255};
  900. const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
  901. 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
  902. 0x01,0x02,0x03,0x04,2,0,0,0,
  903. 0xc8,0xc3,0xcb,0xed,
  904. 5,
  905. 10,255,4,255,0};
  906. /* page with the 255 segment limit */
  907. const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
  908. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  909. 0x01,0x02,0x03,0x04,0,0,0,0,
  910. 0xff,0x7b,0x23,0x17,
  911. 1,
  912. 0};
  913. const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
  914. 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
  915. 0x01,0x02,0x03,0x04,1,0,0,0,
  916. 0xed,0x2a,0x2e,0xa7,
  917. 255,
  918. 10,10,10,10,10,10,10,10,
  919. 10,10,10,10,10,10,10,10,
  920. 10,10,10,10,10,10,10,10,
  921. 10,10,10,10,10,10,10,10,
  922. 10,10,10,10,10,10,10,10,
  923. 10,10,10,10,10,10,10,10,
  924. 10,10,10,10,10,10,10,10,
  925. 10,10,10,10,10,10,10,10,
  926. 10,10,10,10,10,10,10,10,
  927. 10,10,10,10,10,10,10,10,
  928. 10,10,10,10,10,10,10,10,
  929. 10,10,10,10,10,10,10,10,
  930. 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};
  950. const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
  951. 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
  952. 0x01,0x02,0x03,0x04,2,0,0,0,
  953. 0x6c,0x3b,0x82,0x3d,
  954. 1,
  955. 50};
  956. /* packet that overspans over an entire page */
  957. const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
  958. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  959. 0x01,0x02,0x03,0x04,0,0,0,0,
  960. 0xff,0x7b,0x23,0x17,
  961. 1,
  962. 0};
  963. const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
  964. 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
  965. 0x01,0x02,0x03,0x04,1,0,0,0,
  966. 0x3c,0xd9,0x4d,0x3f,
  967. 17,
  968. 100,255,255,255,255,255,255,255,255,
  969. 255,255,255,255,255,255,255,255};
  970. const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
  971. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  972. 0x01,0x02,0x03,0x04,2,0,0,0,
  973. 0x01,0xd2,0xe5,0xe5,
  974. 17,
  975. 255,255,255,255,255,255,255,255,
  976. 255,255,255,255,255,255,255,255,255};
  977. const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
  978. 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
  979. 0x01,0x02,0x03,0x04,3,0,0,0,
  980. 0xef,0xdd,0x88,0xde,
  981. 7,
  982. 255,255,75,255,4,255,0};
  983. /* packet that overspans over an entire page */
  984. const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
  985. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  986. 0x01,0x02,0x03,0x04,0,0,0,0,
  987. 0xff,0x7b,0x23,0x17,
  988. 1,
  989. 0};
  990. const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
  991. 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
  992. 0x01,0x02,0x03,0x04,1,0,0,0,
  993. 0x3c,0xd9,0x4d,0x3f,
  994. 17,
  995. 100,255,255,255,255,255,255,255,255,
  996. 255,255,255,255,255,255,255,255};
  997. const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
  998. 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
  999. 0x01,0x02,0x03,0x04,2,0,0,0,
  1000. 0xd4,0xe0,0x60,0xe5,
  1001. 1,0};
  1002. void test_pack(const int *pl, const int **headers, int byteskip,
  1003. int pageskip, int packetskip){
  1004. unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
  1005. long inptr=0;
  1006. long outptr=0;
  1007. long deptr=0;
  1008. long depacket=0;
  1009. long granule_pos=7,pageno=0;
  1010. int i,j,packets,pageout=pageskip;
  1011. int eosflag=0;
  1012. int bosflag=0;
  1013. int byteskipcount=0;
  1014. ogg_stream_reset(&os_en);
  1015. ogg_stream_reset(&os_de);
  1016. ogg_sync_reset(&oy);
  1017. for(packets=0;packets<packetskip;packets++)
  1018. depacket+=pl[packets];
  1019. for(packets=0;;packets++)if(pl[packets]==-1)break;
  1020. for(i=0;i<packets;i++){
  1021. /* construct a test packet */
  1022. ogg_packet op;
  1023. int len=pl[i];
  1024. op.packet=data+inptr;
  1025. op.bytes=len;
  1026. op.e_o_s=(pl[i+1]<0?1:0);
  1027. op.granulepos=granule_pos;
  1028. granule_pos+=1024;
  1029. for(j=0;j<len;j++)data[inptr++]=i+j;
  1030. /* submit the test packet */
  1031. ogg_stream_packetin(&os_en,&op);
  1032. /* retrieve any finished pages */
  1033. {
  1034. ogg_page og;
  1035. while(ogg_stream_pageout(&os_en,&og)){
  1036. /* We have a page. Check it carefully */
  1037. fprintf(stderr,"%ld, ",pageno);
  1038. if(headers[pageno]==NULL){
  1039. fprintf(stderr,"coded too many pages!\n");
  1040. exit(1);
  1041. }
  1042. check_page(data+outptr,headers[pageno],&og);
  1043. outptr+=og.body_len;
  1044. pageno++;
  1045. if(pageskip){
  1046. bosflag=1;
  1047. pageskip--;
  1048. deptr+=og.body_len;
  1049. }
  1050. /* have a complete page; submit it to sync/decode */
  1051. {
  1052. ogg_page og_de;
  1053. ogg_packet op_de,op_de2;
  1054. char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
  1055. char *next=buf;
  1056. byteskipcount+=og.header_len;
  1057. if(byteskipcount>byteskip){
  1058. memcpy(next,og.header,byteskipcount-byteskip);
  1059. next+=byteskipcount-byteskip;
  1060. byteskipcount=byteskip;
  1061. }
  1062. byteskipcount+=og.body_len;
  1063. if(byteskipcount>byteskip){
  1064. memcpy(next,og.body,byteskipcount-byteskip);
  1065. next+=byteskipcount-byteskip;
  1066. byteskipcount=byteskip;
  1067. }
  1068. ogg_sync_wrote(&oy,next-buf);
  1069. while(1){
  1070. int ret=ogg_sync_pageout(&oy,&og_de);
  1071. if(ret==0)break;
  1072. if(ret<0)continue;
  1073. /* got a page. Happy happy. Verify that it's good. */
  1074. fprintf(stderr,"(%ld), ",pageout);
  1075. check_page(data+deptr,headers[pageout],&og_de);
  1076. deptr+=og_de.body_len;
  1077. pageout++;
  1078. /* submit it to deconstitution */
  1079. ogg_stream_pagein(&os_de,&og_de);
  1080. /* packets out? */
  1081. while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
  1082. ogg_stream_packetpeek(&os_de,NULL);
  1083. ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
  1084. /* verify peek and out match */
  1085. if(memcmp(&op_de,&op_de2,sizeof(op_de))){
  1086. fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
  1087. depacket);
  1088. exit(1);
  1089. }
  1090. /* verify the packet! */
  1091. /* check data */
  1092. if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
  1093. fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
  1094. depacket);
  1095. exit(1);
  1096. }
  1097. /* check bos flag */
  1098. if(bosflag==0 && op_de.b_o_s==0){
  1099. fprintf(stderr,"b_o_s flag not set on packet!\n");
  1100. exit(1);
  1101. }
  1102. if(bosflag && op_de.b_o_s){
  1103. fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
  1104. exit(1);
  1105. }
  1106. bosflag=1;
  1107. depacket+=op_de.bytes;
  1108. /* check eos flag */
  1109. if(eosflag){
  1110. fprintf(stderr,"Multiple decoded packets with eos flag!\n");
  1111. exit(1);
  1112. }
  1113. if(op_de.e_o_s)eosflag=1;
  1114. /* check granulepos flag */
  1115. if(op_de.granulepos!=-1){
  1116. fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
  1117. }
  1118. }
  1119. }
  1120. }
  1121. }
  1122. }
  1123. }
  1124. _ogg_free(data);
  1125. if(headers[pageno]!=NULL){
  1126. fprintf(stderr,"did not write last page!\n");
  1127. exit(1);
  1128. }
  1129. if(headers[pageout]!=NULL){
  1130. fprintf(stderr,"did not decode last page!\n");
  1131. exit(1);
  1132. }
  1133. if(inptr!=outptr){
  1134. fprintf(stderr,"encoded page data incomplete!\n");
  1135. exit(1);
  1136. }
  1137. if(inptr!=deptr){
  1138. fprintf(stderr,"decoded page data incomplete!\n");
  1139. exit(1);
  1140. }
  1141. if(inptr!=depacket){
  1142. fprintf(stderr,"decoded packet data incomplete!\n");
  1143. exit(1);
  1144. }
  1145. if(!eosflag){
  1146. fprintf(stderr,"Never got a packet with EOS set!\n");
  1147. exit(1);
  1148. }
  1149. fprintf(stderr,"ok.\n");
  1150. }
  1151. int main(void){
  1152. ogg_stream_init(&os_en,0x04030201);
  1153. ogg_stream_init(&os_de,0x04030201);
  1154. ogg_sync_init(&oy);
  1155. /* Exercise each code path in the framing code. Also verify that
  1156. the checksums are working. */
  1157. {
  1158. /* 17 only */
  1159. const int packets[]={17, -1};
  1160. const int *headret[]={head1_0,NULL};
  1161. fprintf(stderr,"testing single page encoding... ");
  1162. test_pack(packets,headret,0,0,0);
  1163. }
  1164. {
  1165. /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
  1166. const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
  1167. const int *headret[]={head1_1,head2_1,NULL};
  1168. fprintf(stderr,"testing basic page encoding... ");
  1169. test_pack(packets,headret,0,0,0);
  1170. }
  1171. {
  1172. /* nil packets; beginning,middle,end */
  1173. const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
  1174. const int *headret[]={head1_2,head2_2,NULL};
  1175. fprintf(stderr,"testing basic nil packets... ");
  1176. test_pack(packets,headret,0,0,0);
  1177. }
  1178. {
  1179. /* large initial packet */
  1180. const int packets[]={4345,259,255,-1};
  1181. const int *headret[]={head1_3,head2_3,NULL};
  1182. fprintf(stderr,"testing initial-packet lacing > 4k... ");
  1183. test_pack(packets,headret,0,0,0);
  1184. }
  1185. {
  1186. /* continuing packet test */
  1187. const int packets[]={0,4345,259,255,-1};
  1188. const int *headret[]={head1_4,head2_4,head3_4,NULL};
  1189. fprintf(stderr,"testing single packet page span... ");
  1190. test_pack(packets,headret,0,0,0);
  1191. }
  1192. /* page with the 255 segment limit */
  1193. {
  1194. const int packets[]={0,10,10,10,10,10,10,10,10,
  1195. 10,10,10,10,10,10,10,10,
  1196. 10,10,10,10,10,10,10,10,
  1197. 10,10,10,10,10,10,10,10,
  1198. 10,10,10,10,10,10,10,10,
  1199. 10,10,10,10,10,10,10,10,
  1200. 10,10,10,10,10,10,10,10,
  1201. 10,10,10,10,10,10,10,10,
  1202. 10,10,10,10,10,10,10,10,
  1203. 10,10,10,10,10,10,10,10,
  1204. 10,10,10,10,10,10,10,10,
  1205. 10,10,10,10,10,10,10,10,
  1206. 10,10,10,10,10,10,10,10,
  1207. 10,10,10,10,10,10,10,10,
  1208. 10,10,10,10,10,10,10,10,
  1209. 10,10,10,10,10,10,10,10,
  1210. 10,10,10,10,10,10,10,10,
  1211. 10,10,10,10,10,10,10,10,
  1212. 10,10,10,10,10,10,10,10,
  1213. 10,10,10,10,10,10,10,10,
  1214. 10,10,10,10,10,10,10,10,
  1215. 10,10,10,10,10,10,10,10,
  1216. 10,10,10,10,10,10,10,10,
  1217. 10,10,10,10,10,10,10,10,
  1218. 10,10,10,10,10,10,10,10,
  1219. 10,10,10,10,10,10,10,10,
  1220. 10,10,10,10,10,10,10,10,
  1221. 10,10,10,10,10,10,10,10,
  1222. 10,10,10,10,10,10,10,10,
  1223. 10,10,10,10,10,10,10,10,
  1224. 10,10,10,10,10,10,10,10,
  1225. 10,10,10,10,10,10,10,50,-1};
  1226. const int *headret[]={head1_5,head2_5,head3_5,NULL};
  1227. fprintf(stderr,"testing max packet segments... ");
  1228. test_pack(packets,headret,0,0,0);
  1229. }
  1230. {
  1231. /* packet that overspans over an entire page */
  1232. const int packets[]={0,100,9000,259,255,-1};
  1233. const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
  1234. fprintf(stderr,"testing very large packets... ");
  1235. test_pack(packets,headret,0,0,0);
  1236. }
  1237. {
  1238. /* test for the libogg 1.1.1 resync in large continuation bug
  1239. found by Josh Coalson) */
  1240. const int packets[]={0,100,9000,259,255,-1};
  1241. const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
  1242. fprintf(stderr,"testing continuation resync in very large packets... ");
  1243. test_pack(packets,headret,100,2,3);
  1244. }
  1245. {
  1246. /* term only page. why not? */
  1247. const int packets[]={0,100,4080,-1};
  1248. const int *headret[]={head1_7,head2_7,head3_7,NULL};
  1249. fprintf(stderr,"testing zero data page (1 nil packet)... ");
  1250. test_pack(packets,headret,0,0,0);
  1251. }
  1252. {
  1253. /* build a bunch of pages for testing */
  1254. unsigned char *data=_ogg_malloc(1024*1024);
  1255. int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1};
  1256. int inptr=0,i,j;
  1257. ogg_page og[5];
  1258. ogg_stream_reset(&os_en);
  1259. for(i=0;pl[i]!=-1;i++){
  1260. ogg_packet op;
  1261. int len=pl[i];
  1262. op.packet=data+inptr;
  1263. op.bytes=len;
  1264. op.e_o_s=(pl[i+1]<0?1:0);
  1265. op.granulepos=(i+1)*1000;
  1266. for(j=0;j<len;j++)data[inptr++]=i+j;
  1267. ogg_stream_packetin(&os_en,&op);
  1268. }
  1269. _ogg_free(data);
  1270. /* retrieve finished pages */
  1271. for(i=0;i<5;i++){
  1272. if(ogg_stream_pageout(&os_en,&og[i])==0){
  1273. fprintf(stderr,"Too few pages output building sync tests!\n");
  1274. exit(1);
  1275. }
  1276. copy_page(&og[i]);
  1277. }
  1278. /* Test lost pages on pagein/packetout: no rollback */
  1279. {
  1280. ogg_page temp;
  1281. ogg_packet test;
  1282. fprintf(stderr,"Testing loss of pages... ");
  1283. ogg_sync_reset(&oy);
  1284. ogg_stream_reset(&os_de);
  1285. for(i=0;i<5;i++){
  1286. memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
  1287. og[i].header_len);
  1288. ogg_sync_wrote(&oy,og[i].header_len);
  1289. memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
  1290. ogg_sync_wrote(&oy,og[i].body_len);
  1291. }
  1292. ogg_sync_pageout(&oy,&temp);
  1293. ogg_stream_pagein(&os_de,&temp);
  1294. ogg_sync_pageout(&oy,&temp);
  1295. ogg_stream_pagein(&os_de,&temp);
  1296. ogg_sync_pageout(&oy,&temp);
  1297. /* skip */
  1298. ogg_sync_pageout(&oy,&temp);
  1299. ogg_stream_pagein(&os_de,&temp);
  1300. /* do we get the expected results/packets? */
  1301. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1302. checkpacket(&test,0,0,0);
  1303. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1304. checkpacket(&test,100,1,-1);
  1305. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1306. checkpacket(&test,4079,2,3000);
  1307. if(ogg_stream_packetout(&os_de,&test)!=-1){
  1308. fprintf(stderr,"Error: loss of page did not return error\n");
  1309. exit(1);
  1310. }
  1311. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1312. checkpacket(&test,76,5,-1);
  1313. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1314. checkpacket(&test,34,6,-1);
  1315. fprintf(stderr,"ok.\n");
  1316. }
  1317. /* Test lost pages on pagein/packetout: rollback with continuation */
  1318. {
  1319. ogg_page temp;
  1320. ogg_packet test;
  1321. fprintf(stderr,"Testing loss of pages (rollback required)... ");
  1322. ogg_sync_reset(&oy);
  1323. ogg_stream_reset(&os_de);
  1324. for(i=0;i<5;i++){
  1325. memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
  1326. og[i].header_len);
  1327. ogg_sync_wrote(&oy,og[i].header_len);
  1328. memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
  1329. ogg_sync_wrote(&oy,og[i].body_len);
  1330. }
  1331. ogg_sync_pageout(&oy,&temp);
  1332. ogg_stream_pagein(&os_de,&temp);
  1333. ogg_sync_pageout(&oy,&temp);
  1334. ogg_stream_pagein(&os_de,&temp);
  1335. ogg_sync_pageout(&oy,&temp);
  1336. ogg_stream_pagein(&os_de,&temp);
  1337. ogg_sync_pageout(&oy,&temp);
  1338. /* skip */
  1339. ogg_sync_pageout(&oy,&temp);
  1340. ogg_stream_pagein(&os_de,&temp);
  1341. /* do we get the expected results/packets? */
  1342. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1343. checkpacket(&test,0,0,0);
  1344. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1345. checkpacket(&test,100,1,-1);
  1346. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1347. checkpacket(&test,4079,2,3000);
  1348. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1349. checkpacket(&test,2956,3,4000);
  1350. if(ogg_stream_packetout(&os_de,&test)!=-1){
  1351. fprintf(stderr,"Error: loss of page did not return error\n");
  1352. exit(1);
  1353. }
  1354. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1355. checkpacket(&test,300,13,14000);
  1356. fprintf(stderr,"ok.\n");
  1357. }
  1358. /* the rest only test sync */
  1359. {
  1360. ogg_page og_de;
  1361. /* Test fractional page inputs: incomplete capture */
  1362. fprintf(stderr,"Testing sync on partial inputs... ");
  1363. ogg_sync_reset(&oy);
  1364. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1365. 3);
  1366. ogg_sync_wrote(&oy,3);
  1367. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1368. /* Test fractional page inputs: incomplete fixed header */
  1369. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
  1370. 20);
  1371. ogg_sync_wrote(&oy,20);
  1372. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1373. /* Test fractional page inputs: incomplete header */
  1374. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
  1375. 5);
  1376. ogg_sync_wrote(&oy,5);
  1377. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1378. /* Test fractional page inputs: incomplete body */
  1379. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
  1380. og[1].header_len-28);
  1381. ogg_sync_wrote(&oy,og[1].header_len-28);
  1382. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1383. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
  1384. ogg_sync_wrote(&oy,1000);
  1385. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1386. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
  1387. og[1].body_len-1000);
  1388. ogg_sync_wrote(&oy,og[1].body_len-1000);
  1389. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1390. fprintf(stderr,"ok.\n");
  1391. }
  1392. /* Test fractional page inputs: page + incomplete capture */
  1393. {
  1394. ogg_page og_de;
  1395. fprintf(stderr,"Testing sync on 1+partial inputs... ");
  1396. ogg_sync_reset(&oy);
  1397. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1398. og[1].header_len);
  1399. ogg_sync_wrote(&oy,og[1].header_len);
  1400. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1401. og[1].body_len);
  1402. ogg_sync_wrote(&oy,og[1].body_len);
  1403. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1404. 20);
  1405. ogg_sync_wrote(&oy,20);
  1406. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1407. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1408. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
  1409. og[1].header_len-20);
  1410. ogg_sync_wrote(&oy,og[1].header_len-20);
  1411. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1412. og[1].body_len);
  1413. ogg_sync_wrote(&oy,og[1].body_len);
  1414. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1415. fprintf(stderr,"ok.\n");
  1416. }
  1417. /* Test recapture: garbage + page */
  1418. {
  1419. ogg_page og_de;
  1420. fprintf(stderr,"Testing search for capture... ");
  1421. ogg_sync_reset(&oy);
  1422. /* 'garbage' */
  1423. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1424. og[1].body_len);
  1425. ogg_sync_wrote(&oy,og[1].body_len);
  1426. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1427. og[1].header_len);
  1428. ogg_sync_wrote(&oy,og[1].header_len);
  1429. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1430. og[1].body_len);
  1431. ogg_sync_wrote(&oy,og[1].body_len);
  1432. memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
  1433. 20);
  1434. ogg_sync_wrote(&oy,20);
  1435. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1436. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1437. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1438. memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
  1439. og[2].header_len-20);
  1440. ogg_sync_wrote(&oy,og[2].header_len-20);
  1441. memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
  1442. og[2].body_len);
  1443. ogg_sync_wrote(&oy,og[2].body_len);
  1444. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1445. fprintf(stderr,"ok.\n");
  1446. }
  1447. /* Test recapture: page + garbage + page */
  1448. {
  1449. ogg_page og_de;
  1450. fprintf(stderr,"Testing recapture... ");
  1451. ogg_sync_reset(&oy);
  1452. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1453. og[1].header_len);
  1454. ogg_sync_wrote(&oy,og[1].header_len);
  1455. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1456. og[1].body_len);
  1457. ogg_sync_wrote(&oy,og[1].body_len);
  1458. memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
  1459. og[2].header_len);
  1460. ogg_sync_wrote(&oy,og[2].header_len);
  1461. memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
  1462. og[2].header_len);
  1463. ogg_sync_wrote(&oy,og[2].header_len);
  1464. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1465. memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
  1466. og[2].body_len-5);
  1467. ogg_sync_wrote(&oy,og[2].body_len-5);
  1468. memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
  1469. og[3].header_len);
  1470. ogg_sync_wrote(&oy,og[3].header_len);
  1471. memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
  1472. og[3].body_len);
  1473. ogg_sync_wrote(&oy,og[3].body_len);
  1474. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1475. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1476. fprintf(stderr,"ok.\n");
  1477. }
  1478. /* Free page data that was previously copied */
  1479. {
  1480. for(i=0;i<5;i++){
  1481. free_page(&og[i]);
  1482. }
  1483. }
  1484. }
  1485. return(0);
  1486. }
  1487. #endif