Chris@1
|
1 /********************************************************************
|
Chris@1
|
2 * *
|
Chris@1
|
3 * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. *
|
Chris@1
|
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
Chris@1
|
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
Chris@1
|
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
Chris@1
|
7 * *
|
Chris@1
|
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 *
|
Chris@1
|
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
|
Chris@1
|
10 * *
|
Chris@1
|
11 ********************************************************************
|
Chris@1
|
12
|
Chris@1
|
13 function: code raw packets into framed OggSquish stream and
|
Chris@1
|
14 decode Ogg streams back into raw packets
|
Chris@1
|
15 last mod: $Id: framing.c 18052 2011-08-04 17:57:02Z giles $
|
Chris@1
|
16
|
Chris@1
|
17 note: The CRC code is directly derived from public domain code by
|
Chris@1
|
18 Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html
|
Chris@1
|
19 for details.
|
Chris@1
|
20
|
Chris@1
|
21 ********************************************************************/
|
Chris@1
|
22
|
Chris@1
|
23 #include <stdlib.h>
|
Chris@1
|
24 #include <string.h>
|
Chris@1
|
25 #include <ogg/ogg.h>
|
Chris@1
|
26
|
Chris@1
|
27 /* A complete description of Ogg framing exists in docs/framing.html */
|
Chris@1
|
28
|
Chris@1
|
29 int ogg_page_version(const ogg_page *og){
|
Chris@1
|
30 return((int)(og->header[4]));
|
Chris@1
|
31 }
|
Chris@1
|
32
|
Chris@1
|
33 int ogg_page_continued(const ogg_page *og){
|
Chris@1
|
34 return((int)(og->header[5]&0x01));
|
Chris@1
|
35 }
|
Chris@1
|
36
|
Chris@1
|
37 int ogg_page_bos(const ogg_page *og){
|
Chris@1
|
38 return((int)(og->header[5]&0x02));
|
Chris@1
|
39 }
|
Chris@1
|
40
|
Chris@1
|
41 int ogg_page_eos(const ogg_page *og){
|
Chris@1
|
42 return((int)(og->header[5]&0x04));
|
Chris@1
|
43 }
|
Chris@1
|
44
|
Chris@1
|
45 ogg_int64_t ogg_page_granulepos(const ogg_page *og){
|
Chris@1
|
46 unsigned char *page=og->header;
|
Chris@1
|
47 ogg_int64_t granulepos=page[13]&(0xff);
|
Chris@1
|
48 granulepos= (granulepos<<8)|(page[12]&0xff);
|
Chris@1
|
49 granulepos= (granulepos<<8)|(page[11]&0xff);
|
Chris@1
|
50 granulepos= (granulepos<<8)|(page[10]&0xff);
|
Chris@1
|
51 granulepos= (granulepos<<8)|(page[9]&0xff);
|
Chris@1
|
52 granulepos= (granulepos<<8)|(page[8]&0xff);
|
Chris@1
|
53 granulepos= (granulepos<<8)|(page[7]&0xff);
|
Chris@1
|
54 granulepos= (granulepos<<8)|(page[6]&0xff);
|
Chris@1
|
55 return(granulepos);
|
Chris@1
|
56 }
|
Chris@1
|
57
|
Chris@1
|
58 int ogg_page_serialno(const ogg_page *og){
|
Chris@1
|
59 return(og->header[14] |
|
Chris@1
|
60 (og->header[15]<<8) |
|
Chris@1
|
61 (og->header[16]<<16) |
|
Chris@1
|
62 (og->header[17]<<24));
|
Chris@1
|
63 }
|
Chris@1
|
64
|
Chris@1
|
65 long ogg_page_pageno(const ogg_page *og){
|
Chris@1
|
66 return(og->header[18] |
|
Chris@1
|
67 (og->header[19]<<8) |
|
Chris@1
|
68 (og->header[20]<<16) |
|
Chris@1
|
69 (og->header[21]<<24));
|
Chris@1
|
70 }
|
Chris@1
|
71
|
Chris@1
|
72
|
Chris@1
|
73
|
Chris@1
|
74 /* returns the number of packets that are completed on this page (if
|
Chris@1
|
75 the leading packet is begun on a previous page, but ends on this
|
Chris@1
|
76 page, it's counted */
|
Chris@1
|
77
|
Chris@1
|
78 /* NOTE:
|
Chris@1
|
79 If a page consists of a packet begun on a previous page, and a new
|
Chris@1
|
80 packet begun (but not completed) on this page, the return will be:
|
Chris@1
|
81 ogg_page_packets(page) ==1,
|
Chris@1
|
82 ogg_page_continued(page) !=0
|
Chris@1
|
83
|
Chris@1
|
84 If a page happens to be a single packet that was begun on a
|
Chris@1
|
85 previous page, and spans to the next page (in the case of a three or
|
Chris@1
|
86 more page packet), the return will be:
|
Chris@1
|
87 ogg_page_packets(page) ==0,
|
Chris@1
|
88 ogg_page_continued(page) !=0
|
Chris@1
|
89 */
|
Chris@1
|
90
|
Chris@1
|
91 int ogg_page_packets(const ogg_page *og){
|
Chris@1
|
92 int i,n=og->header[26],count=0;
|
Chris@1
|
93 for(i=0;i<n;i++)
|
Chris@1
|
94 if(og->header[27+i]<255)count++;
|
Chris@1
|
95 return(count);
|
Chris@1
|
96 }
|
Chris@1
|
97
|
Chris@1
|
98
|
Chris@1
|
99 #if 0
|
Chris@1
|
100 /* helper to initialize lookup for direct-table CRC (illustrative; we
|
Chris@1
|
101 use the static init below) */
|
Chris@1
|
102
|
Chris@1
|
103 static ogg_uint32_t _ogg_crc_entry(unsigned long index){
|
Chris@1
|
104 int i;
|
Chris@1
|
105 unsigned long r;
|
Chris@1
|
106
|
Chris@1
|
107 r = index << 24;
|
Chris@1
|
108 for (i=0; i<8; i++)
|
Chris@1
|
109 if (r & 0x80000000UL)
|
Chris@1
|
110 r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
|
Chris@1
|
111 polynomial, although we use an
|
Chris@1
|
112 unreflected alg and an init/final
|
Chris@1
|
113 of 0, not 0xffffffff */
|
Chris@1
|
114 else
|
Chris@1
|
115 r<<=1;
|
Chris@1
|
116 return (r & 0xffffffffUL);
|
Chris@1
|
117 }
|
Chris@1
|
118 #endif
|
Chris@1
|
119
|
Chris@1
|
120 static const ogg_uint32_t crc_lookup[256]={
|
Chris@1
|
121 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
|
Chris@1
|
122 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
|
Chris@1
|
123 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
|
Chris@1
|
124 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
|
Chris@1
|
125 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
|
Chris@1
|
126 0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
|
Chris@1
|
127 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
|
Chris@1
|
128 0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
|
Chris@1
|
129 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
|
Chris@1
|
130 0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
|
Chris@1
|
131 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
|
Chris@1
|
132 0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
|
Chris@1
|
133 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
|
Chris@1
|
134 0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
|
Chris@1
|
135 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
|
Chris@1
|
136 0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
|
Chris@1
|
137 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
|
Chris@1
|
138 0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
|
Chris@1
|
139 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
|
Chris@1
|
140 0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
|
Chris@1
|
141 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
|
Chris@1
|
142 0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
|
Chris@1
|
143 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
|
Chris@1
|
144 0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
|
Chris@1
|
145 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
|
Chris@1
|
146 0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
|
Chris@1
|
147 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
|
Chris@1
|
148 0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
|
Chris@1
|
149 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
|
Chris@1
|
150 0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
|
Chris@1
|
151 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
|
Chris@1
|
152 0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
|
Chris@1
|
153 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
|
Chris@1
|
154 0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
|
Chris@1
|
155 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
|
Chris@1
|
156 0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
|
Chris@1
|
157 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
|
Chris@1
|
158 0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
|
Chris@1
|
159 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
|
Chris@1
|
160 0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
|
Chris@1
|
161 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
|
Chris@1
|
162 0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
|
Chris@1
|
163 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
|
Chris@1
|
164 0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
|
Chris@1
|
165 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
|
Chris@1
|
166 0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
|
Chris@1
|
167 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
|
Chris@1
|
168 0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
|
Chris@1
|
169 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
|
Chris@1
|
170 0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
|
Chris@1
|
171 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
|
Chris@1
|
172 0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
|
Chris@1
|
173 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
|
Chris@1
|
174 0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
|
Chris@1
|
175 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
|
Chris@1
|
176 0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
|
Chris@1
|
177 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
|
Chris@1
|
178 0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
|
Chris@1
|
179 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
|
Chris@1
|
180 0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
|
Chris@1
|
181 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
|
Chris@1
|
182 0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
|
Chris@1
|
183 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
|
Chris@1
|
184 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4};
|
Chris@1
|
185
|
Chris@1
|
186 /* init the encode/decode logical stream state */
|
Chris@1
|
187
|
Chris@1
|
188 int ogg_stream_init(ogg_stream_state *os,int serialno){
|
Chris@1
|
189 if(os){
|
Chris@1
|
190 memset(os,0,sizeof(*os));
|
Chris@1
|
191 os->body_storage=16*1024;
|
Chris@1
|
192 os->lacing_storage=1024;
|
Chris@1
|
193
|
Chris@1
|
194 os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
|
Chris@1
|
195 os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
|
Chris@1
|
196 os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
|
Chris@1
|
197
|
Chris@1
|
198 if(!os->body_data || !os->lacing_vals || !os->granule_vals){
|
Chris@1
|
199 ogg_stream_clear(os);
|
Chris@1
|
200 return -1;
|
Chris@1
|
201 }
|
Chris@1
|
202
|
Chris@1
|
203 os->serialno=serialno;
|
Chris@1
|
204
|
Chris@1
|
205 return(0);
|
Chris@1
|
206 }
|
Chris@1
|
207 return(-1);
|
Chris@1
|
208 }
|
Chris@1
|
209
|
Chris@1
|
210 /* async/delayed error detection for the ogg_stream_state */
|
Chris@1
|
211 int ogg_stream_check(ogg_stream_state *os){
|
Chris@1
|
212 if(!os || !os->body_data) return -1;
|
Chris@1
|
213 return 0;
|
Chris@1
|
214 }
|
Chris@1
|
215
|
Chris@1
|
216 /* _clear does not free os, only the non-flat storage within */
|
Chris@1
|
217 int ogg_stream_clear(ogg_stream_state *os){
|
Chris@1
|
218 if(os){
|
Chris@1
|
219 if(os->body_data)_ogg_free(os->body_data);
|
Chris@1
|
220 if(os->lacing_vals)_ogg_free(os->lacing_vals);
|
Chris@1
|
221 if(os->granule_vals)_ogg_free(os->granule_vals);
|
Chris@1
|
222
|
Chris@1
|
223 memset(os,0,sizeof(*os));
|
Chris@1
|
224 }
|
Chris@1
|
225 return(0);
|
Chris@1
|
226 }
|
Chris@1
|
227
|
Chris@1
|
228 int ogg_stream_destroy(ogg_stream_state *os){
|
Chris@1
|
229 if(os){
|
Chris@1
|
230 ogg_stream_clear(os);
|
Chris@1
|
231 _ogg_free(os);
|
Chris@1
|
232 }
|
Chris@1
|
233 return(0);
|
Chris@1
|
234 }
|
Chris@1
|
235
|
Chris@1
|
236 /* Helpers for ogg_stream_encode; this keeps the structure and
|
Chris@1
|
237 what's happening fairly clear */
|
Chris@1
|
238
|
Chris@1
|
239 static int _os_body_expand(ogg_stream_state *os,int needed){
|
Chris@1
|
240 if(os->body_storage<=os->body_fill+needed){
|
Chris@1
|
241 void *ret;
|
Chris@1
|
242 ret=_ogg_realloc(os->body_data,(os->body_storage+needed+1024)*
|
Chris@1
|
243 sizeof(*os->body_data));
|
Chris@1
|
244 if(!ret){
|
Chris@1
|
245 ogg_stream_clear(os);
|
Chris@1
|
246 return -1;
|
Chris@1
|
247 }
|
Chris@1
|
248 os->body_storage+=(needed+1024);
|
Chris@1
|
249 os->body_data=ret;
|
Chris@1
|
250 }
|
Chris@1
|
251 return 0;
|
Chris@1
|
252 }
|
Chris@1
|
253
|
Chris@1
|
254 static int _os_lacing_expand(ogg_stream_state *os,int needed){
|
Chris@1
|
255 if(os->lacing_storage<=os->lacing_fill+needed){
|
Chris@1
|
256 void *ret;
|
Chris@1
|
257 ret=_ogg_realloc(os->lacing_vals,(os->lacing_storage+needed+32)*
|
Chris@1
|
258 sizeof(*os->lacing_vals));
|
Chris@1
|
259 if(!ret){
|
Chris@1
|
260 ogg_stream_clear(os);
|
Chris@1
|
261 return -1;
|
Chris@1
|
262 }
|
Chris@1
|
263 os->lacing_vals=ret;
|
Chris@1
|
264 ret=_ogg_realloc(os->granule_vals,(os->lacing_storage+needed+32)*
|
Chris@1
|
265 sizeof(*os->granule_vals));
|
Chris@1
|
266 if(!ret){
|
Chris@1
|
267 ogg_stream_clear(os);
|
Chris@1
|
268 return -1;
|
Chris@1
|
269 }
|
Chris@1
|
270 os->granule_vals=ret;
|
Chris@1
|
271 os->lacing_storage+=(needed+32);
|
Chris@1
|
272 }
|
Chris@1
|
273 return 0;
|
Chris@1
|
274 }
|
Chris@1
|
275
|
Chris@1
|
276 /* checksum the page */
|
Chris@1
|
277 /* Direct table CRC; note that this will be faster in the future if we
|
Chris@1
|
278 perform the checksum simultaneously with other copies */
|
Chris@1
|
279
|
Chris@1
|
280 void ogg_page_checksum_set(ogg_page *og){
|
Chris@1
|
281 if(og){
|
Chris@1
|
282 ogg_uint32_t crc_reg=0;
|
Chris@1
|
283 int i;
|
Chris@1
|
284
|
Chris@1
|
285 /* safety; needed for API behavior, but not framing code */
|
Chris@1
|
286 og->header[22]=0;
|
Chris@1
|
287 og->header[23]=0;
|
Chris@1
|
288 og->header[24]=0;
|
Chris@1
|
289 og->header[25]=0;
|
Chris@1
|
290
|
Chris@1
|
291 for(i=0;i<og->header_len;i++)
|
Chris@1
|
292 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
|
Chris@1
|
293 for(i=0;i<og->body_len;i++)
|
Chris@1
|
294 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
|
Chris@1
|
295
|
Chris@1
|
296 og->header[22]=(unsigned char)(crc_reg&0xff);
|
Chris@1
|
297 og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
|
Chris@1
|
298 og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
|
Chris@1
|
299 og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
|
Chris@1
|
300 }
|
Chris@1
|
301 }
|
Chris@1
|
302
|
Chris@1
|
303 /* submit data to the internal buffer of the framing engine */
|
Chris@1
|
304 int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count,
|
Chris@1
|
305 long e_o_s, ogg_int64_t granulepos){
|
Chris@1
|
306
|
Chris@1
|
307 int bytes = 0, lacing_vals, i;
|
Chris@1
|
308
|
Chris@1
|
309 if(ogg_stream_check(os)) return -1;
|
Chris@1
|
310 if(!iov) return 0;
|
Chris@1
|
311
|
Chris@1
|
312 for (i = 0; i < count; ++i) bytes += (int)iov[i].iov_len;
|
Chris@1
|
313 lacing_vals=bytes/255+1;
|
Chris@1
|
314
|
Chris@1
|
315 if(os->body_returned){
|
Chris@1
|
316 /* advance packet data according to the body_returned pointer. We
|
Chris@1
|
317 had to keep it around to return a pointer into the buffer last
|
Chris@1
|
318 call */
|
Chris@1
|
319
|
Chris@1
|
320 os->body_fill-=os->body_returned;
|
Chris@1
|
321 if(os->body_fill)
|
Chris@1
|
322 memmove(os->body_data,os->body_data+os->body_returned,
|
Chris@1
|
323 os->body_fill);
|
Chris@1
|
324 os->body_returned=0;
|
Chris@1
|
325 }
|
Chris@1
|
326
|
Chris@1
|
327 /* make sure we have the buffer storage */
|
Chris@1
|
328 if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals))
|
Chris@1
|
329 return -1;
|
Chris@1
|
330
|
Chris@1
|
331 /* Copy in the submitted packet. Yes, the copy is a waste; this is
|
Chris@1
|
332 the liability of overly clean abstraction for the time being. It
|
Chris@1
|
333 will actually be fairly easy to eliminate the extra copy in the
|
Chris@1
|
334 future */
|
Chris@1
|
335
|
Chris@1
|
336 for (i = 0; i < count; ++i) {
|
Chris@1
|
337 memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len);
|
Chris@1
|
338 os->body_fill += (int)iov[i].iov_len;
|
Chris@1
|
339 }
|
Chris@1
|
340
|
Chris@1
|
341 /* Store lacing vals for this packet */
|
Chris@1
|
342 for(i=0;i<lacing_vals-1;i++){
|
Chris@1
|
343 os->lacing_vals[os->lacing_fill+i]=255;
|
Chris@1
|
344 os->granule_vals[os->lacing_fill+i]=os->granulepos;
|
Chris@1
|
345 }
|
Chris@1
|
346 os->lacing_vals[os->lacing_fill+i]=bytes%255;
|
Chris@1
|
347 os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos;
|
Chris@1
|
348
|
Chris@1
|
349 /* flag the first segment as the beginning of the packet */
|
Chris@1
|
350 os->lacing_vals[os->lacing_fill]|= 0x100;
|
Chris@1
|
351
|
Chris@1
|
352 os->lacing_fill+=lacing_vals;
|
Chris@1
|
353
|
Chris@1
|
354 /* for the sake of completeness */
|
Chris@1
|
355 os->packetno++;
|
Chris@1
|
356
|
Chris@1
|
357 if(e_o_s)os->e_o_s=1;
|
Chris@1
|
358
|
Chris@1
|
359 return(0);
|
Chris@1
|
360 }
|
Chris@1
|
361
|
Chris@1
|
362 int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
|
Chris@1
|
363 ogg_iovec_t iov;
|
Chris@1
|
364 iov.iov_base = op->packet;
|
Chris@1
|
365 iov.iov_len = op->bytes;
|
Chris@1
|
366 return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos);
|
Chris@1
|
367 }
|
Chris@1
|
368
|
Chris@1
|
369 /* Conditionally flush a page; force==0 will only flush nominal-size
|
Chris@1
|
370 pages, force==1 forces us to flush a page regardless of page size
|
Chris@1
|
371 so long as there's any data available at all. */
|
Chris@1
|
372 static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){
|
Chris@1
|
373 int i;
|
Chris@1
|
374 int vals=0;
|
Chris@1
|
375 int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
|
Chris@1
|
376 int bytes=0;
|
Chris@1
|
377 long acc=0;
|
Chris@1
|
378 ogg_int64_t granule_pos=-1;
|
Chris@1
|
379
|
Chris@1
|
380 if(ogg_stream_check(os)) return(0);
|
Chris@1
|
381 if(maxvals==0) return(0);
|
Chris@1
|
382
|
Chris@1
|
383 /* construct a page */
|
Chris@1
|
384 /* decide how many segments to include */
|
Chris@1
|
385
|
Chris@1
|
386 /* If this is the initial header case, the first page must only include
|
Chris@1
|
387 the initial header packet */
|
Chris@1
|
388 if(os->b_o_s==0){ /* 'initial header page' case */
|
Chris@1
|
389 granule_pos=0;
|
Chris@1
|
390 for(vals=0;vals<maxvals;vals++){
|
Chris@1
|
391 if((os->lacing_vals[vals]&0x0ff)<255){
|
Chris@1
|
392 vals++;
|
Chris@1
|
393 break;
|
Chris@1
|
394 }
|
Chris@1
|
395 }
|
Chris@1
|
396 }else{
|
Chris@1
|
397
|
Chris@1
|
398 /* The extra packets_done, packet_just_done logic here attempts to do two things:
|
Chris@1
|
399 1) Don't unneccessarily span pages.
|
Chris@1
|
400 2) Unless necessary, don't flush pages if there are less than four packets on
|
Chris@1
|
401 them; this expands page size to reduce unneccessary overhead if incoming packets
|
Chris@1
|
402 are large.
|
Chris@1
|
403 These are not necessary behaviors, just 'always better than naive flushing'
|
Chris@1
|
404 without requiring an application to explicitly request a specific optimized
|
Chris@1
|
405 behavior. We'll want an explicit behavior setup pathway eventually as well. */
|
Chris@1
|
406
|
Chris@1
|
407 int packets_done=0;
|
Chris@1
|
408 int packet_just_done=0;
|
Chris@1
|
409 for(vals=0;vals<maxvals;vals++){
|
Chris@1
|
410 if(acc>nfill && packet_just_done>=4){
|
Chris@1
|
411 force=1;
|
Chris@1
|
412 break;
|
Chris@1
|
413 }
|
Chris@1
|
414 acc+=os->lacing_vals[vals]&0x0ff;
|
Chris@1
|
415 if((os->lacing_vals[vals]&0xff)<255){
|
Chris@1
|
416 granule_pos=os->granule_vals[vals];
|
Chris@1
|
417 packet_just_done=++packets_done;
|
Chris@1
|
418 }else
|
Chris@1
|
419 packet_just_done=0;
|
Chris@1
|
420 }
|
Chris@1
|
421 if(vals==255)force=1;
|
Chris@1
|
422 }
|
Chris@1
|
423
|
Chris@1
|
424 if(!force) return(0);
|
Chris@1
|
425
|
Chris@1
|
426 /* construct the header in temp storage */
|
Chris@1
|
427 memcpy(os->header,"OggS",4);
|
Chris@1
|
428
|
Chris@1
|
429 /* stream structure version */
|
Chris@1
|
430 os->header[4]=0x00;
|
Chris@1
|
431
|
Chris@1
|
432 /* continued packet flag? */
|
Chris@1
|
433 os->header[5]=0x00;
|
Chris@1
|
434 if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
|
Chris@1
|
435 /* first page flag? */
|
Chris@1
|
436 if(os->b_o_s==0)os->header[5]|=0x02;
|
Chris@1
|
437 /* last page flag? */
|
Chris@1
|
438 if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
|
Chris@1
|
439 os->b_o_s=1;
|
Chris@1
|
440
|
Chris@1
|
441 /* 64 bits of PCM position */
|
Chris@1
|
442 for(i=6;i<14;i++){
|
Chris@1
|
443 os->header[i]=(unsigned char)(granule_pos&0xff);
|
Chris@1
|
444 granule_pos>>=8;
|
Chris@1
|
445 }
|
Chris@1
|
446
|
Chris@1
|
447 /* 32 bits of stream serial number */
|
Chris@1
|
448 {
|
Chris@1
|
449 long serialno=os->serialno;
|
Chris@1
|
450 for(i=14;i<18;i++){
|
Chris@1
|
451 os->header[i]=(unsigned char)(serialno&0xff);
|
Chris@1
|
452 serialno>>=8;
|
Chris@1
|
453 }
|
Chris@1
|
454 }
|
Chris@1
|
455
|
Chris@1
|
456 /* 32 bits of page counter (we have both counter and page header
|
Chris@1
|
457 because this val can roll over) */
|
Chris@1
|
458 if(os->pageno==-1)os->pageno=0; /* because someone called
|
Chris@1
|
459 stream_reset; this would be a
|
Chris@1
|
460 strange thing to do in an
|
Chris@1
|
461 encode stream, but it has
|
Chris@1
|
462 plausible uses */
|
Chris@1
|
463 {
|
Chris@1
|
464 long pageno=os->pageno++;
|
Chris@1
|
465 for(i=18;i<22;i++){
|
Chris@1
|
466 os->header[i]=(unsigned char)(pageno&0xff);
|
Chris@1
|
467 pageno>>=8;
|
Chris@1
|
468 }
|
Chris@1
|
469 }
|
Chris@1
|
470
|
Chris@1
|
471 /* zero for computation; filled in later */
|
Chris@1
|
472 os->header[22]=0;
|
Chris@1
|
473 os->header[23]=0;
|
Chris@1
|
474 os->header[24]=0;
|
Chris@1
|
475 os->header[25]=0;
|
Chris@1
|
476
|
Chris@1
|
477 /* segment table */
|
Chris@1
|
478 os->header[26]=(unsigned char)(vals&0xff);
|
Chris@1
|
479 for(i=0;i<vals;i++)
|
Chris@1
|
480 bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
|
Chris@1
|
481
|
Chris@1
|
482 /* set pointers in the ogg_page struct */
|
Chris@1
|
483 og->header=os->header;
|
Chris@1
|
484 og->header_len=os->header_fill=vals+27;
|
Chris@1
|
485 og->body=os->body_data+os->body_returned;
|
Chris@1
|
486 og->body_len=bytes;
|
Chris@1
|
487
|
Chris@1
|
488 /* advance the lacing data and set the body_returned pointer */
|
Chris@1
|
489
|
Chris@1
|
490 os->lacing_fill-=vals;
|
Chris@1
|
491 memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
|
Chris@1
|
492 memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
|
Chris@1
|
493 os->body_returned+=bytes;
|
Chris@1
|
494
|
Chris@1
|
495 /* calculate the checksum */
|
Chris@1
|
496
|
Chris@1
|
497 ogg_page_checksum_set(og);
|
Chris@1
|
498
|
Chris@1
|
499 /* done */
|
Chris@1
|
500 return(1);
|
Chris@1
|
501 }
|
Chris@1
|
502
|
Chris@1
|
503 /* This will flush remaining packets into a page (returning nonzero),
|
Chris@1
|
504 even if there is not enough data to trigger a flush normally
|
Chris@1
|
505 (undersized page). If there are no packets or partial packets to
|
Chris@1
|
506 flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
|
Chris@1
|
507 try to flush a normal sized page like ogg_stream_pageout; a call to
|
Chris@1
|
508 ogg_stream_flush does not guarantee that all packets have flushed.
|
Chris@1
|
509 Only a return value of 0 from ogg_stream_flush indicates all packet
|
Chris@1
|
510 data is flushed into pages.
|
Chris@1
|
511
|
Chris@1
|
512 since ogg_stream_flush will flush the last page in a stream even if
|
Chris@1
|
513 it's undersized, you almost certainly want to use ogg_stream_pageout
|
Chris@1
|
514 (and *not* ogg_stream_flush) unless you specifically need to flush
|
Chris@1
|
515 a page regardless of size in the middle of a stream. */
|
Chris@1
|
516
|
Chris@1
|
517 int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
|
Chris@1
|
518 return ogg_stream_flush_i(os,og,1,4096);
|
Chris@1
|
519 }
|
Chris@1
|
520
|
Chris@1
|
521 /* Like the above, but an argument is provided to adjust the nominal
|
Chris@1
|
522 page size for applications which are smart enough to provide their
|
Chris@1
|
523 own delay based flushing */
|
Chris@1
|
524
|
Chris@1
|
525 int ogg_stream_flush_fill(ogg_stream_state *os,ogg_page *og, int nfill){
|
Chris@1
|
526 return ogg_stream_flush_i(os,og,1,nfill);
|
Chris@1
|
527 }
|
Chris@1
|
528
|
Chris@1
|
529 /* This constructs pages from buffered packet segments. The pointers
|
Chris@1
|
530 returned are to static buffers; do not free. The returned buffers are
|
Chris@1
|
531 good only until the next call (using the same ogg_stream_state) */
|
Chris@1
|
532
|
Chris@1
|
533 int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
|
Chris@1
|
534 int force=0;
|
Chris@1
|
535 if(ogg_stream_check(os)) return 0;
|
Chris@1
|
536
|
Chris@1
|
537 if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
|
Chris@1
|
538 (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */
|
Chris@1
|
539 force=1;
|
Chris@1
|
540
|
Chris@1
|
541 return(ogg_stream_flush_i(os,og,force,4096));
|
Chris@1
|
542 }
|
Chris@1
|
543
|
Chris@1
|
544 /* Like the above, but an argument is provided to adjust the nominal
|
Chris@1
|
545 page size for applications which are smart enough to provide their
|
Chris@1
|
546 own delay based flushing */
|
Chris@1
|
547
|
Chris@1
|
548 int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){
|
Chris@1
|
549 int force=0;
|
Chris@1
|
550 if(ogg_stream_check(os)) return 0;
|
Chris@1
|
551
|
Chris@1
|
552 if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
|
Chris@1
|
553 (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */
|
Chris@1
|
554 force=1;
|
Chris@1
|
555
|
Chris@1
|
556 return(ogg_stream_flush_i(os,og,force,nfill));
|
Chris@1
|
557 }
|
Chris@1
|
558
|
Chris@1
|
559 int ogg_stream_eos(ogg_stream_state *os){
|
Chris@1
|
560 if(ogg_stream_check(os)) return 1;
|
Chris@1
|
561 return os->e_o_s;
|
Chris@1
|
562 }
|
Chris@1
|
563
|
Chris@1
|
564 /* DECODING PRIMITIVES: packet streaming layer **********************/
|
Chris@1
|
565
|
Chris@1
|
566 /* This has two layers to place more of the multi-serialno and paging
|
Chris@1
|
567 control in the application's hands. First, we expose a data buffer
|
Chris@1
|
568 using ogg_sync_buffer(). The app either copies into the
|
Chris@1
|
569 buffer, or passes it directly to read(), etc. We then call
|
Chris@1
|
570 ogg_sync_wrote() to tell how many bytes we just added.
|
Chris@1
|
571
|
Chris@1
|
572 Pages are returned (pointers into the buffer in ogg_sync_state)
|
Chris@1
|
573 by ogg_sync_pageout(). The page is then submitted to
|
Chris@1
|
574 ogg_stream_pagein() along with the appropriate
|
Chris@1
|
575 ogg_stream_state* (ie, matching serialno). We then get raw
|
Chris@1
|
576 packets out calling ogg_stream_packetout() with a
|
Chris@1
|
577 ogg_stream_state. */
|
Chris@1
|
578
|
Chris@1
|
579 /* initialize the struct to a known state */
|
Chris@1
|
580 int ogg_sync_init(ogg_sync_state *oy){
|
Chris@1
|
581 if(oy){
|
Chris@1
|
582 oy->storage = -1; /* used as a readiness flag */
|
Chris@1
|
583 memset(oy,0,sizeof(*oy));
|
Chris@1
|
584 }
|
Chris@1
|
585 return(0);
|
Chris@1
|
586 }
|
Chris@1
|
587
|
Chris@1
|
588 /* clear non-flat storage within */
|
Chris@1
|
589 int ogg_sync_clear(ogg_sync_state *oy){
|
Chris@1
|
590 if(oy){
|
Chris@1
|
591 if(oy->data)_ogg_free(oy->data);
|
Chris@1
|
592 memset(oy,0,sizeof(*oy));
|
Chris@1
|
593 }
|
Chris@1
|
594 return(0);
|
Chris@1
|
595 }
|
Chris@1
|
596
|
Chris@1
|
597 int ogg_sync_destroy(ogg_sync_state *oy){
|
Chris@1
|
598 if(oy){
|
Chris@1
|
599 ogg_sync_clear(oy);
|
Chris@1
|
600 _ogg_free(oy);
|
Chris@1
|
601 }
|
Chris@1
|
602 return(0);
|
Chris@1
|
603 }
|
Chris@1
|
604
|
Chris@1
|
605 int ogg_sync_check(ogg_sync_state *oy){
|
Chris@1
|
606 if(oy->storage<0) return -1;
|
Chris@1
|
607 return 0;
|
Chris@1
|
608 }
|
Chris@1
|
609
|
Chris@1
|
610 char *ogg_sync_buffer(ogg_sync_state *oy, long size){
|
Chris@1
|
611 if(ogg_sync_check(oy)) return NULL;
|
Chris@1
|
612
|
Chris@1
|
613 /* first, clear out any space that has been previously returned */
|
Chris@1
|
614 if(oy->returned){
|
Chris@1
|
615 oy->fill-=oy->returned;
|
Chris@1
|
616 if(oy->fill>0)
|
Chris@1
|
617 memmove(oy->data,oy->data+oy->returned,oy->fill);
|
Chris@1
|
618 oy->returned=0;
|
Chris@1
|
619 }
|
Chris@1
|
620
|
Chris@1
|
621 if(size>oy->storage-oy->fill){
|
Chris@1
|
622 /* We need to extend the internal buffer */
|
Chris@1
|
623 long newsize=size+oy->fill+4096; /* an extra page to be nice */
|
Chris@1
|
624 void *ret;
|
Chris@1
|
625
|
Chris@1
|
626 if(oy->data)
|
Chris@1
|
627 ret=_ogg_realloc(oy->data,newsize);
|
Chris@1
|
628 else
|
Chris@1
|
629 ret=_ogg_malloc(newsize);
|
Chris@1
|
630 if(!ret){
|
Chris@1
|
631 ogg_sync_clear(oy);
|
Chris@1
|
632 return NULL;
|
Chris@1
|
633 }
|
Chris@1
|
634 oy->data=ret;
|
Chris@1
|
635 oy->storage=newsize;
|
Chris@1
|
636 }
|
Chris@1
|
637
|
Chris@1
|
638 /* expose a segment at least as large as requested at the fill mark */
|
Chris@1
|
639 return((char *)oy->data+oy->fill);
|
Chris@1
|
640 }
|
Chris@1
|
641
|
Chris@1
|
642 int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
|
Chris@1
|
643 if(ogg_sync_check(oy))return -1;
|
Chris@1
|
644 if(oy->fill+bytes>oy->storage)return -1;
|
Chris@1
|
645 oy->fill+=bytes;
|
Chris@1
|
646 return(0);
|
Chris@1
|
647 }
|
Chris@1
|
648
|
Chris@1
|
649 /* sync the stream. This is meant to be useful for finding page
|
Chris@1
|
650 boundaries.
|
Chris@1
|
651
|
Chris@1
|
652 return values for this:
|
Chris@1
|
653 -n) skipped n bytes
|
Chris@1
|
654 0) page not ready; more data (no bytes skipped)
|
Chris@1
|
655 n) page synced at current location; page length n bytes
|
Chris@1
|
656
|
Chris@1
|
657 */
|
Chris@1
|
658
|
Chris@1
|
659 long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
|
Chris@1
|
660 unsigned char *page=oy->data+oy->returned;
|
Chris@1
|
661 unsigned char *next;
|
Chris@1
|
662 long bytes=oy->fill-oy->returned;
|
Chris@1
|
663
|
Chris@1
|
664 if(ogg_sync_check(oy))return 0;
|
Chris@1
|
665
|
Chris@1
|
666 if(oy->headerbytes==0){
|
Chris@1
|
667 int headerbytes,i;
|
Chris@1
|
668 if(bytes<27)return(0); /* not enough for a header */
|
Chris@1
|
669
|
Chris@1
|
670 /* verify capture pattern */
|
Chris@1
|
671 if(memcmp(page,"OggS",4))goto sync_fail;
|
Chris@1
|
672
|
Chris@1
|
673 headerbytes=page[26]+27;
|
Chris@1
|
674 if(bytes<headerbytes)return(0); /* not enough for header + seg table */
|
Chris@1
|
675
|
Chris@1
|
676 /* count up body length in the segment table */
|
Chris@1
|
677
|
Chris@1
|
678 for(i=0;i<page[26];i++)
|
Chris@1
|
679 oy->bodybytes+=page[27+i];
|
Chris@1
|
680 oy->headerbytes=headerbytes;
|
Chris@1
|
681 }
|
Chris@1
|
682
|
Chris@1
|
683 if(oy->bodybytes+oy->headerbytes>bytes)return(0);
|
Chris@1
|
684
|
Chris@1
|
685 /* The whole test page is buffered. Verify the checksum */
|
Chris@1
|
686 {
|
Chris@1
|
687 /* Grab the checksum bytes, set the header field to zero */
|
Chris@1
|
688 char chksum[4];
|
Chris@1
|
689 ogg_page log;
|
Chris@1
|
690
|
Chris@1
|
691 memcpy(chksum,page+22,4);
|
Chris@1
|
692 memset(page+22,0,4);
|
Chris@1
|
693
|
Chris@1
|
694 /* set up a temp page struct and recompute the checksum */
|
Chris@1
|
695 log.header=page;
|
Chris@1
|
696 log.header_len=oy->headerbytes;
|
Chris@1
|
697 log.body=page+oy->headerbytes;
|
Chris@1
|
698 log.body_len=oy->bodybytes;
|
Chris@1
|
699 ogg_page_checksum_set(&log);
|
Chris@1
|
700
|
Chris@1
|
701 /* Compare */
|
Chris@1
|
702 if(memcmp(chksum,page+22,4)){
|
Chris@1
|
703 /* D'oh. Mismatch! Corrupt page (or miscapture and not a page
|
Chris@1
|
704 at all) */
|
Chris@1
|
705 /* replace the computed checksum with the one actually read in */
|
Chris@1
|
706 memcpy(page+22,chksum,4);
|
Chris@1
|
707
|
Chris@1
|
708 /* Bad checksum. Lose sync */
|
Chris@1
|
709 goto sync_fail;
|
Chris@1
|
710 }
|
Chris@1
|
711 }
|
Chris@1
|
712
|
Chris@1
|
713 /* yes, have a whole page all ready to go */
|
Chris@1
|
714 {
|
Chris@1
|
715 unsigned char *page=oy->data+oy->returned;
|
Chris@1
|
716 long bytes;
|
Chris@1
|
717
|
Chris@1
|
718 if(og){
|
Chris@1
|
719 og->header=page;
|
Chris@1
|
720 og->header_len=oy->headerbytes;
|
Chris@1
|
721 og->body=page+oy->headerbytes;
|
Chris@1
|
722 og->body_len=oy->bodybytes;
|
Chris@1
|
723 }
|
Chris@1
|
724
|
Chris@1
|
725 oy->unsynced=0;
|
Chris@1
|
726 oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
|
Chris@1
|
727 oy->headerbytes=0;
|
Chris@1
|
728 oy->bodybytes=0;
|
Chris@1
|
729 return(bytes);
|
Chris@1
|
730 }
|
Chris@1
|
731
|
Chris@1
|
732 sync_fail:
|
Chris@1
|
733
|
Chris@1
|
734 oy->headerbytes=0;
|
Chris@1
|
735 oy->bodybytes=0;
|
Chris@1
|
736
|
Chris@1
|
737 /* search for possible capture */
|
Chris@1
|
738 next=memchr(page+1,'O',bytes-1);
|
Chris@1
|
739 if(!next)
|
Chris@1
|
740 next=oy->data+oy->fill;
|
Chris@1
|
741
|
Chris@1
|
742 oy->returned=(int)(next-oy->data);
|
Chris@1
|
743 return((long)-(next-page));
|
Chris@1
|
744 }
|
Chris@1
|
745
|
Chris@1
|
746 /* sync the stream and get a page. Keep trying until we find a page.
|
Chris@1
|
747 Suppress 'sync errors' after reporting the first.
|
Chris@1
|
748
|
Chris@1
|
749 return values:
|
Chris@1
|
750 -1) recapture (hole in data)
|
Chris@1
|
751 0) need more data
|
Chris@1
|
752 1) page returned
|
Chris@1
|
753
|
Chris@1
|
754 Returns pointers into buffered data; invalidated by next call to
|
Chris@1
|
755 _stream, _clear, _init, or _buffer */
|
Chris@1
|
756
|
Chris@1
|
757 int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
|
Chris@1
|
758
|
Chris@1
|
759 if(ogg_sync_check(oy))return 0;
|
Chris@1
|
760
|
Chris@1
|
761 /* all we need to do is verify a page at the head of the stream
|
Chris@1
|
762 buffer. If it doesn't verify, we look for the next potential
|
Chris@1
|
763 frame */
|
Chris@1
|
764
|
Chris@1
|
765 for(;;){
|
Chris@1
|
766 long ret=ogg_sync_pageseek(oy,og);
|
Chris@1
|
767 if(ret>0){
|
Chris@1
|
768 /* have a page */
|
Chris@1
|
769 return(1);
|
Chris@1
|
770 }
|
Chris@1
|
771 if(ret==0){
|
Chris@1
|
772 /* need more data */
|
Chris@1
|
773 return(0);
|
Chris@1
|
774 }
|
Chris@1
|
775
|
Chris@1
|
776 /* head did not start a synced page... skipped some bytes */
|
Chris@1
|
777 if(!oy->unsynced){
|
Chris@1
|
778 oy->unsynced=1;
|
Chris@1
|
779 return(-1);
|
Chris@1
|
780 }
|
Chris@1
|
781
|
Chris@1
|
782 /* loop. keep looking */
|
Chris@1
|
783
|
Chris@1
|
784 }
|
Chris@1
|
785 }
|
Chris@1
|
786
|
Chris@1
|
787 /* add the incoming page to the stream state; we decompose the page
|
Chris@1
|
788 into packet segments here as well. */
|
Chris@1
|
789
|
Chris@1
|
790 int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
|
Chris@1
|
791 unsigned char *header=og->header;
|
Chris@1
|
792 unsigned char *body=og->body;
|
Chris@1
|
793 long bodysize=og->body_len;
|
Chris@1
|
794 int segptr=0;
|
Chris@1
|
795
|
Chris@1
|
796 int version=ogg_page_version(og);
|
Chris@1
|
797 int continued=ogg_page_continued(og);
|
Chris@1
|
798 int bos=ogg_page_bos(og);
|
Chris@1
|
799 int eos=ogg_page_eos(og);
|
Chris@1
|
800 ogg_int64_t granulepos=ogg_page_granulepos(og);
|
Chris@1
|
801 int serialno=ogg_page_serialno(og);
|
Chris@1
|
802 long pageno=ogg_page_pageno(og);
|
Chris@1
|
803 int segments=header[26];
|
Chris@1
|
804
|
Chris@1
|
805 if(ogg_stream_check(os)) return -1;
|
Chris@1
|
806
|
Chris@1
|
807 /* clean up 'returned data' */
|
Chris@1
|
808 {
|
Chris@1
|
809 long lr=os->lacing_returned;
|
Chris@1
|
810 long br=os->body_returned;
|
Chris@1
|
811
|
Chris@1
|
812 /* body data */
|
Chris@1
|
813 if(br){
|
Chris@1
|
814 os->body_fill-=br;
|
Chris@1
|
815 if(os->body_fill)
|
Chris@1
|
816 memmove(os->body_data,os->body_data+br,os->body_fill);
|
Chris@1
|
817 os->body_returned=0;
|
Chris@1
|
818 }
|
Chris@1
|
819
|
Chris@1
|
820 if(lr){
|
Chris@1
|
821 /* segment table */
|
Chris@1
|
822 if(os->lacing_fill-lr){
|
Chris@1
|
823 memmove(os->lacing_vals,os->lacing_vals+lr,
|
Chris@1
|
824 (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
|
Chris@1
|
825 memmove(os->granule_vals,os->granule_vals+lr,
|
Chris@1
|
826 (os->lacing_fill-lr)*sizeof(*os->granule_vals));
|
Chris@1
|
827 }
|
Chris@1
|
828 os->lacing_fill-=lr;
|
Chris@1
|
829 os->lacing_packet-=lr;
|
Chris@1
|
830 os->lacing_returned=0;
|
Chris@1
|
831 }
|
Chris@1
|
832 }
|
Chris@1
|
833
|
Chris@1
|
834 /* check the serial number */
|
Chris@1
|
835 if(serialno!=os->serialno)return(-1);
|
Chris@1
|
836 if(version>0)return(-1);
|
Chris@1
|
837
|
Chris@1
|
838 if(_os_lacing_expand(os,segments+1)) return -1;
|
Chris@1
|
839
|
Chris@1
|
840 /* are we in sequence? */
|
Chris@1
|
841 if(pageno!=os->pageno){
|
Chris@1
|
842 int i;
|
Chris@1
|
843
|
Chris@1
|
844 /* unroll previous partial packet (if any) */
|
Chris@1
|
845 for(i=os->lacing_packet;i<os->lacing_fill;i++)
|
Chris@1
|
846 os->body_fill-=os->lacing_vals[i]&0xff;
|
Chris@1
|
847 os->lacing_fill=os->lacing_packet;
|
Chris@1
|
848
|
Chris@1
|
849 /* make a note of dropped data in segment table */
|
Chris@1
|
850 if(os->pageno!=-1){
|
Chris@1
|
851 os->lacing_vals[os->lacing_fill++]=0x400;
|
Chris@1
|
852 os->lacing_packet++;
|
Chris@1
|
853 }
|
Chris@1
|
854 }
|
Chris@1
|
855
|
Chris@1
|
856 /* are we a 'continued packet' page? If so, we may need to skip
|
Chris@1
|
857 some segments */
|
Chris@1
|
858 if(continued){
|
Chris@1
|
859 if(os->lacing_fill<1 ||
|
Chris@1
|
860 os->lacing_vals[os->lacing_fill-1]==0x400){
|
Chris@1
|
861 bos=0;
|
Chris@1
|
862 for(;segptr<segments;segptr++){
|
Chris@1
|
863 int val=header[27+segptr];
|
Chris@1
|
864 body+=val;
|
Chris@1
|
865 bodysize-=val;
|
Chris@1
|
866 if(val<255){
|
Chris@1
|
867 segptr++;
|
Chris@1
|
868 break;
|
Chris@1
|
869 }
|
Chris@1
|
870 }
|
Chris@1
|
871 }
|
Chris@1
|
872 }
|
Chris@1
|
873
|
Chris@1
|
874 if(bodysize){
|
Chris@1
|
875 if(_os_body_expand(os,bodysize)) return -1;
|
Chris@1
|
876 memcpy(os->body_data+os->body_fill,body,bodysize);
|
Chris@1
|
877 os->body_fill+=bodysize;
|
Chris@1
|
878 }
|
Chris@1
|
879
|
Chris@1
|
880 {
|
Chris@1
|
881 int saved=-1;
|
Chris@1
|
882 while(segptr<segments){
|
Chris@1
|
883 int val=header[27+segptr];
|
Chris@1
|
884 os->lacing_vals[os->lacing_fill]=val;
|
Chris@1
|
885 os->granule_vals[os->lacing_fill]=-1;
|
Chris@1
|
886
|
Chris@1
|
887 if(bos){
|
Chris@1
|
888 os->lacing_vals[os->lacing_fill]|=0x100;
|
Chris@1
|
889 bos=0;
|
Chris@1
|
890 }
|
Chris@1
|
891
|
Chris@1
|
892 if(val<255)saved=os->lacing_fill;
|
Chris@1
|
893
|
Chris@1
|
894 os->lacing_fill++;
|
Chris@1
|
895 segptr++;
|
Chris@1
|
896
|
Chris@1
|
897 if(val<255)os->lacing_packet=os->lacing_fill;
|
Chris@1
|
898 }
|
Chris@1
|
899
|
Chris@1
|
900 /* set the granulepos on the last granuleval of the last full packet */
|
Chris@1
|
901 if(saved!=-1){
|
Chris@1
|
902 os->granule_vals[saved]=granulepos;
|
Chris@1
|
903 }
|
Chris@1
|
904
|
Chris@1
|
905 }
|
Chris@1
|
906
|
Chris@1
|
907 if(eos){
|
Chris@1
|
908 os->e_o_s=1;
|
Chris@1
|
909 if(os->lacing_fill>0)
|
Chris@1
|
910 os->lacing_vals[os->lacing_fill-1]|=0x200;
|
Chris@1
|
911 }
|
Chris@1
|
912
|
Chris@1
|
913 os->pageno=pageno+1;
|
Chris@1
|
914
|
Chris@1
|
915 return(0);
|
Chris@1
|
916 }
|
Chris@1
|
917
|
Chris@1
|
918 /* clear things to an initial state. Good to call, eg, before seeking */
|
Chris@1
|
919 int ogg_sync_reset(ogg_sync_state *oy){
|
Chris@1
|
920 if(ogg_sync_check(oy))return -1;
|
Chris@1
|
921
|
Chris@1
|
922 oy->fill=0;
|
Chris@1
|
923 oy->returned=0;
|
Chris@1
|
924 oy->unsynced=0;
|
Chris@1
|
925 oy->headerbytes=0;
|
Chris@1
|
926 oy->bodybytes=0;
|
Chris@1
|
927 return(0);
|
Chris@1
|
928 }
|
Chris@1
|
929
|
Chris@1
|
930 int ogg_stream_reset(ogg_stream_state *os){
|
Chris@1
|
931 if(ogg_stream_check(os)) return -1;
|
Chris@1
|
932
|
Chris@1
|
933 os->body_fill=0;
|
Chris@1
|
934 os->body_returned=0;
|
Chris@1
|
935
|
Chris@1
|
936 os->lacing_fill=0;
|
Chris@1
|
937 os->lacing_packet=0;
|
Chris@1
|
938 os->lacing_returned=0;
|
Chris@1
|
939
|
Chris@1
|
940 os->header_fill=0;
|
Chris@1
|
941
|
Chris@1
|
942 os->e_o_s=0;
|
Chris@1
|
943 os->b_o_s=0;
|
Chris@1
|
944 os->pageno=-1;
|
Chris@1
|
945 os->packetno=0;
|
Chris@1
|
946 os->granulepos=0;
|
Chris@1
|
947
|
Chris@1
|
948 return(0);
|
Chris@1
|
949 }
|
Chris@1
|
950
|
Chris@1
|
951 int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
|
Chris@1
|
952 if(ogg_stream_check(os)) return -1;
|
Chris@1
|
953 ogg_stream_reset(os);
|
Chris@1
|
954 os->serialno=serialno;
|
Chris@1
|
955 return(0);
|
Chris@1
|
956 }
|
Chris@1
|
957
|
Chris@1
|
958 static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
|
Chris@1
|
959
|
Chris@1
|
960 /* The last part of decode. We have the stream broken into packet
|
Chris@1
|
961 segments. Now we need to group them into packets (or return the
|
Chris@1
|
962 out of sync markers) */
|
Chris@1
|
963
|
Chris@1
|
964 int ptr=os->lacing_returned;
|
Chris@1
|
965
|
Chris@1
|
966 if(os->lacing_packet<=ptr)return(0);
|
Chris@1
|
967
|
Chris@1
|
968 if(os->lacing_vals[ptr]&0x400){
|
Chris@1
|
969 /* we need to tell the codec there's a gap; it might need to
|
Chris@1
|
970 handle previous packet dependencies. */
|
Chris@1
|
971 os->lacing_returned++;
|
Chris@1
|
972 os->packetno++;
|
Chris@1
|
973 return(-1);
|
Chris@1
|
974 }
|
Chris@1
|
975
|
Chris@1
|
976 if(!op && !adv)return(1); /* just using peek as an inexpensive way
|
Chris@1
|
977 to ask if there's a whole packet
|
Chris@1
|
978 waiting */
|
Chris@1
|
979
|
Chris@1
|
980 /* Gather the whole packet. We'll have no holes or a partial packet */
|
Chris@1
|
981 {
|
Chris@1
|
982 int size=os->lacing_vals[ptr]&0xff;
|
Chris@1
|
983 long bytes=size;
|
Chris@1
|
984 int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
|
Chris@1
|
985 int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
|
Chris@1
|
986
|
Chris@1
|
987 while(size==255){
|
Chris@1
|
988 int val=os->lacing_vals[++ptr];
|
Chris@1
|
989 size=val&0xff;
|
Chris@1
|
990 if(val&0x200)eos=0x200;
|
Chris@1
|
991 bytes+=size;
|
Chris@1
|
992 }
|
Chris@1
|
993
|
Chris@1
|
994 if(op){
|
Chris@1
|
995 op->e_o_s=eos;
|
Chris@1
|
996 op->b_o_s=bos;
|
Chris@1
|
997 op->packet=os->body_data+os->body_returned;
|
Chris@1
|
998 op->packetno=os->packetno;
|
Chris@1
|
999 op->granulepos=os->granule_vals[ptr];
|
Chris@1
|
1000 op->bytes=bytes;
|
Chris@1
|
1001 }
|
Chris@1
|
1002
|
Chris@1
|
1003 if(adv){
|
Chris@1
|
1004 os->body_returned+=bytes;
|
Chris@1
|
1005 os->lacing_returned=ptr+1;
|
Chris@1
|
1006 os->packetno++;
|
Chris@1
|
1007 }
|
Chris@1
|
1008 }
|
Chris@1
|
1009 return(1);
|
Chris@1
|
1010 }
|
Chris@1
|
1011
|
Chris@1
|
1012 int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
|
Chris@1
|
1013 if(ogg_stream_check(os)) return 0;
|
Chris@1
|
1014 return _packetout(os,op,1);
|
Chris@1
|
1015 }
|
Chris@1
|
1016
|
Chris@1
|
1017 int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
|
Chris@1
|
1018 if(ogg_stream_check(os)) return 0;
|
Chris@1
|
1019 return _packetout(os,op,0);
|
Chris@1
|
1020 }
|
Chris@1
|
1021
|
Chris@1
|
1022 void ogg_packet_clear(ogg_packet *op) {
|
Chris@1
|
1023 _ogg_free(op->packet);
|
Chris@1
|
1024 memset(op, 0, sizeof(*op));
|
Chris@1
|
1025 }
|
Chris@1
|
1026
|
Chris@1
|
1027 #ifdef _V_SELFTEST
|
Chris@1
|
1028 #include <stdio.h>
|
Chris@1
|
1029
|
Chris@1
|
1030 ogg_stream_state os_en, os_de;
|
Chris@1
|
1031 ogg_sync_state oy;
|
Chris@1
|
1032
|
Chris@1
|
1033 void checkpacket(ogg_packet *op,long len, int no, long pos){
|
Chris@1
|
1034 long j;
|
Chris@1
|
1035 static int sequence=0;
|
Chris@1
|
1036 static int lastno=0;
|
Chris@1
|
1037
|
Chris@1
|
1038 if(op->bytes!=len){
|
Chris@1
|
1039 fprintf(stderr,"incorrect packet length (%ld != %ld)!\n",op->bytes,len);
|
Chris@1
|
1040 exit(1);
|
Chris@1
|
1041 }
|
Chris@1
|
1042 if(op->granulepos!=pos){
|
Chris@1
|
1043 fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos);
|
Chris@1
|
1044 exit(1);
|
Chris@1
|
1045 }
|
Chris@1
|
1046
|
Chris@1
|
1047 /* packet number just follows sequence/gap; adjust the input number
|
Chris@1
|
1048 for that */
|
Chris@1
|
1049 if(no==0){
|
Chris@1
|
1050 sequence=0;
|
Chris@1
|
1051 }else{
|
Chris@1
|
1052 sequence++;
|
Chris@1
|
1053 if(no>lastno+1)
|
Chris@1
|
1054 sequence++;
|
Chris@1
|
1055 }
|
Chris@1
|
1056 lastno=no;
|
Chris@1
|
1057 if(op->packetno!=sequence){
|
Chris@1
|
1058 fprintf(stderr,"incorrect packet sequence %ld != %d\n",
|
Chris@1
|
1059 (long)(op->packetno),sequence);
|
Chris@1
|
1060 exit(1);
|
Chris@1
|
1061 }
|
Chris@1
|
1062
|
Chris@1
|
1063 /* Test data */
|
Chris@1
|
1064 for(j=0;j<op->bytes;j++)
|
Chris@1
|
1065 if(op->packet[j]!=((j+no)&0xff)){
|
Chris@1
|
1066 fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
|
Chris@1
|
1067 j,op->packet[j],(j+no)&0xff);
|
Chris@1
|
1068 exit(1);
|
Chris@1
|
1069 }
|
Chris@1
|
1070 }
|
Chris@1
|
1071
|
Chris@1
|
1072 void check_page(unsigned char *data,const int *header,ogg_page *og){
|
Chris@1
|
1073 long j;
|
Chris@1
|
1074 /* Test data */
|
Chris@1
|
1075 for(j=0;j<og->body_len;j++)
|
Chris@1
|
1076 if(og->body[j]!=data[j]){
|
Chris@1
|
1077 fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
|
Chris@1
|
1078 j,data[j],og->body[j]);
|
Chris@1
|
1079 exit(1);
|
Chris@1
|
1080 }
|
Chris@1
|
1081
|
Chris@1
|
1082 /* Test header */
|
Chris@1
|
1083 for(j=0;j<og->header_len;j++){
|
Chris@1
|
1084 if(og->header[j]!=header[j]){
|
Chris@1
|
1085 fprintf(stderr,"header content mismatch at pos %ld:\n",j);
|
Chris@1
|
1086 for(j=0;j<header[26]+27;j++)
|
Chris@1
|
1087 fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
|
Chris@1
|
1088 fprintf(stderr,"\n");
|
Chris@1
|
1089 exit(1);
|
Chris@1
|
1090 }
|
Chris@1
|
1091 }
|
Chris@1
|
1092 if(og->header_len!=header[26]+27){
|
Chris@1
|
1093 fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
|
Chris@1
|
1094 og->header_len,header[26]+27);
|
Chris@1
|
1095 exit(1);
|
Chris@1
|
1096 }
|
Chris@1
|
1097 }
|
Chris@1
|
1098
|
Chris@1
|
1099 void print_header(ogg_page *og){
|
Chris@1
|
1100 int j;
|
Chris@1
|
1101 fprintf(stderr,"\nHEADER:\n");
|
Chris@1
|
1102 fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n",
|
Chris@1
|
1103 og->header[0],og->header[1],og->header[2],og->header[3],
|
Chris@1
|
1104 (int)og->header[4],(int)og->header[5]);
|
Chris@1
|
1105
|
Chris@1
|
1106 fprintf(stderr," granulepos: %d serialno: %d pageno: %ld\n",
|
Chris@1
|
1107 (og->header[9]<<24)|(og->header[8]<<16)|
|
Chris@1
|
1108 (og->header[7]<<8)|og->header[6],
|
Chris@1
|
1109 (og->header[17]<<24)|(og->header[16]<<16)|
|
Chris@1
|
1110 (og->header[15]<<8)|og->header[14],
|
Chris@1
|
1111 ((long)(og->header[21])<<24)|(og->header[20]<<16)|
|
Chris@1
|
1112 (og->header[19]<<8)|og->header[18]);
|
Chris@1
|
1113
|
Chris@1
|
1114 fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (",
|
Chris@1
|
1115 (int)og->header[22],(int)og->header[23],
|
Chris@1
|
1116 (int)og->header[24],(int)og->header[25],
|
Chris@1
|
1117 (int)og->header[26]);
|
Chris@1
|
1118
|
Chris@1
|
1119 for(j=27;j<og->header_len;j++)
|
Chris@1
|
1120 fprintf(stderr,"%d ",(int)og->header[j]);
|
Chris@1
|
1121 fprintf(stderr,")\n\n");
|
Chris@1
|
1122 }
|
Chris@1
|
1123
|
Chris@1
|
1124 void copy_page(ogg_page *og){
|
Chris@1
|
1125 unsigned char *temp=_ogg_malloc(og->header_len);
|
Chris@1
|
1126 memcpy(temp,og->header,og->header_len);
|
Chris@1
|
1127 og->header=temp;
|
Chris@1
|
1128
|
Chris@1
|
1129 temp=_ogg_malloc(og->body_len);
|
Chris@1
|
1130 memcpy(temp,og->body,og->body_len);
|
Chris@1
|
1131 og->body=temp;
|
Chris@1
|
1132 }
|
Chris@1
|
1133
|
Chris@1
|
1134 void free_page(ogg_page *og){
|
Chris@1
|
1135 _ogg_free (og->header);
|
Chris@1
|
1136 _ogg_free (og->body);
|
Chris@1
|
1137 }
|
Chris@1
|
1138
|
Chris@1
|
1139 void error(void){
|
Chris@1
|
1140 fprintf(stderr,"error!\n");
|
Chris@1
|
1141 exit(1);
|
Chris@1
|
1142 }
|
Chris@1
|
1143
|
Chris@1
|
1144 /* 17 only */
|
Chris@1
|
1145 const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
|
Chris@1
|
1146 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1147 0x01,0x02,0x03,0x04,0,0,0,0,
|
Chris@1
|
1148 0x15,0xed,0xec,0x91,
|
Chris@1
|
1149 1,
|
Chris@1
|
1150 17};
|
Chris@1
|
1151
|
Chris@1
|
1152 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
|
Chris@1
|
1153 const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
|
Chris@1
|
1154 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1155 0x01,0x02,0x03,0x04,0,0,0,0,
|
Chris@1
|
1156 0x59,0x10,0x6c,0x2c,
|
Chris@1
|
1157 1,
|
Chris@1
|
1158 17};
|
Chris@1
|
1159 const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
|
Chris@1
|
1160 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1161 0x01,0x02,0x03,0x04,1,0,0,0,
|
Chris@1
|
1162 0x89,0x33,0x85,0xce,
|
Chris@1
|
1163 13,
|
Chris@1
|
1164 254,255,0,255,1,255,245,255,255,0,
|
Chris@1
|
1165 255,255,90};
|
Chris@1
|
1166
|
Chris@1
|
1167 /* nil packets; beginning,middle,end */
|
Chris@1
|
1168 const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
|
Chris@1
|
1169 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1170 0x01,0x02,0x03,0x04,0,0,0,0,
|
Chris@1
|
1171 0xff,0x7b,0x23,0x17,
|
Chris@1
|
1172 1,
|
Chris@1
|
1173 0};
|
Chris@1
|
1174 const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
|
Chris@1
|
1175 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1176 0x01,0x02,0x03,0x04,1,0,0,0,
|
Chris@1
|
1177 0x5c,0x3f,0x66,0xcb,
|
Chris@1
|
1178 17,
|
Chris@1
|
1179 17,254,255,0,0,255,1,0,255,245,255,255,0,
|
Chris@1
|
1180 255,255,90,0};
|
Chris@1
|
1181
|
Chris@1
|
1182 /* large initial packet */
|
Chris@1
|
1183 const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
|
Chris@1
|
1184 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1185 0x01,0x02,0x03,0x04,0,0,0,0,
|
Chris@1
|
1186 0x01,0x27,0x31,0xaa,
|
Chris@1
|
1187 18,
|
Chris@1
|
1188 255,255,255,255,255,255,255,255,
|
Chris@1
|
1189 255,255,255,255,255,255,255,255,255,10};
|
Chris@1
|
1190
|
Chris@1
|
1191 const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
|
Chris@1
|
1192 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1193 0x01,0x02,0x03,0x04,1,0,0,0,
|
Chris@1
|
1194 0x7f,0x4e,0x8a,0xd2,
|
Chris@1
|
1195 4,
|
Chris@1
|
1196 255,4,255,0};
|
Chris@1
|
1197
|
Chris@1
|
1198
|
Chris@1
|
1199 /* continuing packet test */
|
Chris@1
|
1200 const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
|
Chris@1
|
1201 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1202 0x01,0x02,0x03,0x04,0,0,0,0,
|
Chris@1
|
1203 0xff,0x7b,0x23,0x17,
|
Chris@1
|
1204 1,
|
Chris@1
|
1205 0};
|
Chris@1
|
1206
|
Chris@1
|
1207 const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
|
Chris@1
|
1208 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
Chris@1
|
1209 0x01,0x02,0x03,0x04,1,0,0,0,
|
Chris@1
|
1210 0xf8,0x3c,0x19,0x79,
|
Chris@1
|
1211 255,
|
Chris@1
|
1212 255,255,255,255,255,255,255,255,
|
Chris@1
|
1213 255,255,255,255,255,255,255,255,
|
Chris@1
|
1214 255,255,255,255,255,255,255,255,
|
Chris@1
|
1215 255,255,255,255,255,255,255,255,
|
Chris@1
|
1216 255,255,255,255,255,255,255,255,
|
Chris@1
|
1217 255,255,255,255,255,255,255,255,
|
Chris@1
|
1218 255,255,255,255,255,255,255,255,
|
Chris@1
|
1219 255,255,255,255,255,255,255,255,
|
Chris@1
|
1220 255,255,255,255,255,255,255,255,
|
Chris@1
|
1221 255,255,255,255,255,255,255,255,
|
Chris@1
|
1222 255,255,255,255,255,255,255,255,
|
Chris@1
|
1223 255,255,255,255,255,255,255,255,
|
Chris@1
|
1224 255,255,255,255,255,255,255,255,
|
Chris@1
|
1225 255,255,255,255,255,255,255,255,
|
Chris@1
|
1226 255,255,255,255,255,255,255,255,
|
Chris@1
|
1227 255,255,255,255,255,255,255,255,
|
Chris@1
|
1228 255,255,255,255,255,255,255,255,
|
Chris@1
|
1229 255,255,255,255,255,255,255,255,
|
Chris@1
|
1230 255,255,255,255,255,255,255,255,
|
Chris@1
|
1231 255,255,255,255,255,255,255,255,
|
Chris@1
|
1232 255,255,255,255,255,255,255,255,
|
Chris@1
|
1233 255,255,255,255,255,255,255,255,
|
Chris@1
|
1234 255,255,255,255,255,255,255,255,
|
Chris@1
|
1235 255,255,255,255,255,255,255,255,
|
Chris@1
|
1236 255,255,255,255,255,255,255,255,
|
Chris@1
|
1237 255,255,255,255,255,255,255,255,
|
Chris@1
|
1238 255,255,255,255,255,255,255,255,
|
Chris@1
|
1239 255,255,255,255,255,255,255,255,
|
Chris@1
|
1240 255,255,255,255,255,255,255,255,
|
Chris@1
|
1241 255,255,255,255,255,255,255,255,
|
Chris@1
|
1242 255,255,255,255,255,255,255,255,
|
Chris@1
|
1243 255,255,255,255,255,255,255};
|
Chris@1
|
1244
|
Chris@1
|
1245 const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
|
Chris@1
|
1246 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1247 0x01,0x02,0x03,0x04,2,0,0,0,
|
Chris@1
|
1248 0x38,0xe6,0xb6,0x28,
|
Chris@1
|
1249 6,
|
Chris@1
|
1250 255,220,255,4,255,0};
|
Chris@1
|
1251
|
Chris@1
|
1252
|
Chris@1
|
1253 /* spill expansion test */
|
Chris@1
|
1254 const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
|
Chris@1
|
1255 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1256 0x01,0x02,0x03,0x04,0,0,0,0,
|
Chris@1
|
1257 0xff,0x7b,0x23,0x17,
|
Chris@1
|
1258 1,
|
Chris@1
|
1259 0};
|
Chris@1
|
1260
|
Chris@1
|
1261 const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
|
Chris@1
|
1262 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1263 0x01,0x02,0x03,0x04,1,0,0,0,
|
Chris@1
|
1264 0xce,0x8f,0x17,0x1a,
|
Chris@1
|
1265 23,
|
Chris@1
|
1266 255,255,255,255,255,255,255,255,
|
Chris@1
|
1267 255,255,255,255,255,255,255,255,255,10,255,4,255,0,0};
|
Chris@1
|
1268
|
Chris@1
|
1269
|
Chris@1
|
1270 const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
|
Chris@1
|
1271 0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1272 0x01,0x02,0x03,0x04,2,0,0,0,
|
Chris@1
|
1273 0x9b,0xb2,0x50,0xa1,
|
Chris@1
|
1274 1,
|
Chris@1
|
1275 0};
|
Chris@1
|
1276
|
Chris@1
|
1277 /* page with the 255 segment limit */
|
Chris@1
|
1278 const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
|
Chris@1
|
1279 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1280 0x01,0x02,0x03,0x04,0,0,0,0,
|
Chris@1
|
1281 0xff,0x7b,0x23,0x17,
|
Chris@1
|
1282 1,
|
Chris@1
|
1283 0};
|
Chris@1
|
1284
|
Chris@1
|
1285 const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
|
Chris@1
|
1286 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1287 0x01,0x02,0x03,0x04,1,0,0,0,
|
Chris@1
|
1288 0xed,0x2a,0x2e,0xa7,
|
Chris@1
|
1289 255,
|
Chris@1
|
1290 10,10,10,10,10,10,10,10,
|
Chris@1
|
1291 10,10,10,10,10,10,10,10,
|
Chris@1
|
1292 10,10,10,10,10,10,10,10,
|
Chris@1
|
1293 10,10,10,10,10,10,10,10,
|
Chris@1
|
1294 10,10,10,10,10,10,10,10,
|
Chris@1
|
1295 10,10,10,10,10,10,10,10,
|
Chris@1
|
1296 10,10,10,10,10,10,10,10,
|
Chris@1
|
1297 10,10,10,10,10,10,10,10,
|
Chris@1
|
1298 10,10,10,10,10,10,10,10,
|
Chris@1
|
1299 10,10,10,10,10,10,10,10,
|
Chris@1
|
1300 10,10,10,10,10,10,10,10,
|
Chris@1
|
1301 10,10,10,10,10,10,10,10,
|
Chris@1
|
1302 10,10,10,10,10,10,10,10,
|
Chris@1
|
1303 10,10,10,10,10,10,10,10,
|
Chris@1
|
1304 10,10,10,10,10,10,10,10,
|
Chris@1
|
1305 10,10,10,10,10,10,10,10,
|
Chris@1
|
1306 10,10,10,10,10,10,10,10,
|
Chris@1
|
1307 10,10,10,10,10,10,10,10,
|
Chris@1
|
1308 10,10,10,10,10,10,10,10,
|
Chris@1
|
1309 10,10,10,10,10,10,10,10,
|
Chris@1
|
1310 10,10,10,10,10,10,10,10,
|
Chris@1
|
1311 10,10,10,10,10,10,10,10,
|
Chris@1
|
1312 10,10,10,10,10,10,10,10,
|
Chris@1
|
1313 10,10,10,10,10,10,10,10,
|
Chris@1
|
1314 10,10,10,10,10,10,10,10,
|
Chris@1
|
1315 10,10,10,10,10,10,10,10,
|
Chris@1
|
1316 10,10,10,10,10,10,10,10,
|
Chris@1
|
1317 10,10,10,10,10,10,10,10,
|
Chris@1
|
1318 10,10,10,10,10,10,10,10,
|
Chris@1
|
1319 10,10,10,10,10,10,10,10,
|
Chris@1
|
1320 10,10,10,10,10,10,10,10,
|
Chris@1
|
1321 10,10,10,10,10,10,10};
|
Chris@1
|
1322
|
Chris@1
|
1323 const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
|
Chris@1
|
1324 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1325 0x01,0x02,0x03,0x04,2,0,0,0,
|
Chris@1
|
1326 0x6c,0x3b,0x82,0x3d,
|
Chris@1
|
1327 1,
|
Chris@1
|
1328 50};
|
Chris@1
|
1329
|
Chris@1
|
1330
|
Chris@1
|
1331 /* packet that overspans over an entire page */
|
Chris@1
|
1332 const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
|
Chris@1
|
1333 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1334 0x01,0x02,0x03,0x04,0,0,0,0,
|
Chris@1
|
1335 0xff,0x7b,0x23,0x17,
|
Chris@1
|
1336 1,
|
Chris@1
|
1337 0};
|
Chris@1
|
1338
|
Chris@1
|
1339 const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
|
Chris@1
|
1340 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1341 0x01,0x02,0x03,0x04,1,0,0,0,
|
Chris@1
|
1342 0x68,0x22,0x7c,0x3d,
|
Chris@1
|
1343 255,
|
Chris@1
|
1344 100,
|
Chris@1
|
1345 255,255,255,255,255,255,255,255,
|
Chris@1
|
1346 255,255,255,255,255,255,255,255,
|
Chris@1
|
1347 255,255,255,255,255,255,255,255,
|
Chris@1
|
1348 255,255,255,255,255,255,255,255,
|
Chris@1
|
1349 255,255,255,255,255,255,255,255,
|
Chris@1
|
1350 255,255,255,255,255,255,255,255,
|
Chris@1
|
1351 255,255,255,255,255,255,255,255,
|
Chris@1
|
1352 255,255,255,255,255,255,255,255,
|
Chris@1
|
1353 255,255,255,255,255,255,255,255,
|
Chris@1
|
1354 255,255,255,255,255,255,255,255,
|
Chris@1
|
1355 255,255,255,255,255,255,255,255,
|
Chris@1
|
1356 255,255,255,255,255,255,255,255,
|
Chris@1
|
1357 255,255,255,255,255,255,255,255,
|
Chris@1
|
1358 255,255,255,255,255,255,255,255,
|
Chris@1
|
1359 255,255,255,255,255,255,255,255,
|
Chris@1
|
1360 255,255,255,255,255,255,255,255,
|
Chris@1
|
1361 255,255,255,255,255,255,255,255,
|
Chris@1
|
1362 255,255,255,255,255,255,255,255,
|
Chris@1
|
1363 255,255,255,255,255,255,255,255,
|
Chris@1
|
1364 255,255,255,255,255,255,255,255,
|
Chris@1
|
1365 255,255,255,255,255,255,255,255,
|
Chris@1
|
1366 255,255,255,255,255,255,255,255,
|
Chris@1
|
1367 255,255,255,255,255,255,255,255,
|
Chris@1
|
1368 255,255,255,255,255,255,255,255,
|
Chris@1
|
1369 255,255,255,255,255,255,255,255,
|
Chris@1
|
1370 255,255,255,255,255,255,255,255,
|
Chris@1
|
1371 255,255,255,255,255,255,255,255,
|
Chris@1
|
1372 255,255,255,255,255,255,255,255,
|
Chris@1
|
1373 255,255,255,255,255,255,255,255,
|
Chris@1
|
1374 255,255,255,255,255,255,255,255,
|
Chris@1
|
1375 255,255,255,255,255,255,255,255,
|
Chris@1
|
1376 255,255,255,255,255,255};
|
Chris@1
|
1377
|
Chris@1
|
1378 const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
|
Chris@1
|
1379 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
Chris@1
|
1380 0x01,0x02,0x03,0x04,2,0,0,0,
|
Chris@1
|
1381 0xf4,0x87,0xba,0xf3,
|
Chris@1
|
1382 255,
|
Chris@1
|
1383 255,255,255,255,255,255,255,255,
|
Chris@1
|
1384 255,255,255,255,255,255,255,255,
|
Chris@1
|
1385 255,255,255,255,255,255,255,255,
|
Chris@1
|
1386 255,255,255,255,255,255,255,255,
|
Chris@1
|
1387 255,255,255,255,255,255,255,255,
|
Chris@1
|
1388 255,255,255,255,255,255,255,255,
|
Chris@1
|
1389 255,255,255,255,255,255,255,255,
|
Chris@1
|
1390 255,255,255,255,255,255,255,255,
|
Chris@1
|
1391 255,255,255,255,255,255,255,255,
|
Chris@1
|
1392 255,255,255,255,255,255,255,255,
|
Chris@1
|
1393 255,255,255,255,255,255,255,255,
|
Chris@1
|
1394 255,255,255,255,255,255,255,255,
|
Chris@1
|
1395 255,255,255,255,255,255,255,255,
|
Chris@1
|
1396 255,255,255,255,255,255,255,255,
|
Chris@1
|
1397 255,255,255,255,255,255,255,255,
|
Chris@1
|
1398 255,255,255,255,255,255,255,255,
|
Chris@1
|
1399 255,255,255,255,255,255,255,255,
|
Chris@1
|
1400 255,255,255,255,255,255,255,255,
|
Chris@1
|
1401 255,255,255,255,255,255,255,255,
|
Chris@1
|
1402 255,255,255,255,255,255,255,255,
|
Chris@1
|
1403 255,255,255,255,255,255,255,255,
|
Chris@1
|
1404 255,255,255,255,255,255,255,255,
|
Chris@1
|
1405 255,255,255,255,255,255,255,255,
|
Chris@1
|
1406 255,255,255,255,255,255,255,255,
|
Chris@1
|
1407 255,255,255,255,255,255,255,255,
|
Chris@1
|
1408 255,255,255,255,255,255,255,255,
|
Chris@1
|
1409 255,255,255,255,255,255,255,255,
|
Chris@1
|
1410 255,255,255,255,255,255,255,255,
|
Chris@1
|
1411 255,255,255,255,255,255,255,255,
|
Chris@1
|
1412 255,255,255,255,255,255,255,255,
|
Chris@1
|
1413 255,255,255,255,255,255,255,255,
|
Chris@1
|
1414 255,255,255,255,255,255,255};
|
Chris@1
|
1415
|
Chris@1
|
1416 const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
|
Chris@1
|
1417 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1418 0x01,0x02,0x03,0x04,3,0,0,0,
|
Chris@1
|
1419 0xf7,0x2f,0x6c,0x60,
|
Chris@1
|
1420 5,
|
Chris@1
|
1421 254,255,4,255,0};
|
Chris@1
|
1422
|
Chris@1
|
1423 /* packet that overspans over an entire page */
|
Chris@1
|
1424 const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
|
Chris@1
|
1425 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1426 0x01,0x02,0x03,0x04,0,0,0,0,
|
Chris@1
|
1427 0xff,0x7b,0x23,0x17,
|
Chris@1
|
1428 1,
|
Chris@1
|
1429 0};
|
Chris@1
|
1430
|
Chris@1
|
1431 const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
|
Chris@1
|
1432 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1433 0x01,0x02,0x03,0x04,1,0,0,0,
|
Chris@1
|
1434 0x68,0x22,0x7c,0x3d,
|
Chris@1
|
1435 255,
|
Chris@1
|
1436 100,
|
Chris@1
|
1437 255,255,255,255,255,255,255,255,
|
Chris@1
|
1438 255,255,255,255,255,255,255,255,
|
Chris@1
|
1439 255,255,255,255,255,255,255,255,
|
Chris@1
|
1440 255,255,255,255,255,255,255,255,
|
Chris@1
|
1441 255,255,255,255,255,255,255,255,
|
Chris@1
|
1442 255,255,255,255,255,255,255,255,
|
Chris@1
|
1443 255,255,255,255,255,255,255,255,
|
Chris@1
|
1444 255,255,255,255,255,255,255,255,
|
Chris@1
|
1445 255,255,255,255,255,255,255,255,
|
Chris@1
|
1446 255,255,255,255,255,255,255,255,
|
Chris@1
|
1447 255,255,255,255,255,255,255,255,
|
Chris@1
|
1448 255,255,255,255,255,255,255,255,
|
Chris@1
|
1449 255,255,255,255,255,255,255,255,
|
Chris@1
|
1450 255,255,255,255,255,255,255,255,
|
Chris@1
|
1451 255,255,255,255,255,255,255,255,
|
Chris@1
|
1452 255,255,255,255,255,255,255,255,
|
Chris@1
|
1453 255,255,255,255,255,255,255,255,
|
Chris@1
|
1454 255,255,255,255,255,255,255,255,
|
Chris@1
|
1455 255,255,255,255,255,255,255,255,
|
Chris@1
|
1456 255,255,255,255,255,255,255,255,
|
Chris@1
|
1457 255,255,255,255,255,255,255,255,
|
Chris@1
|
1458 255,255,255,255,255,255,255,255,
|
Chris@1
|
1459 255,255,255,255,255,255,255,255,
|
Chris@1
|
1460 255,255,255,255,255,255,255,255,
|
Chris@1
|
1461 255,255,255,255,255,255,255,255,
|
Chris@1
|
1462 255,255,255,255,255,255,255,255,
|
Chris@1
|
1463 255,255,255,255,255,255,255,255,
|
Chris@1
|
1464 255,255,255,255,255,255,255,255,
|
Chris@1
|
1465 255,255,255,255,255,255,255,255,
|
Chris@1
|
1466 255,255,255,255,255,255,255,255,
|
Chris@1
|
1467 255,255,255,255,255,255,255,255,
|
Chris@1
|
1468 255,255,255,255,255,255};
|
Chris@1
|
1469
|
Chris@1
|
1470 const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
|
Chris@1
|
1471 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
|
Chris@1
|
1472 0x01,0x02,0x03,0x04,2,0,0,0,
|
Chris@1
|
1473 0xd4,0xe0,0x60,0xe5,
|
Chris@1
|
1474 1,
|
Chris@1
|
1475 0};
|
Chris@1
|
1476
|
Chris@1
|
1477 void test_pack(const int *pl, const int **headers, int byteskip,
|
Chris@1
|
1478 int pageskip, int packetskip){
|
Chris@1
|
1479 unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
|
Chris@1
|
1480 long inptr=0;
|
Chris@1
|
1481 long outptr=0;
|
Chris@1
|
1482 long deptr=0;
|
Chris@1
|
1483 long depacket=0;
|
Chris@1
|
1484 long granule_pos=7,pageno=0;
|
Chris@1
|
1485 int i,j,packets,pageout=pageskip;
|
Chris@1
|
1486 int eosflag=0;
|
Chris@1
|
1487 int bosflag=0;
|
Chris@1
|
1488
|
Chris@1
|
1489 int byteskipcount=0;
|
Chris@1
|
1490
|
Chris@1
|
1491 ogg_stream_reset(&os_en);
|
Chris@1
|
1492 ogg_stream_reset(&os_de);
|
Chris@1
|
1493 ogg_sync_reset(&oy);
|
Chris@1
|
1494
|
Chris@1
|
1495 for(packets=0;packets<packetskip;packets++)
|
Chris@1
|
1496 depacket+=pl[packets];
|
Chris@1
|
1497
|
Chris@1
|
1498 for(packets=0;;packets++)if(pl[packets]==-1)break;
|
Chris@1
|
1499
|
Chris@1
|
1500 for(i=0;i<packets;i++){
|
Chris@1
|
1501 /* construct a test packet */
|
Chris@1
|
1502 ogg_packet op;
|
Chris@1
|
1503 int len=pl[i];
|
Chris@1
|
1504
|
Chris@1
|
1505 op.packet=data+inptr;
|
Chris@1
|
1506 op.bytes=len;
|
Chris@1
|
1507 op.e_o_s=(pl[i+1]<0?1:0);
|
Chris@1
|
1508 op.granulepos=granule_pos;
|
Chris@1
|
1509
|
Chris@1
|
1510 granule_pos+=1024;
|
Chris@1
|
1511
|
Chris@1
|
1512 for(j=0;j<len;j++)data[inptr++]=i+j;
|
Chris@1
|
1513
|
Chris@1
|
1514 /* submit the test packet */
|
Chris@1
|
1515 ogg_stream_packetin(&os_en,&op);
|
Chris@1
|
1516
|
Chris@1
|
1517 /* retrieve any finished pages */
|
Chris@1
|
1518 {
|
Chris@1
|
1519 ogg_page og;
|
Chris@1
|
1520
|
Chris@1
|
1521 while(ogg_stream_pageout(&os_en,&og)){
|
Chris@1
|
1522 /* We have a page. Check it carefully */
|
Chris@1
|
1523
|
Chris@1
|
1524 fprintf(stderr,"%ld, ",pageno);
|
Chris@1
|
1525
|
Chris@1
|
1526 if(headers[pageno]==NULL){
|
Chris@1
|
1527 fprintf(stderr,"coded too many pages!\n");
|
Chris@1
|
1528 exit(1);
|
Chris@1
|
1529 }
|
Chris@1
|
1530
|
Chris@1
|
1531 check_page(data+outptr,headers[pageno],&og);
|
Chris@1
|
1532
|
Chris@1
|
1533 outptr+=og.body_len;
|
Chris@1
|
1534 pageno++;
|
Chris@1
|
1535 if(pageskip){
|
Chris@1
|
1536 bosflag=1;
|
Chris@1
|
1537 pageskip--;
|
Chris@1
|
1538 deptr+=og.body_len;
|
Chris@1
|
1539 }
|
Chris@1
|
1540
|
Chris@1
|
1541 /* have a complete page; submit it to sync/decode */
|
Chris@1
|
1542
|
Chris@1
|
1543 {
|
Chris@1
|
1544 ogg_page og_de;
|
Chris@1
|
1545 ogg_packet op_de,op_de2;
|
Chris@1
|
1546 char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
|
Chris@1
|
1547 char *next=buf;
|
Chris@1
|
1548 byteskipcount+=og.header_len;
|
Chris@1
|
1549 if(byteskipcount>byteskip){
|
Chris@1
|
1550 memcpy(next,og.header,byteskipcount-byteskip);
|
Chris@1
|
1551 next+=byteskipcount-byteskip;
|
Chris@1
|
1552 byteskipcount=byteskip;
|
Chris@1
|
1553 }
|
Chris@1
|
1554
|
Chris@1
|
1555 byteskipcount+=og.body_len;
|
Chris@1
|
1556 if(byteskipcount>byteskip){
|
Chris@1
|
1557 memcpy(next,og.body,byteskipcount-byteskip);
|
Chris@1
|
1558 next+=byteskipcount-byteskip;
|
Chris@1
|
1559 byteskipcount=byteskip;
|
Chris@1
|
1560 }
|
Chris@1
|
1561
|
Chris@1
|
1562 ogg_sync_wrote(&oy,next-buf);
|
Chris@1
|
1563
|
Chris@1
|
1564 while(1){
|
Chris@1
|
1565 int ret=ogg_sync_pageout(&oy,&og_de);
|
Chris@1
|
1566 if(ret==0)break;
|
Chris@1
|
1567 if(ret<0)continue;
|
Chris@1
|
1568 /* got a page. Happy happy. Verify that it's good. */
|
Chris@1
|
1569
|
Chris@1
|
1570 fprintf(stderr,"(%d), ",pageout);
|
Chris@1
|
1571
|
Chris@1
|
1572 check_page(data+deptr,headers[pageout],&og_de);
|
Chris@1
|
1573 deptr+=og_de.body_len;
|
Chris@1
|
1574 pageout++;
|
Chris@1
|
1575
|
Chris@1
|
1576 /* submit it to deconstitution */
|
Chris@1
|
1577 ogg_stream_pagein(&os_de,&og_de);
|
Chris@1
|
1578
|
Chris@1
|
1579 /* packets out? */
|
Chris@1
|
1580 while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
|
Chris@1
|
1581 ogg_stream_packetpeek(&os_de,NULL);
|
Chris@1
|
1582 ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
|
Chris@1
|
1583
|
Chris@1
|
1584 /* verify peek and out match */
|
Chris@1
|
1585 if(memcmp(&op_de,&op_de2,sizeof(op_de))){
|
Chris@1
|
1586 fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
|
Chris@1
|
1587 depacket);
|
Chris@1
|
1588 exit(1);
|
Chris@1
|
1589 }
|
Chris@1
|
1590
|
Chris@1
|
1591 /* verify the packet! */
|
Chris@1
|
1592 /* check data */
|
Chris@1
|
1593 if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
|
Chris@1
|
1594 fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
|
Chris@1
|
1595 depacket);
|
Chris@1
|
1596 exit(1);
|
Chris@1
|
1597 }
|
Chris@1
|
1598 /* check bos flag */
|
Chris@1
|
1599 if(bosflag==0 && op_de.b_o_s==0){
|
Chris@1
|
1600 fprintf(stderr,"b_o_s flag not set on packet!\n");
|
Chris@1
|
1601 exit(1);
|
Chris@1
|
1602 }
|
Chris@1
|
1603 if(bosflag && op_de.b_o_s){
|
Chris@1
|
1604 fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
|
Chris@1
|
1605 exit(1);
|
Chris@1
|
1606 }
|
Chris@1
|
1607 bosflag=1;
|
Chris@1
|
1608 depacket+=op_de.bytes;
|
Chris@1
|
1609
|
Chris@1
|
1610 /* check eos flag */
|
Chris@1
|
1611 if(eosflag){
|
Chris@1
|
1612 fprintf(stderr,"Multiple decoded packets with eos flag!\n");
|
Chris@1
|
1613 exit(1);
|
Chris@1
|
1614 }
|
Chris@1
|
1615
|
Chris@1
|
1616 if(op_de.e_o_s)eosflag=1;
|
Chris@1
|
1617
|
Chris@1
|
1618 /* check granulepos flag */
|
Chris@1
|
1619 if(op_de.granulepos!=-1){
|
Chris@1
|
1620 fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
|
Chris@1
|
1621 }
|
Chris@1
|
1622 }
|
Chris@1
|
1623 }
|
Chris@1
|
1624 }
|
Chris@1
|
1625 }
|
Chris@1
|
1626 }
|
Chris@1
|
1627 }
|
Chris@1
|
1628 _ogg_free(data);
|
Chris@1
|
1629 if(headers[pageno]!=NULL){
|
Chris@1
|
1630 fprintf(stderr,"did not write last page!\n");
|
Chris@1
|
1631 exit(1);
|
Chris@1
|
1632 }
|
Chris@1
|
1633 if(headers[pageout]!=NULL){
|
Chris@1
|
1634 fprintf(stderr,"did not decode last page!\n");
|
Chris@1
|
1635 exit(1);
|
Chris@1
|
1636 }
|
Chris@1
|
1637 if(inptr!=outptr){
|
Chris@1
|
1638 fprintf(stderr,"encoded page data incomplete!\n");
|
Chris@1
|
1639 exit(1);
|
Chris@1
|
1640 }
|
Chris@1
|
1641 if(inptr!=deptr){
|
Chris@1
|
1642 fprintf(stderr,"decoded page data incomplete!\n");
|
Chris@1
|
1643 exit(1);
|
Chris@1
|
1644 }
|
Chris@1
|
1645 if(inptr!=depacket){
|
Chris@1
|
1646 fprintf(stderr,"decoded packet data incomplete!\n");
|
Chris@1
|
1647 exit(1);
|
Chris@1
|
1648 }
|
Chris@1
|
1649 if(!eosflag){
|
Chris@1
|
1650 fprintf(stderr,"Never got a packet with EOS set!\n");
|
Chris@1
|
1651 exit(1);
|
Chris@1
|
1652 }
|
Chris@1
|
1653 fprintf(stderr,"ok.\n");
|
Chris@1
|
1654 }
|
Chris@1
|
1655
|
Chris@1
|
1656 int main(void){
|
Chris@1
|
1657
|
Chris@1
|
1658 ogg_stream_init(&os_en,0x04030201);
|
Chris@1
|
1659 ogg_stream_init(&os_de,0x04030201);
|
Chris@1
|
1660 ogg_sync_init(&oy);
|
Chris@1
|
1661
|
Chris@1
|
1662 /* Exercise each code path in the framing code. Also verify that
|
Chris@1
|
1663 the checksums are working. */
|
Chris@1
|
1664
|
Chris@1
|
1665 {
|
Chris@1
|
1666 /* 17 only */
|
Chris@1
|
1667 const int packets[]={17, -1};
|
Chris@1
|
1668 const int *headret[]={head1_0,NULL};
|
Chris@1
|
1669
|
Chris@1
|
1670 fprintf(stderr,"testing single page encoding... ");
|
Chris@1
|
1671 test_pack(packets,headret,0,0,0);
|
Chris@1
|
1672 }
|
Chris@1
|
1673
|
Chris@1
|
1674 {
|
Chris@1
|
1675 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
|
Chris@1
|
1676 const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
|
Chris@1
|
1677 const int *headret[]={head1_1,head2_1,NULL};
|
Chris@1
|
1678
|
Chris@1
|
1679 fprintf(stderr,"testing basic page encoding... ");
|
Chris@1
|
1680 test_pack(packets,headret,0,0,0);
|
Chris@1
|
1681 }
|
Chris@1
|
1682
|
Chris@1
|
1683 {
|
Chris@1
|
1684 /* nil packets; beginning,middle,end */
|
Chris@1
|
1685 const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
|
Chris@1
|
1686 const int *headret[]={head1_2,head2_2,NULL};
|
Chris@1
|
1687
|
Chris@1
|
1688 fprintf(stderr,"testing basic nil packets... ");
|
Chris@1
|
1689 test_pack(packets,headret,0,0,0);
|
Chris@1
|
1690 }
|
Chris@1
|
1691
|
Chris@1
|
1692 {
|
Chris@1
|
1693 /* large initial packet */
|
Chris@1
|
1694 const int packets[]={4345,259,255,-1};
|
Chris@1
|
1695 const int *headret[]={head1_3,head2_3,NULL};
|
Chris@1
|
1696
|
Chris@1
|
1697 fprintf(stderr,"testing initial-packet lacing > 4k... ");
|
Chris@1
|
1698 test_pack(packets,headret,0,0,0);
|
Chris@1
|
1699 }
|
Chris@1
|
1700
|
Chris@1
|
1701 {
|
Chris@1
|
1702 /* continuing packet test; with page spill expansion, we have to
|
Chris@1
|
1703 overflow the lacing table. */
|
Chris@1
|
1704 const int packets[]={0,65500,259,255,-1};
|
Chris@1
|
1705 const int *headret[]={head1_4,head2_4,head3_4,NULL};
|
Chris@1
|
1706
|
Chris@1
|
1707 fprintf(stderr,"testing single packet page span... ");
|
Chris@1
|
1708 test_pack(packets,headret,0,0,0);
|
Chris@1
|
1709 }
|
Chris@1
|
1710
|
Chris@1
|
1711 {
|
Chris@1
|
1712 /* spill expand packet test */
|
Chris@1
|
1713 const int packets[]={0,4345,259,255,0,0,-1};
|
Chris@1
|
1714 const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
|
Chris@1
|
1715
|
Chris@1
|
1716 fprintf(stderr,"testing page spill expansion... ");
|
Chris@1
|
1717 test_pack(packets,headret,0,0,0);
|
Chris@1
|
1718 }
|
Chris@1
|
1719
|
Chris@1
|
1720 /* page with the 255 segment limit */
|
Chris@1
|
1721 {
|
Chris@1
|
1722
|
Chris@1
|
1723 const int packets[]={0,10,10,10,10,10,10,10,10,
|
Chris@1
|
1724 10,10,10,10,10,10,10,10,
|
Chris@1
|
1725 10,10,10,10,10,10,10,10,
|
Chris@1
|
1726 10,10,10,10,10,10,10,10,
|
Chris@1
|
1727 10,10,10,10,10,10,10,10,
|
Chris@1
|
1728 10,10,10,10,10,10,10,10,
|
Chris@1
|
1729 10,10,10,10,10,10,10,10,
|
Chris@1
|
1730 10,10,10,10,10,10,10,10,
|
Chris@1
|
1731 10,10,10,10,10,10,10,10,
|
Chris@1
|
1732 10,10,10,10,10,10,10,10,
|
Chris@1
|
1733 10,10,10,10,10,10,10,10,
|
Chris@1
|
1734 10,10,10,10,10,10,10,10,
|
Chris@1
|
1735 10,10,10,10,10,10,10,10,
|
Chris@1
|
1736 10,10,10,10,10,10,10,10,
|
Chris@1
|
1737 10,10,10,10,10,10,10,10,
|
Chris@1
|
1738 10,10,10,10,10,10,10,10,
|
Chris@1
|
1739 10,10,10,10,10,10,10,10,
|
Chris@1
|
1740 10,10,10,10,10,10,10,10,
|
Chris@1
|
1741 10,10,10,10,10,10,10,10,
|
Chris@1
|
1742 10,10,10,10,10,10,10,10,
|
Chris@1
|
1743 10,10,10,10,10,10,10,10,
|
Chris@1
|
1744 10,10,10,10,10,10,10,10,
|
Chris@1
|
1745 10,10,10,10,10,10,10,10,
|
Chris@1
|
1746 10,10,10,10,10,10,10,10,
|
Chris@1
|
1747 10,10,10,10,10,10,10,10,
|
Chris@1
|
1748 10,10,10,10,10,10,10,10,
|
Chris@1
|
1749 10,10,10,10,10,10,10,10,
|
Chris@1
|
1750 10,10,10,10,10,10,10,10,
|
Chris@1
|
1751 10,10,10,10,10,10,10,10,
|
Chris@1
|
1752 10,10,10,10,10,10,10,10,
|
Chris@1
|
1753 10,10,10,10,10,10,10,10,
|
Chris@1
|
1754 10,10,10,10,10,10,10,50,-1};
|
Chris@1
|
1755 const int *headret[]={head1_5,head2_5,head3_5,NULL};
|
Chris@1
|
1756
|
Chris@1
|
1757 fprintf(stderr,"testing max packet segments... ");
|
Chris@1
|
1758 test_pack(packets,headret,0,0,0);
|
Chris@1
|
1759 }
|
Chris@1
|
1760
|
Chris@1
|
1761 {
|
Chris@1
|
1762 /* packet that overspans over an entire page */
|
Chris@1
|
1763 const int packets[]={0,100,130049,259,255,-1};
|
Chris@1
|
1764 const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
|
Chris@1
|
1765
|
Chris@1
|
1766 fprintf(stderr,"testing very large packets... ");
|
Chris@1
|
1767 test_pack(packets,headret,0,0,0);
|
Chris@1
|
1768 }
|
Chris@1
|
1769
|
Chris@1
|
1770 {
|
Chris@1
|
1771 /* test for the libogg 1.1.1 resync in large continuation bug
|
Chris@1
|
1772 found by Josh Coalson) */
|
Chris@1
|
1773 const int packets[]={0,100,130049,259,255,-1};
|
Chris@1
|
1774 const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
|
Chris@1
|
1775
|
Chris@1
|
1776 fprintf(stderr,"testing continuation resync in very large packets... ");
|
Chris@1
|
1777 test_pack(packets,headret,100,2,3);
|
Chris@1
|
1778 }
|
Chris@1
|
1779
|
Chris@1
|
1780 {
|
Chris@1
|
1781 /* term only page. why not? */
|
Chris@1
|
1782 const int packets[]={0,100,64770,-1};
|
Chris@1
|
1783 const int *headret[]={head1_7,head2_7,head3_7,NULL};
|
Chris@1
|
1784
|
Chris@1
|
1785 fprintf(stderr,"testing zero data page (1 nil packet)... ");
|
Chris@1
|
1786 test_pack(packets,headret,0,0,0);
|
Chris@1
|
1787 }
|
Chris@1
|
1788
|
Chris@1
|
1789
|
Chris@1
|
1790
|
Chris@1
|
1791 {
|
Chris@1
|
1792 /* build a bunch of pages for testing */
|
Chris@1
|
1793 unsigned char *data=_ogg_malloc(1024*1024);
|
Chris@1
|
1794 int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
|
Chris@1
|
1795 int inptr=0,i,j;
|
Chris@1
|
1796 ogg_page og[5];
|
Chris@1
|
1797
|
Chris@1
|
1798 ogg_stream_reset(&os_en);
|
Chris@1
|
1799
|
Chris@1
|
1800 for(i=0;pl[i]!=-1;i++){
|
Chris@1
|
1801 ogg_packet op;
|
Chris@1
|
1802 int len=pl[i];
|
Chris@1
|
1803
|
Chris@1
|
1804 op.packet=data+inptr;
|
Chris@1
|
1805 op.bytes=len;
|
Chris@1
|
1806 op.e_o_s=(pl[i+1]<0?1:0);
|
Chris@1
|
1807 op.granulepos=(i+1)*1000;
|
Chris@1
|
1808
|
Chris@1
|
1809 for(j=0;j<len;j++)data[inptr++]=i+j;
|
Chris@1
|
1810 ogg_stream_packetin(&os_en,&op);
|
Chris@1
|
1811 }
|
Chris@1
|
1812
|
Chris@1
|
1813 _ogg_free(data);
|
Chris@1
|
1814
|
Chris@1
|
1815 /* retrieve finished pages */
|
Chris@1
|
1816 for(i=0;i<5;i++){
|
Chris@1
|
1817 if(ogg_stream_pageout(&os_en,&og[i])==0){
|
Chris@1
|
1818 fprintf(stderr,"Too few pages output building sync tests!\n");
|
Chris@1
|
1819 exit(1);
|
Chris@1
|
1820 }
|
Chris@1
|
1821 copy_page(&og[i]);
|
Chris@1
|
1822 }
|
Chris@1
|
1823
|
Chris@1
|
1824 /* Test lost pages on pagein/packetout: no rollback */
|
Chris@1
|
1825 {
|
Chris@1
|
1826 ogg_page temp;
|
Chris@1
|
1827 ogg_packet test;
|
Chris@1
|
1828
|
Chris@1
|
1829 fprintf(stderr,"Testing loss of pages... ");
|
Chris@1
|
1830
|
Chris@1
|
1831 ogg_sync_reset(&oy);
|
Chris@1
|
1832 ogg_stream_reset(&os_de);
|
Chris@1
|
1833 for(i=0;i<5;i++){
|
Chris@1
|
1834 memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
|
Chris@1
|
1835 og[i].header_len);
|
Chris@1
|
1836 ogg_sync_wrote(&oy,og[i].header_len);
|
Chris@1
|
1837 memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
|
Chris@1
|
1838 ogg_sync_wrote(&oy,og[i].body_len);
|
Chris@1
|
1839 }
|
Chris@1
|
1840
|
Chris@1
|
1841 ogg_sync_pageout(&oy,&temp);
|
Chris@1
|
1842 ogg_stream_pagein(&os_de,&temp);
|
Chris@1
|
1843 ogg_sync_pageout(&oy,&temp);
|
Chris@1
|
1844 ogg_stream_pagein(&os_de,&temp);
|
Chris@1
|
1845 ogg_sync_pageout(&oy,&temp);
|
Chris@1
|
1846 /* skip */
|
Chris@1
|
1847 ogg_sync_pageout(&oy,&temp);
|
Chris@1
|
1848 ogg_stream_pagein(&os_de,&temp);
|
Chris@1
|
1849
|
Chris@1
|
1850 /* do we get the expected results/packets? */
|
Chris@1
|
1851
|
Chris@1
|
1852 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1853 checkpacket(&test,0,0,0);
|
Chris@1
|
1854 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1855 checkpacket(&test,1,1,-1);
|
Chris@1
|
1856 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1857 checkpacket(&test,1,2,-1);
|
Chris@1
|
1858 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1859 checkpacket(&test,98,3,-1);
|
Chris@1
|
1860 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1861 checkpacket(&test,4079,4,5000);
|
Chris@1
|
1862 if(ogg_stream_packetout(&os_de,&test)!=-1){
|
Chris@1
|
1863 fprintf(stderr,"Error: loss of page did not return error\n");
|
Chris@1
|
1864 exit(1);
|
Chris@1
|
1865 }
|
Chris@1
|
1866 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1867 checkpacket(&test,76,9,-1);
|
Chris@1
|
1868 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1869 checkpacket(&test,34,10,-1);
|
Chris@1
|
1870 fprintf(stderr,"ok.\n");
|
Chris@1
|
1871 }
|
Chris@1
|
1872
|
Chris@1
|
1873 /* Test lost pages on pagein/packetout: rollback with continuation */
|
Chris@1
|
1874 {
|
Chris@1
|
1875 ogg_page temp;
|
Chris@1
|
1876 ogg_packet test;
|
Chris@1
|
1877
|
Chris@1
|
1878 fprintf(stderr,"Testing loss of pages (rollback required)... ");
|
Chris@1
|
1879
|
Chris@1
|
1880 ogg_sync_reset(&oy);
|
Chris@1
|
1881 ogg_stream_reset(&os_de);
|
Chris@1
|
1882 for(i=0;i<5;i++){
|
Chris@1
|
1883 memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
|
Chris@1
|
1884 og[i].header_len);
|
Chris@1
|
1885 ogg_sync_wrote(&oy,og[i].header_len);
|
Chris@1
|
1886 memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
|
Chris@1
|
1887 ogg_sync_wrote(&oy,og[i].body_len);
|
Chris@1
|
1888 }
|
Chris@1
|
1889
|
Chris@1
|
1890 ogg_sync_pageout(&oy,&temp);
|
Chris@1
|
1891 ogg_stream_pagein(&os_de,&temp);
|
Chris@1
|
1892 ogg_sync_pageout(&oy,&temp);
|
Chris@1
|
1893 ogg_stream_pagein(&os_de,&temp);
|
Chris@1
|
1894 ogg_sync_pageout(&oy,&temp);
|
Chris@1
|
1895 ogg_stream_pagein(&os_de,&temp);
|
Chris@1
|
1896 ogg_sync_pageout(&oy,&temp);
|
Chris@1
|
1897 /* skip */
|
Chris@1
|
1898 ogg_sync_pageout(&oy,&temp);
|
Chris@1
|
1899 ogg_stream_pagein(&os_de,&temp);
|
Chris@1
|
1900
|
Chris@1
|
1901 /* do we get the expected results/packets? */
|
Chris@1
|
1902
|
Chris@1
|
1903 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1904 checkpacket(&test,0,0,0);
|
Chris@1
|
1905 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1906 checkpacket(&test,1,1,-1);
|
Chris@1
|
1907 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1908 checkpacket(&test,1,2,-1);
|
Chris@1
|
1909 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1910 checkpacket(&test,98,3,-1);
|
Chris@1
|
1911 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1912 checkpacket(&test,4079,4,5000);
|
Chris@1
|
1913 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1914 checkpacket(&test,1,5,-1);
|
Chris@1
|
1915 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1916 checkpacket(&test,1,6,-1);
|
Chris@1
|
1917 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1918 checkpacket(&test,2954,7,-1);
|
Chris@1
|
1919 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1920 checkpacket(&test,2057,8,9000);
|
Chris@1
|
1921 if(ogg_stream_packetout(&os_de,&test)!=-1){
|
Chris@1
|
1922 fprintf(stderr,"Error: loss of page did not return error\n");
|
Chris@1
|
1923 exit(1);
|
Chris@1
|
1924 }
|
Chris@1
|
1925 if(ogg_stream_packetout(&os_de,&test)!=1)error();
|
Chris@1
|
1926 checkpacket(&test,300,17,18000);
|
Chris@1
|
1927 fprintf(stderr,"ok.\n");
|
Chris@1
|
1928 }
|
Chris@1
|
1929
|
Chris@1
|
1930 /* the rest only test sync */
|
Chris@1
|
1931 {
|
Chris@1
|
1932 ogg_page og_de;
|
Chris@1
|
1933 /* Test fractional page inputs: incomplete capture */
|
Chris@1
|
1934 fprintf(stderr,"Testing sync on partial inputs... ");
|
Chris@1
|
1935 ogg_sync_reset(&oy);
|
Chris@1
|
1936 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
|
Chris@1
|
1937 3);
|
Chris@1
|
1938 ogg_sync_wrote(&oy,3);
|
Chris@1
|
1939 if(ogg_sync_pageout(&oy,&og_de)>0)error();
|
Chris@1
|
1940
|
Chris@1
|
1941 /* Test fractional page inputs: incomplete fixed header */
|
Chris@1
|
1942 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
|
Chris@1
|
1943 20);
|
Chris@1
|
1944 ogg_sync_wrote(&oy,20);
|
Chris@1
|
1945 if(ogg_sync_pageout(&oy,&og_de)>0)error();
|
Chris@1
|
1946
|
Chris@1
|
1947 /* Test fractional page inputs: incomplete header */
|
Chris@1
|
1948 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
|
Chris@1
|
1949 5);
|
Chris@1
|
1950 ogg_sync_wrote(&oy,5);
|
Chris@1
|
1951 if(ogg_sync_pageout(&oy,&og_de)>0)error();
|
Chris@1
|
1952
|
Chris@1
|
1953 /* Test fractional page inputs: incomplete body */
|
Chris@1
|
1954
|
Chris@1
|
1955 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
|
Chris@1
|
1956 og[1].header_len-28);
|
Chris@1
|
1957 ogg_sync_wrote(&oy,og[1].header_len-28);
|
Chris@1
|
1958 if(ogg_sync_pageout(&oy,&og_de)>0)error();
|
Chris@1
|
1959
|
Chris@1
|
1960 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
|
Chris@1
|
1961 ogg_sync_wrote(&oy,1000);
|
Chris@1
|
1962 if(ogg_sync_pageout(&oy,&og_de)>0)error();
|
Chris@1
|
1963
|
Chris@1
|
1964 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
|
Chris@1
|
1965 og[1].body_len-1000);
|
Chris@1
|
1966 ogg_sync_wrote(&oy,og[1].body_len-1000);
|
Chris@1
|
1967 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
|
Chris@1
|
1968
|
Chris@1
|
1969 fprintf(stderr,"ok.\n");
|
Chris@1
|
1970 }
|
Chris@1
|
1971
|
Chris@1
|
1972 /* Test fractional page inputs: page + incomplete capture */
|
Chris@1
|
1973 {
|
Chris@1
|
1974 ogg_page og_de;
|
Chris@1
|
1975 fprintf(stderr,"Testing sync on 1+partial inputs... ");
|
Chris@1
|
1976 ogg_sync_reset(&oy);
|
Chris@1
|
1977
|
Chris@1
|
1978 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
|
Chris@1
|
1979 og[1].header_len);
|
Chris@1
|
1980 ogg_sync_wrote(&oy,og[1].header_len);
|
Chris@1
|
1981
|
Chris@1
|
1982 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
|
Chris@1
|
1983 og[1].body_len);
|
Chris@1
|
1984 ogg_sync_wrote(&oy,og[1].body_len);
|
Chris@1
|
1985
|
Chris@1
|
1986 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
|
Chris@1
|
1987 20);
|
Chris@1
|
1988 ogg_sync_wrote(&oy,20);
|
Chris@1
|
1989 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
|
Chris@1
|
1990 if(ogg_sync_pageout(&oy,&og_de)>0)error();
|
Chris@1
|
1991
|
Chris@1
|
1992 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
|
Chris@1
|
1993 og[1].header_len-20);
|
Chris@1
|
1994 ogg_sync_wrote(&oy,og[1].header_len-20);
|
Chris@1
|
1995 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
|
Chris@1
|
1996 og[1].body_len);
|
Chris@1
|
1997 ogg_sync_wrote(&oy,og[1].body_len);
|
Chris@1
|
1998 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
|
Chris@1
|
1999
|
Chris@1
|
2000 fprintf(stderr,"ok.\n");
|
Chris@1
|
2001 }
|
Chris@1
|
2002
|
Chris@1
|
2003 /* Test recapture: garbage + page */
|
Chris@1
|
2004 {
|
Chris@1
|
2005 ogg_page og_de;
|
Chris@1
|
2006 fprintf(stderr,"Testing search for capture... ");
|
Chris@1
|
2007 ogg_sync_reset(&oy);
|
Chris@1
|
2008
|
Chris@1
|
2009 /* 'garbage' */
|
Chris@1
|
2010 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
|
Chris@1
|
2011 og[1].body_len);
|
Chris@1
|
2012 ogg_sync_wrote(&oy,og[1].body_len);
|
Chris@1
|
2013
|
Chris@1
|
2014 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
|
Chris@1
|
2015 og[1].header_len);
|
Chris@1
|
2016 ogg_sync_wrote(&oy,og[1].header_len);
|
Chris@1
|
2017
|
Chris@1
|
2018 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
|
Chris@1
|
2019 og[1].body_len);
|
Chris@1
|
2020 ogg_sync_wrote(&oy,og[1].body_len);
|
Chris@1
|
2021
|
Chris@1
|
2022 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
|
Chris@1
|
2023 20);
|
Chris@1
|
2024 ogg_sync_wrote(&oy,20);
|
Chris@1
|
2025 if(ogg_sync_pageout(&oy,&og_de)>0)error();
|
Chris@1
|
2026 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
|
Chris@1
|
2027 if(ogg_sync_pageout(&oy,&og_de)>0)error();
|
Chris@1
|
2028
|
Chris@1
|
2029 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
|
Chris@1
|
2030 og[2].header_len-20);
|
Chris@1
|
2031 ogg_sync_wrote(&oy,og[2].header_len-20);
|
Chris@1
|
2032 memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
|
Chris@1
|
2033 og[2].body_len);
|
Chris@1
|
2034 ogg_sync_wrote(&oy,og[2].body_len);
|
Chris@1
|
2035 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
|
Chris@1
|
2036
|
Chris@1
|
2037 fprintf(stderr,"ok.\n");
|
Chris@1
|
2038 }
|
Chris@1
|
2039
|
Chris@1
|
2040 /* Test recapture: page + garbage + page */
|
Chris@1
|
2041 {
|
Chris@1
|
2042 ogg_page og_de;
|
Chris@1
|
2043 fprintf(stderr,"Testing recapture... ");
|
Chris@1
|
2044 ogg_sync_reset(&oy);
|
Chris@1
|
2045
|
Chris@1
|
2046 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
|
Chris@1
|
2047 og[1].header_len);
|
Chris@1
|
2048 ogg_sync_wrote(&oy,og[1].header_len);
|
Chris@1
|
2049
|
Chris@1
|
2050 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
|
Chris@1
|
2051 og[1].body_len);
|
Chris@1
|
2052 ogg_sync_wrote(&oy,og[1].body_len);
|
Chris@1
|
2053
|
Chris@1
|
2054 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
|
Chris@1
|
2055 og[2].header_len);
|
Chris@1
|
2056 ogg_sync_wrote(&oy,og[2].header_len);
|
Chris@1
|
2057
|
Chris@1
|
2058 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
|
Chris@1
|
2059 og[2].header_len);
|
Chris@1
|
2060 ogg_sync_wrote(&oy,og[2].header_len);
|
Chris@1
|
2061
|
Chris@1
|
2062 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
|
Chris@1
|
2063
|
Chris@1
|
2064 memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
|
Chris@1
|
2065 og[2].body_len-5);
|
Chris@1
|
2066 ogg_sync_wrote(&oy,og[2].body_len-5);
|
Chris@1
|
2067
|
Chris@1
|
2068 memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
|
Chris@1
|
2069 og[3].header_len);
|
Chris@1
|
2070 ogg_sync_wrote(&oy,og[3].header_len);
|
Chris@1
|
2071
|
Chris@1
|
2072 memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
|
Chris@1
|
2073 og[3].body_len);
|
Chris@1
|
2074 ogg_sync_wrote(&oy,og[3].body_len);
|
Chris@1
|
2075
|
Chris@1
|
2076 if(ogg_sync_pageout(&oy,&og_de)>0)error();
|
Chris@1
|
2077 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
|
Chris@1
|
2078
|
Chris@1
|
2079 fprintf(stderr,"ok.\n");
|
Chris@1
|
2080 }
|
Chris@1
|
2081
|
Chris@1
|
2082 /* Free page data that was previously copied */
|
Chris@1
|
2083 {
|
Chris@1
|
2084 for(i=0;i<5;i++){
|
Chris@1
|
2085 free_page(&og[i]);
|
Chris@1
|
2086 }
|
Chris@1
|
2087 }
|
Chris@1
|
2088 }
|
Chris@1
|
2089
|
Chris@1
|
2090 return(0);
|
Chris@1
|
2091 }
|
Chris@1
|
2092
|
Chris@1
|
2093 #endif
|