1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libogg/src/ogg_framing.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2093 @@ 1.4 +/******************************************************************** 1.5 + * * 1.6 + * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. * 1.7 + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 1.8 + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 1.9 + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 1.10 + * * 1.11 + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 * 1.12 + * by the Xiph.Org Foundation http://www.xiph.org/ * 1.13 + * * 1.14 + ******************************************************************** 1.15 + 1.16 + function: code raw packets into framed OggSquish stream and 1.17 + decode Ogg streams back into raw packets 1.18 + last mod: $Id: framing.c 18052 2011-08-04 17:57:02Z giles $ 1.19 + 1.20 + note: The CRC code is directly derived from public domain code by 1.21 + Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html 1.22 + for details. 1.23 + 1.24 + ********************************************************************/ 1.25 + 1.26 +#include <stdlib.h> 1.27 +#include <string.h> 1.28 +#include <ogg/ogg.h> 1.29 + 1.30 +/* A complete description of Ogg framing exists in docs/framing.html */ 1.31 + 1.32 +int ogg_page_version(const ogg_page *og){ 1.33 + return((int)(og->header[4])); 1.34 +} 1.35 + 1.36 +int ogg_page_continued(const ogg_page *og){ 1.37 + return((int)(og->header[5]&0x01)); 1.38 +} 1.39 + 1.40 +int ogg_page_bos(const ogg_page *og){ 1.41 + return((int)(og->header[5]&0x02)); 1.42 +} 1.43 + 1.44 +int ogg_page_eos(const ogg_page *og){ 1.45 + return((int)(og->header[5]&0x04)); 1.46 +} 1.47 + 1.48 +ogg_int64_t ogg_page_granulepos(const ogg_page *og){ 1.49 + unsigned char *page=og->header; 1.50 + ogg_int64_t granulepos=page[13]&(0xff); 1.51 + granulepos= (granulepos<<8)|(page[12]&0xff); 1.52 + granulepos= (granulepos<<8)|(page[11]&0xff); 1.53 + granulepos= (granulepos<<8)|(page[10]&0xff); 1.54 + granulepos= (granulepos<<8)|(page[9]&0xff); 1.55 + granulepos= (granulepos<<8)|(page[8]&0xff); 1.56 + granulepos= (granulepos<<8)|(page[7]&0xff); 1.57 + granulepos= (granulepos<<8)|(page[6]&0xff); 1.58 + return(granulepos); 1.59 +} 1.60 + 1.61 +int ogg_page_serialno(const ogg_page *og){ 1.62 + return(og->header[14] | 1.63 + (og->header[15]<<8) | 1.64 + (og->header[16]<<16) | 1.65 + (og->header[17]<<24)); 1.66 +} 1.67 + 1.68 +long ogg_page_pageno(const ogg_page *og){ 1.69 + return(og->header[18] | 1.70 + (og->header[19]<<8) | 1.71 + (og->header[20]<<16) | 1.72 + (og->header[21]<<24)); 1.73 +} 1.74 + 1.75 + 1.76 + 1.77 +/* returns the number of packets that are completed on this page (if 1.78 + the leading packet is begun on a previous page, but ends on this 1.79 + page, it's counted */ 1.80 + 1.81 +/* NOTE: 1.82 + If a page consists of a packet begun on a previous page, and a new 1.83 + packet begun (but not completed) on this page, the return will be: 1.84 + ogg_page_packets(page) ==1, 1.85 + ogg_page_continued(page) !=0 1.86 + 1.87 + If a page happens to be a single packet that was begun on a 1.88 + previous page, and spans to the next page (in the case of a three or 1.89 + more page packet), the return will be: 1.90 + ogg_page_packets(page) ==0, 1.91 + ogg_page_continued(page) !=0 1.92 +*/ 1.93 + 1.94 +int ogg_page_packets(const ogg_page *og){ 1.95 + int i,n=og->header[26],count=0; 1.96 + for(i=0;i<n;i++) 1.97 + if(og->header[27+i]<255)count++; 1.98 + return(count); 1.99 +} 1.100 + 1.101 + 1.102 +#if 0 1.103 +/* helper to initialize lookup for direct-table CRC (illustrative; we 1.104 + use the static init below) */ 1.105 + 1.106 +static ogg_uint32_t _ogg_crc_entry(unsigned long index){ 1.107 + int i; 1.108 + unsigned long r; 1.109 + 1.110 + r = index << 24; 1.111 + for (i=0; i<8; i++) 1.112 + if (r & 0x80000000UL) 1.113 + r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator 1.114 + polynomial, although we use an 1.115 + unreflected alg and an init/final 1.116 + of 0, not 0xffffffff */ 1.117 + else 1.118 + r<<=1; 1.119 + return (r & 0xffffffffUL); 1.120 +} 1.121 +#endif 1.122 + 1.123 +static const ogg_uint32_t crc_lookup[256]={ 1.124 + 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9, 1.125 + 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005, 1.126 + 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61, 1.127 + 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd, 1.128 + 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9, 1.129 + 0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75, 1.130 + 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011, 1.131 + 0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd, 1.132 + 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039, 1.133 + 0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5, 1.134 + 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81, 1.135 + 0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d, 1.136 + 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49, 1.137 + 0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95, 1.138 + 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1, 1.139 + 0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d, 1.140 + 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae, 1.141 + 0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072, 1.142 + 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16, 1.143 + 0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca, 1.144 + 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde, 1.145 + 0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02, 1.146 + 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066, 1.147 + 0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba, 1.148 + 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e, 1.149 + 0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692, 1.150 + 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6, 1.151 + 0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a, 1.152 + 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e, 1.153 + 0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2, 1.154 + 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686, 1.155 + 0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a, 1.156 + 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637, 1.157 + 0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb, 1.158 + 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f, 1.159 + 0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53, 1.160 + 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47, 1.161 + 0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b, 1.162 + 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff, 1.163 + 0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623, 1.164 + 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7, 1.165 + 0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b, 1.166 + 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f, 1.167 + 0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3, 1.168 + 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7, 1.169 + 0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b, 1.170 + 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f, 1.171 + 0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3, 1.172 + 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640, 1.173 + 0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c, 1.174 + 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8, 1.175 + 0x68860bfd,0x6c47164a,0x61043093,0x65c52d24, 1.176 + 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30, 1.177 + 0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec, 1.178 + 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088, 1.179 + 0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654, 1.180 + 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0, 1.181 + 0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c, 1.182 + 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18, 1.183 + 0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4, 1.184 + 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0, 1.185 + 0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c, 1.186 + 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668, 1.187 + 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4}; 1.188 + 1.189 +/* init the encode/decode logical stream state */ 1.190 + 1.191 +int ogg_stream_init(ogg_stream_state *os,int serialno){ 1.192 + if(os){ 1.193 + memset(os,0,sizeof(*os)); 1.194 + os->body_storage=16*1024; 1.195 + os->lacing_storage=1024; 1.196 + 1.197 + os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data)); 1.198 + os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals)); 1.199 + os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals)); 1.200 + 1.201 + if(!os->body_data || !os->lacing_vals || !os->granule_vals){ 1.202 + ogg_stream_clear(os); 1.203 + return -1; 1.204 + } 1.205 + 1.206 + os->serialno=serialno; 1.207 + 1.208 + return(0); 1.209 + } 1.210 + return(-1); 1.211 +} 1.212 + 1.213 +/* async/delayed error detection for the ogg_stream_state */ 1.214 +int ogg_stream_check(ogg_stream_state *os){ 1.215 + if(!os || !os->body_data) return -1; 1.216 + return 0; 1.217 +} 1.218 + 1.219 +/* _clear does not free os, only the non-flat storage within */ 1.220 +int ogg_stream_clear(ogg_stream_state *os){ 1.221 + if(os){ 1.222 + if(os->body_data)_ogg_free(os->body_data); 1.223 + if(os->lacing_vals)_ogg_free(os->lacing_vals); 1.224 + if(os->granule_vals)_ogg_free(os->granule_vals); 1.225 + 1.226 + memset(os,0,sizeof(*os)); 1.227 + } 1.228 + return(0); 1.229 +} 1.230 + 1.231 +int ogg_stream_destroy(ogg_stream_state *os){ 1.232 + if(os){ 1.233 + ogg_stream_clear(os); 1.234 + _ogg_free(os); 1.235 + } 1.236 + return(0); 1.237 +} 1.238 + 1.239 +/* Helpers for ogg_stream_encode; this keeps the structure and 1.240 + what's happening fairly clear */ 1.241 + 1.242 +static int _os_body_expand(ogg_stream_state *os,int needed){ 1.243 + if(os->body_storage<=os->body_fill+needed){ 1.244 + void *ret; 1.245 + ret=_ogg_realloc(os->body_data,(os->body_storage+needed+1024)* 1.246 + sizeof(*os->body_data)); 1.247 + if(!ret){ 1.248 + ogg_stream_clear(os); 1.249 + return -1; 1.250 + } 1.251 + os->body_storage+=(needed+1024); 1.252 + os->body_data=ret; 1.253 + } 1.254 + return 0; 1.255 +} 1.256 + 1.257 +static int _os_lacing_expand(ogg_stream_state *os,int needed){ 1.258 + if(os->lacing_storage<=os->lacing_fill+needed){ 1.259 + void *ret; 1.260 + ret=_ogg_realloc(os->lacing_vals,(os->lacing_storage+needed+32)* 1.261 + sizeof(*os->lacing_vals)); 1.262 + if(!ret){ 1.263 + ogg_stream_clear(os); 1.264 + return -1; 1.265 + } 1.266 + os->lacing_vals=ret; 1.267 + ret=_ogg_realloc(os->granule_vals,(os->lacing_storage+needed+32)* 1.268 + sizeof(*os->granule_vals)); 1.269 + if(!ret){ 1.270 + ogg_stream_clear(os); 1.271 + return -1; 1.272 + } 1.273 + os->granule_vals=ret; 1.274 + os->lacing_storage+=(needed+32); 1.275 + } 1.276 + return 0; 1.277 +} 1.278 + 1.279 +/* checksum the page */ 1.280 +/* Direct table CRC; note that this will be faster in the future if we 1.281 + perform the checksum simultaneously with other copies */ 1.282 + 1.283 +void ogg_page_checksum_set(ogg_page *og){ 1.284 + if(og){ 1.285 + ogg_uint32_t crc_reg=0; 1.286 + int i; 1.287 + 1.288 + /* safety; needed for API behavior, but not framing code */ 1.289 + og->header[22]=0; 1.290 + og->header[23]=0; 1.291 + og->header[24]=0; 1.292 + og->header[25]=0; 1.293 + 1.294 + for(i=0;i<og->header_len;i++) 1.295 + crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]]; 1.296 + for(i=0;i<og->body_len;i++) 1.297 + crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]]; 1.298 + 1.299 + og->header[22]=(unsigned char)(crc_reg&0xff); 1.300 + og->header[23]=(unsigned char)((crc_reg>>8)&0xff); 1.301 + og->header[24]=(unsigned char)((crc_reg>>16)&0xff); 1.302 + og->header[25]=(unsigned char)((crc_reg>>24)&0xff); 1.303 + } 1.304 +} 1.305 + 1.306 +/* submit data to the internal buffer of the framing engine */ 1.307 +int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count, 1.308 + long e_o_s, ogg_int64_t granulepos){ 1.309 + 1.310 + int bytes = 0, lacing_vals, i; 1.311 + 1.312 + if(ogg_stream_check(os)) return -1; 1.313 + if(!iov) return 0; 1.314 + 1.315 + for (i = 0; i < count; ++i) bytes += (int)iov[i].iov_len; 1.316 + lacing_vals=bytes/255+1; 1.317 + 1.318 + if(os->body_returned){ 1.319 + /* advance packet data according to the body_returned pointer. We 1.320 + had to keep it around to return a pointer into the buffer last 1.321 + call */ 1.322 + 1.323 + os->body_fill-=os->body_returned; 1.324 + if(os->body_fill) 1.325 + memmove(os->body_data,os->body_data+os->body_returned, 1.326 + os->body_fill); 1.327 + os->body_returned=0; 1.328 + } 1.329 + 1.330 + /* make sure we have the buffer storage */ 1.331 + if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals)) 1.332 + return -1; 1.333 + 1.334 + /* Copy in the submitted packet. Yes, the copy is a waste; this is 1.335 + the liability of overly clean abstraction for the time being. It 1.336 + will actually be fairly easy to eliminate the extra copy in the 1.337 + future */ 1.338 + 1.339 + for (i = 0; i < count; ++i) { 1.340 + memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len); 1.341 + os->body_fill += (int)iov[i].iov_len; 1.342 + } 1.343 + 1.344 + /* Store lacing vals for this packet */ 1.345 + for(i=0;i<lacing_vals-1;i++){ 1.346 + os->lacing_vals[os->lacing_fill+i]=255; 1.347 + os->granule_vals[os->lacing_fill+i]=os->granulepos; 1.348 + } 1.349 + os->lacing_vals[os->lacing_fill+i]=bytes%255; 1.350 + os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos; 1.351 + 1.352 + /* flag the first segment as the beginning of the packet */ 1.353 + os->lacing_vals[os->lacing_fill]|= 0x100; 1.354 + 1.355 + os->lacing_fill+=lacing_vals; 1.356 + 1.357 + /* for the sake of completeness */ 1.358 + os->packetno++; 1.359 + 1.360 + if(e_o_s)os->e_o_s=1; 1.361 + 1.362 + return(0); 1.363 +} 1.364 + 1.365 +int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){ 1.366 + ogg_iovec_t iov; 1.367 + iov.iov_base = op->packet; 1.368 + iov.iov_len = op->bytes; 1.369 + return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos); 1.370 +} 1.371 + 1.372 +/* Conditionally flush a page; force==0 will only flush nominal-size 1.373 + pages, force==1 forces us to flush a page regardless of page size 1.374 + so long as there's any data available at all. */ 1.375 +static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){ 1.376 + int i; 1.377 + int vals=0; 1.378 + int maxvals=(os->lacing_fill>255?255:os->lacing_fill); 1.379 + int bytes=0; 1.380 + long acc=0; 1.381 + ogg_int64_t granule_pos=-1; 1.382 + 1.383 + if(ogg_stream_check(os)) return(0); 1.384 + if(maxvals==0) return(0); 1.385 + 1.386 + /* construct a page */ 1.387 + /* decide how many segments to include */ 1.388 + 1.389 + /* If this is the initial header case, the first page must only include 1.390 + the initial header packet */ 1.391 + if(os->b_o_s==0){ /* 'initial header page' case */ 1.392 + granule_pos=0; 1.393 + for(vals=0;vals<maxvals;vals++){ 1.394 + if((os->lacing_vals[vals]&0x0ff)<255){ 1.395 + vals++; 1.396 + break; 1.397 + } 1.398 + } 1.399 + }else{ 1.400 + 1.401 + /* The extra packets_done, packet_just_done logic here attempts to do two things: 1.402 + 1) Don't unneccessarily span pages. 1.403 + 2) Unless necessary, don't flush pages if there are less than four packets on 1.404 + them; this expands page size to reduce unneccessary overhead if incoming packets 1.405 + are large. 1.406 + These are not necessary behaviors, just 'always better than naive flushing' 1.407 + without requiring an application to explicitly request a specific optimized 1.408 + behavior. We'll want an explicit behavior setup pathway eventually as well. */ 1.409 + 1.410 + int packets_done=0; 1.411 + int packet_just_done=0; 1.412 + for(vals=0;vals<maxvals;vals++){ 1.413 + if(acc>nfill && packet_just_done>=4){ 1.414 + force=1; 1.415 + break; 1.416 + } 1.417 + acc+=os->lacing_vals[vals]&0x0ff; 1.418 + if((os->lacing_vals[vals]&0xff)<255){ 1.419 + granule_pos=os->granule_vals[vals]; 1.420 + packet_just_done=++packets_done; 1.421 + }else 1.422 + packet_just_done=0; 1.423 + } 1.424 + if(vals==255)force=1; 1.425 + } 1.426 + 1.427 + if(!force) return(0); 1.428 + 1.429 + /* construct the header in temp storage */ 1.430 + memcpy(os->header,"OggS",4); 1.431 + 1.432 + /* stream structure version */ 1.433 + os->header[4]=0x00; 1.434 + 1.435 + /* continued packet flag? */ 1.436 + os->header[5]=0x00; 1.437 + if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01; 1.438 + /* first page flag? */ 1.439 + if(os->b_o_s==0)os->header[5]|=0x02; 1.440 + /* last page flag? */ 1.441 + if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04; 1.442 + os->b_o_s=1; 1.443 + 1.444 + /* 64 bits of PCM position */ 1.445 + for(i=6;i<14;i++){ 1.446 + os->header[i]=(unsigned char)(granule_pos&0xff); 1.447 + granule_pos>>=8; 1.448 + } 1.449 + 1.450 + /* 32 bits of stream serial number */ 1.451 + { 1.452 + long serialno=os->serialno; 1.453 + for(i=14;i<18;i++){ 1.454 + os->header[i]=(unsigned char)(serialno&0xff); 1.455 + serialno>>=8; 1.456 + } 1.457 + } 1.458 + 1.459 + /* 32 bits of page counter (we have both counter and page header 1.460 + because this val can roll over) */ 1.461 + if(os->pageno==-1)os->pageno=0; /* because someone called 1.462 + stream_reset; this would be a 1.463 + strange thing to do in an 1.464 + encode stream, but it has 1.465 + plausible uses */ 1.466 + { 1.467 + long pageno=os->pageno++; 1.468 + for(i=18;i<22;i++){ 1.469 + os->header[i]=(unsigned char)(pageno&0xff); 1.470 + pageno>>=8; 1.471 + } 1.472 + } 1.473 + 1.474 + /* zero for computation; filled in later */ 1.475 + os->header[22]=0; 1.476 + os->header[23]=0; 1.477 + os->header[24]=0; 1.478 + os->header[25]=0; 1.479 + 1.480 + /* segment table */ 1.481 + os->header[26]=(unsigned char)(vals&0xff); 1.482 + for(i=0;i<vals;i++) 1.483 + bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff); 1.484 + 1.485 + /* set pointers in the ogg_page struct */ 1.486 + og->header=os->header; 1.487 + og->header_len=os->header_fill=vals+27; 1.488 + og->body=os->body_data+os->body_returned; 1.489 + og->body_len=bytes; 1.490 + 1.491 + /* advance the lacing data and set the body_returned pointer */ 1.492 + 1.493 + os->lacing_fill-=vals; 1.494 + memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals)); 1.495 + memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals)); 1.496 + os->body_returned+=bytes; 1.497 + 1.498 + /* calculate the checksum */ 1.499 + 1.500 + ogg_page_checksum_set(og); 1.501 + 1.502 + /* done */ 1.503 + return(1); 1.504 +} 1.505 + 1.506 +/* This will flush remaining packets into a page (returning nonzero), 1.507 + even if there is not enough data to trigger a flush normally 1.508 + (undersized page). If there are no packets or partial packets to 1.509 + flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will 1.510 + try to flush a normal sized page like ogg_stream_pageout; a call to 1.511 + ogg_stream_flush does not guarantee that all packets have flushed. 1.512 + Only a return value of 0 from ogg_stream_flush indicates all packet 1.513 + data is flushed into pages. 1.514 + 1.515 + since ogg_stream_flush will flush the last page in a stream even if 1.516 + it's undersized, you almost certainly want to use ogg_stream_pageout 1.517 + (and *not* ogg_stream_flush) unless you specifically need to flush 1.518 + a page regardless of size in the middle of a stream. */ 1.519 + 1.520 +int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){ 1.521 + return ogg_stream_flush_i(os,og,1,4096); 1.522 +} 1.523 + 1.524 +/* Like the above, but an argument is provided to adjust the nominal 1.525 + page size for applications which are smart enough to provide their 1.526 + own delay based flushing */ 1.527 + 1.528 +int ogg_stream_flush_fill(ogg_stream_state *os,ogg_page *og, int nfill){ 1.529 + return ogg_stream_flush_i(os,og,1,nfill); 1.530 +} 1.531 + 1.532 +/* This constructs pages from buffered packet segments. The pointers 1.533 +returned are to static buffers; do not free. The returned buffers are 1.534 +good only until the next call (using the same ogg_stream_state) */ 1.535 + 1.536 +int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){ 1.537 + int force=0; 1.538 + if(ogg_stream_check(os)) return 0; 1.539 + 1.540 + if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */ 1.541 + (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */ 1.542 + force=1; 1.543 + 1.544 + return(ogg_stream_flush_i(os,og,force,4096)); 1.545 +} 1.546 + 1.547 +/* Like the above, but an argument is provided to adjust the nominal 1.548 +page size for applications which are smart enough to provide their 1.549 +own delay based flushing */ 1.550 + 1.551 +int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){ 1.552 + int force=0; 1.553 + if(ogg_stream_check(os)) return 0; 1.554 + 1.555 + if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */ 1.556 + (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */ 1.557 + force=1; 1.558 + 1.559 + return(ogg_stream_flush_i(os,og,force,nfill)); 1.560 +} 1.561 + 1.562 +int ogg_stream_eos(ogg_stream_state *os){ 1.563 + if(ogg_stream_check(os)) return 1; 1.564 + return os->e_o_s; 1.565 +} 1.566 + 1.567 +/* DECODING PRIMITIVES: packet streaming layer **********************/ 1.568 + 1.569 +/* This has two layers to place more of the multi-serialno and paging 1.570 + control in the application's hands. First, we expose a data buffer 1.571 + using ogg_sync_buffer(). The app either copies into the 1.572 + buffer, or passes it directly to read(), etc. We then call 1.573 + ogg_sync_wrote() to tell how many bytes we just added. 1.574 + 1.575 + Pages are returned (pointers into the buffer in ogg_sync_state) 1.576 + by ogg_sync_pageout(). The page is then submitted to 1.577 + ogg_stream_pagein() along with the appropriate 1.578 + ogg_stream_state* (ie, matching serialno). We then get raw 1.579 + packets out calling ogg_stream_packetout() with a 1.580 + ogg_stream_state. */ 1.581 + 1.582 +/* initialize the struct to a known state */ 1.583 +int ogg_sync_init(ogg_sync_state *oy){ 1.584 + if(oy){ 1.585 + oy->storage = -1; /* used as a readiness flag */ 1.586 + memset(oy,0,sizeof(*oy)); 1.587 + } 1.588 + return(0); 1.589 +} 1.590 + 1.591 +/* clear non-flat storage within */ 1.592 +int ogg_sync_clear(ogg_sync_state *oy){ 1.593 + if(oy){ 1.594 + if(oy->data)_ogg_free(oy->data); 1.595 + memset(oy,0,sizeof(*oy)); 1.596 + } 1.597 + return(0); 1.598 +} 1.599 + 1.600 +int ogg_sync_destroy(ogg_sync_state *oy){ 1.601 + if(oy){ 1.602 + ogg_sync_clear(oy); 1.603 + _ogg_free(oy); 1.604 + } 1.605 + return(0); 1.606 +} 1.607 + 1.608 +int ogg_sync_check(ogg_sync_state *oy){ 1.609 + if(oy->storage<0) return -1; 1.610 + return 0; 1.611 +} 1.612 + 1.613 +char *ogg_sync_buffer(ogg_sync_state *oy, long size){ 1.614 + if(ogg_sync_check(oy)) return NULL; 1.615 + 1.616 + /* first, clear out any space that has been previously returned */ 1.617 + if(oy->returned){ 1.618 + oy->fill-=oy->returned; 1.619 + if(oy->fill>0) 1.620 + memmove(oy->data,oy->data+oy->returned,oy->fill); 1.621 + oy->returned=0; 1.622 + } 1.623 + 1.624 + if(size>oy->storage-oy->fill){ 1.625 + /* We need to extend the internal buffer */ 1.626 + long newsize=size+oy->fill+4096; /* an extra page to be nice */ 1.627 + void *ret; 1.628 + 1.629 + if(oy->data) 1.630 + ret=_ogg_realloc(oy->data,newsize); 1.631 + else 1.632 + ret=_ogg_malloc(newsize); 1.633 + if(!ret){ 1.634 + ogg_sync_clear(oy); 1.635 + return NULL; 1.636 + } 1.637 + oy->data=ret; 1.638 + oy->storage=newsize; 1.639 + } 1.640 + 1.641 + /* expose a segment at least as large as requested at the fill mark */ 1.642 + return((char *)oy->data+oy->fill); 1.643 +} 1.644 + 1.645 +int ogg_sync_wrote(ogg_sync_state *oy, long bytes){ 1.646 + if(ogg_sync_check(oy))return -1; 1.647 + if(oy->fill+bytes>oy->storage)return -1; 1.648 + oy->fill+=bytes; 1.649 + return(0); 1.650 +} 1.651 + 1.652 +/* sync the stream. This is meant to be useful for finding page 1.653 + boundaries. 1.654 + 1.655 + return values for this: 1.656 + -n) skipped n bytes 1.657 + 0) page not ready; more data (no bytes skipped) 1.658 + n) page synced at current location; page length n bytes 1.659 + 1.660 +*/ 1.661 + 1.662 +long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ 1.663 + unsigned char *page=oy->data+oy->returned; 1.664 + unsigned char *next; 1.665 + long bytes=oy->fill-oy->returned; 1.666 + 1.667 + if(ogg_sync_check(oy))return 0; 1.668 + 1.669 + if(oy->headerbytes==0){ 1.670 + int headerbytes,i; 1.671 + if(bytes<27)return(0); /* not enough for a header */ 1.672 + 1.673 + /* verify capture pattern */ 1.674 + if(memcmp(page,"OggS",4))goto sync_fail; 1.675 + 1.676 + headerbytes=page[26]+27; 1.677 + if(bytes<headerbytes)return(0); /* not enough for header + seg table */ 1.678 + 1.679 + /* count up body length in the segment table */ 1.680 + 1.681 + for(i=0;i<page[26];i++) 1.682 + oy->bodybytes+=page[27+i]; 1.683 + oy->headerbytes=headerbytes; 1.684 + } 1.685 + 1.686 + if(oy->bodybytes+oy->headerbytes>bytes)return(0); 1.687 + 1.688 + /* The whole test page is buffered. Verify the checksum */ 1.689 + { 1.690 + /* Grab the checksum bytes, set the header field to zero */ 1.691 + char chksum[4]; 1.692 + ogg_page log; 1.693 + 1.694 + memcpy(chksum,page+22,4); 1.695 + memset(page+22,0,4); 1.696 + 1.697 + /* set up a temp page struct and recompute the checksum */ 1.698 + log.header=page; 1.699 + log.header_len=oy->headerbytes; 1.700 + log.body=page+oy->headerbytes; 1.701 + log.body_len=oy->bodybytes; 1.702 + ogg_page_checksum_set(&log); 1.703 + 1.704 + /* Compare */ 1.705 + if(memcmp(chksum,page+22,4)){ 1.706 + /* D'oh. Mismatch! Corrupt page (or miscapture and not a page 1.707 + at all) */ 1.708 + /* replace the computed checksum with the one actually read in */ 1.709 + memcpy(page+22,chksum,4); 1.710 + 1.711 + /* Bad checksum. Lose sync */ 1.712 + goto sync_fail; 1.713 + } 1.714 + } 1.715 + 1.716 + /* yes, have a whole page all ready to go */ 1.717 + { 1.718 + unsigned char *page=oy->data+oy->returned; 1.719 + long bytes; 1.720 + 1.721 + if(og){ 1.722 + og->header=page; 1.723 + og->header_len=oy->headerbytes; 1.724 + og->body=page+oy->headerbytes; 1.725 + og->body_len=oy->bodybytes; 1.726 + } 1.727 + 1.728 + oy->unsynced=0; 1.729 + oy->returned+=(bytes=oy->headerbytes+oy->bodybytes); 1.730 + oy->headerbytes=0; 1.731 + oy->bodybytes=0; 1.732 + return(bytes); 1.733 + } 1.734 + 1.735 + sync_fail: 1.736 + 1.737 + oy->headerbytes=0; 1.738 + oy->bodybytes=0; 1.739 + 1.740 + /* search for possible capture */ 1.741 + next=memchr(page+1,'O',bytes-1); 1.742 + if(!next) 1.743 + next=oy->data+oy->fill; 1.744 + 1.745 + oy->returned=(int)(next-oy->data); 1.746 + return((long)-(next-page)); 1.747 +} 1.748 + 1.749 +/* sync the stream and get a page. Keep trying until we find a page. 1.750 + Suppress 'sync errors' after reporting the first. 1.751 + 1.752 + return values: 1.753 + -1) recapture (hole in data) 1.754 + 0) need more data 1.755 + 1) page returned 1.756 + 1.757 + Returns pointers into buffered data; invalidated by next call to 1.758 + _stream, _clear, _init, or _buffer */ 1.759 + 1.760 +int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){ 1.761 + 1.762 + if(ogg_sync_check(oy))return 0; 1.763 + 1.764 + /* all we need to do is verify a page at the head of the stream 1.765 + buffer. If it doesn't verify, we look for the next potential 1.766 + frame */ 1.767 + 1.768 + for(;;){ 1.769 + long ret=ogg_sync_pageseek(oy,og); 1.770 + if(ret>0){ 1.771 + /* have a page */ 1.772 + return(1); 1.773 + } 1.774 + if(ret==0){ 1.775 + /* need more data */ 1.776 + return(0); 1.777 + } 1.778 + 1.779 + /* head did not start a synced page... skipped some bytes */ 1.780 + if(!oy->unsynced){ 1.781 + oy->unsynced=1; 1.782 + return(-1); 1.783 + } 1.784 + 1.785 + /* loop. keep looking */ 1.786 + 1.787 + } 1.788 +} 1.789 + 1.790 +/* add the incoming page to the stream state; we decompose the page 1.791 + into packet segments here as well. */ 1.792 + 1.793 +int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){ 1.794 + unsigned char *header=og->header; 1.795 + unsigned char *body=og->body; 1.796 + long bodysize=og->body_len; 1.797 + int segptr=0; 1.798 + 1.799 + int version=ogg_page_version(og); 1.800 + int continued=ogg_page_continued(og); 1.801 + int bos=ogg_page_bos(og); 1.802 + int eos=ogg_page_eos(og); 1.803 + ogg_int64_t granulepos=ogg_page_granulepos(og); 1.804 + int serialno=ogg_page_serialno(og); 1.805 + long pageno=ogg_page_pageno(og); 1.806 + int segments=header[26]; 1.807 + 1.808 + if(ogg_stream_check(os)) return -1; 1.809 + 1.810 + /* clean up 'returned data' */ 1.811 + { 1.812 + long lr=os->lacing_returned; 1.813 + long br=os->body_returned; 1.814 + 1.815 + /* body data */ 1.816 + if(br){ 1.817 + os->body_fill-=br; 1.818 + if(os->body_fill) 1.819 + memmove(os->body_data,os->body_data+br,os->body_fill); 1.820 + os->body_returned=0; 1.821 + } 1.822 + 1.823 + if(lr){ 1.824 + /* segment table */ 1.825 + if(os->lacing_fill-lr){ 1.826 + memmove(os->lacing_vals,os->lacing_vals+lr, 1.827 + (os->lacing_fill-lr)*sizeof(*os->lacing_vals)); 1.828 + memmove(os->granule_vals,os->granule_vals+lr, 1.829 + (os->lacing_fill-lr)*sizeof(*os->granule_vals)); 1.830 + } 1.831 + os->lacing_fill-=lr; 1.832 + os->lacing_packet-=lr; 1.833 + os->lacing_returned=0; 1.834 + } 1.835 + } 1.836 + 1.837 + /* check the serial number */ 1.838 + if(serialno!=os->serialno)return(-1); 1.839 + if(version>0)return(-1); 1.840 + 1.841 + if(_os_lacing_expand(os,segments+1)) return -1; 1.842 + 1.843 + /* are we in sequence? */ 1.844 + if(pageno!=os->pageno){ 1.845 + int i; 1.846 + 1.847 + /* unroll previous partial packet (if any) */ 1.848 + for(i=os->lacing_packet;i<os->lacing_fill;i++) 1.849 + os->body_fill-=os->lacing_vals[i]&0xff; 1.850 + os->lacing_fill=os->lacing_packet; 1.851 + 1.852 + /* make a note of dropped data in segment table */ 1.853 + if(os->pageno!=-1){ 1.854 + os->lacing_vals[os->lacing_fill++]=0x400; 1.855 + os->lacing_packet++; 1.856 + } 1.857 + } 1.858 + 1.859 + /* are we a 'continued packet' page? If so, we may need to skip 1.860 + some segments */ 1.861 + if(continued){ 1.862 + if(os->lacing_fill<1 || 1.863 + os->lacing_vals[os->lacing_fill-1]==0x400){ 1.864 + bos=0; 1.865 + for(;segptr<segments;segptr++){ 1.866 + int val=header[27+segptr]; 1.867 + body+=val; 1.868 + bodysize-=val; 1.869 + if(val<255){ 1.870 + segptr++; 1.871 + break; 1.872 + } 1.873 + } 1.874 + } 1.875 + } 1.876 + 1.877 + if(bodysize){ 1.878 + if(_os_body_expand(os,bodysize)) return -1; 1.879 + memcpy(os->body_data+os->body_fill,body,bodysize); 1.880 + os->body_fill+=bodysize; 1.881 + } 1.882 + 1.883 + { 1.884 + int saved=-1; 1.885 + while(segptr<segments){ 1.886 + int val=header[27+segptr]; 1.887 + os->lacing_vals[os->lacing_fill]=val; 1.888 + os->granule_vals[os->lacing_fill]=-1; 1.889 + 1.890 + if(bos){ 1.891 + os->lacing_vals[os->lacing_fill]|=0x100; 1.892 + bos=0; 1.893 + } 1.894 + 1.895 + if(val<255)saved=os->lacing_fill; 1.896 + 1.897 + os->lacing_fill++; 1.898 + segptr++; 1.899 + 1.900 + if(val<255)os->lacing_packet=os->lacing_fill; 1.901 + } 1.902 + 1.903 + /* set the granulepos on the last granuleval of the last full packet */ 1.904 + if(saved!=-1){ 1.905 + os->granule_vals[saved]=granulepos; 1.906 + } 1.907 + 1.908 + } 1.909 + 1.910 + if(eos){ 1.911 + os->e_o_s=1; 1.912 + if(os->lacing_fill>0) 1.913 + os->lacing_vals[os->lacing_fill-1]|=0x200; 1.914 + } 1.915 + 1.916 + os->pageno=pageno+1; 1.917 + 1.918 + return(0); 1.919 +} 1.920 + 1.921 +/* clear things to an initial state. Good to call, eg, before seeking */ 1.922 +int ogg_sync_reset(ogg_sync_state *oy){ 1.923 + if(ogg_sync_check(oy))return -1; 1.924 + 1.925 + oy->fill=0; 1.926 + oy->returned=0; 1.927 + oy->unsynced=0; 1.928 + oy->headerbytes=0; 1.929 + oy->bodybytes=0; 1.930 + return(0); 1.931 +} 1.932 + 1.933 +int ogg_stream_reset(ogg_stream_state *os){ 1.934 + if(ogg_stream_check(os)) return -1; 1.935 + 1.936 + os->body_fill=0; 1.937 + os->body_returned=0; 1.938 + 1.939 + os->lacing_fill=0; 1.940 + os->lacing_packet=0; 1.941 + os->lacing_returned=0; 1.942 + 1.943 + os->header_fill=0; 1.944 + 1.945 + os->e_o_s=0; 1.946 + os->b_o_s=0; 1.947 + os->pageno=-1; 1.948 + os->packetno=0; 1.949 + os->granulepos=0; 1.950 + 1.951 + return(0); 1.952 +} 1.953 + 1.954 +int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){ 1.955 + if(ogg_stream_check(os)) return -1; 1.956 + ogg_stream_reset(os); 1.957 + os->serialno=serialno; 1.958 + return(0); 1.959 +} 1.960 + 1.961 +static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){ 1.962 + 1.963 + /* The last part of decode. We have the stream broken into packet 1.964 + segments. Now we need to group them into packets (or return the 1.965 + out of sync markers) */ 1.966 + 1.967 + int ptr=os->lacing_returned; 1.968 + 1.969 + if(os->lacing_packet<=ptr)return(0); 1.970 + 1.971 + if(os->lacing_vals[ptr]&0x400){ 1.972 + /* we need to tell the codec there's a gap; it might need to 1.973 + handle previous packet dependencies. */ 1.974 + os->lacing_returned++; 1.975 + os->packetno++; 1.976 + return(-1); 1.977 + } 1.978 + 1.979 + if(!op && !adv)return(1); /* just using peek as an inexpensive way 1.980 + to ask if there's a whole packet 1.981 + waiting */ 1.982 + 1.983 + /* Gather the whole packet. We'll have no holes or a partial packet */ 1.984 + { 1.985 + int size=os->lacing_vals[ptr]&0xff; 1.986 + long bytes=size; 1.987 + int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */ 1.988 + int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */ 1.989 + 1.990 + while(size==255){ 1.991 + int val=os->lacing_vals[++ptr]; 1.992 + size=val&0xff; 1.993 + if(val&0x200)eos=0x200; 1.994 + bytes+=size; 1.995 + } 1.996 + 1.997 + if(op){ 1.998 + op->e_o_s=eos; 1.999 + op->b_o_s=bos; 1.1000 + op->packet=os->body_data+os->body_returned; 1.1001 + op->packetno=os->packetno; 1.1002 + op->granulepos=os->granule_vals[ptr]; 1.1003 + op->bytes=bytes; 1.1004 + } 1.1005 + 1.1006 + if(adv){ 1.1007 + os->body_returned+=bytes; 1.1008 + os->lacing_returned=ptr+1; 1.1009 + os->packetno++; 1.1010 + } 1.1011 + } 1.1012 + return(1); 1.1013 +} 1.1014 + 1.1015 +int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){ 1.1016 + if(ogg_stream_check(os)) return 0; 1.1017 + return _packetout(os,op,1); 1.1018 +} 1.1019 + 1.1020 +int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){ 1.1021 + if(ogg_stream_check(os)) return 0; 1.1022 + return _packetout(os,op,0); 1.1023 +} 1.1024 + 1.1025 +void ogg_packet_clear(ogg_packet *op) { 1.1026 + _ogg_free(op->packet); 1.1027 + memset(op, 0, sizeof(*op)); 1.1028 +} 1.1029 + 1.1030 +#ifdef _V_SELFTEST 1.1031 +#include <stdio.h> 1.1032 + 1.1033 +ogg_stream_state os_en, os_de; 1.1034 +ogg_sync_state oy; 1.1035 + 1.1036 +void checkpacket(ogg_packet *op,long len, int no, long pos){ 1.1037 + long j; 1.1038 + static int sequence=0; 1.1039 + static int lastno=0; 1.1040 + 1.1041 + if(op->bytes!=len){ 1.1042 + fprintf(stderr,"incorrect packet length (%ld != %ld)!\n",op->bytes,len); 1.1043 + exit(1); 1.1044 + } 1.1045 + if(op->granulepos!=pos){ 1.1046 + fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos); 1.1047 + exit(1); 1.1048 + } 1.1049 + 1.1050 + /* packet number just follows sequence/gap; adjust the input number 1.1051 + for that */ 1.1052 + if(no==0){ 1.1053 + sequence=0; 1.1054 + }else{ 1.1055 + sequence++; 1.1056 + if(no>lastno+1) 1.1057 + sequence++; 1.1058 + } 1.1059 + lastno=no; 1.1060 + if(op->packetno!=sequence){ 1.1061 + fprintf(stderr,"incorrect packet sequence %ld != %d\n", 1.1062 + (long)(op->packetno),sequence); 1.1063 + exit(1); 1.1064 + } 1.1065 + 1.1066 + /* Test data */ 1.1067 + for(j=0;j<op->bytes;j++) 1.1068 + if(op->packet[j]!=((j+no)&0xff)){ 1.1069 + fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n", 1.1070 + j,op->packet[j],(j+no)&0xff); 1.1071 + exit(1); 1.1072 + } 1.1073 +} 1.1074 + 1.1075 +void check_page(unsigned char *data,const int *header,ogg_page *og){ 1.1076 + long j; 1.1077 + /* Test data */ 1.1078 + for(j=0;j<og->body_len;j++) 1.1079 + if(og->body[j]!=data[j]){ 1.1080 + fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n", 1.1081 + j,data[j],og->body[j]); 1.1082 + exit(1); 1.1083 + } 1.1084 + 1.1085 + /* Test header */ 1.1086 + for(j=0;j<og->header_len;j++){ 1.1087 + if(og->header[j]!=header[j]){ 1.1088 + fprintf(stderr,"header content mismatch at pos %ld:\n",j); 1.1089 + for(j=0;j<header[26]+27;j++) 1.1090 + fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]); 1.1091 + fprintf(stderr,"\n"); 1.1092 + exit(1); 1.1093 + } 1.1094 + } 1.1095 + if(og->header_len!=header[26]+27){ 1.1096 + fprintf(stderr,"header length incorrect! (%ld!=%d)\n", 1.1097 + og->header_len,header[26]+27); 1.1098 + exit(1); 1.1099 + } 1.1100 +} 1.1101 + 1.1102 +void print_header(ogg_page *og){ 1.1103 + int j; 1.1104 + fprintf(stderr,"\nHEADER:\n"); 1.1105 + fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n", 1.1106 + og->header[0],og->header[1],og->header[2],og->header[3], 1.1107 + (int)og->header[4],(int)og->header[5]); 1.1108 + 1.1109 + fprintf(stderr," granulepos: %d serialno: %d pageno: %ld\n", 1.1110 + (og->header[9]<<24)|(og->header[8]<<16)| 1.1111 + (og->header[7]<<8)|og->header[6], 1.1112 + (og->header[17]<<24)|(og->header[16]<<16)| 1.1113 + (og->header[15]<<8)|og->header[14], 1.1114 + ((long)(og->header[21])<<24)|(og->header[20]<<16)| 1.1115 + (og->header[19]<<8)|og->header[18]); 1.1116 + 1.1117 + fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (", 1.1118 + (int)og->header[22],(int)og->header[23], 1.1119 + (int)og->header[24],(int)og->header[25], 1.1120 + (int)og->header[26]); 1.1121 + 1.1122 + for(j=27;j<og->header_len;j++) 1.1123 + fprintf(stderr,"%d ",(int)og->header[j]); 1.1124 + fprintf(stderr,")\n\n"); 1.1125 +} 1.1126 + 1.1127 +void copy_page(ogg_page *og){ 1.1128 + unsigned char *temp=_ogg_malloc(og->header_len); 1.1129 + memcpy(temp,og->header,og->header_len); 1.1130 + og->header=temp; 1.1131 + 1.1132 + temp=_ogg_malloc(og->body_len); 1.1133 + memcpy(temp,og->body,og->body_len); 1.1134 + og->body=temp; 1.1135 +} 1.1136 + 1.1137 +void free_page(ogg_page *og){ 1.1138 + _ogg_free (og->header); 1.1139 + _ogg_free (og->body); 1.1140 +} 1.1141 + 1.1142 +void error(void){ 1.1143 + fprintf(stderr,"error!\n"); 1.1144 + exit(1); 1.1145 +} 1.1146 + 1.1147 +/* 17 only */ 1.1148 +const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06, 1.1149 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1.1150 + 0x01,0x02,0x03,0x04,0,0,0,0, 1.1151 + 0x15,0xed,0xec,0x91, 1.1152 + 1, 1.1153 + 17}; 1.1154 + 1.1155 +/* 17, 254, 255, 256, 500, 510, 600 byte, pad */ 1.1156 +const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02, 1.1157 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1.1158 + 0x01,0x02,0x03,0x04,0,0,0,0, 1.1159 + 0x59,0x10,0x6c,0x2c, 1.1160 + 1, 1.1161 + 17}; 1.1162 +const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04, 1.1163 + 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00, 1.1164 + 0x01,0x02,0x03,0x04,1,0,0,0, 1.1165 + 0x89,0x33,0x85,0xce, 1.1166 + 13, 1.1167 + 254,255,0,255,1,255,245,255,255,0, 1.1168 + 255,255,90}; 1.1169 + 1.1170 +/* nil packets; beginning,middle,end */ 1.1171 +const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02, 1.1172 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1.1173 + 0x01,0x02,0x03,0x04,0,0,0,0, 1.1174 + 0xff,0x7b,0x23,0x17, 1.1175 + 1, 1.1176 + 0}; 1.1177 +const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04, 1.1178 + 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00, 1.1179 + 0x01,0x02,0x03,0x04,1,0,0,0, 1.1180 + 0x5c,0x3f,0x66,0xcb, 1.1181 + 17, 1.1182 + 17,254,255,0,0,255,1,0,255,245,255,255,0, 1.1183 + 255,255,90,0}; 1.1184 + 1.1185 +/* large initial packet */ 1.1186 +const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02, 1.1187 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1.1188 + 0x01,0x02,0x03,0x04,0,0,0,0, 1.1189 + 0x01,0x27,0x31,0xaa, 1.1190 + 18, 1.1191 + 255,255,255,255,255,255,255,255, 1.1192 + 255,255,255,255,255,255,255,255,255,10}; 1.1193 + 1.1194 +const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04, 1.1195 + 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, 1.1196 + 0x01,0x02,0x03,0x04,1,0,0,0, 1.1197 + 0x7f,0x4e,0x8a,0xd2, 1.1198 + 4, 1.1199 + 255,4,255,0}; 1.1200 + 1.1201 + 1.1202 +/* continuing packet test */ 1.1203 +const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02, 1.1204 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1.1205 + 0x01,0x02,0x03,0x04,0,0,0,0, 1.1206 + 0xff,0x7b,0x23,0x17, 1.1207 + 1, 1.1208 + 0}; 1.1209 + 1.1210 +const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00, 1.1211 + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 1.1212 + 0x01,0x02,0x03,0x04,1,0,0,0, 1.1213 + 0xf8,0x3c,0x19,0x79, 1.1214 + 255, 1.1215 + 255,255,255,255,255,255,255,255, 1.1216 + 255,255,255,255,255,255,255,255, 1.1217 + 255,255,255,255,255,255,255,255, 1.1218 + 255,255,255,255,255,255,255,255, 1.1219 + 255,255,255,255,255,255,255,255, 1.1220 + 255,255,255,255,255,255,255,255, 1.1221 + 255,255,255,255,255,255,255,255, 1.1222 + 255,255,255,255,255,255,255,255, 1.1223 + 255,255,255,255,255,255,255,255, 1.1224 + 255,255,255,255,255,255,255,255, 1.1225 + 255,255,255,255,255,255,255,255, 1.1226 + 255,255,255,255,255,255,255,255, 1.1227 + 255,255,255,255,255,255,255,255, 1.1228 + 255,255,255,255,255,255,255,255, 1.1229 + 255,255,255,255,255,255,255,255, 1.1230 + 255,255,255,255,255,255,255,255, 1.1231 + 255,255,255,255,255,255,255,255, 1.1232 + 255,255,255,255,255,255,255,255, 1.1233 + 255,255,255,255,255,255,255,255, 1.1234 + 255,255,255,255,255,255,255,255, 1.1235 + 255,255,255,255,255,255,255,255, 1.1236 + 255,255,255,255,255,255,255,255, 1.1237 + 255,255,255,255,255,255,255,255, 1.1238 + 255,255,255,255,255,255,255,255, 1.1239 + 255,255,255,255,255,255,255,255, 1.1240 + 255,255,255,255,255,255,255,255, 1.1241 + 255,255,255,255,255,255,255,255, 1.1242 + 255,255,255,255,255,255,255,255, 1.1243 + 255,255,255,255,255,255,255,255, 1.1244 + 255,255,255,255,255,255,255,255, 1.1245 + 255,255,255,255,255,255,255,255, 1.1246 + 255,255,255,255,255,255,255}; 1.1247 + 1.1248 +const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05, 1.1249 + 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, 1.1250 + 0x01,0x02,0x03,0x04,2,0,0,0, 1.1251 + 0x38,0xe6,0xb6,0x28, 1.1252 + 6, 1.1253 + 255,220,255,4,255,0}; 1.1254 + 1.1255 + 1.1256 +/* spill expansion test */ 1.1257 +const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02, 1.1258 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1.1259 + 0x01,0x02,0x03,0x04,0,0,0,0, 1.1260 + 0xff,0x7b,0x23,0x17, 1.1261 + 1, 1.1262 + 0}; 1.1263 + 1.1264 +const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00, 1.1265 + 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00, 1.1266 + 0x01,0x02,0x03,0x04,1,0,0,0, 1.1267 + 0xce,0x8f,0x17,0x1a, 1.1268 + 23, 1.1269 + 255,255,255,255,255,255,255,255, 1.1270 + 255,255,255,255,255,255,255,255,255,10,255,4,255,0,0}; 1.1271 + 1.1272 + 1.1273 +const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04, 1.1274 + 0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00, 1.1275 + 0x01,0x02,0x03,0x04,2,0,0,0, 1.1276 + 0x9b,0xb2,0x50,0xa1, 1.1277 + 1, 1.1278 + 0}; 1.1279 + 1.1280 +/* page with the 255 segment limit */ 1.1281 +const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02, 1.1282 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1.1283 + 0x01,0x02,0x03,0x04,0,0,0,0, 1.1284 + 0xff,0x7b,0x23,0x17, 1.1285 + 1, 1.1286 + 0}; 1.1287 + 1.1288 +const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00, 1.1289 + 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00, 1.1290 + 0x01,0x02,0x03,0x04,1,0,0,0, 1.1291 + 0xed,0x2a,0x2e,0xa7, 1.1292 + 255, 1.1293 + 10,10,10,10,10,10,10,10, 1.1294 + 10,10,10,10,10,10,10,10, 1.1295 + 10,10,10,10,10,10,10,10, 1.1296 + 10,10,10,10,10,10,10,10, 1.1297 + 10,10,10,10,10,10,10,10, 1.1298 + 10,10,10,10,10,10,10,10, 1.1299 + 10,10,10,10,10,10,10,10, 1.1300 + 10,10,10,10,10,10,10,10, 1.1301 + 10,10,10,10,10,10,10,10, 1.1302 + 10,10,10,10,10,10,10,10, 1.1303 + 10,10,10,10,10,10,10,10, 1.1304 + 10,10,10,10,10,10,10,10, 1.1305 + 10,10,10,10,10,10,10,10, 1.1306 + 10,10,10,10,10,10,10,10, 1.1307 + 10,10,10,10,10,10,10,10, 1.1308 + 10,10,10,10,10,10,10,10, 1.1309 + 10,10,10,10,10,10,10,10, 1.1310 + 10,10,10,10,10,10,10,10, 1.1311 + 10,10,10,10,10,10,10,10, 1.1312 + 10,10,10,10,10,10,10,10, 1.1313 + 10,10,10,10,10,10,10,10, 1.1314 + 10,10,10,10,10,10,10,10, 1.1315 + 10,10,10,10,10,10,10,10, 1.1316 + 10,10,10,10,10,10,10,10, 1.1317 + 10,10,10,10,10,10,10,10, 1.1318 + 10,10,10,10,10,10,10,10, 1.1319 + 10,10,10,10,10,10,10,10, 1.1320 + 10,10,10,10,10,10,10,10, 1.1321 + 10,10,10,10,10,10,10,10, 1.1322 + 10,10,10,10,10,10,10,10, 1.1323 + 10,10,10,10,10,10,10,10, 1.1324 + 10,10,10,10,10,10,10}; 1.1325 + 1.1326 +const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04, 1.1327 + 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00, 1.1328 + 0x01,0x02,0x03,0x04,2,0,0,0, 1.1329 + 0x6c,0x3b,0x82,0x3d, 1.1330 + 1, 1.1331 + 50}; 1.1332 + 1.1333 + 1.1334 +/* packet that overspans over an entire page */ 1.1335 +const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02, 1.1336 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1.1337 + 0x01,0x02,0x03,0x04,0,0,0,0, 1.1338 + 0xff,0x7b,0x23,0x17, 1.1339 + 1, 1.1340 + 0}; 1.1341 + 1.1342 +const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00, 1.1343 + 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, 1.1344 + 0x01,0x02,0x03,0x04,1,0,0,0, 1.1345 + 0x68,0x22,0x7c,0x3d, 1.1346 + 255, 1.1347 + 100, 1.1348 + 255,255,255,255,255,255,255,255, 1.1349 + 255,255,255,255,255,255,255,255, 1.1350 + 255,255,255,255,255,255,255,255, 1.1351 + 255,255,255,255,255,255,255,255, 1.1352 + 255,255,255,255,255,255,255,255, 1.1353 + 255,255,255,255,255,255,255,255, 1.1354 + 255,255,255,255,255,255,255,255, 1.1355 + 255,255,255,255,255,255,255,255, 1.1356 + 255,255,255,255,255,255,255,255, 1.1357 + 255,255,255,255,255,255,255,255, 1.1358 + 255,255,255,255,255,255,255,255, 1.1359 + 255,255,255,255,255,255,255,255, 1.1360 + 255,255,255,255,255,255,255,255, 1.1361 + 255,255,255,255,255,255,255,255, 1.1362 + 255,255,255,255,255,255,255,255, 1.1363 + 255,255,255,255,255,255,255,255, 1.1364 + 255,255,255,255,255,255,255,255, 1.1365 + 255,255,255,255,255,255,255,255, 1.1366 + 255,255,255,255,255,255,255,255, 1.1367 + 255,255,255,255,255,255,255,255, 1.1368 + 255,255,255,255,255,255,255,255, 1.1369 + 255,255,255,255,255,255,255,255, 1.1370 + 255,255,255,255,255,255,255,255, 1.1371 + 255,255,255,255,255,255,255,255, 1.1372 + 255,255,255,255,255,255,255,255, 1.1373 + 255,255,255,255,255,255,255,255, 1.1374 + 255,255,255,255,255,255,255,255, 1.1375 + 255,255,255,255,255,255,255,255, 1.1376 + 255,255,255,255,255,255,255,255, 1.1377 + 255,255,255,255,255,255,255,255, 1.1378 + 255,255,255,255,255,255,255,255, 1.1379 + 255,255,255,255,255,255}; 1.1380 + 1.1381 +const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01, 1.1382 + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 1.1383 + 0x01,0x02,0x03,0x04,2,0,0,0, 1.1384 + 0xf4,0x87,0xba,0xf3, 1.1385 + 255, 1.1386 + 255,255,255,255,255,255,255,255, 1.1387 + 255,255,255,255,255,255,255,255, 1.1388 + 255,255,255,255,255,255,255,255, 1.1389 + 255,255,255,255,255,255,255,255, 1.1390 + 255,255,255,255,255,255,255,255, 1.1391 + 255,255,255,255,255,255,255,255, 1.1392 + 255,255,255,255,255,255,255,255, 1.1393 + 255,255,255,255,255,255,255,255, 1.1394 + 255,255,255,255,255,255,255,255, 1.1395 + 255,255,255,255,255,255,255,255, 1.1396 + 255,255,255,255,255,255,255,255, 1.1397 + 255,255,255,255,255,255,255,255, 1.1398 + 255,255,255,255,255,255,255,255, 1.1399 + 255,255,255,255,255,255,255,255, 1.1400 + 255,255,255,255,255,255,255,255, 1.1401 + 255,255,255,255,255,255,255,255, 1.1402 + 255,255,255,255,255,255,255,255, 1.1403 + 255,255,255,255,255,255,255,255, 1.1404 + 255,255,255,255,255,255,255,255, 1.1405 + 255,255,255,255,255,255,255,255, 1.1406 + 255,255,255,255,255,255,255,255, 1.1407 + 255,255,255,255,255,255,255,255, 1.1408 + 255,255,255,255,255,255,255,255, 1.1409 + 255,255,255,255,255,255,255,255, 1.1410 + 255,255,255,255,255,255,255,255, 1.1411 + 255,255,255,255,255,255,255,255, 1.1412 + 255,255,255,255,255,255,255,255, 1.1413 + 255,255,255,255,255,255,255,255, 1.1414 + 255,255,255,255,255,255,255,255, 1.1415 + 255,255,255,255,255,255,255,255, 1.1416 + 255,255,255,255,255,255,255,255, 1.1417 + 255,255,255,255,255,255,255}; 1.1418 + 1.1419 +const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05, 1.1420 + 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00, 1.1421 + 0x01,0x02,0x03,0x04,3,0,0,0, 1.1422 + 0xf7,0x2f,0x6c,0x60, 1.1423 + 5, 1.1424 + 254,255,4,255,0}; 1.1425 + 1.1426 +/* packet that overspans over an entire page */ 1.1427 +const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02, 1.1428 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1.1429 + 0x01,0x02,0x03,0x04,0,0,0,0, 1.1430 + 0xff,0x7b,0x23,0x17, 1.1431 + 1, 1.1432 + 0}; 1.1433 + 1.1434 +const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00, 1.1435 + 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, 1.1436 + 0x01,0x02,0x03,0x04,1,0,0,0, 1.1437 + 0x68,0x22,0x7c,0x3d, 1.1438 + 255, 1.1439 + 100, 1.1440 + 255,255,255,255,255,255,255,255, 1.1441 + 255,255,255,255,255,255,255,255, 1.1442 + 255,255,255,255,255,255,255,255, 1.1443 + 255,255,255,255,255,255,255,255, 1.1444 + 255,255,255,255,255,255,255,255, 1.1445 + 255,255,255,255,255,255,255,255, 1.1446 + 255,255,255,255,255,255,255,255, 1.1447 + 255,255,255,255,255,255,255,255, 1.1448 + 255,255,255,255,255,255,255,255, 1.1449 + 255,255,255,255,255,255,255,255, 1.1450 + 255,255,255,255,255,255,255,255, 1.1451 + 255,255,255,255,255,255,255,255, 1.1452 + 255,255,255,255,255,255,255,255, 1.1453 + 255,255,255,255,255,255,255,255, 1.1454 + 255,255,255,255,255,255,255,255, 1.1455 + 255,255,255,255,255,255,255,255, 1.1456 + 255,255,255,255,255,255,255,255, 1.1457 + 255,255,255,255,255,255,255,255, 1.1458 + 255,255,255,255,255,255,255,255, 1.1459 + 255,255,255,255,255,255,255,255, 1.1460 + 255,255,255,255,255,255,255,255, 1.1461 + 255,255,255,255,255,255,255,255, 1.1462 + 255,255,255,255,255,255,255,255, 1.1463 + 255,255,255,255,255,255,255,255, 1.1464 + 255,255,255,255,255,255,255,255, 1.1465 + 255,255,255,255,255,255,255,255, 1.1466 + 255,255,255,255,255,255,255,255, 1.1467 + 255,255,255,255,255,255,255,255, 1.1468 + 255,255,255,255,255,255,255,255, 1.1469 + 255,255,255,255,255,255,255,255, 1.1470 + 255,255,255,255,255,255,255,255, 1.1471 + 255,255,255,255,255,255}; 1.1472 + 1.1473 +const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05, 1.1474 + 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, 1.1475 + 0x01,0x02,0x03,0x04,2,0,0,0, 1.1476 + 0xd4,0xe0,0x60,0xe5, 1.1477 + 1, 1.1478 + 0}; 1.1479 + 1.1480 +void test_pack(const int *pl, const int **headers, int byteskip, 1.1481 + int pageskip, int packetskip){ 1.1482 + unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */ 1.1483 + long inptr=0; 1.1484 + long outptr=0; 1.1485 + long deptr=0; 1.1486 + long depacket=0; 1.1487 + long granule_pos=7,pageno=0; 1.1488 + int i,j,packets,pageout=pageskip; 1.1489 + int eosflag=0; 1.1490 + int bosflag=0; 1.1491 + 1.1492 + int byteskipcount=0; 1.1493 + 1.1494 + ogg_stream_reset(&os_en); 1.1495 + ogg_stream_reset(&os_de); 1.1496 + ogg_sync_reset(&oy); 1.1497 + 1.1498 + for(packets=0;packets<packetskip;packets++) 1.1499 + depacket+=pl[packets]; 1.1500 + 1.1501 + for(packets=0;;packets++)if(pl[packets]==-1)break; 1.1502 + 1.1503 + for(i=0;i<packets;i++){ 1.1504 + /* construct a test packet */ 1.1505 + ogg_packet op; 1.1506 + int len=pl[i]; 1.1507 + 1.1508 + op.packet=data+inptr; 1.1509 + op.bytes=len; 1.1510 + op.e_o_s=(pl[i+1]<0?1:0); 1.1511 + op.granulepos=granule_pos; 1.1512 + 1.1513 + granule_pos+=1024; 1.1514 + 1.1515 + for(j=0;j<len;j++)data[inptr++]=i+j; 1.1516 + 1.1517 + /* submit the test packet */ 1.1518 + ogg_stream_packetin(&os_en,&op); 1.1519 + 1.1520 + /* retrieve any finished pages */ 1.1521 + { 1.1522 + ogg_page og; 1.1523 + 1.1524 + while(ogg_stream_pageout(&os_en,&og)){ 1.1525 + /* We have a page. Check it carefully */ 1.1526 + 1.1527 + fprintf(stderr,"%ld, ",pageno); 1.1528 + 1.1529 + if(headers[pageno]==NULL){ 1.1530 + fprintf(stderr,"coded too many pages!\n"); 1.1531 + exit(1); 1.1532 + } 1.1533 + 1.1534 + check_page(data+outptr,headers[pageno],&og); 1.1535 + 1.1536 + outptr+=og.body_len; 1.1537 + pageno++; 1.1538 + if(pageskip){ 1.1539 + bosflag=1; 1.1540 + pageskip--; 1.1541 + deptr+=og.body_len; 1.1542 + } 1.1543 + 1.1544 + /* have a complete page; submit it to sync/decode */ 1.1545 + 1.1546 + { 1.1547 + ogg_page og_de; 1.1548 + ogg_packet op_de,op_de2; 1.1549 + char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len); 1.1550 + char *next=buf; 1.1551 + byteskipcount+=og.header_len; 1.1552 + if(byteskipcount>byteskip){ 1.1553 + memcpy(next,og.header,byteskipcount-byteskip); 1.1554 + next+=byteskipcount-byteskip; 1.1555 + byteskipcount=byteskip; 1.1556 + } 1.1557 + 1.1558 + byteskipcount+=og.body_len; 1.1559 + if(byteskipcount>byteskip){ 1.1560 + memcpy(next,og.body,byteskipcount-byteskip); 1.1561 + next+=byteskipcount-byteskip; 1.1562 + byteskipcount=byteskip; 1.1563 + } 1.1564 + 1.1565 + ogg_sync_wrote(&oy,next-buf); 1.1566 + 1.1567 + while(1){ 1.1568 + int ret=ogg_sync_pageout(&oy,&og_de); 1.1569 + if(ret==0)break; 1.1570 + if(ret<0)continue; 1.1571 + /* got a page. Happy happy. Verify that it's good. */ 1.1572 + 1.1573 + fprintf(stderr,"(%d), ",pageout); 1.1574 + 1.1575 + check_page(data+deptr,headers[pageout],&og_de); 1.1576 + deptr+=og_de.body_len; 1.1577 + pageout++; 1.1578 + 1.1579 + /* submit it to deconstitution */ 1.1580 + ogg_stream_pagein(&os_de,&og_de); 1.1581 + 1.1582 + /* packets out? */ 1.1583 + while(ogg_stream_packetpeek(&os_de,&op_de2)>0){ 1.1584 + ogg_stream_packetpeek(&os_de,NULL); 1.1585 + ogg_stream_packetout(&os_de,&op_de); /* just catching them all */ 1.1586 + 1.1587 + /* verify peek and out match */ 1.1588 + if(memcmp(&op_de,&op_de2,sizeof(op_de))){ 1.1589 + fprintf(stderr,"packetout != packetpeek! pos=%ld\n", 1.1590 + depacket); 1.1591 + exit(1); 1.1592 + } 1.1593 + 1.1594 + /* verify the packet! */ 1.1595 + /* check data */ 1.1596 + if(memcmp(data+depacket,op_de.packet,op_de.bytes)){ 1.1597 + fprintf(stderr,"packet data mismatch in decode! pos=%ld\n", 1.1598 + depacket); 1.1599 + exit(1); 1.1600 + } 1.1601 + /* check bos flag */ 1.1602 + if(bosflag==0 && op_de.b_o_s==0){ 1.1603 + fprintf(stderr,"b_o_s flag not set on packet!\n"); 1.1604 + exit(1); 1.1605 + } 1.1606 + if(bosflag && op_de.b_o_s){ 1.1607 + fprintf(stderr,"b_o_s flag incorrectly set on packet!\n"); 1.1608 + exit(1); 1.1609 + } 1.1610 + bosflag=1; 1.1611 + depacket+=op_de.bytes; 1.1612 + 1.1613 + /* check eos flag */ 1.1614 + if(eosflag){ 1.1615 + fprintf(stderr,"Multiple decoded packets with eos flag!\n"); 1.1616 + exit(1); 1.1617 + } 1.1618 + 1.1619 + if(op_de.e_o_s)eosflag=1; 1.1620 + 1.1621 + /* check granulepos flag */ 1.1622 + if(op_de.granulepos!=-1){ 1.1623 + fprintf(stderr," granule:%ld ",(long)op_de.granulepos); 1.1624 + } 1.1625 + } 1.1626 + } 1.1627 + } 1.1628 + } 1.1629 + } 1.1630 + } 1.1631 + _ogg_free(data); 1.1632 + if(headers[pageno]!=NULL){ 1.1633 + fprintf(stderr,"did not write last page!\n"); 1.1634 + exit(1); 1.1635 + } 1.1636 + if(headers[pageout]!=NULL){ 1.1637 + fprintf(stderr,"did not decode last page!\n"); 1.1638 + exit(1); 1.1639 + } 1.1640 + if(inptr!=outptr){ 1.1641 + fprintf(stderr,"encoded page data incomplete!\n"); 1.1642 + exit(1); 1.1643 + } 1.1644 + if(inptr!=deptr){ 1.1645 + fprintf(stderr,"decoded page data incomplete!\n"); 1.1646 + exit(1); 1.1647 + } 1.1648 + if(inptr!=depacket){ 1.1649 + fprintf(stderr,"decoded packet data incomplete!\n"); 1.1650 + exit(1); 1.1651 + } 1.1652 + if(!eosflag){ 1.1653 + fprintf(stderr,"Never got a packet with EOS set!\n"); 1.1654 + exit(1); 1.1655 + } 1.1656 + fprintf(stderr,"ok.\n"); 1.1657 +} 1.1658 + 1.1659 +int main(void){ 1.1660 + 1.1661 + ogg_stream_init(&os_en,0x04030201); 1.1662 + ogg_stream_init(&os_de,0x04030201); 1.1663 + ogg_sync_init(&oy); 1.1664 + 1.1665 + /* Exercise each code path in the framing code. Also verify that 1.1666 + the checksums are working. */ 1.1667 + 1.1668 + { 1.1669 + /* 17 only */ 1.1670 + const int packets[]={17, -1}; 1.1671 + const int *headret[]={head1_0,NULL}; 1.1672 + 1.1673 + fprintf(stderr,"testing single page encoding... "); 1.1674 + test_pack(packets,headret,0,0,0); 1.1675 + } 1.1676 + 1.1677 + { 1.1678 + /* 17, 254, 255, 256, 500, 510, 600 byte, pad */ 1.1679 + const int packets[]={17, 254, 255, 256, 500, 510, 600, -1}; 1.1680 + const int *headret[]={head1_1,head2_1,NULL}; 1.1681 + 1.1682 + fprintf(stderr,"testing basic page encoding... "); 1.1683 + test_pack(packets,headret,0,0,0); 1.1684 + } 1.1685 + 1.1686 + { 1.1687 + /* nil packets; beginning,middle,end */ 1.1688 + const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1}; 1.1689 + const int *headret[]={head1_2,head2_2,NULL}; 1.1690 + 1.1691 + fprintf(stderr,"testing basic nil packets... "); 1.1692 + test_pack(packets,headret,0,0,0); 1.1693 + } 1.1694 + 1.1695 + { 1.1696 + /* large initial packet */ 1.1697 + const int packets[]={4345,259,255,-1}; 1.1698 + const int *headret[]={head1_3,head2_3,NULL}; 1.1699 + 1.1700 + fprintf(stderr,"testing initial-packet lacing > 4k... "); 1.1701 + test_pack(packets,headret,0,0,0); 1.1702 + } 1.1703 + 1.1704 + { 1.1705 + /* continuing packet test; with page spill expansion, we have to 1.1706 + overflow the lacing table. */ 1.1707 + const int packets[]={0,65500,259,255,-1}; 1.1708 + const int *headret[]={head1_4,head2_4,head3_4,NULL}; 1.1709 + 1.1710 + fprintf(stderr,"testing single packet page span... "); 1.1711 + test_pack(packets,headret,0,0,0); 1.1712 + } 1.1713 + 1.1714 + { 1.1715 + /* spill expand packet test */ 1.1716 + const int packets[]={0,4345,259,255,0,0,-1}; 1.1717 + const int *headret[]={head1_4b,head2_4b,head3_4b,NULL}; 1.1718 + 1.1719 + fprintf(stderr,"testing page spill expansion... "); 1.1720 + test_pack(packets,headret,0,0,0); 1.1721 + } 1.1722 + 1.1723 + /* page with the 255 segment limit */ 1.1724 + { 1.1725 + 1.1726 + const int packets[]={0,10,10,10,10,10,10,10,10, 1.1727 + 10,10,10,10,10,10,10,10, 1.1728 + 10,10,10,10,10,10,10,10, 1.1729 + 10,10,10,10,10,10,10,10, 1.1730 + 10,10,10,10,10,10,10,10, 1.1731 + 10,10,10,10,10,10,10,10, 1.1732 + 10,10,10,10,10,10,10,10, 1.1733 + 10,10,10,10,10,10,10,10, 1.1734 + 10,10,10,10,10,10,10,10, 1.1735 + 10,10,10,10,10,10,10,10, 1.1736 + 10,10,10,10,10,10,10,10, 1.1737 + 10,10,10,10,10,10,10,10, 1.1738 + 10,10,10,10,10,10,10,10, 1.1739 + 10,10,10,10,10,10,10,10, 1.1740 + 10,10,10,10,10,10,10,10, 1.1741 + 10,10,10,10,10,10,10,10, 1.1742 + 10,10,10,10,10,10,10,10, 1.1743 + 10,10,10,10,10,10,10,10, 1.1744 + 10,10,10,10,10,10,10,10, 1.1745 + 10,10,10,10,10,10,10,10, 1.1746 + 10,10,10,10,10,10,10,10, 1.1747 + 10,10,10,10,10,10,10,10, 1.1748 + 10,10,10,10,10,10,10,10, 1.1749 + 10,10,10,10,10,10,10,10, 1.1750 + 10,10,10,10,10,10,10,10, 1.1751 + 10,10,10,10,10,10,10,10, 1.1752 + 10,10,10,10,10,10,10,10, 1.1753 + 10,10,10,10,10,10,10,10, 1.1754 + 10,10,10,10,10,10,10,10, 1.1755 + 10,10,10,10,10,10,10,10, 1.1756 + 10,10,10,10,10,10,10,10, 1.1757 + 10,10,10,10,10,10,10,50,-1}; 1.1758 + const int *headret[]={head1_5,head2_5,head3_5,NULL}; 1.1759 + 1.1760 + fprintf(stderr,"testing max packet segments... "); 1.1761 + test_pack(packets,headret,0,0,0); 1.1762 + } 1.1763 + 1.1764 + { 1.1765 + /* packet that overspans over an entire page */ 1.1766 + const int packets[]={0,100,130049,259,255,-1}; 1.1767 + const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL}; 1.1768 + 1.1769 + fprintf(stderr,"testing very large packets... "); 1.1770 + test_pack(packets,headret,0,0,0); 1.1771 + } 1.1772 + 1.1773 + { 1.1774 + /* test for the libogg 1.1.1 resync in large continuation bug 1.1775 + found by Josh Coalson) */ 1.1776 + const int packets[]={0,100,130049,259,255,-1}; 1.1777 + const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL}; 1.1778 + 1.1779 + fprintf(stderr,"testing continuation resync in very large packets... "); 1.1780 + test_pack(packets,headret,100,2,3); 1.1781 + } 1.1782 + 1.1783 + { 1.1784 + /* term only page. why not? */ 1.1785 + const int packets[]={0,100,64770,-1}; 1.1786 + const int *headret[]={head1_7,head2_7,head3_7,NULL}; 1.1787 + 1.1788 + fprintf(stderr,"testing zero data page (1 nil packet)... "); 1.1789 + test_pack(packets,headret,0,0,0); 1.1790 + } 1.1791 + 1.1792 + 1.1793 + 1.1794 + { 1.1795 + /* build a bunch of pages for testing */ 1.1796 + unsigned char *data=_ogg_malloc(1024*1024); 1.1797 + int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1}; 1.1798 + int inptr=0,i,j; 1.1799 + ogg_page og[5]; 1.1800 + 1.1801 + ogg_stream_reset(&os_en); 1.1802 + 1.1803 + for(i=0;pl[i]!=-1;i++){ 1.1804 + ogg_packet op; 1.1805 + int len=pl[i]; 1.1806 + 1.1807 + op.packet=data+inptr; 1.1808 + op.bytes=len; 1.1809 + op.e_o_s=(pl[i+1]<0?1:0); 1.1810 + op.granulepos=(i+1)*1000; 1.1811 + 1.1812 + for(j=0;j<len;j++)data[inptr++]=i+j; 1.1813 + ogg_stream_packetin(&os_en,&op); 1.1814 + } 1.1815 + 1.1816 + _ogg_free(data); 1.1817 + 1.1818 + /* retrieve finished pages */ 1.1819 + for(i=0;i<5;i++){ 1.1820 + if(ogg_stream_pageout(&os_en,&og[i])==0){ 1.1821 + fprintf(stderr,"Too few pages output building sync tests!\n"); 1.1822 + exit(1); 1.1823 + } 1.1824 + copy_page(&og[i]); 1.1825 + } 1.1826 + 1.1827 + /* Test lost pages on pagein/packetout: no rollback */ 1.1828 + { 1.1829 + ogg_page temp; 1.1830 + ogg_packet test; 1.1831 + 1.1832 + fprintf(stderr,"Testing loss of pages... "); 1.1833 + 1.1834 + ogg_sync_reset(&oy); 1.1835 + ogg_stream_reset(&os_de); 1.1836 + for(i=0;i<5;i++){ 1.1837 + memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header, 1.1838 + og[i].header_len); 1.1839 + ogg_sync_wrote(&oy,og[i].header_len); 1.1840 + memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len); 1.1841 + ogg_sync_wrote(&oy,og[i].body_len); 1.1842 + } 1.1843 + 1.1844 + ogg_sync_pageout(&oy,&temp); 1.1845 + ogg_stream_pagein(&os_de,&temp); 1.1846 + ogg_sync_pageout(&oy,&temp); 1.1847 + ogg_stream_pagein(&os_de,&temp); 1.1848 + ogg_sync_pageout(&oy,&temp); 1.1849 + /* skip */ 1.1850 + ogg_sync_pageout(&oy,&temp); 1.1851 + ogg_stream_pagein(&os_de,&temp); 1.1852 + 1.1853 + /* do we get the expected results/packets? */ 1.1854 + 1.1855 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1856 + checkpacket(&test,0,0,0); 1.1857 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1858 + checkpacket(&test,1,1,-1); 1.1859 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1860 + checkpacket(&test,1,2,-1); 1.1861 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1862 + checkpacket(&test,98,3,-1); 1.1863 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1864 + checkpacket(&test,4079,4,5000); 1.1865 + if(ogg_stream_packetout(&os_de,&test)!=-1){ 1.1866 + fprintf(stderr,"Error: loss of page did not return error\n"); 1.1867 + exit(1); 1.1868 + } 1.1869 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1870 + checkpacket(&test,76,9,-1); 1.1871 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1872 + checkpacket(&test,34,10,-1); 1.1873 + fprintf(stderr,"ok.\n"); 1.1874 + } 1.1875 + 1.1876 + /* Test lost pages on pagein/packetout: rollback with continuation */ 1.1877 + { 1.1878 + ogg_page temp; 1.1879 + ogg_packet test; 1.1880 + 1.1881 + fprintf(stderr,"Testing loss of pages (rollback required)... "); 1.1882 + 1.1883 + ogg_sync_reset(&oy); 1.1884 + ogg_stream_reset(&os_de); 1.1885 + for(i=0;i<5;i++){ 1.1886 + memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header, 1.1887 + og[i].header_len); 1.1888 + ogg_sync_wrote(&oy,og[i].header_len); 1.1889 + memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len); 1.1890 + ogg_sync_wrote(&oy,og[i].body_len); 1.1891 + } 1.1892 + 1.1893 + ogg_sync_pageout(&oy,&temp); 1.1894 + ogg_stream_pagein(&os_de,&temp); 1.1895 + ogg_sync_pageout(&oy,&temp); 1.1896 + ogg_stream_pagein(&os_de,&temp); 1.1897 + ogg_sync_pageout(&oy,&temp); 1.1898 + ogg_stream_pagein(&os_de,&temp); 1.1899 + ogg_sync_pageout(&oy,&temp); 1.1900 + /* skip */ 1.1901 + ogg_sync_pageout(&oy,&temp); 1.1902 + ogg_stream_pagein(&os_de,&temp); 1.1903 + 1.1904 + /* do we get the expected results/packets? */ 1.1905 + 1.1906 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1907 + checkpacket(&test,0,0,0); 1.1908 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1909 + checkpacket(&test,1,1,-1); 1.1910 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1911 + checkpacket(&test,1,2,-1); 1.1912 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1913 + checkpacket(&test,98,3,-1); 1.1914 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1915 + checkpacket(&test,4079,4,5000); 1.1916 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1917 + checkpacket(&test,1,5,-1); 1.1918 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1919 + checkpacket(&test,1,6,-1); 1.1920 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1921 + checkpacket(&test,2954,7,-1); 1.1922 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1923 + checkpacket(&test,2057,8,9000); 1.1924 + if(ogg_stream_packetout(&os_de,&test)!=-1){ 1.1925 + fprintf(stderr,"Error: loss of page did not return error\n"); 1.1926 + exit(1); 1.1927 + } 1.1928 + if(ogg_stream_packetout(&os_de,&test)!=1)error(); 1.1929 + checkpacket(&test,300,17,18000); 1.1930 + fprintf(stderr,"ok.\n"); 1.1931 + } 1.1932 + 1.1933 + /* the rest only test sync */ 1.1934 + { 1.1935 + ogg_page og_de; 1.1936 + /* Test fractional page inputs: incomplete capture */ 1.1937 + fprintf(stderr,"Testing sync on partial inputs... "); 1.1938 + ogg_sync_reset(&oy); 1.1939 + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, 1.1940 + 3); 1.1941 + ogg_sync_wrote(&oy,3); 1.1942 + if(ogg_sync_pageout(&oy,&og_de)>0)error(); 1.1943 + 1.1944 + /* Test fractional page inputs: incomplete fixed header */ 1.1945 + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3, 1.1946 + 20); 1.1947 + ogg_sync_wrote(&oy,20); 1.1948 + if(ogg_sync_pageout(&oy,&og_de)>0)error(); 1.1949 + 1.1950 + /* Test fractional page inputs: incomplete header */ 1.1951 + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23, 1.1952 + 5); 1.1953 + ogg_sync_wrote(&oy,5); 1.1954 + if(ogg_sync_pageout(&oy,&og_de)>0)error(); 1.1955 + 1.1956 + /* Test fractional page inputs: incomplete body */ 1.1957 + 1.1958 + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28, 1.1959 + og[1].header_len-28); 1.1960 + ogg_sync_wrote(&oy,og[1].header_len-28); 1.1961 + if(ogg_sync_pageout(&oy,&og_de)>0)error(); 1.1962 + 1.1963 + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000); 1.1964 + ogg_sync_wrote(&oy,1000); 1.1965 + if(ogg_sync_pageout(&oy,&og_de)>0)error(); 1.1966 + 1.1967 + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000, 1.1968 + og[1].body_len-1000); 1.1969 + ogg_sync_wrote(&oy,og[1].body_len-1000); 1.1970 + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); 1.1971 + 1.1972 + fprintf(stderr,"ok.\n"); 1.1973 + } 1.1974 + 1.1975 + /* Test fractional page inputs: page + incomplete capture */ 1.1976 + { 1.1977 + ogg_page og_de; 1.1978 + fprintf(stderr,"Testing sync on 1+partial inputs... "); 1.1979 + ogg_sync_reset(&oy); 1.1980 + 1.1981 + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, 1.1982 + og[1].header_len); 1.1983 + ogg_sync_wrote(&oy,og[1].header_len); 1.1984 + 1.1985 + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, 1.1986 + og[1].body_len); 1.1987 + ogg_sync_wrote(&oy,og[1].body_len); 1.1988 + 1.1989 + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, 1.1990 + 20); 1.1991 + ogg_sync_wrote(&oy,20); 1.1992 + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); 1.1993 + if(ogg_sync_pageout(&oy,&og_de)>0)error(); 1.1994 + 1.1995 + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20, 1.1996 + og[1].header_len-20); 1.1997 + ogg_sync_wrote(&oy,og[1].header_len-20); 1.1998 + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, 1.1999 + og[1].body_len); 1.2000 + ogg_sync_wrote(&oy,og[1].body_len); 1.2001 + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); 1.2002 + 1.2003 + fprintf(stderr,"ok.\n"); 1.2004 + } 1.2005 + 1.2006 + /* Test recapture: garbage + page */ 1.2007 + { 1.2008 + ogg_page og_de; 1.2009 + fprintf(stderr,"Testing search for capture... "); 1.2010 + ogg_sync_reset(&oy); 1.2011 + 1.2012 + /* 'garbage' */ 1.2013 + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, 1.2014 + og[1].body_len); 1.2015 + ogg_sync_wrote(&oy,og[1].body_len); 1.2016 + 1.2017 + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, 1.2018 + og[1].header_len); 1.2019 + ogg_sync_wrote(&oy,og[1].header_len); 1.2020 + 1.2021 + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, 1.2022 + og[1].body_len); 1.2023 + ogg_sync_wrote(&oy,og[1].body_len); 1.2024 + 1.2025 + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, 1.2026 + 20); 1.2027 + ogg_sync_wrote(&oy,20); 1.2028 + if(ogg_sync_pageout(&oy,&og_de)>0)error(); 1.2029 + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); 1.2030 + if(ogg_sync_pageout(&oy,&og_de)>0)error(); 1.2031 + 1.2032 + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20, 1.2033 + og[2].header_len-20); 1.2034 + ogg_sync_wrote(&oy,og[2].header_len-20); 1.2035 + memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body, 1.2036 + og[2].body_len); 1.2037 + ogg_sync_wrote(&oy,og[2].body_len); 1.2038 + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); 1.2039 + 1.2040 + fprintf(stderr,"ok.\n"); 1.2041 + } 1.2042 + 1.2043 + /* Test recapture: page + garbage + page */ 1.2044 + { 1.2045 + ogg_page og_de; 1.2046 + fprintf(stderr,"Testing recapture... "); 1.2047 + ogg_sync_reset(&oy); 1.2048 + 1.2049 + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, 1.2050 + og[1].header_len); 1.2051 + ogg_sync_wrote(&oy,og[1].header_len); 1.2052 + 1.2053 + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, 1.2054 + og[1].body_len); 1.2055 + ogg_sync_wrote(&oy,og[1].body_len); 1.2056 + 1.2057 + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, 1.2058 + og[2].header_len); 1.2059 + ogg_sync_wrote(&oy,og[2].header_len); 1.2060 + 1.2061 + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, 1.2062 + og[2].header_len); 1.2063 + ogg_sync_wrote(&oy,og[2].header_len); 1.2064 + 1.2065 + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); 1.2066 + 1.2067 + memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body, 1.2068 + og[2].body_len-5); 1.2069 + ogg_sync_wrote(&oy,og[2].body_len-5); 1.2070 + 1.2071 + memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header, 1.2072 + og[3].header_len); 1.2073 + ogg_sync_wrote(&oy,og[3].header_len); 1.2074 + 1.2075 + memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body, 1.2076 + og[3].body_len); 1.2077 + ogg_sync_wrote(&oy,og[3].body_len); 1.2078 + 1.2079 + if(ogg_sync_pageout(&oy,&og_de)>0)error(); 1.2080 + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); 1.2081 + 1.2082 + fprintf(stderr,"ok.\n"); 1.2083 + } 1.2084 + 1.2085 + /* Free page data that was previously copied */ 1.2086 + { 1.2087 + for(i=0;i<5;i++){ 1.2088 + free_page(&og[i]); 1.2089 + } 1.2090 + } 1.2091 + } 1.2092 + 1.2093 + return(0); 1.2094 +} 1.2095 + 1.2096 +#endif