framing.c 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748
  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.23 2002/09/29 07:10:37 giles 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/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 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. // lowered for DOOM
  167. os->body_storage=8*1024;
  168. os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
  169. os->lacing_storage=1024;
  170. os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
  171. os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
  172. os->serialno=serialno;
  173. return(0);
  174. }
  175. return(-1);
  176. }
  177. /* _clear does not free os, only the non-flat storage within */
  178. int ogg_stream_clear(ogg_stream_state *os){
  179. if(os){
  180. if(os->body_data)_ogg_free(os->body_data);
  181. if(os->lacing_vals)_ogg_free(os->lacing_vals);
  182. if(os->granule_vals)_ogg_free(os->granule_vals);
  183. memset(os,0,sizeof(*os));
  184. }
  185. return(0);
  186. }
  187. int ogg_stream_destroy(ogg_stream_state *os){
  188. if(os){
  189. ogg_stream_clear(os);
  190. _ogg_free(os);
  191. }
  192. return(0);
  193. }
  194. /* Helpers for ogg_stream_encode; this keeps the structure and
  195. what's happening fairly clear */
  196. static void _os_body_expand(ogg_stream_state *os,int needed){
  197. if(os->body_storage<=os->body_fill+needed){
  198. os->body_storage+=(needed+1024);
  199. os->body_data=_ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data));
  200. }
  201. }
  202. static void _os_lacing_expand(ogg_stream_state *os,int needed){
  203. if(os->lacing_storage<=os->lacing_fill+needed){
  204. os->lacing_storage+=(needed+32);
  205. os->lacing_vals=_ogg_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals));
  206. os->granule_vals=_ogg_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals));
  207. }
  208. }
  209. /* checksum the page */
  210. /* Direct table CRC; note that this will be faster in the future if we
  211. perform the checksum silmultaneously with other copies */
  212. void ogg_page_checksum_set(ogg_page *og){
  213. if(og){
  214. ogg_uint32_t crc_reg=0;
  215. int i;
  216. /* safety; needed for API behavior, but not framing code */
  217. og->header[22]=0;
  218. og->header[23]=0;
  219. og->header[24]=0;
  220. og->header[25]=0;
  221. for(i=0;i<og->header_len;i++)
  222. crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
  223. for(i=0;i<og->body_len;i++)
  224. crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
  225. og->header[22]=crc_reg&0xff;
  226. og->header[23]=(crc_reg>>8)&0xff;
  227. og->header[24]=(crc_reg>>16)&0xff;
  228. og->header[25]=(crc_reg>>24)&0xff;
  229. }
  230. }
  231. /* submit data to the internal buffer of the framing engine */
  232. int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
  233. int lacing_vals=op->bytes/255+1,i;
  234. if(os->body_returned){
  235. /* advance packet data according to the body_returned pointer. We
  236. had to keep it around to return a pointer into the buffer last
  237. call */
  238. os->body_fill-=os->body_returned;
  239. if(os->body_fill)
  240. memmove(os->body_data,os->body_data+os->body_returned,
  241. os->body_fill);
  242. os->body_returned=0;
  243. }
  244. /* make sure we have the buffer storage */
  245. _os_body_expand(os,op->bytes);
  246. _os_lacing_expand(os,lacing_vals);
  247. /* Copy in the submitted packet. Yes, the copy is a waste; this is
  248. the liability of overly clean abstraction for the time being. It
  249. will actually be fairly easy to eliminate the extra copy in the
  250. future */
  251. memcpy(os->body_data+os->body_fill,op->packet,op->bytes);
  252. os->body_fill+=op->bytes;
  253. /* Store lacing vals for this packet */
  254. for(i=0;i<lacing_vals-1;i++){
  255. os->lacing_vals[os->lacing_fill+i]=255;
  256. os->granule_vals[os->lacing_fill+i]=os->granulepos;
  257. }
  258. os->lacing_vals[os->lacing_fill+i]=(op->bytes)%255;
  259. os->granulepos=os->granule_vals[os->lacing_fill+i]=op->granulepos;
  260. /* flag the first segment as the beginning of the packet */
  261. os->lacing_vals[os->lacing_fill]|= 0x100;
  262. os->lacing_fill+=lacing_vals;
  263. /* for the sake of completeness */
  264. os->packetno++;
  265. if(op->e_o_s)os->e_o_s=1;
  266. return(0);
  267. }
  268. /* This will flush remaining packets into a page (returning nonzero),
  269. even if there is not enough data to trigger a flush normally
  270. (undersized page). If there are no packets or partial packets to
  271. flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
  272. try to flush a normal sized page like ogg_stream_pageout; a call to
  273. ogg_stream_flush does not guarantee that all packets have flushed.
  274. Only a return value of 0 from ogg_stream_flush indicates all packet
  275. data is flushed into pages.
  276. since ogg_stream_flush will flush the last page in a stream even if
  277. it's undersized, you almost certainly want to use ogg_stream_pageout
  278. (and *not* ogg_stream_flush) unless you specifically need to flush
  279. an page regardless of size in the middle of a stream. */
  280. int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
  281. int i;
  282. int vals=0;
  283. int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
  284. int bytes=0;
  285. long acc=0;
  286. ogg_int64_t granule_pos=os->granule_vals[0];
  287. if(maxvals==0)return(0);
  288. /* construct a page */
  289. /* decide how many segments to include */
  290. /* If this is the initial header case, the first page must only include
  291. the initial header packet */
  292. if(os->b_o_s==0){ /* 'initial header page' case */
  293. granule_pos=0;
  294. for(vals=0;vals<maxvals;vals++){
  295. if((os->lacing_vals[vals]&0x0ff)<255){
  296. vals++;
  297. break;
  298. }
  299. }
  300. }else{
  301. for(vals=0;vals<maxvals;vals++){
  302. if(acc>4096)break;
  303. acc+=os->lacing_vals[vals]&0x0ff;
  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]=(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]=(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]=(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]=vals&0xff;
  353. for(i=0;i<vals;i++)
  354. bytes+=os->header[i+27]=(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. See the 'frame-prog.txt' docs for details and
  398. example code. */
  399. /* initialize the struct to a known state */
  400. int ogg_sync_init(ogg_sync_state *oy){
  401. if(oy){
  402. memset(oy,0,sizeof(*oy));
  403. }
  404. return(0);
  405. }
  406. /* clear non-flat storage within */
  407. int ogg_sync_clear(ogg_sync_state *oy){
  408. if(oy){
  409. if(oy->data)_ogg_free(oy->data);
  410. ogg_sync_init(oy);
  411. }
  412. return(0);
  413. }
  414. int ogg_sync_destroy(ogg_sync_state *oy){
  415. if(oy){
  416. ogg_sync_clear(oy);
  417. _ogg_free(oy);
  418. }
  419. return(0);
  420. }
  421. char *ogg_sync_buffer(ogg_sync_state *oy, long size){
  422. /* first, clear out any space that has been previously returned */
  423. if(oy->returned){
  424. oy->fill-=oy->returned;
  425. if(oy->fill>0)
  426. memmove(oy->data,oy->data+oy->returned,oy->fill);
  427. oy->returned=0;
  428. }
  429. if(size>oy->storage-oy->fill){
  430. /* We need to extend the internal buffer */
  431. long newsize=size+oy->fill+4096; /* an extra page to be nice */
  432. if(oy->data)
  433. oy->data=_ogg_realloc(oy->data,newsize);
  434. else
  435. oy->data=_ogg_malloc(newsize);
  436. oy->storage=newsize;
  437. }
  438. /* expose a segment at least as large as requested at the fill mark */
  439. return((char *)oy->data+oy->fill);
  440. }
  441. int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
  442. if(oy->fill+bytes>oy->storage)return(-1);
  443. oy->fill+=bytes;
  444. return(0);
  445. }
  446. /* sync the stream. This is meant to be useful for finding page
  447. boundaries.
  448. return values for this:
  449. -n) skipped n bytes
  450. 0) page not ready; more data (no bytes skipped)
  451. n) page synced at current location; page length n bytes
  452. */
  453. long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
  454. unsigned char *page=oy->data+oy->returned;
  455. unsigned char *next;
  456. long bytes=oy->fill-oy->returned;
  457. if(oy->headerbytes==0){
  458. int headerbytes,i;
  459. if(bytes<27)return(0); /* not enough for a header */
  460. /* verify capture pattern */
  461. if(memcmp(page,"OggS",4))goto sync_fail;
  462. headerbytes=page[26]+27;
  463. if(bytes<headerbytes)return(0); /* not enough for header + seg table */
  464. /* count up body length in the segment table */
  465. for(i=0;i<page[26];i++)
  466. oy->bodybytes+=page[27+i];
  467. oy->headerbytes=headerbytes;
  468. }
  469. if(oy->bodybytes+oy->headerbytes>bytes)return(0);
  470. /* The whole test page is buffered. Verify the checksum */
  471. {
  472. /* Grab the checksum bytes, set the header field to zero */
  473. char chksum[4];
  474. ogg_page log;
  475. memcpy(chksum,page+22,4);
  476. memset(page+22,0,4);
  477. /* set up a temp page struct and recompute the checksum */
  478. log.header=page;
  479. log.header_len=oy->headerbytes;
  480. log.body=page+oy->headerbytes;
  481. log.body_len=oy->bodybytes;
  482. ogg_page_checksum_set(&log);
  483. /* Compare */
  484. if(memcmp(chksum,page+22,4)){
  485. /* D'oh. Mismatch! Corrupt page (or miscapture and not a page
  486. at all) */
  487. /* replace the computed checksum with the one actually read in */
  488. memcpy(page+22,chksum,4);
  489. /* Bad checksum. Lose sync */
  490. goto sync_fail;
  491. }
  492. }
  493. /* yes, have a whole page all ready to go */
  494. {
  495. unsigned char *page=oy->data+oy->returned;
  496. long bytes;
  497. if(og){
  498. og->header=page;
  499. og->header_len=oy->headerbytes;
  500. og->body=page+oy->headerbytes;
  501. og->body_len=oy->bodybytes;
  502. }
  503. oy->unsynced=0;
  504. oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
  505. oy->headerbytes=0;
  506. oy->bodybytes=0;
  507. return(bytes);
  508. }
  509. sync_fail:
  510. oy->headerbytes=0;
  511. oy->bodybytes=0;
  512. /* search for possible capture */
  513. next=memchr(page+1,'O',bytes-1);
  514. if(!next)
  515. next=oy->data+oy->fill;
  516. oy->returned=next-oy->data;
  517. return(-(next-page));
  518. }
  519. /* sync the stream and get a page. Keep trying until we find a page.
  520. Supress 'sync errors' after reporting the first.
  521. return values:
  522. -1) recapture (hole in data)
  523. 0) need more data
  524. 1) page returned
  525. Returns pointers into buffered data; invalidated by next call to
  526. _stream, _clear, _init, or _buffer */
  527. int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
  528. /* all we need to do is verify a page at the head of the stream
  529. buffer. If it doesn't verify, we look for the next potential
  530. frame */
  531. while(1){
  532. long ret=ogg_sync_pageseek(oy,og);
  533. if(ret>0){
  534. /* have a page */
  535. return(1);
  536. }
  537. if(ret==0){
  538. /* need more data */
  539. return(0);
  540. }
  541. /* head did not start a synced page... skipped some bytes */
  542. if(!oy->unsynced){
  543. oy->unsynced=1;
  544. return(-1);
  545. }
  546. /* loop. keep looking */
  547. }
  548. }
  549. /* add the incoming page to the stream state; we decompose the page
  550. into packet segments here as well. */
  551. int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
  552. unsigned char *header=og->header;
  553. unsigned char *body=og->body;
  554. long bodysize=og->body_len;
  555. int segptr=0;
  556. int version=ogg_page_version(og);
  557. int continued=ogg_page_continued(og);
  558. int bos=ogg_page_bos(og);
  559. int eos=ogg_page_eos(og);
  560. ogg_int64_t granulepos=ogg_page_granulepos(og);
  561. int serialno=ogg_page_serialno(og);
  562. long pageno=ogg_page_pageno(og);
  563. int segments=header[26];
  564. /* clean up 'returned data' */
  565. {
  566. long lr=os->lacing_returned;
  567. long br=os->body_returned;
  568. /* body data */
  569. if(br){
  570. os->body_fill-=br;
  571. if(os->body_fill)
  572. memmove(os->body_data,os->body_data+br,os->body_fill);
  573. os->body_returned=0;
  574. }
  575. if(lr){
  576. /* segment table */
  577. if(os->lacing_fill-lr){
  578. memmove(os->lacing_vals,os->lacing_vals+lr,
  579. (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
  580. memmove(os->granule_vals,os->granule_vals+lr,
  581. (os->lacing_fill-lr)*sizeof(*os->granule_vals));
  582. }
  583. os->lacing_fill-=lr;
  584. os->lacing_packet-=lr;
  585. os->lacing_returned=0;
  586. }
  587. }
  588. /* check the serial number */
  589. if(serialno!=os->serialno)return(-1);
  590. if(version>0)return(-1);
  591. _os_lacing_expand(os,segments+1);
  592. /* are we in sequence? */
  593. if(pageno!=os->pageno){
  594. int i;
  595. /* unroll previous partial packet (if any) */
  596. for(i=os->lacing_packet;i<os->lacing_fill;i++)
  597. os->body_fill-=os->lacing_vals[i]&0xff;
  598. os->lacing_fill=os->lacing_packet;
  599. /* make a note of dropped data in segment table */
  600. if(os->pageno!=-1){
  601. os->lacing_vals[os->lacing_fill++]=0x400;
  602. os->lacing_packet++;
  603. }
  604. /* are we a 'continued packet' page? If so, we'll need to skip
  605. some segments */
  606. if(continued){
  607. bos=0;
  608. for(;segptr<segments;segptr++){
  609. int val=header[27+segptr];
  610. body+=val;
  611. bodysize-=val;
  612. if(val<255){
  613. segptr++;
  614. break;
  615. }
  616. }
  617. }
  618. }
  619. if(bodysize){
  620. _os_body_expand(os,bodysize);
  621. memcpy(os->body_data+os->body_fill,body,bodysize);
  622. os->body_fill+=bodysize;
  623. }
  624. {
  625. int saved=-1;
  626. while(segptr<segments){
  627. int val=header[27+segptr];
  628. os->lacing_vals[os->lacing_fill]=val;
  629. os->granule_vals[os->lacing_fill]=-1;
  630. if(bos){
  631. os->lacing_vals[os->lacing_fill]|=0x100;
  632. bos=0;
  633. }
  634. if(val<255)saved=os->lacing_fill;
  635. os->lacing_fill++;
  636. segptr++;
  637. if(val<255)os->lacing_packet=os->lacing_fill;
  638. }
  639. /* set the granulepos on the last granuleval of the last full packet */
  640. if(saved!=-1){
  641. os->granule_vals[saved]=granulepos;
  642. }
  643. }
  644. if(eos){
  645. os->e_o_s=1;
  646. if(os->lacing_fill>0)
  647. os->lacing_vals[os->lacing_fill-1]|=0x200;
  648. }
  649. os->pageno=pageno+1;
  650. return(0);
  651. }
  652. /* clear things to an initial state. Good to call, eg, before seeking */
  653. int ogg_sync_reset(ogg_sync_state *oy){
  654. oy->fill=0;
  655. oy->returned=0;
  656. oy->unsynced=0;
  657. oy->headerbytes=0;
  658. oy->bodybytes=0;
  659. return(0);
  660. }
  661. int ogg_stream_reset(ogg_stream_state *os){
  662. os->body_fill=0;
  663. os->body_returned=0;
  664. os->lacing_fill=0;
  665. os->lacing_packet=0;
  666. os->lacing_returned=0;
  667. os->header_fill=0;
  668. os->e_o_s=0;
  669. os->b_o_s=0;
  670. os->pageno=-1;
  671. os->packetno=0;
  672. os->granulepos=0;
  673. return(0);
  674. }
  675. int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
  676. ogg_stream_reset(os);
  677. os->serialno=serialno;
  678. return(0);
  679. }
  680. static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
  681. /* The last part of decode. We have the stream broken into packet
  682. segments. Now we need to group them into packets (or return the
  683. out of sync markers) */
  684. int ptr=os->lacing_returned;
  685. if(os->lacing_packet<=ptr)return(0);
  686. if(os->lacing_vals[ptr]&0x400){
  687. /* we need to tell the codec there's a gap; it might need to
  688. handle previous packet dependencies. */
  689. os->lacing_returned++;
  690. os->packetno++;
  691. return(-1);
  692. }
  693. if(!op && !adv)return(1); /* just using peek as an inexpensive way
  694. to ask if there's a whole packet
  695. waiting */
  696. /* Gather the whole packet. We'll have no holes or a partial packet */
  697. {
  698. int size=os->lacing_vals[ptr]&0xff;
  699. int bytes=size;
  700. int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
  701. int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
  702. while(size==255){
  703. int val=os->lacing_vals[++ptr];
  704. size=val&0xff;
  705. if(val&0x200)eos=0x200;
  706. bytes+=size;
  707. }
  708. if(op){
  709. op->e_o_s=eos;
  710. op->b_o_s=bos;
  711. op->packet=os->body_data+os->body_returned;
  712. op->packetno=os->packetno;
  713. op->granulepos=os->granule_vals[ptr];
  714. op->bytes=bytes;
  715. }
  716. if(adv){
  717. os->body_returned+=bytes;
  718. os->lacing_returned=ptr+1;
  719. os->packetno++;
  720. }
  721. }
  722. return(1);
  723. }
  724. int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
  725. return _packetout(os,op,1);
  726. }
  727. int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
  728. return _packetout(os,op,0);
  729. }
  730. void ogg_packet_clear(ogg_packet *op) {
  731. _ogg_free(op->packet);
  732. memset(op, 0, sizeof(*op));
  733. }
  734. #ifdef _V_SELFTEST
  735. #include <stdio.h>
  736. ogg_stream_state os_en, os_de;
  737. ogg_sync_state oy;
  738. void checkpacket(ogg_packet *op,int len, int no, int pos){
  739. long j;
  740. static int sequence=0;
  741. static int lastno=0;
  742. if(op->bytes!=len){
  743. fprintf(stderr,"incorrect packet length!\n");
  744. exit(1);
  745. }
  746. if(op->granulepos!=pos){
  747. fprintf(stderr,"incorrect packet position!\n");
  748. exit(1);
  749. }
  750. /* packet number just follows sequence/gap; adjust the input number
  751. for that */
  752. if(no==0){
  753. sequence=0;
  754. }else{
  755. sequence++;
  756. if(no>lastno+1)
  757. sequence++;
  758. }
  759. lastno=no;
  760. if(op->packetno!=sequence){
  761. fprintf(stderr,"incorrect packet sequence %ld != %d\n",
  762. (long)(op->packetno),sequence);
  763. exit(1);
  764. }
  765. /* Test data */
  766. for(j=0;j<op->bytes;j++)
  767. if(op->packet[j]!=((j+no)&0xff)){
  768. fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
  769. j,op->packet[j],(j+no)&0xff);
  770. exit(1);
  771. }
  772. }
  773. void check_page(unsigned char *data,const int *header,ogg_page *og){
  774. long j;
  775. /* Test data */
  776. for(j=0;j<og->body_len;j++)
  777. if(og->body[j]!=data[j]){
  778. fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
  779. j,data[j],og->body[j]);
  780. exit(1);
  781. }
  782. /* Test header */
  783. for(j=0;j<og->header_len;j++){
  784. if(og->header[j]!=header[j]){
  785. fprintf(stderr,"header content mismatch at pos %ld:\n",j);
  786. for(j=0;j<header[26]+27;j++)
  787. fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
  788. fprintf(stderr,"\n");
  789. exit(1);
  790. }
  791. }
  792. if(og->header_len!=header[26]+27){
  793. fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
  794. og->header_len,header[26]+27);
  795. exit(1);
  796. }
  797. }
  798. void print_header(ogg_page *og){
  799. int j;
  800. fprintf(stderr,"\nHEADER:\n");
  801. fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n",
  802. og->header[0],og->header[1],og->header[2],og->header[3],
  803. (int)og->header[4],(int)og->header[5]);
  804. fprintf(stderr," granulepos: %d serialno: %d pageno: %ld\n",
  805. (og->header[9]<<24)|(og->header[8]<<16)|
  806. (og->header[7]<<8)|og->header[6],
  807. (og->header[17]<<24)|(og->header[16]<<16)|
  808. (og->header[15]<<8)|og->header[14],
  809. ((long)(og->header[21])<<24)|(og->header[20]<<16)|
  810. (og->header[19]<<8)|og->header[18]);
  811. fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (",
  812. (int)og->header[22],(int)og->header[23],
  813. (int)og->header[24],(int)og->header[25],
  814. (int)og->header[26]);
  815. for(j=27;j<og->header_len;j++)
  816. fprintf(stderr,"%d ",(int)og->header[j]);
  817. fprintf(stderr,")\n\n");
  818. }
  819. void copy_page(ogg_page *og){
  820. unsigned char *temp=_ogg_malloc(og->header_len);
  821. memcpy(temp,og->header,og->header_len);
  822. og->header=temp;
  823. temp=_ogg_malloc(og->body_len);
  824. memcpy(temp,og->body,og->body_len);
  825. og->body=temp;
  826. }
  827. void error(void){
  828. fprintf(stderr,"error!\n");
  829. exit(1);
  830. }
  831. /* 17 only */
  832. const int head1_0[] = {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. /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
  839. const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
  840. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  841. 0x01,0x02,0x03,0x04,0,0,0,0,
  842. 0x59,0x10,0x6c,0x2c,
  843. 1,
  844. 17};
  845. const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
  846. 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
  847. 0x01,0x02,0x03,0x04,1,0,0,0,
  848. 0x89,0x33,0x85,0xce,
  849. 13,
  850. 254,255,0,255,1,255,245,255,255,0,
  851. 255,255,90};
  852. /* nil packets; beginning,middle,end */
  853. const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
  854. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  855. 0x01,0x02,0x03,0x04,0,0,0,0,
  856. 0xff,0x7b,0x23,0x17,
  857. 1,
  858. 0};
  859. const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
  860. 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
  861. 0x01,0x02,0x03,0x04,1,0,0,0,
  862. 0x5c,0x3f,0x66,0xcb,
  863. 17,
  864. 17,254,255,0,0,255,1,0,255,245,255,255,0,
  865. 255,255,90,0};
  866. /* large initial packet */
  867. const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
  868. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  869. 0x01,0x02,0x03,0x04,0,0,0,0,
  870. 0x01,0x27,0x31,0xaa,
  871. 18,
  872. 255,255,255,255,255,255,255,255,
  873. 255,255,255,255,255,255,255,255,255,10};
  874. const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
  875. 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
  876. 0x01,0x02,0x03,0x04,1,0,0,0,
  877. 0x7f,0x4e,0x8a,0xd2,
  878. 4,
  879. 255,4,255,0};
  880. /* continuing packet test */
  881. const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
  882. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  883. 0x01,0x02,0x03,0x04,0,0,0,0,
  884. 0xff,0x7b,0x23,0x17,
  885. 1,
  886. 0};
  887. const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
  888. 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  889. 0x01,0x02,0x03,0x04,1,0,0,0,
  890. 0x34,0x24,0xd5,0x29,
  891. 17,
  892. 255,255,255,255,255,255,255,255,
  893. 255,255,255,255,255,255,255,255,255};
  894. const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
  895. 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
  896. 0x01,0x02,0x03,0x04,2,0,0,0,
  897. 0xc8,0xc3,0xcb,0xed,
  898. 5,
  899. 10,255,4,255,0};
  900. /* page with the 255 segment limit */
  901. const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
  902. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  903. 0x01,0x02,0x03,0x04,0,0,0,0,
  904. 0xff,0x7b,0x23,0x17,
  905. 1,
  906. 0};
  907. const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
  908. 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
  909. 0x01,0x02,0x03,0x04,1,0,0,0,
  910. 0xed,0x2a,0x2e,0xa7,
  911. 255,
  912. 10,10,10,10,10,10,10,10,
  913. 10,10,10,10,10,10,10,10,
  914. 10,10,10,10,10,10,10,10,
  915. 10,10,10,10,10,10,10,10,
  916. 10,10,10,10,10,10,10,10,
  917. 10,10,10,10,10,10,10,10,
  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};
  944. const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
  945. 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
  946. 0x01,0x02,0x03,0x04,2,0,0,0,
  947. 0x6c,0x3b,0x82,0x3d,
  948. 1,
  949. 50};
  950. /* packet that overspans over an entire page */
  951. const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
  952. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  953. 0x01,0x02,0x03,0x04,0,0,0,0,
  954. 0xff,0x7b,0x23,0x17,
  955. 1,
  956. 0};
  957. const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
  958. 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
  959. 0x01,0x02,0x03,0x04,1,0,0,0,
  960. 0x3c,0xd9,0x4d,0x3f,
  961. 17,
  962. 100,255,255,255,255,255,255,255,255,
  963. 255,255,255,255,255,255,255,255};
  964. const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
  965. 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
  966. 0x01,0x02,0x03,0x04,2,0,0,0,
  967. 0xbd,0xd5,0xb5,0x8b,
  968. 17,
  969. 255,255,255,255,255,255,255,255,
  970. 255,255,255,255,255,255,255,255,255};
  971. const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
  972. 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
  973. 0x01,0x02,0x03,0x04,3,0,0,0,
  974. 0xef,0xdd,0x88,0xde,
  975. 7,
  976. 255,255,75,255,4,255,0};
  977. /* packet that overspans over an entire page */
  978. const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
  979. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  980. 0x01,0x02,0x03,0x04,0,0,0,0,
  981. 0xff,0x7b,0x23,0x17,
  982. 1,
  983. 0};
  984. const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
  985. 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
  986. 0x01,0x02,0x03,0x04,1,0,0,0,
  987. 0x3c,0xd9,0x4d,0x3f,
  988. 17,
  989. 100,255,255,255,255,255,255,255,255,
  990. 255,255,255,255,255,255,255,255};
  991. const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
  992. 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
  993. 0x01,0x02,0x03,0x04,2,0,0,0,
  994. 0xd4,0xe0,0x60,0xe5,
  995. 1,0};
  996. void test_pack(const int *pl, const int **headers){
  997. unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
  998. long inptr=0;
  999. long outptr=0;
  1000. long deptr=0;
  1001. long depacket=0;
  1002. long granule_pos=7,pageno=0;
  1003. int i,j,packets,pageout=0;
  1004. int eosflag=0;
  1005. int bosflag=0;
  1006. ogg_stream_reset(&os_en);
  1007. ogg_stream_reset(&os_de);
  1008. ogg_sync_reset(&oy);
  1009. for(packets=0;;packets++)if(pl[packets]==-1)break;
  1010. for(i=0;i<packets;i++){
  1011. /* construct a test packet */
  1012. ogg_packet op;
  1013. int len=pl[i];
  1014. op.packet=data+inptr;
  1015. op.bytes=len;
  1016. op.e_o_s=(pl[i+1]<0?1:0);
  1017. op.granulepos=granule_pos;
  1018. granule_pos+=1024;
  1019. for(j=0;j<len;j++)data[inptr++]=i+j;
  1020. /* submit the test packet */
  1021. ogg_stream_packetin(&os_en,&op);
  1022. /* retrieve any finished pages */
  1023. {
  1024. ogg_page og;
  1025. while(ogg_stream_pageout(&os_en,&og)){
  1026. /* We have a page. Check it carefully */
  1027. fprintf(stderr,"%ld, ",pageno);
  1028. if(headers[pageno]==NULL){
  1029. fprintf(stderr,"coded too many pages!\n");
  1030. exit(1);
  1031. }
  1032. check_page(data+outptr,headers[pageno],&og);
  1033. outptr+=og.body_len;
  1034. pageno++;
  1035. /* have a complete page; submit it to sync/decode */
  1036. {
  1037. ogg_page og_de;
  1038. ogg_packet op_de,op_de2;
  1039. char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
  1040. memcpy(buf,og.header,og.header_len);
  1041. memcpy(buf+og.header_len,og.body,og.body_len);
  1042. ogg_sync_wrote(&oy,og.header_len+og.body_len);
  1043. while(ogg_sync_pageout(&oy,&og_de)>0){
  1044. /* got a page. Happy happy. Verify that it's good. */
  1045. check_page(data+deptr,headers[pageout],&og_de);
  1046. deptr+=og_de.body_len;
  1047. pageout++;
  1048. /* submit it to deconstitution */
  1049. ogg_stream_pagein(&os_de,&og_de);
  1050. /* packets out? */
  1051. while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
  1052. ogg_stream_packetpeek(&os_de,NULL);
  1053. ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
  1054. /* verify peek and out match */
  1055. if(memcmp(&op_de,&op_de2,sizeof(op_de))){
  1056. fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
  1057. depacket);
  1058. exit(1);
  1059. }
  1060. /* verify the packet! */
  1061. /* check data */
  1062. if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
  1063. fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
  1064. depacket);
  1065. exit(1);
  1066. }
  1067. /* check bos flag */
  1068. if(bosflag==0 && op_de.b_o_s==0){
  1069. fprintf(stderr,"b_o_s flag not set on packet!\n");
  1070. exit(1);
  1071. }
  1072. if(bosflag && op_de.b_o_s){
  1073. fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
  1074. exit(1);
  1075. }
  1076. bosflag=1;
  1077. depacket+=op_de.bytes;
  1078. /* check eos flag */
  1079. if(eosflag){
  1080. fprintf(stderr,"Multiple decoded packets with eos flag!\n");
  1081. exit(1);
  1082. }
  1083. if(op_de.e_o_s)eosflag=1;
  1084. /* check granulepos flag */
  1085. if(op_de.granulepos!=-1){
  1086. fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
  1087. }
  1088. }
  1089. }
  1090. }
  1091. }
  1092. }
  1093. }
  1094. _ogg_free(data);
  1095. if(headers[pageno]!=NULL){
  1096. fprintf(stderr,"did not write last page!\n");
  1097. exit(1);
  1098. }
  1099. if(headers[pageout]!=NULL){
  1100. fprintf(stderr,"did not decode last page!\n");
  1101. exit(1);
  1102. }
  1103. if(inptr!=outptr){
  1104. fprintf(stderr,"encoded page data incomplete!\n");
  1105. exit(1);
  1106. }
  1107. if(inptr!=deptr){
  1108. fprintf(stderr,"decoded page data incomplete!\n");
  1109. exit(1);
  1110. }
  1111. if(inptr!=depacket){
  1112. fprintf(stderr,"decoded packet data incomplete!\n");
  1113. exit(1);
  1114. }
  1115. if(!eosflag){
  1116. fprintf(stderr,"Never got a packet with EOS set!\n");
  1117. exit(1);
  1118. }
  1119. fprintf(stderr,"ok.\n");
  1120. }
  1121. int main(void){
  1122. ogg_stream_init(&os_en,0x04030201);
  1123. ogg_stream_init(&os_de,0x04030201);
  1124. ogg_sync_init(&oy);
  1125. /* Exercise each code path in the framing code. Also verify that
  1126. the checksums are working. */
  1127. {
  1128. /* 17 only */
  1129. const int packets[]={17, -1};
  1130. const int *headret[]={head1_0,NULL};
  1131. fprintf(stderr,"testing single page encoding... ");
  1132. test_pack(packets,headret);
  1133. }
  1134. {
  1135. /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
  1136. const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
  1137. const int *headret[]={head1_1,head2_1,NULL};
  1138. fprintf(stderr,"testing basic page encoding... ");
  1139. test_pack(packets,headret);
  1140. }
  1141. {
  1142. /* nil packets; beginning,middle,end */
  1143. const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
  1144. const int *headret[]={head1_2,head2_2,NULL};
  1145. fprintf(stderr,"testing basic nil packets... ");
  1146. test_pack(packets,headret);
  1147. }
  1148. {
  1149. /* large initial packet */
  1150. const int packets[]={4345,259,255,-1};
  1151. const int *headret[]={head1_3,head2_3,NULL};
  1152. fprintf(stderr,"testing initial-packet lacing > 4k... ");
  1153. test_pack(packets,headret);
  1154. }
  1155. {
  1156. /* continuing packet test */
  1157. const int packets[]={0,4345,259,255,-1};
  1158. const int *headret[]={head1_4,head2_4,head3_4,NULL};
  1159. fprintf(stderr,"testing single packet page span... ");
  1160. test_pack(packets,headret);
  1161. }
  1162. /* page with the 255 segment limit */
  1163. {
  1164. const int packets[]={0,10,10,10,10,10,10,10,10,
  1165. 10,10,10,10,10,10,10,10,
  1166. 10,10,10,10,10,10,10,10,
  1167. 10,10,10,10,10,10,10,10,
  1168. 10,10,10,10,10,10,10,10,
  1169. 10,10,10,10,10,10,10,10,
  1170. 10,10,10,10,10,10,10,10,
  1171. 10,10,10,10,10,10,10,10,
  1172. 10,10,10,10,10,10,10,10,
  1173. 10,10,10,10,10,10,10,10,
  1174. 10,10,10,10,10,10,10,10,
  1175. 10,10,10,10,10,10,10,10,
  1176. 10,10,10,10,10,10,10,10,
  1177. 10,10,10,10,10,10,10,10,
  1178. 10,10,10,10,10,10,10,10,
  1179. 10,10,10,10,10,10,10,10,
  1180. 10,10,10,10,10,10,10,10,
  1181. 10,10,10,10,10,10,10,10,
  1182. 10,10,10,10,10,10,10,10,
  1183. 10,10,10,10,10,10,10,10,
  1184. 10,10,10,10,10,10,10,10,
  1185. 10,10,10,10,10,10,10,10,
  1186. 10,10,10,10,10,10,10,10,
  1187. 10,10,10,10,10,10,10,10,
  1188. 10,10,10,10,10,10,10,10,
  1189. 10,10,10,10,10,10,10,10,
  1190. 10,10,10,10,10,10,10,10,
  1191. 10,10,10,10,10,10,10,10,
  1192. 10,10,10,10,10,10,10,10,
  1193. 10,10,10,10,10,10,10,10,
  1194. 10,10,10,10,10,10,10,10,
  1195. 10,10,10,10,10,10,10,50,-1};
  1196. const int *headret[]={head1_5,head2_5,head3_5,NULL};
  1197. fprintf(stderr,"testing max packet segments... ");
  1198. test_pack(packets,headret);
  1199. }
  1200. {
  1201. /* packet that overspans over an entire page */
  1202. const int packets[]={0,100,9000,259,255,-1};
  1203. const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
  1204. fprintf(stderr,"testing very large packets... ");
  1205. test_pack(packets,headret);
  1206. }
  1207. {
  1208. /* term only page. why not? */
  1209. const int packets[]={0,100,4080,-1};
  1210. const int *headret[]={head1_7,head2_7,head3_7,NULL};
  1211. fprintf(stderr,"testing zero data page (1 nil packet)... ");
  1212. test_pack(packets,headret);
  1213. }
  1214. {
  1215. /* build a bunch of pages for testing */
  1216. unsigned char *data=_ogg_malloc(1024*1024);
  1217. int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1};
  1218. int inptr=0,i,j;
  1219. ogg_page og[5];
  1220. ogg_stream_reset(&os_en);
  1221. for(i=0;pl[i]!=-1;i++){
  1222. ogg_packet op;
  1223. int len=pl[i];
  1224. op.packet=data+inptr;
  1225. op.bytes=len;
  1226. op.e_o_s=(pl[i+1]<0?1:0);
  1227. op.granulepos=(i+1)*1000;
  1228. for(j=0;j<len;j++)data[inptr++]=i+j;
  1229. ogg_stream_packetin(&os_en,&op);
  1230. }
  1231. _ogg_free(data);
  1232. /* retrieve finished pages */
  1233. for(i=0;i<5;i++){
  1234. if(ogg_stream_pageout(&os_en,&og[i])==0){
  1235. fprintf(stderr,"Too few pages output building sync tests!\n");
  1236. exit(1);
  1237. }
  1238. copy_page(&og[i]);
  1239. }
  1240. /* Test lost pages on pagein/packetout: no rollback */
  1241. {
  1242. ogg_page temp;
  1243. ogg_packet test;
  1244. fprintf(stderr,"Testing loss of pages... ");
  1245. ogg_sync_reset(&oy);
  1246. ogg_stream_reset(&os_de);
  1247. for(i=0;i<5;i++){
  1248. memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
  1249. og[i].header_len);
  1250. ogg_sync_wrote(&oy,og[i].header_len);
  1251. memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
  1252. ogg_sync_wrote(&oy,og[i].body_len);
  1253. }
  1254. ogg_sync_pageout(&oy,&temp);
  1255. ogg_stream_pagein(&os_de,&temp);
  1256. ogg_sync_pageout(&oy,&temp);
  1257. ogg_stream_pagein(&os_de,&temp);
  1258. ogg_sync_pageout(&oy,&temp);
  1259. /* skip */
  1260. ogg_sync_pageout(&oy,&temp);
  1261. ogg_stream_pagein(&os_de,&temp);
  1262. /* do we get the expected results/packets? */
  1263. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1264. checkpacket(&test,0,0,0);
  1265. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1266. checkpacket(&test,100,1,-1);
  1267. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1268. checkpacket(&test,4079,2,3000);
  1269. if(ogg_stream_packetout(&os_de,&test)!=-1){
  1270. fprintf(stderr,"Error: loss of page did not return error\n");
  1271. exit(1);
  1272. }
  1273. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1274. checkpacket(&test,76,5,-1);
  1275. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1276. checkpacket(&test,34,6,-1);
  1277. fprintf(stderr,"ok.\n");
  1278. }
  1279. /* Test lost pages on pagein/packetout: rollback with continuation */
  1280. {
  1281. ogg_page temp;
  1282. ogg_packet test;
  1283. fprintf(stderr,"Testing loss of pages (rollback required)... ");
  1284. ogg_sync_reset(&oy);
  1285. ogg_stream_reset(&os_de);
  1286. for(i=0;i<5;i++){
  1287. memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
  1288. og[i].header_len);
  1289. ogg_sync_wrote(&oy,og[i].header_len);
  1290. memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
  1291. ogg_sync_wrote(&oy,og[i].body_len);
  1292. }
  1293. ogg_sync_pageout(&oy,&temp);
  1294. ogg_stream_pagein(&os_de,&temp);
  1295. ogg_sync_pageout(&oy,&temp);
  1296. ogg_stream_pagein(&os_de,&temp);
  1297. ogg_sync_pageout(&oy,&temp);
  1298. ogg_stream_pagein(&os_de,&temp);
  1299. ogg_sync_pageout(&oy,&temp);
  1300. /* skip */
  1301. ogg_sync_pageout(&oy,&temp);
  1302. ogg_stream_pagein(&os_de,&temp);
  1303. /* do we get the expected results/packets? */
  1304. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1305. checkpacket(&test,0,0,0);
  1306. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1307. checkpacket(&test,100,1,-1);
  1308. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1309. checkpacket(&test,4079,2,3000);
  1310. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1311. checkpacket(&test,2956,3,4000);
  1312. if(ogg_stream_packetout(&os_de,&test)!=-1){
  1313. fprintf(stderr,"Error: loss of page did not return error\n");
  1314. exit(1);
  1315. }
  1316. if(ogg_stream_packetout(&os_de,&test)!=1)error();
  1317. checkpacket(&test,300,13,14000);
  1318. fprintf(stderr,"ok.\n");
  1319. }
  1320. /* the rest only test sync */
  1321. {
  1322. ogg_page og_de;
  1323. /* Test fractional page inputs: incomplete capture */
  1324. fprintf(stderr,"Testing sync on partial inputs... ");
  1325. ogg_sync_reset(&oy);
  1326. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1327. 3);
  1328. ogg_sync_wrote(&oy,3);
  1329. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1330. /* Test fractional page inputs: incomplete fixed header */
  1331. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
  1332. 20);
  1333. ogg_sync_wrote(&oy,20);
  1334. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1335. /* Test fractional page inputs: incomplete header */
  1336. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
  1337. 5);
  1338. ogg_sync_wrote(&oy,5);
  1339. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1340. /* Test fractional page inputs: incomplete body */
  1341. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
  1342. og[1].header_len-28);
  1343. ogg_sync_wrote(&oy,og[1].header_len-28);
  1344. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1345. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
  1346. ogg_sync_wrote(&oy,1000);
  1347. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1348. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
  1349. og[1].body_len-1000);
  1350. ogg_sync_wrote(&oy,og[1].body_len-1000);
  1351. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1352. fprintf(stderr,"ok.\n");
  1353. }
  1354. /* Test fractional page inputs: page + incomplete capture */
  1355. {
  1356. ogg_page og_de;
  1357. fprintf(stderr,"Testing sync on 1+partial inputs... ");
  1358. ogg_sync_reset(&oy);
  1359. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1360. og[1].header_len);
  1361. ogg_sync_wrote(&oy,og[1].header_len);
  1362. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1363. og[1].body_len);
  1364. ogg_sync_wrote(&oy,og[1].body_len);
  1365. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1366. 20);
  1367. ogg_sync_wrote(&oy,20);
  1368. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1369. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1370. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
  1371. og[1].header_len-20);
  1372. ogg_sync_wrote(&oy,og[1].header_len-20);
  1373. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1374. og[1].body_len);
  1375. ogg_sync_wrote(&oy,og[1].body_len);
  1376. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1377. fprintf(stderr,"ok.\n");
  1378. }
  1379. /* Test recapture: garbage + page */
  1380. {
  1381. ogg_page og_de;
  1382. fprintf(stderr,"Testing search for capture... ");
  1383. ogg_sync_reset(&oy);
  1384. /* 'garbage' */
  1385. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1386. og[1].body_len);
  1387. ogg_sync_wrote(&oy,og[1].body_len);
  1388. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1389. og[1].header_len);
  1390. ogg_sync_wrote(&oy,og[1].header_len);
  1391. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1392. og[1].body_len);
  1393. ogg_sync_wrote(&oy,og[1].body_len);
  1394. memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
  1395. 20);
  1396. ogg_sync_wrote(&oy,20);
  1397. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1398. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1399. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1400. memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
  1401. og[2].header_len-20);
  1402. ogg_sync_wrote(&oy,og[2].header_len-20);
  1403. memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
  1404. og[2].body_len);
  1405. ogg_sync_wrote(&oy,og[2].body_len);
  1406. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1407. fprintf(stderr,"ok.\n");
  1408. }
  1409. /* Test recapture: page + garbage + page */
  1410. {
  1411. ogg_page og_de;
  1412. fprintf(stderr,"Testing recapture... ");
  1413. ogg_sync_reset(&oy);
  1414. memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
  1415. og[1].header_len);
  1416. ogg_sync_wrote(&oy,og[1].header_len);
  1417. memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
  1418. og[1].body_len);
  1419. ogg_sync_wrote(&oy,og[1].body_len);
  1420. memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
  1421. og[2].header_len);
  1422. ogg_sync_wrote(&oy,og[2].header_len);
  1423. memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
  1424. og[2].header_len);
  1425. ogg_sync_wrote(&oy,og[2].header_len);
  1426. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1427. memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
  1428. og[2].body_len-5);
  1429. ogg_sync_wrote(&oy,og[2].body_len-5);
  1430. memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
  1431. og[3].header_len);
  1432. ogg_sync_wrote(&oy,og[3].header_len);
  1433. memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
  1434. og[3].body_len);
  1435. ogg_sync_wrote(&oy,og[3].body_len);
  1436. if(ogg_sync_pageout(&oy,&og_de)>0)error();
  1437. if(ogg_sync_pageout(&oy,&og_de)<=0)error();
  1438. fprintf(stderr,"ok.\n");
  1439. }
  1440. }
  1441. return(0);
  1442. }
  1443. #endif