summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNils Wallménius <nils@rockbox.org>2010-12-06 14:36:52 +0000
committerNils Wallménius <nils@rockbox.org>2010-12-06 14:36:52 +0000
commit67efbc13870ee87ce3df442f7c396c13481921ec (patch)
treeeaf63d36c5bf2d41a6b3bb2addecb4d3c05f7eef
parent1f64b7fb1fa5058e3b7871078055156eac0c511d (diff)
downloadrockbox-67efbc13870ee87ce3df442f7c396c13481921ec.tar.gz
rockbox-67efbc13870ee87ce3df442f7c396c13481921ec.zip
libtremor:
Merge in upstream revision 17375. This removes tremor's internal ogg code and now uses libogg instead so a bunch of changes are just adjusting to the new api. Also brings in improvements to vorbisfile which fixes FS#10484. Disabled a lot of unused code in the libogg files and moved some small functions into the ogg.h header so they can be inlined. Some small tweaks to fix warnings. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28742 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/libtremor/bitwise.c949
-rw-r--r--apps/codecs/libtremor/codebook.c18
-rw-r--r--apps/codecs/libtremor/framing.c2672
-rw-r--r--apps/codecs/libtremor/info.c4
-rw-r--r--apps/codecs/libtremor/ivorbisfile.h10
-rw-r--r--apps/codecs/libtremor/ogg.h387
-rw-r--r--apps/codecs/libtremor/synthesis.c6
-rw-r--r--apps/codecs/libtremor/vorbisfile.c509
8 files changed, 3102 insertions, 1453 deletions
diff --git a/apps/codecs/libtremor/bitwise.c b/apps/codecs/libtremor/bitwise.c
index dabba468b9..050fb67c60 100644
--- a/apps/codecs/libtremor/bitwise.c
+++ b/apps/codecs/libtremor/bitwise.c
@@ -1,28 +1,31 @@
1/******************************************************************** 1/********************************************************************
2 * * 2 * *
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * 3 * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. *
4 * *
5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * * 7 * *
9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * 8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 *
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * 9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 * * 10 * *
12 ******************************************************************** 11 ********************************************************************
13 12
14 function: packing variable sized words into an octet stream 13 function: packing variable sized words into an octet stream
14 last mod: $Id$
15 15
16 ********************************************************************/ 16 ********************************************************************/
17 17
18/* We're 'LSb' endian; if we write a word but read individual bits, 18/* We're 'LSb' endian; if we write a word but read individual bits,
19 then we'll read the lsb first */ 19 then we'll read the lsb first */
20 20
21#include "config-tremor.h"
22#include <string.h> 21#include <string.h>
22#include <stdlib.h>
23#include <limits.h>
23#include "ogg.h" 24#include "ogg.h"
24 25
25const unsigned long oggpack_mask[] ICONST_ATTR = 26#define BUFFER_INCREMENT 256
27
28const unsigned long mask[] ICONST_ATTR =
26{0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, 29{0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
27 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, 30 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
28 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, 31 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
@@ -31,184 +34,832 @@ const unsigned long oggpack_mask[] ICONST_ATTR =
31 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, 34 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
32 0x3fffffff,0x7fffffff,0xffffffff }; 35 0x3fffffff,0x7fffffff,0xffffffff };
33 36
34void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){ 37#if 0
38static const unsigned int mask8B[]=
39{0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};
40
41void oggpack_writeinit(oggpack_buffer *b){
35 memset(b,0,sizeof(*b)); 42 memset(b,0,sizeof(*b));
43 b->ptr=b->buffer=_ogg_malloc(BUFFER_INCREMENT);
44 b->buffer[0]='\0';
45 b->storage=BUFFER_INCREMENT;
46}
47
48void oggpackB_writeinit(oggpack_buffer *b){
49 oggpack_writeinit(b);
50}
36 51
37 b->tail=b->head=r; 52int oggpack_writecheck(oggpack_buffer *b){
38 b->count=0; 53 if(!b->ptr || !b->storage)return -1;
39 b->headptr=b->head->buffer->data+b->head->begin; 54 return 0;
40 b->headend=b->head->length;
41 _span(b);
42} 55}
43 56
44#define _lookspan() while(!end){\ 57int oggpackB_writecheck(oggpack_buffer *b){
45 head=head->next;\ 58 return oggpack_writecheck(b);
46 if(!head) return -1;\ 59}
47 ptr=head->buffer->data + head->begin;\
48 end=head->length;\
49 }
50 60
51/* Read in bits without advancing the bitptr; bits <= 32 */ 61void oggpack_writetrunc(oggpack_buffer *b,long bits){
52long oggpack_look_full(oggpack_buffer *b,int bits) ICODE_ATTR_TREMOR_NOT_MDCT; 62 long bytes=bits>>3;
53long oggpack_look_full(oggpack_buffer *b,int bits){ 63 if(b->ptr){
54 unsigned long m=oggpack_mask[bits]; 64 bits-=bytes*8;
55 unsigned long ret=-1; 65 b->ptr=b->buffer+bytes;
56 66 b->endbit=bits;
57 bits+=b->headbit; 67 b->endbyte=bytes;
58 68 *b->ptr&=mask[bits];
59 if(bits >= b->headend<<3){ 69 }
60 int end=b->headend; 70}
61 unsigned char *ptr=b->headptr; 71
62 ogg_reference *head=b->head; 72void oggpackB_writetrunc(oggpack_buffer *b,long bits){
63 73 long bytes=bits>>3;
64 if(end<0)return -1; 74 if(b->ptr){
65 75 bits-=bytes*8;
66 if(bits){ 76 b->ptr=b->buffer+bytes;
67 _lookspan(); 77 b->endbit=bits;
68 ret=*ptr++>>b->headbit; 78 b->endbyte=bytes;
69 if(bits>8){ 79 *b->ptr&=mask8B[bits];
70 --end; 80 }
71 _lookspan(); 81}
72 ret|=*ptr++<<(8-b->headbit); 82
73 if(bits>16){ 83/* Takes only up to 32 bits. */
74 --end; 84void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){
75 _lookspan(); 85 if(bits<0 || bits>32) goto err;
76 ret|=*ptr++<<(16-b->headbit); 86 if(b->endbyte>=b->storage-4){
77 if(bits>24){ 87 void *ret;
78 --end; 88 if(!b->ptr)return;
79 _lookspan(); 89 if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err;
80 ret|=*ptr++<<(24-b->headbit); 90 ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
81 if(bits>32 && b->headbit){ 91 if(!ret) goto err;
82 --end; 92 b->buffer=ret;
83 _lookspan(); 93 b->storage+=BUFFER_INCREMENT;
84 ret|=*ptr<<(32-b->headbit); 94 b->ptr=b->buffer+b->endbyte;
85 } 95 }
86 } 96
97 value&=mask[bits];
98 bits+=b->endbit;
99
100 b->ptr[0]|=value<<b->endbit;
101
102 if(bits>=8){
103 b->ptr[1]=(unsigned char)(value>>(8-b->endbit));
104 if(bits>=16){
105 b->ptr[2]=(unsigned char)(value>>(16-b->endbit));
106 if(bits>=24){
107 b->ptr[3]=(unsigned char)(value>>(24-b->endbit));
108 if(bits>=32){
109 if(b->endbit)
110 b->ptr[4]=(unsigned char)(value>>(32-b->endbit));
111 else
112 b->ptr[4]=0;
87 } 113 }
88 } 114 }
89 } 115 }
116 }
90 117
91 }else{ 118 b->endbyte+=bits/8;
119 b->ptr+=bits/8;
120 b->endbit=bits&7;
121 return;
122 err:
123 oggpack_writeclear(b);
124}
125
126/* Takes only up to 32 bits. */
127void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){
128 if(bits<0 || bits>32) goto err;
129 if(b->endbyte>=b->storage-4){
130 void *ret;
131 if(!b->ptr)return;
132 if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err;
133 ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
134 if(!ret) goto err;
135 b->buffer=ret;
136 b->storage+=BUFFER_INCREMENT;
137 b->ptr=b->buffer+b->endbyte;
138 }
139
140 value=(value&mask[bits])<<(32-bits);
141 bits+=b->endbit;
92 142
93 /* make this a switch jump-table */ 143 b->ptr[0]|=value>>(24+b->endbit);
94 ret=b->headptr[0]>>b->headbit; 144
95 if(bits>8){ 145 if(bits>=8){
96 ret|=b->headptr[1]<<(8-b->headbit); 146 b->ptr[1]=(unsigned char)(value>>(16+b->endbit));
97 if(bits>16){ 147 if(bits>=16){
98 ret|=b->headptr[2]<<(16-b->headbit); 148 b->ptr[2]=(unsigned char)(value>>(8+b->endbit));
99 if(bits>24){ 149 if(bits>=24){
100 ret|=b->headptr[3]<<(24-b->headbit); 150 b->ptr[3]=(unsigned char)(value>>(b->endbit));
101 if(bits>32 && b->headbit) 151 if(bits>=32){
102 ret|=b->headptr[4]<<(32-b->headbit); 152 if(b->endbit)
153 b->ptr[4]=(unsigned char)(value<<(8-b->endbit));
154 else
155 b->ptr[4]=0;
103 } 156 }
104 } 157 }
105 } 158 }
106 } 159 }
107 160
108 ret&=m; 161 b->endbyte+=bits/8;
109 return ret; 162 b->ptr+=bits/8;
163 b->endbit=bits&7;
164 return;
165 err:
166 oggpack_writeclear(b);
167}
168
169void oggpack_writealign(oggpack_buffer *b){
170 int bits=8-b->endbit;
171 if(bits<8)
172 oggpack_write(b,0,bits);
173}
174
175void oggpackB_writealign(oggpack_buffer *b){
176 int bits=8-b->endbit;
177 if(bits<8)
178 oggpackB_write(b,0,bits);
179}
180
181static void oggpack_writecopy_helper(oggpack_buffer *b,
182 void *source,
183 long bits,
184 void (*w)(oggpack_buffer *,
185 unsigned long,
186 int),
187 int msb){
188 unsigned char *ptr=(unsigned char *)source;
189
190 long bytes=bits/8;
191 bits-=bytes*8;
192
193 if(b->endbit){
194 int i;
195 /* unaligned copy. Do it the hard way. */
196 for(i=0;i<bytes;i++)
197 w(b,(unsigned long)(ptr[i]),8);
198 }else{
199 /* aligned block copy */
200 if(b->endbyte+bytes+1>=b->storage){
201 void *ret;
202 if(!b->ptr) goto err;
203 if(b->endbyte+bytes+BUFFER_INCREMENT>b->storage) goto err;
204 b->storage=b->endbyte+bytes+BUFFER_INCREMENT;
205 ret=_ogg_realloc(b->buffer,b->storage);
206 if(!ret) goto err;
207 b->buffer=ret;
208 b->ptr=b->buffer+b->endbyte;
209 }
210
211 memmove(b->ptr,source,bytes);
212 b->ptr+=bytes;
213 b->endbyte+=bytes;
214 *b->ptr=0;
215
216 }
217 if(bits){
218 if(msb)
219 w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits);
220 else
221 w(b,(unsigned long)(ptr[bytes]),bits);
222 }
223 return;
224 err:
225 oggpack_writeclear(b);
226}
227
228void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){
229 oggpack_writecopy_helper(b,source,bits,oggpack_write,0);
230}
231
232void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits){
233 oggpack_writecopy_helper(b,source,bits,oggpackB_write,1);
234}
235
236void oggpack_reset(oggpack_buffer *b){
237 if(!b->ptr)return;
238 b->ptr=b->buffer;
239 b->buffer[0]=0;
240 b->endbit=b->endbyte=0;
241}
242
243void oggpackB_reset(oggpack_buffer *b){
244 oggpack_reset(b);
245}
246
247void oggpack_writeclear(oggpack_buffer *b){
248 if(b->buffer)_ogg_free(b->buffer);
249 memset(b,0,sizeof(*b));
250}
251
252void oggpackB_writeclear(oggpack_buffer *b){
253 oggpack_writeclear(b);
110} 254}
255#endif
256void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
257 memset(b,0,sizeof(*b));
258 b->buffer=b->ptr=buf;
259 b->storage=bytes;
260}
261#if 0
262void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
263 oggpack_readinit(b,buf,bytes);
264}
265#endif
266/* Read in bits without advancing the bitptr; bits <= 32 */
267/* moved to ogg.h for inlining */
268#if 0
269long oggpack_look(oggpack_buffer *b,int bits){
270 unsigned long ret;
271 unsigned long m;
272
273 if(bits<0 || bits>32) return -1;
274 m=mask[bits];
275 bits+=b->endbit;
276
277 if(b->endbyte >= b->storage-4){
278 /* not the main path */
279 if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
280 /* special case to avoid reading b->ptr[0], which might be past the end of
281 the buffer; also skips some useless accounting */
282 else if(!bits)return(0L);
283 }
111 284
112/* spans forward and finds next byte. Never halts */ 285 ret=b->ptr[0]>>b->endbit;
113static void _span_one(oggpack_buffer *b){ 286 if(bits>8){
114 while(b->headend<1){ 287 ret|=b->ptr[1]<<(8-b->endbit);
115 if(b->head->next){ 288 if(bits>16){
116 b->count+=b->head->length; 289 ret|=b->ptr[2]<<(16-b->endbit);
117 b->head=b->head->next; 290 if(bits>24){
118 b->headptr=b->head->buffer->data+b->head->begin; 291 ret|=b->ptr[3]<<(24-b->endbit);
119 b->headend=b->head->length; 292 if(bits>32 && b->endbit)
120 }else 293 ret|=b->ptr[4]<<(32-b->endbit);
121 break; 294 }
295 }
122 } 296 }
297 return(m&ret);
123} 298}
299#endif
300
301#if 0
302/* Read in bits without advancing the bitptr; bits <= 32 */
303long oggpackB_look(oggpack_buffer *b,int bits){
304 unsigned long ret;
305 int m=32-bits;
306
307 if(m<0 || m>32) return -1;
308 bits+=b->endbit;
124 309
125static int _halt_one(oggpack_buffer *b){ 310 if(b->endbyte >= b->storage-4){
126 if(b->headend<1){ 311 /* not the main path */
127 _adv_halt(b); 312 if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
128 return -1; 313 /* special case to avoid reading b->ptr[0], which might be past the end of
314 the buffer; also skips some useless accounting */
315 else if(!bits)return(0L);
129 } 316 }
130 return 0; 317
318 ret=b->ptr[0]<<(24+b->endbit);
319 if(bits>8){
320 ret|=b->ptr[1]<<(16+b->endbit);
321 if(bits>16){
322 ret|=b->ptr[2]<<(8+b->endbit);
323 if(bits>24){
324 ret|=b->ptr[3]<<(b->endbit);
325 if(bits>32 && b->endbit)
326 ret|=b->ptr[4]>>(8-b->endbit);
327 }
328 }
329 }
330 return ((ret&0xffffffff)>>(m>>1))>>((m+1)>>1);
331}
332#endif
333long oggpack_look1(oggpack_buffer *b){
334 if(b->endbyte>=b->storage)return(-1);
335 return((b->ptr[0]>>b->endbit)&1);
131} 336}
337#if 0
338long oggpackB_look1(oggpack_buffer *b){
339 if(b->endbyte>=b->storage)return(-1);
340 return((b->ptr[0]>>(7-b->endbit))&1);
341}
342#endif
343/* moved to ogg.h for inlining
344void oggpack_adv(oggpack_buffer *b,int bits){
345 bits+=b->endbit;
346
347 if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
348
349 b->ptr+=bits/8;
350 b->endbyte+=bits/8;
351 b->endbit=bits&7;
352 return;
132 353
354 overflow:
355 b->ptr=NULL;
356 b->endbyte=b->storage;
357 b->endbit=1;
358}
359*/
360#if 0
361void oggpackB_adv(oggpack_buffer *b,int bits){
362 oggpack_adv(b,bits);
363}
364#endif
365void oggpack_adv1(oggpack_buffer *b){
366 if(++(b->endbit)>7){
367 b->endbit=0;
368 b->ptr++;
369 b->endbyte++;
370 }
371}
372#if 0
373void oggpackB_adv1(oggpack_buffer *b){
374 oggpack_adv1(b);
375}
376#endif
133/* bits <= 32 */ 377/* bits <= 32 */
134long oggpack_read(oggpack_buffer *b,register int bits) ICODE_ATTR_TREMOR_NOT_MDCT; 378long oggpack_read(oggpack_buffer *b,int bits) ICODE_ATTR_TREMOR_NOT_MDCT;
135long oggpack_read(oggpack_buffer *b,register int bits){ 379long oggpack_read(oggpack_buffer *b,int bits){
136 unsigned long m=oggpack_mask[bits]; 380 long ret;
137 ogg_uint32_t ret=-1; 381 unsigned long m;
138 382
139 bits+=b->headbit; 383 if(bits<0 || bits>32) goto err;
384 m=mask[bits];
385 bits+=b->endbit;
140 386
141 if(bits >= b->headend<<3){ 387 if(b->endbyte >= b->storage-4){
388 /* not the main path */
389 if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
390 /* special case to avoid reading b->ptr[0], which might be past the end of
391 the buffer; also skips some useless accounting */
392 else if(!bits)return(0L);
393 }
142 394
143 if(b->headend<0)return -1; 395 ret=b->ptr[0]>>b->endbit;
144 396 if(bits>8){
145 if(bits){ 397 ret|=b->ptr[1]<<(8-b->endbit);
146 if (_halt_one(b)) return -1; 398 if(bits>16){
147 ret=*b->headptr>>b->headbit; 399 ret|=b->ptr[2]<<(16-b->endbit);
148 400 if(bits>24){
149 if(bits>=8){ 401 ret|=b->ptr[3]<<(24-b->endbit);
150 ++b->headptr; 402 if(bits>32 && b->endbit){
151 --b->headend; 403 ret|=b->ptr[4]<<(32-b->endbit);
152 _span_one(b);
153 if(bits>8){
154 if (_halt_one(b)) return -1;
155 ret|=*b->headptr<<(8-b->headbit);
156
157 if(bits>=16){
158 ++b->headptr;
159 --b->headend;
160 _span_one(b);
161 if(bits>16){
162 if (_halt_one(b)) return -1;
163 ret|=*b->headptr<<(16-b->headbit);
164
165 if(bits>=24){
166 ++b->headptr;
167 --b->headend;
168 _span_one(b);
169 if(bits>24){
170 if (_halt_one(b)) return -1;
171 ret|=*b->headptr<<(24-b->headbit);
172
173 if(bits>=32){
174 ++b->headptr;
175 --b->headend;
176 _span_one(b);
177 if(bits>32){
178 if (_halt_one(b)) return -1;
179 if(b->headbit)ret|=*b->headptr<<(32-b->headbit);
180
181 }
182 }
183 }
184 }
185 }
186 }
187 } 404 }
188 } 405 }
189 } 406 }
190 }else{ 407 }
408 ret&=m;
409 b->ptr+=bits/8;
410 b->endbyte+=bits/8;
411 b->endbit=bits&7;
412 return ret;
191 413
192 ret=b->headptr[0]>>b->headbit; 414 overflow:
193 if(bits>8){ 415 err:
194 ret|=b->headptr[1]<<(8-b->headbit); 416 b->ptr=NULL;
195 if(bits>16){ 417 b->endbyte=b->storage;
196 ret|=b->headptr[2]<<(16-b->headbit); 418 b->endbit=1;
197 if(bits>24){ 419 return -1L;
198 ret|=b->headptr[3]<<(24-b->headbit); 420}
199 if(bits>32 && b->headbit){ 421#if 0
200 ret|=b->headptr[4]<<(32-b->headbit); 422/* bits <= 32 */
201 } 423long oggpackB_read(oggpack_buffer *b,int bits){
202 } 424 long ret;
425 long m=32-bits;
426
427 if(m<0 || m>32) goto err;
428 bits+=b->endbit;
429
430 if(b->endbyte+4>=b->storage){
431 /* not the main path */
432 if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
433 /* special case to avoid reading b->ptr[0], which might be past the end of
434 the buffer; also skips some useless accounting */
435 else if(!bits)return(0L);
436 }
437
438 ret=b->ptr[0]<<(24+b->endbit);
439 if(bits>8){
440 ret|=b->ptr[1]<<(16+b->endbit);
441 if(bits>16){
442 ret|=b->ptr[2]<<(8+b->endbit);
443 if(bits>24){
444 ret|=b->ptr[3]<<(b->endbit);
445 if(bits>32 && b->endbit)
446 ret|=b->ptr[4]>>(8-b->endbit);
203 } 447 }
204 } 448 }
205
206 b->headptr+=((unsigned)bits)/8;
207 b->headend-=((unsigned)bits)/8;
208 } 449 }
450 ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1);
209 451
210 ret&=m; 452 b->ptr+=bits/8;
211 b->headbit=bits&7; 453 b->endbyte+=bits/8;
454 b->endbit=bits&7;
212 return ret; 455 return ret;
456
457 overflow:
458 err:
459 b->ptr=NULL;
460 b->endbyte=b->storage;
461 b->endbit=1;
462 return -1L;
213} 463}
464#endif
465long oggpack_read1(oggpack_buffer *b){
466 long ret;
467
468 if(b->endbyte >= b->storage) goto overflow;
469 ret=(b->ptr[0]>>b->endbit)&1;
470
471 b->endbit++;
472 if(b->endbit>7){
473 b->endbit=0;
474 b->ptr++;
475 b->endbyte++;
476 }
477 return ret;
478
479 overflow:
480 b->ptr=NULL;
481 b->endbyte=b->storage;
482 b->endbit=1;
483 return -1L;
484}
485#if 0
486long oggpackB_read1(oggpack_buffer *b){
487 long ret;
488
489 if(b->endbyte >= b->storage) goto overflow;
490 ret=(b->ptr[0]>>(7-b->endbit))&1;
491
492 b->endbit++;
493 if(b->endbit>7){
494 b->endbit=0;
495 b->ptr++;
496 b->endbyte++;
497 }
498 return ret;
499
500 overflow:
501 b->ptr=NULL;
502 b->endbyte=b->storage;
503 b->endbit=1;
504 return -1L;
505}
506
507long oggpack_bytes(oggpack_buffer *b){
508 return(b->endbyte+(b->endbit+7)/8);
509}
510
511long oggpack_bits(oggpack_buffer *b){
512 return(b->endbyte*8+b->endbit);
513}
514
515long oggpackB_bytes(oggpack_buffer *b){
516 return oggpack_bytes(b);
517}
518
519long oggpackB_bits(oggpack_buffer *b){
520 return oggpack_bits(b);
521}
522
523unsigned char *oggpack_get_buffer(oggpack_buffer *b){
524 return(b->buffer);
525}
526
527unsigned char *oggpackB_get_buffer(oggpack_buffer *b){
528 return oggpack_get_buffer(b);
529}
530#endif
531/* Self test of the bitwise routines; everything else is based on
532 them, so they damned well better be solid. */
533
534#ifdef _V_SELFTEST
535#include <stdio.h>
536
537static int ilog(unsigned int v){
538 int ret=0;
539 while(v){
540 ret++;
541 v>>=1;
542 }
543 return(ret);
544}
545
546oggpack_buffer o;
547oggpack_buffer r;
548
549void report(char *in){
550 fprintf(stderr,"%s",in);
551 exit(1);
552}
553
554void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){
555 long bytes,i;
556 unsigned char *buffer;
557
558 oggpack_reset(&o);
559 for(i=0;i<vals;i++)
560 oggpack_write(&o,b[i],bits?bits:ilog(b[i]));
561 buffer=oggpack_get_buffer(&o);
562 bytes=oggpack_bytes(&o);
563 if(bytes!=compsize)report("wrong number of bytes!\n");
564 for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){
565 for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]);
566 report("wrote incorrect value!\n");
567 }
568 oggpack_readinit(&r,buffer,bytes);
569 for(i=0;i<vals;i++){
570 int tbit=bits?bits:ilog(b[i]);
571 if(oggpack_look(&r,tbit)==-1)
572 report("out of data!\n");
573 if(oggpack_look(&r,tbit)!=(b[i]&mask[tbit]))
574 report("looked at incorrect value!\n");
575 if(tbit==1)
576 if(oggpack_look1(&r)!=(b[i]&mask[tbit]))
577 report("looked at single bit incorrect value!\n");
578 if(tbit==1){
579 if(oggpack_read1(&r)!=(b[i]&mask[tbit]))
580 report("read incorrect single bit value!\n");
581 }else{
582 if(oggpack_read(&r,tbit)!=(b[i]&mask[tbit]))
583 report("read incorrect value!\n");
584 }
585 }
586 if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
587}
588
589void cliptestB(unsigned long *b,int vals,int bits,int *comp,int compsize){
590 long bytes,i;
591 unsigned char *buffer;
592
593 oggpackB_reset(&o);
594 for(i=0;i<vals;i++)
595 oggpackB_write(&o,b[i],bits?bits:ilog(b[i]));
596 buffer=oggpackB_get_buffer(&o);
597 bytes=oggpackB_bytes(&o);
598 if(bytes!=compsize)report("wrong number of bytes!\n");
599 for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){
600 for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]);
601 report("wrote incorrect value!\n");
602 }
603 oggpackB_readinit(&r,buffer,bytes);
604 for(i=0;i<vals;i++){
605 int tbit=bits?bits:ilog(b[i]);
606 if(oggpackB_look(&r,tbit)==-1)
607 report("out of data!\n");
608 if(oggpackB_look(&r,tbit)!=(b[i]&mask[tbit]))
609 report("looked at incorrect value!\n");
610 if(tbit==1)
611 if(oggpackB_look1(&r)!=(b[i]&mask[tbit]))
612 report("looked at single bit incorrect value!\n");
613 if(tbit==1){
614 if(oggpackB_read1(&r)!=(b[i]&mask[tbit]))
615 report("read incorrect single bit value!\n");
616 }else{
617 if(oggpackB_read(&r,tbit)!=(b[i]&mask[tbit]))
618 report("read incorrect value!\n");
619 }
620 }
621 if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n");
622}
623
624int main(void){
625 unsigned char *buffer;
626 long bytes,i;
627 static unsigned long testbuffer1[]=
628 {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7,
629 567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4};
630 int test1size=43;
631
632 static unsigned long testbuffer2[]=
633 {216531625L,1237861823,56732452,131,3212421,12325343,34547562,12313212,
634 1233432,534,5,346435231,14436467,7869299,76326614,167548585,
635 85525151,0,12321,1,349528352};
636 int test2size=21;
637
638 static unsigned long testbuffer3[]=
639 {1,0,14,0,1,0,12,0,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1,
640 0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1};
641 int test3size=56;
642
643 static unsigned long large[]=
644 {2136531625L,2137861823,56732452,131,3212421,12325343,34547562,12313212,
645 1233432,534,5,2146435231,14436467,7869299,76326614,167548585,
646 85525151,0,12321,1,2146528352};
647
648 int onesize=33;
649 static int one[33]={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40,
650 34,242,223,136,35,222,211,86,171,50,225,135,214,75,172,
651 223,4};
652 static int oneB[33]={150,101,131,33,203,15,204,216,105,193,156,65,84,85,222,
653 8,139,145,227,126,34,55,244,171,85,100,39,195,173,18,
654 245,251,128};
655
656 int twosize=6;
657 static int two[6]={61,255,255,251,231,29};
658 static int twoB[6]={247,63,255,253,249,120};
659
660 int threesize=54;
661 static int three[54]={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254,
662 142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83,
663 58,135,196,61,55,129,183,54,101,100,170,37,127,126,10,
664 100,52,4,14,18,86,77,1};
665 static int threeB[54]={206,128,42,153,57,8,183,251,13,89,36,30,32,144,183,
666 130,59,240,121,59,85,223,19,228,180,134,33,107,74,98,
667 233,253,196,135,63,2,110,114,50,155,90,127,37,170,104,
668 200,20,254,4,58,106,176,144,0};
669
670 int foursize=38;
671 static int four[38]={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72,
672 132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169,
673 28,2,133,0,1};
674 static int fourB[38]={36,48,102,83,243,24,52,7,4,35,132,10,145,21,2,93,2,41,
675 1,219,184,16,33,184,54,149,170,132,18,30,29,98,229,67,
676 129,10,4,32};
677
678 int fivesize=45;
679 static int five[45]={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62,
680 241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169,
681 84,75,159,2,1,0,132,192,8,0,0,18,22};
682 static int fiveB[45]={1,84,145,111,245,100,128,8,56,36,40,71,126,78,213,226,
683 124,105,12,0,133,128,0,162,233,242,67,152,77,205,77,
684 172,150,169,129,79,128,0,6,4,32,0,27,9,0};
685
686 int sixsize=7;
687 static int six[7]={17,177,170,242,169,19,148};
688 static int sixB[7]={136,141,85,79,149,200,41};
689
690 /* Test read/write together */
691 /* Later we test against pregenerated bitstreams */
692 oggpack_writeinit(&o);
693
694 fprintf(stderr,"\nSmall preclipped packing (LSb): ");
695 cliptest(testbuffer1,test1size,0,one,onesize);
696 fprintf(stderr,"ok.");
697
698 fprintf(stderr,"\nNull bit call (LSb): ");
699 cliptest(testbuffer3,test3size,0,two,twosize);
700 fprintf(stderr,"ok.");
701
702 fprintf(stderr,"\nLarge preclipped packing (LSb): ");
703 cliptest(testbuffer2,test2size,0,three,threesize);
704 fprintf(stderr,"ok.");
705
706 fprintf(stderr,"\n32 bit preclipped packing (LSb): ");
707 oggpack_reset(&o);
708 for(i=0;i<test2size;i++)
709 oggpack_write(&o,large[i],32);
710 buffer=oggpack_get_buffer(&o);
711 bytes=oggpack_bytes(&o);
712 oggpack_readinit(&r,buffer,bytes);
713 for(i=0;i<test2size;i++){
714 if(oggpack_look(&r,32)==-1)report("out of data. failed!");
715 if(oggpack_look(&r,32)!=large[i]){
716 fprintf(stderr,"%ld != %ld (%lx!=%lx):",oggpack_look(&r,32),large[i],
717 oggpack_look(&r,32),large[i]);
718 report("read incorrect value!\n");
719 }
720 oggpack_adv(&r,32);
721 }
722 if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
723 fprintf(stderr,"ok.");
724
725 fprintf(stderr,"\nSmall unclipped packing (LSb): ");
726 cliptest(testbuffer1,test1size,7,four,foursize);
727 fprintf(stderr,"ok.");
728
729 fprintf(stderr,"\nLarge unclipped packing (LSb): ");
730 cliptest(testbuffer2,test2size,17,five,fivesize);
731 fprintf(stderr,"ok.");
732
733 fprintf(stderr,"\nSingle bit unclipped packing (LSb): ");
734 cliptest(testbuffer3,test3size,1,six,sixsize);
735 fprintf(stderr,"ok.");
736
737 fprintf(stderr,"\nTesting read past end (LSb): ");
738 oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
739 for(i=0;i<64;i++){
740 if(oggpack_read(&r,1)!=0){
741 fprintf(stderr,"failed; got -1 prematurely.\n");
742 exit(1);
743 }
744 }
745 if(oggpack_look(&r,1)!=-1 ||
746 oggpack_read(&r,1)!=-1){
747 fprintf(stderr,"failed; read past end without -1.\n");
748 exit(1);
749 }
750 oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
751 if(oggpack_read(&r,30)!=0 || oggpack_read(&r,16)!=0){
752 fprintf(stderr,"failed 2; got -1 prematurely.\n");
753 exit(1);
754 }
755
756 if(oggpack_look(&r,18)!=0 ||
757 oggpack_look(&r,18)!=0){
758 fprintf(stderr,"failed 3; got -1 prematurely.\n");
759 exit(1);
760 }
761 if(oggpack_look(&r,19)!=-1 ||
762 oggpack_look(&r,19)!=-1){
763 fprintf(stderr,"failed; read past end without -1.\n");
764 exit(1);
765 }
766 if(oggpack_look(&r,32)!=-1 ||
767 oggpack_look(&r,32)!=-1){
768 fprintf(stderr,"failed; read past end without -1.\n");
769 exit(1);
770 }
771 oggpack_writeclear(&o);
772 fprintf(stderr,"ok.\n");
773
774 /********** lazy, cut-n-paste retest with MSb packing ***********/
775
776 /* Test read/write together */
777 /* Later we test against pregenerated bitstreams */
778 oggpackB_writeinit(&o);
779
780 fprintf(stderr,"\nSmall preclipped packing (MSb): ");
781 cliptestB(testbuffer1,test1size,0,oneB,onesize);
782 fprintf(stderr,"ok.");
783
784 fprintf(stderr,"\nNull bit call (MSb): ");
785 cliptestB(testbuffer3,test3size,0,twoB,twosize);
786 fprintf(stderr,"ok.");
787
788 fprintf(stderr,"\nLarge preclipped packing (MSb): ");
789 cliptestB(testbuffer2,test2size,0,threeB,threesize);
790 fprintf(stderr,"ok.");
791
792 fprintf(stderr,"\n32 bit preclipped packing (MSb): ");
793 oggpackB_reset(&o);
794 for(i=0;i<test2size;i++)
795 oggpackB_write(&o,large[i],32);
796 buffer=oggpackB_get_buffer(&o);
797 bytes=oggpackB_bytes(&o);
798 oggpackB_readinit(&r,buffer,bytes);
799 for(i=0;i<test2size;i++){
800 if(oggpackB_look(&r,32)==-1)report("out of data. failed!");
801 if(oggpackB_look(&r,32)!=large[i]){
802 fprintf(stderr,"%ld != %ld (%lx!=%lx):",oggpackB_look(&r,32),large[i],
803 oggpackB_look(&r,32),large[i]);
804 report("read incorrect value!\n");
805 }
806 oggpackB_adv(&r,32);
807 }
808 if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n");
809 fprintf(stderr,"ok.");
810
811 fprintf(stderr,"\nSmall unclipped packing (MSb): ");
812 cliptestB(testbuffer1,test1size,7,fourB,foursize);
813 fprintf(stderr,"ok.");
814
815 fprintf(stderr,"\nLarge unclipped packing (MSb): ");
816 cliptestB(testbuffer2,test2size,17,fiveB,fivesize);
817 fprintf(stderr,"ok.");
818
819 fprintf(stderr,"\nSingle bit unclipped packing (MSb): ");
820 cliptestB(testbuffer3,test3size,1,sixB,sixsize);
821 fprintf(stderr,"ok.");
822
823 fprintf(stderr,"\nTesting read past end (MSb): ");
824 oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
825 for(i=0;i<64;i++){
826 if(oggpackB_read(&r,1)!=0){
827 fprintf(stderr,"failed; got -1 prematurely.\n");
828 exit(1);
829 }
830 }
831 if(oggpackB_look(&r,1)!=-1 ||
832 oggpackB_read(&r,1)!=-1){
833 fprintf(stderr,"failed; read past end without -1.\n");
834 exit(1);
835 }
836 oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
837 if(oggpackB_read(&r,30)!=0 || oggpackB_read(&r,16)!=0){
838 fprintf(stderr,"failed 2; got -1 prematurely.\n");
839 exit(1);
840 }
841
842 if(oggpackB_look(&r,18)!=0 ||
843 oggpackB_look(&r,18)!=0){
844 fprintf(stderr,"failed 3; got -1 prematurely.\n");
845 exit(1);
846 }
847 if(oggpackB_look(&r,19)!=-1 ||
848 oggpackB_look(&r,19)!=-1){
849 fprintf(stderr,"failed; read past end without -1.\n");
850 exit(1);
851 }
852 if(oggpackB_look(&r,32)!=-1 ||
853 oggpackB_look(&r,32)!=-1){
854 fprintf(stderr,"failed; read past end without -1.\n");
855 exit(1);
856 }
857 oggpackB_writeclear(&o);
858 fprintf(stderr,"ok.\n\n");
859
860
861 return(0);
862}
863#endif /* _V_SELFTEST */
214 864
865#undef BUFFER_INCREMENT
diff --git a/apps/codecs/libtremor/codebook.c b/apps/codecs/libtremor/codebook.c
index 561b597aeb..860cf07bad 100644
--- a/apps/codecs/libtremor/codebook.c
+++ b/apps/codecs/libtremor/codebook.c
@@ -279,7 +279,7 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
279 long *bufend = buf + n; 279 long *bufend = buf + n;
280 280
281 while (bufptr<bufend) { 281 while (bufptr<bufend) {
282 if (b->headend > 8) { 282 if(b->endbyte < b->storage - 8) {
283 ogg_uint32_t *ptr; 283 ogg_uint32_t *ptr;
284 unsigned long bit, bitend; 284 unsigned long bit, bitend;
285 unsigned long adr; 285 unsigned long adr;
@@ -292,10 +292,10 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
292 const ogg_uint32_t *book_codelist = book->codelist; 292 const ogg_uint32_t *book_codelist = book->codelist;
293 const char *book_dec_codelengths = book->dec_codelengths; 293 const char *book_dec_codelengths = book->dec_codelengths;
294 294
295 adr = (unsigned long)b->headptr; 295 adr = (unsigned long)b->ptr;
296 bit = (adr&3)*8+b->headbit; 296 bit = (adr&3)*8+b->endbit;
297 ptr = (ogg_uint32_t*)(adr&~3); 297 ptr = (ogg_uint32_t*)(adr&~3);
298 bitend = ((adr&3)+b->headend)*8; 298 bitend = ((adr&3)+(b->storage-b->endbyte))*8;
299 while (bufptr<bufend){ 299 while (bufptr<bufend){
300 if (UNLIKELY(cachesize<book_dec_maxlength)) { 300 if (UNLIKELY(cachesize<book_dec_maxlength)) {
301 if (bit-cachesize+32>=bitend) 301 if (bit-cachesize+32>=bitend)
@@ -323,11 +323,11 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
323 cache >>= l; 323 cache >>= l;
324 } 324 }
325 325
326 adr=(unsigned long)b->headptr; 326 adr=(unsigned long)b->ptr;
327 bit-=(adr&3)*8+cachesize; 327 bit-=(adr&3)*8+cachesize;
328 b->headend-=(bit/8); 328 b->endbyte+=bit/8;
329 b->headptr+=bit/8; 329 b->ptr+=bit/8;
330 b->headbit=bit%8; 330 b->endbit=bit&7;
331 } else { 331 } else {
332 long r = decode_packed_entry_number(book, b); 332 long r = decode_packed_entry_number(book, b);
333 if (r == -1) return bufptr-buf; 333 if (r == -1) return bufptr-buf;
@@ -337,7 +337,6 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
337 return n; 337 return n;
338} 338}
339 339
340
341/* Decode side is specced and easier, because we don't need to find 340/* Decode side is specced and easier, because we don't need to find
342 matches using different criteria; we simply read and map. There are 341 matches using different criteria; we simply read and map. There are
343 two things we need to do 'depending': 342 two things we need to do 'depending':
@@ -570,3 +569,4 @@ long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,
570 } 569 }
571 return(0); 570 return(0);
572} 571}
572
diff --git a/apps/codecs/libtremor/framing.c b/apps/codecs/libtremor/framing.c
index ac95831d5d..a40e8dec65 100644
--- a/apps/codecs/libtremor/framing.c
+++ b/apps/codecs/libtremor/framing.c
@@ -1,17 +1,18 @@
1/******************************************************************** 1/********************************************************************
2 * * 2 * *
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * 3 * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. *
4 * *
5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * * 7 * *
9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * 8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 *
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * 9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 * * 10 * *
12 ******************************************************************** 11 ********************************************************************
13 12
14 function: decode Ogg streams back into raw packets 13 function: code raw packets into framed OggSquish stream and
14 decode Ogg streams back into raw packets
15 last mod: $Id$
15 16
16 note: The CRC code is directly derived from public domain code by 17 note: The CRC code is directly derived from public domain code by
17 Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html 18 Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html
@@ -19,458 +20,102 @@
19 20
20 ********************************************************************/ 21 ********************************************************************/
21 22
22#include "config-tremor.h" 23#include <stdlib.h>
23#include <string.h> 24#include <string.h>
24#include "ogg.h" 25#include "ogg.h"
25#include "misc.h"
26
27 26
28/* A complete description of Ogg framing exists in docs/framing.html */ 27/* A complete description of Ogg framing exists in docs/framing.html */
29 28
30/* basic, centralized Ogg memory management based on linked lists of 29int ogg_page_version(const ogg_page *og){
31 references to refcounted memory buffers. References and buffers 30 return((int)(og->header[4]));
32 are both recycled. Buffers are passed around and consumed in
33 reference form. */
34
35static ogg_buffer_state *ogg_buffer_create(void){
36 ogg_buffer_state *bs=_ogg_calloc(1,sizeof(*bs));
37 return bs;
38}
39
40/* destruction is 'lazy'; there may be memory references outstanding,
41 and yanking the buffer state out from underneath would be
42 antisocial. Dealloc what is currently unused and have
43 _release_one watch for the stragglers to come in. When they do,
44 finish destruction. */
45
46/* call the helper while holding lock */
47static void _ogg_buffer_destroy(ogg_buffer_state *bs){
48 ogg_buffer *bt;
49 ogg_reference *rt;
50
51 if(bs->shutdown){
52
53 bt=bs->unused_buffers;
54 rt=bs->unused_references;
55
56 while(bt){
57 ogg_buffer *b=bt;
58 bt=b->ptr.next;
59 if(b->data)_ogg_free(b->data);
60 _ogg_free(b);
61 }
62 bs->unused_buffers=0;
63 while(rt){
64 ogg_reference *r=rt;
65 rt=r->next;
66 _ogg_free(r);
67 }
68 bs->unused_references=0;
69
70 if(!bs->outstanding)
71 _ogg_free(bs);
72
73 }
74}
75
76static void ogg_buffer_destroy(ogg_buffer_state *bs){
77 bs->shutdown=1;
78 _ogg_buffer_destroy(bs);
79}
80
81static ogg_buffer *_fetch_buffer(ogg_buffer_state *bs,long bytes){
82 ogg_buffer *ob;
83 bs->outstanding++;
84
85 /* do we have an unused buffer sitting in the pool? */
86 if(bs->unused_buffers){
87 ob=bs->unused_buffers;
88 bs->unused_buffers=ob->ptr.next;
89
90 /* if the unused buffer is too small, grow it */
91 if(ob->size<bytes){
92 ob->data=_ogg_realloc(ob->data,bytes);
93 ob->size=bytes;
94 }
95 }else{
96 /* allocate a new buffer */
97 ob=_ogg_malloc(sizeof(*ob));
98 ob->data=_ogg_malloc(bytes<16?16:bytes);
99 ob->size=bytes;
100 }
101
102 ob->refcount=1;
103 ob->ptr.owner=bs;
104 return ob;
105}
106
107STATICIRAM_NOT_MDCT ogg_reference *_fetch_ref(ogg_buffer_state *bs)
108 ICODE_ATTR_TREMOR_NOT_MDCT;
109STATICIRAM_NOT_MDCT ogg_reference *_fetch_ref(ogg_buffer_state *bs){
110 ogg_reference *or;
111 bs->outstanding++;
112
113 /* do we have an unused reference sitting in the pool? */
114 if(bs->unused_references){
115 or=bs->unused_references;
116 bs->unused_references=or->next;
117 }else{
118 /* allocate a new reference */
119 or=_ogg_malloc(sizeof(*or));
120 }
121
122 or->begin=0;
123 or->length=0;
124 or->next=0;
125 return or;
126}
127
128/* fetch a reference pointing to a fresh, initially continguous buffer
129 of at least [bytes] length */
130static ogg_reference *ogg_buffer_alloc(ogg_buffer_state *bs,long bytes){
131 ogg_buffer *ob=_fetch_buffer(bs,bytes);
132 ogg_reference *or=_fetch_ref(bs);
133 or->buffer=ob;
134 return or;
135}
136
137/* enlarge the data buffer in the current link */
138static void ogg_buffer_realloc(ogg_reference *or,long bytes){
139 ogg_buffer *ob=or->buffer;
140
141 /* if the unused buffer is too small, grow it */
142 if(ob->size<bytes){
143 ob->data=_ogg_realloc(ob->data,bytes);
144 ob->size=bytes;
145 }
146} 31}
147 32
148static void _ogg_buffer_mark_one(ogg_reference *or){ 33int ogg_page_continued(const ogg_page *og){
149 or->buffer->refcount++; 34 return((int)(og->header[5]&0x01));
150} 35}
151 36
152/* increase the refcount of the buffers to which the reference points */ 37int ogg_page_bos(const ogg_page *og){
153static void ogg_buffer_mark(ogg_reference *or){ 38 return((int)(og->header[5]&0x02));
154 while(or){
155 _ogg_buffer_mark_one(or);
156 or=or->next;
157 }
158} 39}
159 40
160/* duplicate a reference (pointing to the same actual buffer memory) 41int ogg_page_eos(const ogg_page *og){
161 and increment buffer refcount. If the desired segment begins out 42 return((int)(og->header[5]&0x04));
162 of range, NULL is returned; if the desired segment is simply zero
163 length, a zero length ref is returned. Partial range overlap
164 returns the overlap of the ranges */
165static ogg_reference *ogg_buffer_sub(ogg_reference *or,long begin,long length){
166 ogg_reference *ret=0,*head=0;
167
168 /* walk past any preceeding fragments we don't want */
169 while(or && begin>=or->length){
170 begin-=or->length;
171 or=or->next;
172 }
173
174 /* duplicate the reference chain; increment refcounts */
175 while(or && length){
176 ogg_reference *temp=_fetch_ref(or->buffer->ptr.owner);
177 if(head)
178 head->next=temp;
179 else
180 ret=temp;
181 head=temp;
182 head->buffer=or->buffer;
183 head->begin=or->begin+begin;
184 head->length=length;
185 if(head->length>or->length-begin)
186 head->length=or->length-begin;
187
188 begin=0;
189 length-=head->length;
190 or=or->next;
191 }
192
193 ogg_buffer_mark(ret);
194 return ret;
195} 43}
196 44
197static ogg_reference *ogg_buffer_dup(ogg_reference *or){ 45ogg_int64_t ogg_page_granulepos(const ogg_page *og){
198 ogg_reference *ret=0,*head=0; 46 unsigned char *page=og->header;
199 /* duplicate the reference chain; increment refcounts */ 47 ogg_int64_t granulepos=page[13]&(0xff);
200 while(or){ 48 granulepos= (granulepos<<8)|(page[12]&0xff);
201 ogg_reference *temp=_fetch_ref(or->buffer->ptr.owner); 49 granulepos= (granulepos<<8)|(page[11]&0xff);
202 if(head) 50 granulepos= (granulepos<<8)|(page[10]&0xff);
203 head->next=temp; 51 granulepos= (granulepos<<8)|(page[9]&0xff);
204 else 52 granulepos= (granulepos<<8)|(page[8]&0xff);
205 ret=temp; 53 granulepos= (granulepos<<8)|(page[7]&0xff);
206 head=temp; 54 granulepos= (granulepos<<8)|(page[6]&0xff);
207 head->buffer=or->buffer; 55 return(granulepos);
208 head->begin=or->begin;
209 head->length=or->length;
210 or=or->next;
211 }
212
213 ogg_buffer_mark(ret);
214 return ret;
215} 56}
216 57
217/* split a reference into two references; 'return' is a reference to 58ogg_uint32_t ogg_page_serialno(const ogg_page *og){
218 the buffer preceeding pos and 'head'/'tail' are the buffer past the 59 return(og->header[14] |
219 split. If pos is at or past the end of the passed in segment, 60 (og->header[15]<<8) |
220 'head/tail' are NULL */ 61 (og->header[16]<<16) |
221static ogg_reference *ogg_buffer_split(ogg_reference **tail, 62 (og->header[17]<<24));
222 ogg_reference **head,long pos){
223
224 /* walk past any preceeding fragments to one of:
225 a) the exact boundary that seps two fragments
226 b) the fragment that needs split somewhere in the middle */
227 ogg_reference *ret=*tail;
228 ogg_reference *or=*tail;
229
230 while(or && pos>or->length){
231 pos-=or->length;
232 or=or->next;
233 }
234
235 if(!or || pos==0){
236
237 return 0;
238
239 }else{
240
241 if(pos>=or->length){
242 /* exact split, or off the end? */
243 if(or->next){
244
245 /* a split */
246 *tail=or->next;
247 or->next=0;
248
249 }else{
250
251 /* off or at the end */
252 *tail=*head=0;
253
254 }
255 }else{
256
257 /* split within a fragment */
258 long lengthA=pos;
259 long beginB=or->begin+pos;
260 long lengthB=or->length-pos;
261
262 /* make a new reference to tail the second piece */
263 *tail=_fetch_ref(or->buffer->ptr.owner);
264
265 (*tail)->buffer=or->buffer;
266 (*tail)->begin=beginB;
267 (*tail)->length=lengthB;
268 (*tail)->next=or->next;
269 _ogg_buffer_mark_one(*tail);
270 if(head && or==*head)*head=*tail;
271
272 /* update the first piece */
273 or->next=0;
274 or->length=lengthA;
275
276 }
277 }
278 return ret;
279}
280
281static void ogg_buffer_release_one(ogg_reference *or){
282 ogg_buffer *ob=or->buffer;
283 ogg_buffer_state *bs=ob->ptr.owner;
284
285 ob->refcount--;
286 if(ob->refcount==0){
287 bs->outstanding--; /* for the returned buffer */
288 ob->ptr.next=bs->unused_buffers;
289 bs->unused_buffers=ob;
290 }
291
292 bs->outstanding--; /* for the returned reference */
293 or->next=bs->unused_references;
294 bs->unused_references=or;
295
296 _ogg_buffer_destroy(bs); /* lazy cleanup (if needed) */
297
298}
299
300/* release the references, decrease the refcounts of buffers to which
301 they point, release any buffers with a refcount that drops to zero */
302static void ogg_buffer_release(ogg_reference *or){
303 while(or){
304 ogg_reference *next=or->next;
305 ogg_buffer_release_one(or);
306 or=next;
307 }
308}
309
310static ogg_reference *ogg_buffer_pretruncate(ogg_reference *or,long pos){
311 /* release preceeding fragments we don't want */
312 while(or && pos>=or->length){
313 ogg_reference *next=or->next;
314 pos-=or->length;
315 ogg_buffer_release_one(or);
316 or=next;
317 }
318 if (or) {
319 or->begin+=pos;
320 or->length-=pos;
321 }
322 return or;
323}
324
325static ogg_reference *ogg_buffer_walk(ogg_reference *or){
326 if(!or)return NULL;
327 while(or->next){
328 or=or->next;
329 }
330 return(or);
331}
332
333/* *head is appended to the front end (head) of *tail; both continue to
334 be valid pointers, with *tail at the tail and *head at the head */
335static ogg_reference *ogg_buffer_cat(ogg_reference *tail, ogg_reference *head){
336 if(!tail)return head;
337
338 while(tail->next){
339 tail=tail->next;
340 }
341 tail->next=head;
342 return ogg_buffer_walk(head);
343}
344
345static void _positionB(oggbyte_buffer *b,int pos){
346 if(pos<b->pos){
347 /* start at beginning, scan forward */
348 b->ref=b->baseref;
349 b->pos=0;
350 b->end=b->pos+b->ref->length;
351 b->ptr=b->ref->buffer->data+b->ref->begin;
352 }
353}
354
355static void _positionF(oggbyte_buffer *b,int pos){
356 /* scan forward for position */
357 while(pos>=b->end){
358 /* just seek forward */
359 b->pos+=b->ref->length;
360 b->ref=b->ref->next;
361 b->end=b->ref->length+b->pos;
362 b->ptr=b->ref->buffer->data+b->ref->begin;
363 }
364}
365
366static int oggbyte_init(oggbyte_buffer *b,ogg_reference *or){
367 memset(b,0,sizeof(*b));
368 if(or){
369 b->ref=b->baseref=or;
370 b->pos=0;
371 b->end=b->ref->length;
372 b->ptr=b->ref->buffer->data+b->ref->begin;
373 return 0;
374 }else
375 return -1;
376}
377
378static void oggbyte_set4(oggbyte_buffer *b,ogg_uint32_t val,int pos){
379 int i;
380 _positionB(b,pos);
381 for(i=0;i<4;i++){
382 _positionF(b,pos);
383 b->ptr[pos-b->pos]=val;
384 val>>=8;
385 ++pos;
386 }
387} 63}
388 64
389static unsigned char oggbyte_read1(oggbyte_buffer *b,int pos){ 65long ogg_page_pageno(const ogg_page *og){
390 _positionB(b,pos); 66 return(og->header[18] |
391 _positionF(b,pos); 67 (og->header[19]<<8) |
392 return b->ptr[pos-b->pos]; 68 (og->header[20]<<16) |
393} 69 (og->header[21]<<24));
394
395static ogg_uint32_t oggbyte_read4(oggbyte_buffer *b,int pos){
396 ogg_uint32_t ret;
397 _positionB(b,pos);
398 _positionF(b,pos);
399 ret=b->ptr[pos-b->pos];
400 _positionF(b,++pos);
401 ret|=b->ptr[pos-b->pos]<<8;
402 _positionF(b,++pos);
403 ret|=b->ptr[pos-b->pos]<<16;
404 _positionF(b,++pos);
405 ret|=b->ptr[pos-b->pos]<<24;
406 return ret;
407} 70}
408 71
409static ogg_int64_t oggbyte_read8(oggbyte_buffer *b,int pos){
410 ogg_int64_t ret;
411 unsigned char t[7];
412 int i;
413 _positionB(b,pos);
414 for(i=0;i<7;i++){
415 _positionF(b,pos);
416 t[i]=b->ptr[pos++ -b->pos];
417 }
418 72
419 _positionF(b,pos);
420 ret=b->ptr[pos-b->pos];
421 73
422 for(i=6;i>=0;--i) 74/* returns the number of packets that are completed on this page (if
423 ret= ret<<8 | t[i]; 75 the leading packet is begun on a previous page, but ends on this
76 page, it's counted */
424 77
425 return ret; 78/* NOTE:
426} 79If a page consists of a packet begun on a previous page, and a new
80packet begun (but not completed) on this page, the return will be:
81 ogg_page_packets(page) ==1,
82 ogg_page_continued(page) !=0
427 83
428/* Now we get to the actual framing code */ 84If a page happens to be a single packet that was begun on a
429 85previous page, and spans to the next page (in the case of a three or
430int ogg_page_version(ogg_page *og){ 86more page packet), the return will be:
431 oggbyte_buffer ob; 87 ogg_page_packets(page) ==0,
432 oggbyte_init(&ob,og->header); 88 ogg_page_continued(page) !=0
433 return oggbyte_read1(&ob,4); 89*/
434}
435 90
436int ogg_page_continued(ogg_page *og){ 91int ogg_page_packets(const ogg_page *og){
437 oggbyte_buffer ob; 92 int i,n=og->header[26],count=0;
438 oggbyte_init(&ob,og->header); 93 for(i=0;i<n;i++)
439 return oggbyte_read1(&ob,5)&0x01; 94 if(og->header[27+i]<255)count++;
95 return(count);
440} 96}
441 97
442int ogg_page_bos(ogg_page *og){
443 oggbyte_buffer ob;
444 oggbyte_init(&ob,og->header);
445 return oggbyte_read1(&ob,5)&0x02;
446}
447 98
448int ogg_page_eos(ogg_page *og){ 99#if 0
449 oggbyte_buffer ob; 100/* helper to initialize lookup for direct-table CRC (illustrative; we
450 oggbyte_init(&ob,og->header); 101 use the static init below) */
451 return oggbyte_read1(&ob,5)&0x04;
452}
453 102
454ogg_int64_t ogg_page_granulepos(ogg_page *og){ 103static ogg_uint32_t _ogg_crc_entry(unsigned long index){
455 oggbyte_buffer ob; 104 int i;
456 oggbyte_init(&ob,og->header); 105 unsigned long r;
457 return oggbyte_read8(&ob,6);
458}
459 106
460ogg_uint32_t ogg_page_serialno(ogg_page *og){ 107 r = index << 24;
461 oggbyte_buffer ob; 108 for (i=0; i<8; i++)
462 oggbyte_init(&ob,og->header); 109 if (r & 0x80000000UL)
463 return oggbyte_read4(&ob,14); 110 r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
464} 111 polynomial, although we use an
465 112 unreflected alg and an init/final
466ogg_uint32_t ogg_page_pageno(ogg_page *og){ 113 of 0, not 0xffffffff */
467 oggbyte_buffer ob; 114 else
468 oggbyte_init(&ob,og->header); 115 r<<=1;
469 return oggbyte_read4(&ob,18); 116 return (r & 0xffffffffUL);
470} 117}
471 118#endif
472/* Static CRC calculation table. See older code in CVS for dead
473 run-time initialization code. */
474 119
475static const ogg_uint32_t crc_lookup[256] ICONST_ATTR = { 120static const ogg_uint32_t crc_lookup[256] ICONST_ATTR = {
476 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9, 121 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
@@ -538,92 +183,462 @@ static const ogg_uint32_t crc_lookup[256] ICONST_ATTR = {
538 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668, 183 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
539 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4}; 184 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4};
540 185
541ogg_sync_state *ogg_sync_create(void){ 186/* init the encode/decode logical stream state */
542 ogg_sync_state *oy=_ogg_calloc(1,sizeof(*oy)); 187
543 memset(oy,0,sizeof(*oy)); 188int ogg_stream_init(ogg_stream_state *os,int serialno){
544 oy->bufferpool=ogg_buffer_create(); 189 if(os){
545 return oy; 190 memset(os,0,sizeof(*os));
191 os->body_storage=16*1024;
192 os->lacing_storage=1024;
193
194 os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
195 os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
196 os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
197
198 if(!os->body_data || !os->lacing_vals || !os->granule_vals){
199 ogg_stream_clear(os);
200 return -1;
201 }
202
203 os->serialno=serialno;
204
205 return(0);
206 }
207 return(-1);
208}
209
210/* async/delayed error detection for the ogg_stream_state */
211int ogg_stream_check(ogg_stream_state *os){
212 if(!os || !os->body_data) return -1;
213 return 0;
546} 214}
547 215
548int ogg_sync_destroy(ogg_sync_state *oy){ 216/* _clear does not free os, only the non-flat storage within */
549 if(oy){ 217int ogg_stream_clear(ogg_stream_state *os){
550 ogg_sync_reset(oy); 218 if(os){
551 ogg_buffer_destroy(oy->bufferpool); 219 if(os->body_data)_ogg_free(os->body_data);
552 memset(oy,0,sizeof(*oy)); 220 if(os->lacing_vals)_ogg_free(os->lacing_vals);
553 _ogg_free(oy); 221 if(os->granule_vals)_ogg_free(os->granule_vals);
222
223 memset(os,0,sizeof(*os));
224 }
225 return(0);
226}
227
228int ogg_stream_destroy(ogg_stream_state *os){
229 if(os){
230 ogg_stream_clear(os);
231 _ogg_free(os);
232 }
233 return(0);
234}
235
236/* Helpers for ogg_stream_encode; this keeps the structure and
237 what's happening fairly clear */
238
239static int _os_body_expand(ogg_stream_state *os,int needed){
240 if(os->body_storage<=os->body_fill+needed){
241 void *ret;
242 ret=_ogg_realloc(os->body_data,(os->body_storage+needed+1024)*
243 sizeof(*os->body_data));
244 if(!ret){
245 ogg_stream_clear(os);
246 return -1;
247 }
248 os->body_storage+=(needed+1024);
249 os->body_data=ret;
554 } 250 }
555 return OGG_SUCCESS; 251 return 0;
556} 252}
557 253
558unsigned char *ogg_sync_bufferin(ogg_sync_state *oy, long bytes){ 254static int _os_lacing_expand(ogg_stream_state *os,int needed){
559 255 if(os->lacing_storage<=os->lacing_fill+needed){
560 /* [allocate and] expose a buffer for data submission. 256 void *ret;
561 257 ret=_ogg_realloc(os->lacing_vals,(os->lacing_storage+needed+32)*
562 If there is no head fragment 258 sizeof(*os->lacing_vals));
563 allocate one and expose it 259 if(!ret){
564 else 260 ogg_stream_clear(os);
565 if the current head fragment has sufficient unused space 261 return -1;
566 expose it 262 }
567 else 263 os->lacing_vals=ret;
568 if the current head fragment is unused 264 ret=_ogg_realloc(os->granule_vals,(os->lacing_storage+needed+32)*
569 resize and expose it 265 sizeof(*os->granule_vals));
570 else 266 if(!ret){
571 allocate new fragment and expose it 267 ogg_stream_clear(os);
572 */ 268 return -1;
573 269 }
574 /* base case; fifo uninitialized */ 270 os->granule_vals=ret;
575 if(!oy->fifo_head){ 271 os->lacing_storage+=(needed+32);
576 oy->fifo_head=oy->fifo_tail=ogg_buffer_alloc(oy->bufferpool,bytes);
577 return oy->fifo_head->buffer->data;
578 } 272 }
579 273 return 0;
580 /* space left in current fragment case */ 274}
581 if(oy->fifo_head->buffer->size- 275
582 oy->fifo_head->length- 276/* checksum the page */
583 oy->fifo_head->begin >= bytes) 277/* Direct table CRC; note that this will be faster in the future if we
584 return oy->fifo_head->buffer->data+ 278 perform the checksum simultaneously with other copies */
585 oy->fifo_head->length+oy->fifo_head->begin; 279
586 280void ogg_page_checksum_set(ogg_page *og){
587 /* current fragment is unused, but too small */ 281 if(og){
588 if(!oy->fifo_head->length){ 282 ogg_uint32_t crc_reg=0;
589 ogg_buffer_realloc(oy->fifo_head,bytes); 283 int i;
590 return oy->fifo_head->buffer->data+oy->fifo_head->begin; 284
285 /* safety; needed for API behavior, but not framing code */
286 og->header[22]=0;
287 og->header[23]=0;
288 og->header[24]=0;
289 og->header[25]=0;
290
291 for(i=0;i<og->header_len;i++)
292 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
293 for(i=0;i<og->body_len;i++)
294 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
295
296 og->header[22]=(unsigned char)(crc_reg&0xff);
297 og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
298 og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
299 og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
591 } 300 }
592 301}
593 /* current fragment used/full; get new fragment */ 302
303#if 0
304/* submit data to the internal buffer of the framing engine */
305int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count,
306 long e_o_s, ogg_int64_t granulepos){
307
308 int bytes = 0, lacing_vals, i;
309
310 if(ogg_stream_check(os)) return -1;
311 if(!iov) return 0;
312
313 for (i = 0; i < count; ++i) bytes += (int)iov[i].iov_len;
314 lacing_vals=bytes/255+1;
315
316 if(os->body_returned){
317 /* advance packet data according to the body_returned pointer. We
318 had to keep it around to return a pointer into the buffer last
319 call */
320
321 os->body_fill-=os->body_returned;
322 if(os->body_fill)
323 memmove(os->body_data,os->body_data+os->body_returned,
324 os->body_fill);
325 os->body_returned=0;
326 }
327
328 /* make sure we have the buffer storage */
329 if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals))
330 return -1;
331
332 /* Copy in the submitted packet. Yes, the copy is a waste; this is
333 the liability of overly clean abstraction for the time being. It
334 will actually be fairly easy to eliminate the extra copy in the
335 future */
336
337 for (i = 0; i < count; ++i) {
338 memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len);
339 os->body_fill += (int)iov[i].iov_len;
340 }
341
342 /* Store lacing vals for this packet */
343 for(i=0;i<lacing_vals-1;i++){
344 os->lacing_vals[os->lacing_fill+i]=255;
345 os->granule_vals[os->lacing_fill+i]=os->granulepos;
346 }
347 os->lacing_vals[os->lacing_fill+i]=bytes%255;
348 os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos;
349
350 /* flag the first segment as the beginning of the packet */
351 os->lacing_vals[os->lacing_fill]|= 0x100;
352
353 os->lacing_fill+=lacing_vals;
354
355 /* for the sake of completeness */
356 os->packetno++;
357
358 if(e_o_s)os->e_o_s=1;
359
360 return(0);
361}
362
363int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
364 ogg_iovec_t iov;
365 iov.iov_base = op->packet;
366 iov.iov_len = op->bytes;
367 return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos);
368}
369
370
371/* Conditionally flush a page; force==0 will only flush nominal-size
372 pages, force==1 forces us to flush a page regardless of page size
373 so long as there's any data available at all. */
374static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){
375 int i;
376 int vals=0;
377 int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
378 int bytes=0;
379 long acc=0;
380 ogg_int64_t granule_pos=-1;
381
382 if(ogg_stream_check(os)) return(0);
383 if(maxvals==0) return(0);
384
385 /* construct a page */
386 /* decide how many segments to include */
387
388 /* If this is the initial header case, the first page must only include
389 the initial header packet */
390 if(os->b_o_s==0){ /* 'initial header page' case */
391 granule_pos=0;
392 for(vals=0;vals<maxvals;vals++){
393 if((os->lacing_vals[vals]&0x0ff)<255){
394 vals++;
395 break;
396 }
397 }
398 }else{
399
400 /* The extra packets_done, packet_just_done logic here attempts to do two things:
401 1) Don't unneccessarily span pages.
402 2) Unless necessary, don't flush pages if there are less than four packets on
403 them; this expands page size to reduce unneccessary overhead if incoming packets
404 are large.
405 These are not necessary behaviors, just 'always better than naive flushing'
406 without requiring an application to explicitly request a specific optimized
407 behavior. We'll want an explicit behavior setup pathway eventually as well. */
408
409 int packets_done=0;
410 int packet_just_done=0;
411 for(vals=0;vals<maxvals;vals++){
412 if(acc>nfill && packet_just_done>=4){
413 force=1;
414 break;
415 }
416 acc+=os->lacing_vals[vals]&0x0ff;
417 if((os->lacing_vals[vals]&0xff)<255){
418 granule_pos=os->granule_vals[vals];
419 packet_just_done=++packets_done;
420 }else
421 packet_just_done=0;
422 }
423 if(vals==255)force=1;
424 }
425
426 if(!force) return(0);
427
428 /* construct the header in temp storage */
429 memcpy(os->header,"OggS",4);
430
431 /* stream structure version */
432 os->header[4]=0x00;
433
434 /* continued packet flag? */
435 os->header[5]=0x00;
436 if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
437 /* first page flag? */
438 if(os->b_o_s==0)os->header[5]|=0x02;
439 /* last page flag? */
440 if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
441 os->b_o_s=1;
442
443 /* 64 bits of PCM position */
444 for(i=6;i<14;i++){
445 os->header[i]=(unsigned char)(granule_pos&0xff);
446 granule_pos>>=8;
447 }
448
449 /* 32 bits of stream serial number */
450 {
451 long serialno=os->serialno;
452 for(i=14;i<18;i++){
453 os->header[i]=(unsigned char)(serialno&0xff);
454 serialno>>=8;
455 }
456 }
457
458 /* 32 bits of page counter (we have both counter and page header
459 because this val can roll over) */
460 if(os->pageno==-1)os->pageno=0; /* because someone called
461 stream_reset; this would be a
462 strange thing to do in an
463 encode stream, but it has
464 plausible uses */
594 { 465 {
595 ogg_reference *new=ogg_buffer_alloc(oy->bufferpool,bytes); 466 long pageno=os->pageno++;
596 oy->fifo_head->next=new; 467 for(i=18;i<22;i++){
597 oy->fifo_head=new; 468 os->header[i]=(unsigned char)(pageno&0xff);
469 pageno>>=8;
470 }
598 } 471 }
599 return oy->fifo_head->buffer->data; 472
473 /* zero for computation; filled in later */
474 os->header[22]=0;
475 os->header[23]=0;
476 os->header[24]=0;
477 os->header[25]=0;
478
479 /* segment table */
480 os->header[26]=(unsigned char)(vals&0xff);
481 for(i=0;i<vals;i++)
482 bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
483
484 /* set pointers in the ogg_page struct */
485 og->header=os->header;
486 og->header_len=os->header_fill=vals+27;
487 og->body=os->body_data+os->body_returned;
488 og->body_len=bytes;
489
490 /* advance the lacing data and set the body_returned pointer */
491
492 os->lacing_fill-=vals;
493 memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
494 memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
495 os->body_returned+=bytes;
496
497 /* calculate the checksum */
498
499 ogg_page_checksum_set(og);
500
501 /* done */
502 return(1);
600} 503}
601 504
602int ogg_sync_wrote(ogg_sync_state *oy, long bytes){ 505/* This will flush remaining packets into a page (returning nonzero),
603 if(!oy->fifo_head)return OGG_EINVAL; 506 even if there is not enough data to trigger a flush normally
604 if(oy->fifo_head->buffer->size-oy->fifo_head->length-oy->fifo_head->begin < 507 (undersized page). If there are no packets or partial packets to
605 bytes)return OGG_EINVAL; 508 flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
606 oy->fifo_head->length+=bytes; 509 try to flush a normal sized page like ogg_stream_pageout; a call to
607 oy->fifo_fill+=bytes; 510 ogg_stream_flush does not guarantee that all packets have flushed.
608 return OGG_SUCCESS; 511 Only a return value of 0 from ogg_stream_flush indicates all packet
512 data is flushed into pages.
513
514 since ogg_stream_flush will flush the last page in a stream even if
515 it's undersized, you almost certainly want to use ogg_stream_pageout
516 (and *not* ogg_stream_flush) unless you specifically need to flush
517 an page regardless of size in the middle of a stream. */
518
519int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
520 return ogg_stream_flush_i(os,og,1,4096);
521}
522
523/* This constructs pages from buffered packet segments. The pointers
524returned are to static buffers; do not free. The returned buffers are
525good only until the next call (using the same ogg_stream_state) */
526
527int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
528 int force=0;
529 if(ogg_stream_check(os)) return 0;
530
531 if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
532 (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */
533 force=1;
534
535 return(ogg_stream_flush_i(os,og,force,4096));
609} 536}
610 537
611static ogg_uint32_t _checksum(ogg_reference *or, int bytes){ 538/* Like the above, but an argument is provided to adjust the nominal
612 ogg_uint32_t crc_reg=0; 539page size for applications which are smart enough to provide their
613 int j,post; 540own delay based flushing */
614 541
615 while(or){ 542int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){
616 unsigned char *data=or->buffer->data+or->begin; 543 int force=0;
617 post=(bytes<or->length?bytes:or->length); 544 if(ogg_stream_check(os)) return 0;
618 for(j=0;j<post;++j) 545
619 crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^data[j]]; 546 if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
620 bytes-=j; 547 (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */
621 or=or->next; 548 force=1;
549
550 return(ogg_stream_flush_i(os,og,force,nfill));
551}
552
553int ogg_stream_eos(ogg_stream_state *os){
554 if(ogg_stream_check(os)) return 1;
555 return os->e_o_s;
556}
557#endif
558/* DECODING PRIMITIVES: packet streaming layer **********************/
559
560/* This has two layers to place more of the multi-serialno and paging
561 control in the application's hands. First, we expose a data buffer
562 using ogg_sync_buffer(). The app either copies into the
563 buffer, or passes it directly to read(), etc. We then call
564 ogg_sync_wrote() to tell how many bytes we just added.
565
566 Pages are returned (pointers into the buffer in ogg_sync_state)
567 by ogg_sync_pageout(). The page is then submitted to
568 ogg_stream_pagein() along with the appropriate
569 ogg_stream_state* (ie, matching serialno). We then get raw
570 packets out calling ogg_stream_packetout() with a
571 ogg_stream_state. */
572
573/* initialize the struct to a known state */
574int ogg_sync_init(ogg_sync_state *oy){
575 if(oy){
576 oy->storage = -1; /* used as a readiness flag */
577 memset(oy,0,sizeof(*oy));
622 } 578 }
579 return(0);
580}
581
582/* clear non-flat storage within */
583int ogg_sync_clear(ogg_sync_state *oy){
584 if(oy){
585 if(oy->data)_ogg_free(oy->data);
586 memset(oy,0,sizeof(*oy));
587 }
588 return(0);
589}
590
591int ogg_sync_destroy(ogg_sync_state *oy){
592 if(oy){
593 ogg_sync_clear(oy);
594 _ogg_free(oy);
595 }
596 return(0);
597}
623 598
624 return crc_reg; 599int ogg_sync_check(ogg_sync_state *oy){
600 if(oy->storage<0) return -1;
601 return 0;
625} 602}
626 603
604char *ogg_sync_buffer(ogg_sync_state *oy, long size){
605 if(ogg_sync_check(oy)) return NULL;
606
607 /* first, clear out any space that has been previously returned */
608 if(oy->returned){
609 oy->fill-=oy->returned;
610 if(oy->fill>0)
611 memmove(oy->data,oy->data+oy->returned,oy->fill);
612 oy->returned=0;
613 }
614
615 if(size>oy->storage-oy->fill){
616 /* We need to extend the internal buffer */
617 long newsize=size+oy->fill+4096; /* an extra page to be nice */
618 void *ret;
619
620 if(oy->data)
621 ret=_ogg_realloc(oy->data,newsize);
622 else
623 ret=_ogg_malloc(newsize);
624 if(!ret){
625 ogg_sync_clear(oy);
626 return NULL;
627 }
628 oy->data=ret;
629 oy->storage=newsize;
630 }
631
632 /* expose a segment at least as large as requested at the fill mark */
633 return((char *)oy->data+oy->fill);
634}
635
636int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
637 if(ogg_sync_check(oy))return -1;
638 if(oy->fill+bytes>oy->storage)return -1;
639 oy->fill+=bytes;
640 return(0);
641}
627 642
628/* sync the stream. This is meant to be useful for finding page 643/* sync the stream. This is meant to be useful for finding page
629 boundaries. 644 boundaries.
@@ -636,248 +651,130 @@ static ogg_uint32_t _checksum(ogg_reference *or, int bytes){
636*/ 651*/
637 652
638long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ 653long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
639 oggbyte_buffer page; 654 unsigned char *page=oy->data+oy->returned;
640 long bytes,ret=0; 655 unsigned char *next;
641 656 long bytes=oy->fill-oy->returned;
642 ogg_page_release(og);
643
644 bytes=oy->fifo_fill;
645 oggbyte_init(&page,oy->fifo_tail);
646 657
658 if(ogg_sync_check(oy))return 0;
659
647 if(oy->headerbytes==0){ 660 if(oy->headerbytes==0){
648 if(bytes<27)goto sync_out; /* not enough for even a minimal header */ 661 int headerbytes,i;
662 if(bytes<27)return(0); /* not enough for a header */
649 663
650 /* verify capture pattern */ 664 /* verify capture pattern */
651 if(oggbyte_read1(&page,0)!=(int)'O' || 665 if(memcmp(page,"OggS",4))goto sync_fail;
652 oggbyte_read1(&page,1)!=(int)'g' || 666
653 oggbyte_read1(&page,2)!=(int)'g' || 667 headerbytes=page[26]+27;
654 oggbyte_read1(&page,3)!=(int)'S' ) goto sync_fail; 668 if(bytes<headerbytes)return(0); /* not enough for header + seg table */
655 669
656 oy->headerbytes=oggbyte_read1(&page,26)+27;
657 }
658 if(bytes<oy->headerbytes)goto sync_out; /* not enough for header +
659 seg table */
660 if(oy->bodybytes==0){
661 int i;
662 /* count up body length in the segment table */ 670 /* count up body length in the segment table */
663 for(i=0;i<oy->headerbytes-27;i++) 671
664 oy->bodybytes+=oggbyte_read1(&page,27+i); 672 for(i=0;i<page[26];i++)
673 oy->bodybytes+=page[27+i];
674 oy->headerbytes=headerbytes;
665 } 675 }
666 676
667 if(oy->bodybytes+oy->headerbytes>bytes)goto sync_out; 677 if(oy->bodybytes+oy->headerbytes>bytes)return(0);
668 678
669 /* we have what appears to be a complete page; last test: verify 679 /* The whole test page is buffered. Verify the checksum */
670 checksum */
671 { 680 {
672 ogg_uint32_t chksum=oggbyte_read4(&page,22); 681 /* Grab the checksum bytes, set the header field to zero */
673 oggbyte_set4(&page,0,22); 682 char chksum[4];
674 683 ogg_page log;
675 /* Compare checksums; memory continues to be common access */ 684
676 if(chksum!=_checksum(oy->fifo_tail,oy->bodybytes+oy->headerbytes)){ 685 memcpy(chksum,page+22,4);
677 686 memset(page+22,0,4);
687
688 /* set up a temp page struct and recompute the checksum */
689 log.header=page;
690 log.header_len=oy->headerbytes;
691 log.body=page+oy->headerbytes;
692 log.body_len=oy->bodybytes;
693 ogg_page_checksum_set(&log);
694
695 /* Compare */
696 if(memcmp(chksum,page+22,4)){
678 /* D'oh. Mismatch! Corrupt page (or miscapture and not a page 697 /* D'oh. Mismatch! Corrupt page (or miscapture and not a page
679 at all). replace the computed checksum with the one actually 698 at all) */
680 read in; remember all the memory is common access */ 699 /* replace the computed checksum with the one actually read in */
700 memcpy(page+22,chksum,4);
681 701
682 oggbyte_set4(&page,chksum,22); 702 /* Bad checksum. Lose sync */
683 goto sync_fail; 703 goto sync_fail;
684 } 704 }
685 oggbyte_set4(&page,chksum,22);
686 }
687
688 /* We have a page. Set up page return. */
689 if(og){
690 /* set up page output */
691 og->header=ogg_buffer_split(&oy->fifo_tail,&oy->fifo_head,oy->headerbytes);
692 og->header_len=oy->headerbytes;
693 og->body=ogg_buffer_split(&oy->fifo_tail,&oy->fifo_head,oy->bodybytes);
694 og->body_len=oy->bodybytes;
695 }else{
696 /* simply advance */
697 oy->fifo_tail=
698 ogg_buffer_pretruncate(oy->fifo_tail,oy->headerbytes+oy->bodybytes);
699 if(!oy->fifo_tail)oy->fifo_head=0;
700 } 705 }
701 706
702 ret=oy->headerbytes+oy->bodybytes; 707 /* yes, have a whole page all ready to go */
703 oy->unsynced=0; 708 {
704 oy->headerbytes=0; 709 unsigned char *page=oy->data+oy->returned;
705 oy->bodybytes=0; 710 long bytes;
706 oy->fifo_fill-=ret; 711
712 if(og){
713 og->header=page;
714 og->header_len=oy->headerbytes;
715 og->body=page+oy->headerbytes;
716 og->body_len=oy->bodybytes;
717 }
707 718
708 return ret; 719 oy->unsynced=0;
720 oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
721 oy->headerbytes=0;
722 oy->bodybytes=0;
723 return(bytes);
724 }
709 725
710 sync_fail: 726 sync_fail:
711 727
712 oy->headerbytes=0; 728 oy->headerbytes=0;
713 oy->bodybytes=0; 729 oy->bodybytes=0;
714 oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,1);
715 ret--;
716 730
717 /* search forward through fragments for possible capture */ 731 /* search for possible capture */
718 while(oy->fifo_tail){ 732 next=memchr(page+1,'O',bytes-1);
719 /* invariant: fifo_cursor points to a position in fifo_tail */ 733 if(!next)
720 unsigned char *now=oy->fifo_tail->buffer->data+oy->fifo_tail->begin; 734 next=oy->data+oy->fill;
721 unsigned char *next=memchr(now, 'O', oy->fifo_tail->length);
722
723 if(next){
724 /* possible capture in this segment */
725 long bytes=next-now;
726 oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,bytes);
727 ret-=bytes;
728 break;
729 }else{
730 /* no capture. advance to next segment */
731 long bytes=oy->fifo_tail->length;
732 ret-=bytes;
733 oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,bytes);
734 }
735 }
736 if(!oy->fifo_tail)oy->fifo_head=0;
737 oy->fifo_fill+=ret;
738 735
739 sync_out: 736 oy->returned=(int)(next-oy->data);
740 return ret; 737 return((long)-(next-page));
741} 738}
742 739
743/* clear things to an initial state. Good to call, eg, before seeking */ 740/* sync the stream and get a page. Keep trying until we find a page.
744int ogg_sync_reset(ogg_sync_state *oy){ 741 Suppress 'sync errors' after reporting the first.
745 742
746 ogg_buffer_release(oy->fifo_tail); 743 return values:
747 oy->fifo_tail=0; 744 -1) recapture (hole in data)
748 oy->fifo_head=0; 745 0) need more data
749 oy->fifo_fill=0; 746 1) page returned
750 747
751 oy->unsynced=0; 748 Returns pointers into buffered data; invalidated by next call to
752 oy->headerbytes=0; 749 _stream, _clear, _init, or _buffer */
753 oy->bodybytes=0;
754 return OGG_SUCCESS;
755}
756 750
757ogg_stream_state *ogg_stream_create(int serialno){ 751int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
758 ogg_stream_state *os=_ogg_calloc(1,sizeof(*os));
759 os->serialno=serialno;
760 os->pageno=-1;
761 return os;
762}
763 752
764int ogg_stream_destroy(ogg_stream_state *os){ 753 if(ogg_sync_check(oy))return 0;
765 if(os){
766 ogg_buffer_release(os->header_tail);
767 ogg_buffer_release(os->body_tail);
768 memset(os,0,sizeof(*os));
769 _ogg_free(os);
770 }
771 return OGG_SUCCESS;
772}
773 754
755 /* all we need to do is verify a page at the head of the stream
756 buffer. If it doesn't verify, we look for the next potential
757 frame */
774 758
775#define FINFLAG 0x80000000UL 759 for(;;){
776#define FINMASK 0x7fffffffUL 760 long ret=ogg_sync_pageseek(oy,og);
777 761 if(ret>0){
778static void _next_lace(oggbyte_buffer *ob,ogg_stream_state *os){ 762 /* have a page */
779 /* search ahead one lace */ 763 return(1);
780 os->body_fill_next=0; 764 }
781 while(os->laceptr<os->lacing_fill){ 765 if(ret==0){
782 int val=oggbyte_read1(ob,27+os->laceptr++); 766 /* need more data */
783 os->body_fill_next+=val; 767 return(0);
784 if(val<255){
785 os->body_fill_next|=FINFLAG;
786 os->clearflag=1;
787 break;
788 } 768 }
789 }
790}
791
792STATICIRAM_NOT_MDCT void _span_queued_page(ogg_stream_state *os)
793 ICODE_ATTR_TREMOR_NOT_MDCT;
794STATICIRAM_NOT_MDCT void _span_queued_page(ogg_stream_state *os){
795 while( !(os->body_fill&FINFLAG) ){
796
797 if(!os->header_tail)break;
798
799 /* first flush out preceeding page header (if any). Body is
800 flushed as it's consumed, so that's not done here. */
801
802 if(os->lacing_fill>=0)
803 os->header_tail=ogg_buffer_pretruncate(os->header_tail,
804 os->lacing_fill+27);
805 os->lacing_fill=0;
806 os->laceptr=0;
807 os->clearflag=0;
808
809 if(!os->header_tail){
810 os->header_head=0;
811 break;
812 }else{
813
814 /* process/prepare next page, if any */
815
816 long pageno;
817 oggbyte_buffer ob;
818 ogg_page og; /* only for parsing header values */
819 og.header=os->header_tail; /* only for parsing header values */
820 pageno=ogg_page_pageno(&og);
821
822 oggbyte_init(&ob,os->header_tail);
823 os->lacing_fill=oggbyte_read1(&ob,26);
824
825 /* are we in sequence? */
826 if(pageno!=os->pageno){
827 if(os->pageno==-1) /* indicates seek or reset */
828 os->holeflag=1; /* set for internal use */
829 else
830 os->holeflag=2; /* set for external reporting */
831
832 os->body_tail=ogg_buffer_pretruncate(os->body_tail,
833 os->body_fill);
834 if(os->body_tail==0)os->body_head=0;
835 os->body_fill=0;
836
837 }
838 769
839 if(ogg_page_continued(&og)){ 770 /* head did not start a synced page... skipped some bytes */
840 if(os->body_fill==0){ 771 if(!oy->unsynced){
841 /* continued packet, but no preceeding data to continue */ 772 oy->unsynced=1;
842 /* dump the first partial packet on the page */ 773 return(-1);
843 _next_lace(&ob,os); 774 }
844 os->body_tail=
845 ogg_buffer_pretruncate(os->body_tail,os->body_fill_next&FINMASK);
846 if(os->body_tail==0)os->body_head=0;
847 /* set span flag */
848 if(!os->spanflag && !os->holeflag)os->spanflag=2;
849 }
850 }else{
851 if(os->body_fill>0){
852 /* preceeding data to continue, but not a continued page */
853 /* dump body_fill */
854 os->body_tail=ogg_buffer_pretruncate(os->body_tail,
855 os->body_fill);
856 if(os->body_tail==0)os->body_head=0;
857 os->body_fill=0;
858
859 /* set espan flag */
860 if(!os->spanflag && !os->holeflag)os->spanflag=2;
861 }
862 }
863
864 if(os->laceptr<os->lacing_fill){
865 os->granulepos=ogg_page_granulepos(&og);
866 775
867 /* get current packet size & flag */ 776 /* loop. keep looking */
868 _next_lace(&ob,os);
869 os->body_fill+=os->body_fill_next; /* addition handles the flag fine;
870 unsigned on purpose */
871 /* ...and next packet size & flag */
872 _next_lace(&ob,os);
873 777
874 }
875
876 os->pageno=pageno+1;
877 os->e_o_s=ogg_page_eos(&og);
878 os->b_o_s=ogg_page_bos(&og);
879
880 }
881 } 778 }
882} 779}
883 780
@@ -885,45 +782,156 @@ STATICIRAM_NOT_MDCT void _span_queued_page(ogg_stream_state *os){
885 into packet segments here as well. */ 782 into packet segments here as well. */
886 783
887int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){ 784int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
785 unsigned char *header=og->header;
786 unsigned char *body=og->body;
787 long bodysize=og->body_len;
788 int segptr=0;
888 789
889 int serialno=ogg_page_serialno(og);
890 int version=ogg_page_version(og); 790 int version=ogg_page_version(og);
791 int continued=ogg_page_continued(og);
792 int bos=ogg_page_bos(og);
793 int eos=ogg_page_eos(og);
794 ogg_int64_t granulepos=ogg_page_granulepos(og);
795 ogg_uint32_t serialno=ogg_page_serialno(og);
796 long pageno=ogg_page_pageno(og);
797 int segments=header[26];
798
799 if(ogg_stream_check(os)) return -1;
800
801 /* clean up 'returned data' */
802 {
803 long lr=os->lacing_returned;
804 long br=os->body_returned;
805
806 /* body data */
807 if(br){
808 os->body_fill-=br;
809 if(os->body_fill)
810 memmove(os->body_data,os->body_data+br,os->body_fill);
811 os->body_returned=0;
812 }
813
814 if(lr){
815 /* segment table */
816 if(os->lacing_fill-lr){
817 memmove(os->lacing_vals,os->lacing_vals+lr,
818 (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
819 memmove(os->granule_vals,os->granule_vals+lr,
820 (os->lacing_fill-lr)*sizeof(*os->granule_vals));
821 }
822 os->lacing_fill-=lr;
823 os->lacing_packet-=lr;
824 os->lacing_returned=0;
825 }
826 }
891 827
892 /* check the serial number */ 828 /* check the serial number */
893 if(serialno!=os->serialno){ 829 if(serialno!=os->serialno)return(-1);
894 ogg_page_release(og); 830 if(version>0)return(-1);
895 return OGG_ESERIAL; 831
832 if(_os_lacing_expand(os,segments+1)) return -1;
833
834 /* are we in sequence? */
835 if(pageno!=os->pageno){
836 int i;
837
838 /* unroll previous partial packet (if any) */
839 for(i=os->lacing_packet;i<os->lacing_fill;i++)
840 os->body_fill-=os->lacing_vals[i]&0xff;
841 os->lacing_fill=os->lacing_packet;
842
843 /* make a note of dropped data in segment table */
844 if(os->pageno!=-1){
845 os->lacing_vals[os->lacing_fill++]=0x400;
846 os->lacing_packet++;
847 }
848 }
849
850 /* are we a 'continued packet' page? If so, we may need to skip
851 some segments */
852 if(continued){
853 if(os->lacing_fill<1 ||
854 os->lacing_vals[os->lacing_fill-1]==0x400){
855 bos=0;
856 for(;segptr<segments;segptr++){
857 int val=header[27+segptr];
858 body+=val;
859 bodysize-=val;
860 if(val<255){
861 segptr++;
862 break;
863 }
864 }
865 }
896 } 866 }
897 if(version>0){ 867
898 ogg_page_release(og); 868 if(bodysize){
899 return OGG_EVERSION; 869 if(_os_body_expand(os,bodysize)) return -1;
870 memcpy(os->body_data+os->body_fill,body,bodysize);
871 os->body_fill+=bodysize;
900 } 872 }
901 873
902 /* add to fifos */ 874 {
903 if(!os->body_tail){ 875 int saved=-1;
904 os->body_tail=og->body; 876 while(segptr<segments){
905 os->body_head=ogg_buffer_walk(og->body); 877 int val=header[27+segptr];
906 }else{ 878 os->lacing_vals[os->lacing_fill]=val;
907 os->body_head=ogg_buffer_cat(os->body_head,og->body); 879 os->granule_vals[os->lacing_fill]=-1;
880
881 if(bos){
882 os->lacing_vals[os->lacing_fill]|=0x100;
883 bos=0;
884 }
885
886 if(val<255)saved=os->lacing_fill;
887
888 os->lacing_fill++;
889 segptr++;
890
891 if(val<255)os->lacing_packet=os->lacing_fill;
892 }
893
894 /* set the granulepos on the last granuleval of the last full packet */
895 if(saved!=-1){
896 os->granule_vals[saved]=granulepos;
897 }
898
908 } 899 }
909 if(!os->header_tail){ 900
910 os->header_tail=og->header; 901 if(eos){
911 os->header_head=ogg_buffer_walk(og->header); 902 os->e_o_s=1;
912 os->lacing_fill=-27; 903 if(os->lacing_fill>0)
913 }else{ 904 os->lacing_vals[os->lacing_fill-1]|=0x200;
914 os->header_head=ogg_buffer_cat(os->header_head,og->header);
915 } 905 }
916 906
917 memset(og,0,sizeof(*og)); 907 os->pageno=pageno+1;
918 return OGG_SUCCESS; 908
909 return(0);
910}
911
912/* clear things to an initial state. Good to call, eg, before seeking */
913int ogg_sync_reset(ogg_sync_state *oy){
914 if(ogg_sync_check(oy))return -1;
915
916 oy->fill=0;
917 oy->returned=0;
918 oy->unsynced=0;
919 oy->headerbytes=0;
920 oy->bodybytes=0;
921 return(0);
919} 922}
920 923
921int ogg_stream_reset(ogg_stream_state *os){ 924int ogg_stream_reset(ogg_stream_state *os){
925 if(ogg_stream_check(os)) return -1;
926
927 os->body_fill=0;
928 os->body_returned=0;
922 929
923 ogg_buffer_release(os->header_tail); 930 os->lacing_fill=0;
924 ogg_buffer_release(os->body_tail); 931 os->lacing_packet=0;
925 os->header_tail=os->header_head=0; 932 os->lacing_returned=0;
926 os->body_tail=os->body_head=0; 933
934/* os->header_fill=0; */
927 935
928 os->e_o_s=0; 936 os->e_o_s=0;
929 os->b_o_s=0; 937 os->b_o_s=0;
@@ -931,137 +939,1159 @@ int ogg_stream_reset(ogg_stream_state *os){
931 os->packetno=0; 939 os->packetno=0;
932 os->granulepos=0; 940 os->granulepos=0;
933 941
934 os->body_fill=0; 942 return(0);
935 os->lacing_fill=0;
936
937 os->holeflag=0;
938 os->spanflag=0;
939 os->clearflag=0;
940 os->laceptr=0;
941 os->body_fill_next=0;
942
943 return OGG_SUCCESS;
944} 943}
945 944
946int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){ 945int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
946 if(ogg_stream_check(os)) return -1;
947 ogg_stream_reset(os); 947 ogg_stream_reset(os);
948 os->serialno=serialno; 948 os->serialno=serialno;
949 return OGG_SUCCESS; 949 return(0);
950} 950}
951 951
952STATICIRAM_NOT_MDCT int _packetout(ogg_stream_state *os,ogg_packet *op,int adv) 952static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv)
953 ICODE_ATTR_TREMOR_NOT_MDCT; 953 ICODE_ATTR_TREMOR_NOT_MDCT;
954STATICIRAM_NOT_MDCT int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){ 954static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
955 955
956 ogg_packet_release(op); 956 /* The last part of decode. We have the stream broken into packet
957 _span_queued_page(os); 957 segments. Now we need to group them into packets (or return the
958 out of sync markers) */
958 959
959 if(os->holeflag){ 960 int ptr=os->lacing_returned;
960 int temp=os->holeflag; 961
961 if(os->clearflag) 962 if(os->lacing_packet<=ptr)return(0);
962 os->holeflag=0; 963
963 else 964 if(os->lacing_vals[ptr]&0x400){
964 os->holeflag=1; 965 /* we need to tell the codec there's a gap; it might need to
965 if(temp==2){ 966 handle previous packet dependencies. */
966 os->packetno++; 967 os->lacing_returned++;
967 return OGG_HOLE; 968 os->packetno++;
968 } 969 return(-1);
969 }
970 if(os->spanflag){
971 int temp=os->spanflag;
972 if(os->clearflag)
973 os->spanflag=0;
974 else
975 os->spanflag=1;
976 if(temp==2){
977 os->packetno++;
978 return OGG_SPAN;
979 }
980 } 970 }
981 971
982 if(!(os->body_fill&FINFLAG)) return 0; 972 if(!op && !adv)return(1); /* just using peek as an inexpensive way
983 if(!op && !adv)return 1; /* just using peek as an inexpensive way
984 to ask if there's a whole packet 973 to ask if there's a whole packet
985 waiting */ 974 waiting */
986 if(op){
987 op->b_o_s=os->b_o_s;
988 if(os->e_o_s && os->body_fill_next==0)
989 op->e_o_s=os->e_o_s;
990 else
991 op->e_o_s=0;
992 if( (os->body_fill&FINFLAG) && !(os->body_fill_next&FINFLAG) )
993 op->granulepos=os->granulepos;
994 else
995 op->granulepos=-1;
996 op->packetno=os->packetno;
997 }
998 975
999 if(adv){ 976 /* Gather the whole packet. We'll have no holes or a partial packet */
1000 oggbyte_buffer ob; 977 {
1001 oggbyte_init(&ob,os->header_tail); 978 int size=os->lacing_vals[ptr]&0xff;
979 long bytes=size;
980 int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
981 int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
982
983 while(size==255){
984 int val=os->lacing_vals[++ptr];
985 size=val&0xff;
986 if(val&0x200)eos=0x200;
987 bytes+=size;
988 }
1002 989
1003 /* split the body contents off */
1004 if(op){ 990 if(op){
1005 op->packet=ogg_buffer_split(&os->body_tail,&os->body_head, 991 op->e_o_s=eos;
1006 os->body_fill&FINMASK); 992 op->b_o_s=bos;
1007 op->bytes=os->body_fill&FINMASK; 993 op->packet=os->body_data+os->body_returned;
1008 }else{ 994 op->packetno=os->packetno;
1009 os->body_tail=ogg_buffer_pretruncate(os->body_tail, 995 op->granulepos=os->granule_vals[ptr];
1010 os->body_fill&FINMASK); 996 op->bytes=bytes;
1011 if(os->body_tail==0)os->body_head=0;
1012 } 997 }
1013 998
1014 /* update lacing pointers */ 999 if(adv){
1015 os->body_fill=os->body_fill_next; 1000 os->body_returned+=bytes;
1016 _next_lace(&ob,os); 1001 os->lacing_returned=ptr+1;
1017 }else{ 1002 os->packetno++;
1018 if(op){
1019 op->packet=ogg_buffer_sub(os->body_tail,0,os->body_fill&FINMASK);
1020 op->bytes=os->body_fill&FINMASK;
1021 } 1003 }
1022 } 1004 }
1023 1005 return(1);
1024 if(adv){
1025 os->packetno++;
1026 os->b_o_s=0;
1027 }
1028
1029 return 1;
1030} 1006}
1031 1007
1032int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op) 1008int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op)
1033 ICODE_ATTR_TREMOR_NOT_MDCT; 1009 ICODE_ATTR_TREMOR_NOT_MDCT;
1034int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){ 1010int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
1011 if(ogg_stream_check(os)) return 0;
1035 return _packetout(os,op,1); 1012 return _packetout(os,op,1);
1036} 1013}
1037 1014
1038int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op) 1015int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op)
1039 ICODE_ATTR_TREMOR_NOT_MDCT; 1016 ICODE_ATTR_TREMOR_NOT_MDCT;
1040int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){ 1017int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
1018 if(ogg_stream_check(os)) return 0;
1041 return _packetout(os,op,0); 1019 return _packetout(os,op,0);
1042} 1020}
1043 1021
1044int ogg_packet_release(ogg_packet *op) { 1022void ogg_packet_clear(ogg_packet *op) {
1045 if(op){ 1023 _ogg_free(op->packet);
1046 ogg_buffer_release(op->packet); 1024 memset(op, 0, sizeof(*op));
1047 memset(op, 0, sizeof(*op)); 1025}
1026
1027#ifdef _V_SELFTEST
1028#include <stdio.h>
1029
1030ogg_stream_state os_en, os_de;
1031ogg_sync_state oy;
1032
1033void checkpacket(ogg_packet *op,long len, int no, long pos){
1034 long j;
1035 static int sequence=0;
1036 static int lastno=0;
1037
1038 if(op->bytes!=len){
1039 fprintf(stderr,"incorrect packet length (%ld != %ld)!\n",op->bytes,len);
1040 exit(1);
1041 }
1042 if(op->granulepos!=pos){
1043 fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos);
1044 exit(1);
1045 }
1046
1047 /* packet number just follows sequence/gap; adjust the input number
1048 for that */
1049 if(no==0){
1050 sequence=0;
1051 }else{
1052 sequence++;
1053 if(no>lastno+1)
1054 sequence++;
1055 }
1056 lastno=no;
1057 if(op->packetno!=sequence){
1058 fprintf(stderr,"incorrect packet sequence %ld != %d\n",
1059 (long)(op->packetno),sequence);
1060 exit(1);
1048 } 1061 }
1049 return OGG_SUCCESS; 1062
1063 /* Test data */
1064 for(j=0;j<op->bytes;j++)
1065 if(op->packet[j]!=((j+no)&0xff)){
1066 fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
1067 j,op->packet[j],(j+no)&0xff);
1068 exit(1);
1069 }
1050} 1070}
1051 1071
1052int ogg_page_release(ogg_page *og) { 1072void check_page(unsigned char *data,const int *header,ogg_page *og){
1053 if(og){ 1073 long j;
1054 ogg_buffer_release(og->header); 1074 /* Test data */
1055 ogg_buffer_release(og->body); 1075 for(j=0;j<og->body_len;j++)
1056 memset(og, 0, sizeof(*og)); 1076 if(og->body[j]!=data[j]){
1077 fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
1078 j,data[j],og->body[j]);
1079 exit(1);
1080 }
1081
1082 /* Test header */
1083 for(j=0;j<og->header_len;j++){
1084 if(og->header[j]!=header[j]){
1085 fprintf(stderr,"header content mismatch at pos %ld:\n",j);
1086 for(j=0;j<header[26]+27;j++)
1087 fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
1088 fprintf(stderr,"\n");
1089 exit(1);
1090 }
1057 } 1091 }
1058 return OGG_SUCCESS; 1092 if(og->header_len!=header[26]+27){
1093 fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
1094 og->header_len,header[26]+27);
1095 exit(1);
1096 }
1097}
1098
1099void print_header(ogg_page *og){
1100 int j;
1101 fprintf(stderr,"\nHEADER:\n");
1102 fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n",
1103 og->header[0],og->header[1],og->header[2],og->header[3],
1104 (int)og->header[4],(int)og->header[5]);
1105
1106 fprintf(stderr," granulepos: %d serialno: %d pageno: %ld\n",
1107 (og->header[9]<<24)|(og->header[8]<<16)|
1108 (og->header[7]<<8)|og->header[6],
1109 (og->header[17]<<24)|(og->header[16]<<16)|
1110 (og->header[15]<<8)|og->header[14],
1111 ((long)(og->header[21])<<24)|(og->header[20]<<16)|
1112 (og->header[19]<<8)|og->header[18]);
1113
1114 fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (",
1115 (int)og->header[22],(int)og->header[23],
1116 (int)og->header[24],(int)og->header[25],
1117 (int)og->header[26]);
1118
1119 for(j=27;j<og->header_len;j++)
1120 fprintf(stderr,"%d ",(int)og->header[j]);
1121 fprintf(stderr,")\n\n");
1059} 1122}
1060 1123
1061void ogg_page_dup(ogg_page *dup,ogg_page *orig){ 1124void copy_page(ogg_page *og){
1062 dup->header_len=orig->header_len; 1125 unsigned char *temp=_ogg_malloc(og->header_len);
1063 dup->body_len=orig->body_len; 1126 memcpy(temp,og->header,og->header_len);
1064 dup->header=ogg_buffer_dup(orig->header); 1127 og->header=temp;
1065 dup->body=ogg_buffer_dup(orig->body); 1128
1129 temp=_ogg_malloc(og->body_len);
1130 memcpy(temp,og->body,og->body_len);
1131 og->body=temp;
1132}
1133
1134void free_page(ogg_page *og){
1135 _ogg_free (og->header);
1136 _ogg_free (og->body);
1137}
1138
1139void error(void){
1140 fprintf(stderr,"error!\n");
1141 exit(1);
1142}
1143
1144/* 17 only */
1145const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
1146 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1147 0x01,0x02,0x03,0x04,0,0,0,0,
1148 0x15,0xed,0xec,0x91,
1149 1,
1150 17};
1151
1152/* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1153const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
1154 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1155 0x01,0x02,0x03,0x04,0,0,0,0,
1156 0x59,0x10,0x6c,0x2c,
1157 1,
1158 17};
1159const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
1160 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
1161 0x01,0x02,0x03,0x04,1,0,0,0,
1162 0x89,0x33,0x85,0xce,
1163 13,
1164 254,255,0,255,1,255,245,255,255,0,
1165 255,255,90};
1166
1167/* nil packets; beginning,middle,end */
1168const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
1169 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1170 0x01,0x02,0x03,0x04,0,0,0,0,
1171 0xff,0x7b,0x23,0x17,
1172 1,
1173 0};
1174const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
1175 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
1176 0x01,0x02,0x03,0x04,1,0,0,0,
1177 0x5c,0x3f,0x66,0xcb,
1178 17,
1179 17,254,255,0,0,255,1,0,255,245,255,255,0,
1180 255,255,90,0};
1181
1182/* large initial packet */
1183const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
1184 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1185 0x01,0x02,0x03,0x04,0,0,0,0,
1186 0x01,0x27,0x31,0xaa,
1187 18,
1188 255,255,255,255,255,255,255,255,
1189 255,255,255,255,255,255,255,255,255,10};
1190
1191const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
1192 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1193 0x01,0x02,0x03,0x04,1,0,0,0,
1194 0x7f,0x4e,0x8a,0xd2,
1195 4,
1196 255,4,255,0};
1197
1198
1199/* continuing packet test */
1200const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
1201 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1202 0x01,0x02,0x03,0x04,0,0,0,0,
1203 0xff,0x7b,0x23,0x17,
1204 1,
1205 0};
1206
1207const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
1208 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1209 0x01,0x02,0x03,0x04,1,0,0,0,
1210 0xf8,0x3c,0x19,0x79,
1211 255,
1212 255,255,255,255,255,255,255,255,
1213 255,255,255,255,255,255,255,255,
1214 255,255,255,255,255,255,255,255,
1215 255,255,255,255,255,255,255,255,
1216 255,255,255,255,255,255,255,255,
1217 255,255,255,255,255,255,255,255,
1218 255,255,255,255,255,255,255,255,
1219 255,255,255,255,255,255,255,255,
1220 255,255,255,255,255,255,255,255,
1221 255,255,255,255,255,255,255,255,
1222 255,255,255,255,255,255,255,255,
1223 255,255,255,255,255,255,255,255,
1224 255,255,255,255,255,255,255,255,
1225 255,255,255,255,255,255,255,255,
1226 255,255,255,255,255,255,255,255,
1227 255,255,255,255,255,255,255,255,
1228 255,255,255,255,255,255,255,255,
1229 255,255,255,255,255,255,255,255,
1230 255,255,255,255,255,255,255,255,
1231 255,255,255,255,255,255,255,255,
1232 255,255,255,255,255,255,255,255,
1233 255,255,255,255,255,255,255,255,
1234 255,255,255,255,255,255,255,255,
1235 255,255,255,255,255,255,255,255,
1236 255,255,255,255,255,255,255,255,
1237 255,255,255,255,255,255,255,255,
1238 255,255,255,255,255,255,255,255,
1239 255,255,255,255,255,255,255,255,
1240 255,255,255,255,255,255,255,255,
1241 255,255,255,255,255,255,255,255,
1242 255,255,255,255,255,255,255,255,
1243 255,255,255,255,255,255,255};
1244
1245const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
1246 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
1247 0x01,0x02,0x03,0x04,2,0,0,0,
1248 0x38,0xe6,0xb6,0x28,
1249 6,
1250 255,220,255,4,255,0};
1251
1252
1253/* spill expansion test */
1254const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
1255 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1256 0x01,0x02,0x03,0x04,0,0,0,0,
1257 0xff,0x7b,0x23,0x17,
1258 1,
1259 0};
1260
1261const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
1262 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1263 0x01,0x02,0x03,0x04,1,0,0,0,
1264 0xce,0x8f,0x17,0x1a,
1265 23,
1266 255,255,255,255,255,255,255,255,
1267 255,255,255,255,255,255,255,255,255,10,255,4,255,0,0};
1268
1269
1270const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
1271 0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
1272 0x01,0x02,0x03,0x04,2,0,0,0,
1273 0x9b,0xb2,0x50,0xa1,
1274 1,
1275 0};
1276
1277/* page with the 255 segment limit */
1278const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
1279 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1280 0x01,0x02,0x03,0x04,0,0,0,0,
1281 0xff,0x7b,0x23,0x17,
1282 1,
1283 0};
1284
1285const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
1286 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
1287 0x01,0x02,0x03,0x04,1,0,0,0,
1288 0xed,0x2a,0x2e,0xa7,
1289 255,
1290 10,10,10,10,10,10,10,10,
1291 10,10,10,10,10,10,10,10,
1292 10,10,10,10,10,10,10,10,
1293 10,10,10,10,10,10,10,10,
1294 10,10,10,10,10,10,10,10,
1295 10,10,10,10,10,10,10,10,
1296 10,10,10,10,10,10,10,10,
1297 10,10,10,10,10,10,10,10,
1298 10,10,10,10,10,10,10,10,
1299 10,10,10,10,10,10,10,10,
1300 10,10,10,10,10,10,10,10,
1301 10,10,10,10,10,10,10,10,
1302 10,10,10,10,10,10,10,10,
1303 10,10,10,10,10,10,10,10,
1304 10,10,10,10,10,10,10,10,
1305 10,10,10,10,10,10,10,10,
1306 10,10,10,10,10,10,10,10,
1307 10,10,10,10,10,10,10,10,
1308 10,10,10,10,10,10,10,10,
1309 10,10,10,10,10,10,10,10,
1310 10,10,10,10,10,10,10,10,
1311 10,10,10,10,10,10,10,10,
1312 10,10,10,10,10,10,10,10,
1313 10,10,10,10,10,10,10,10,
1314 10,10,10,10,10,10,10,10,
1315 10,10,10,10,10,10,10,10,
1316 10,10,10,10,10,10,10,10,
1317 10,10,10,10,10,10,10,10,
1318 10,10,10,10,10,10,10,10,
1319 10,10,10,10,10,10,10,10,
1320 10,10,10,10,10,10,10,10,
1321 10,10,10,10,10,10,10};
1322
1323const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
1324 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
1325 0x01,0x02,0x03,0x04,2,0,0,0,
1326 0x6c,0x3b,0x82,0x3d,
1327 1,
1328 50};
1329
1330
1331/* packet that overspans over an entire page */
1332const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
1333 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1334 0x01,0x02,0x03,0x04,0,0,0,0,
1335 0xff,0x7b,0x23,0x17,
1336 1,
1337 0};
1338
1339const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
1340 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1341 0x01,0x02,0x03,0x04,1,0,0,0,
1342 0x68,0x22,0x7c,0x3d,
1343 255,
1344 100,
1345 255,255,255,255,255,255,255,255,
1346 255,255,255,255,255,255,255,255,
1347 255,255,255,255,255,255,255,255,
1348 255,255,255,255,255,255,255,255,
1349 255,255,255,255,255,255,255,255,
1350 255,255,255,255,255,255,255,255,
1351 255,255,255,255,255,255,255,255,
1352 255,255,255,255,255,255,255,255,
1353 255,255,255,255,255,255,255,255,
1354 255,255,255,255,255,255,255,255,
1355 255,255,255,255,255,255,255,255,
1356 255,255,255,255,255,255,255,255,
1357 255,255,255,255,255,255,255,255,
1358 255,255,255,255,255,255,255,255,
1359 255,255,255,255,255,255,255,255,
1360 255,255,255,255,255,255,255,255,
1361 255,255,255,255,255,255,255,255,
1362 255,255,255,255,255,255,255,255,
1363 255,255,255,255,255,255,255,255,
1364 255,255,255,255,255,255,255,255,
1365 255,255,255,255,255,255,255,255,
1366 255,255,255,255,255,255,255,255,
1367 255,255,255,255,255,255,255,255,
1368 255,255,255,255,255,255,255,255,
1369 255,255,255,255,255,255,255,255,
1370 255,255,255,255,255,255,255,255,
1371 255,255,255,255,255,255,255,255,
1372 255,255,255,255,255,255,255,255,
1373 255,255,255,255,255,255,255,255,
1374 255,255,255,255,255,255,255,255,
1375 255,255,255,255,255,255,255,255,
1376 255,255,255,255,255,255};
1377
1378const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
1379 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1380 0x01,0x02,0x03,0x04,2,0,0,0,
1381 0xf4,0x87,0xba,0xf3,
1382 255,
1383 255,255,255,255,255,255,255,255,
1384 255,255,255,255,255,255,255,255,
1385 255,255,255,255,255,255,255,255,
1386 255,255,255,255,255,255,255,255,
1387 255,255,255,255,255,255,255,255,
1388 255,255,255,255,255,255,255,255,
1389 255,255,255,255,255,255,255,255,
1390 255,255,255,255,255,255,255,255,
1391 255,255,255,255,255,255,255,255,
1392 255,255,255,255,255,255,255,255,
1393 255,255,255,255,255,255,255,255,
1394 255,255,255,255,255,255,255,255,
1395 255,255,255,255,255,255,255,255,
1396 255,255,255,255,255,255,255,255,
1397 255,255,255,255,255,255,255,255,
1398 255,255,255,255,255,255,255,255,
1399 255,255,255,255,255,255,255,255,
1400 255,255,255,255,255,255,255,255,
1401 255,255,255,255,255,255,255,255,
1402 255,255,255,255,255,255,255,255,
1403 255,255,255,255,255,255,255,255,
1404 255,255,255,255,255,255,255,255,
1405 255,255,255,255,255,255,255,255,
1406 255,255,255,255,255,255,255,255,
1407 255,255,255,255,255,255,255,255,
1408 255,255,255,255,255,255,255,255,
1409 255,255,255,255,255,255,255,255,
1410 255,255,255,255,255,255,255,255,
1411 255,255,255,255,255,255,255,255,
1412 255,255,255,255,255,255,255,255,
1413 255,255,255,255,255,255,255,255,
1414 255,255,255,255,255,255,255};
1415
1416const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
1417 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1418 0x01,0x02,0x03,0x04,3,0,0,0,
1419 0xf7,0x2f,0x6c,0x60,
1420 5,
1421 254,255,4,255,0};
1422
1423/* packet that overspans over an entire page */
1424const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
1425 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1426 0x01,0x02,0x03,0x04,0,0,0,0,
1427 0xff,0x7b,0x23,0x17,
1428 1,
1429 0};
1430
1431const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
1432 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1433 0x01,0x02,0x03,0x04,1,0,0,0,
1434 0x68,0x22,0x7c,0x3d,
1435 255,
1436 100,
1437 255,255,255,255,255,255,255,255,
1438 255,255,255,255,255,255,255,255,
1439 255,255,255,255,255,255,255,255,
1440 255,255,255,255,255,255,255,255,
1441 255,255,255,255,255,255,255,255,
1442 255,255,255,255,255,255,255,255,
1443 255,255,255,255,255,255,255,255,
1444 255,255,255,255,255,255,255,255,
1445 255,255,255,255,255,255,255,255,
1446 255,255,255,255,255,255,255,255,
1447 255,255,255,255,255,255,255,255,
1448 255,255,255,255,255,255,255,255,
1449 255,255,255,255,255,255,255,255,
1450 255,255,255,255,255,255,255,255,
1451 255,255,255,255,255,255,255,255,
1452 255,255,255,255,255,255,255,255,
1453 255,255,255,255,255,255,255,255,
1454 255,255,255,255,255,255,255,255,
1455 255,255,255,255,255,255,255,255,
1456 255,255,255,255,255,255,255,255,
1457 255,255,255,255,255,255,255,255,
1458 255,255,255,255,255,255,255,255,
1459 255,255,255,255,255,255,255,255,
1460 255,255,255,255,255,255,255,255,
1461 255,255,255,255,255,255,255,255,
1462 255,255,255,255,255,255,255,255,
1463 255,255,255,255,255,255,255,255,
1464 255,255,255,255,255,255,255,255,
1465 255,255,255,255,255,255,255,255,
1466 255,255,255,255,255,255,255,255,
1467 255,255,255,255,255,255,255,255,
1468 255,255,255,255,255,255};
1469
1470const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
1471 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1472 0x01,0x02,0x03,0x04,2,0,0,0,
1473 0xd4,0xe0,0x60,0xe5,
1474 1,
1475 0};
1476
1477void test_pack(const int *pl, const int **headers, int byteskip,
1478 int pageskip, int packetskip){
1479 unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
1480 long inptr=0;
1481 long outptr=0;
1482 long deptr=0;
1483 long depacket=0;
1484 long granule_pos=7,pageno=0;
1485 int i,j,packets,pageout=pageskip;
1486 int eosflag=0;
1487 int bosflag=0;
1488
1489 int byteskipcount=0;
1490
1491 ogg_stream_reset(&os_en);
1492 ogg_stream_reset(&os_de);
1493 ogg_sync_reset(&oy);
1494
1495 for(packets=0;packets<packetskip;packets++)
1496 depacket+=pl[packets];
1497
1498 for(packets=0;;packets++)if(pl[packets]==-1)break;
1499
1500 for(i=0;i<packets;i++){
1501 /* construct a test packet */
1502 ogg_packet op;
1503 int len=pl[i];
1504
1505 op.packet=data+inptr;
1506 op.bytes=len;
1507 op.e_o_s=(pl[i+1]<0?1:0);
1508 op.granulepos=granule_pos;
1509
1510 granule_pos+=1024;
1511
1512 for(j=0;j<len;j++)data[inptr++]=i+j;
1513
1514 /* submit the test packet */
1515 ogg_stream_packetin(&os_en,&op);
1516
1517 /* retrieve any finished pages */
1518 {
1519 ogg_page og;
1520
1521 while(ogg_stream_pageout(&os_en,&og)){
1522 /* We have a page. Check it carefully */
1523
1524 fprintf(stderr,"%ld, ",pageno);
1525
1526 if(headers[pageno]==NULL){
1527 fprintf(stderr,"coded too many pages!\n");
1528 exit(1);
1529 }
1530
1531 check_page(data+outptr,headers[pageno],&og);
1532
1533 outptr+=og.body_len;
1534 pageno++;
1535 if(pageskip){
1536 bosflag=1;
1537 pageskip--;
1538 deptr+=og.body_len;
1539 }
1540
1541 /* have a complete page; submit it to sync/decode */
1542
1543 {
1544 ogg_page og_de;
1545 ogg_packet op_de,op_de2;
1546 char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
1547 char *next=buf;
1548 byteskipcount+=og.header_len;
1549 if(byteskipcount>byteskip){
1550 memcpy(next,og.header,byteskipcount-byteskip);
1551 next+=byteskipcount-byteskip;
1552 byteskipcount=byteskip;
1553 }
1554
1555 byteskipcount+=og.body_len;
1556 if(byteskipcount>byteskip){
1557 memcpy(next,og.body,byteskipcount-byteskip);
1558 next+=byteskipcount-byteskip;
1559 byteskipcount=byteskip;
1560 }
1561
1562 ogg_sync_wrote(&oy,next-buf);
1563
1564 while(1){
1565 int ret=ogg_sync_pageout(&oy,&og_de);
1566 if(ret==0)break;
1567 if(ret<0)continue;
1568 /* got a page. Happy happy. Verify that it's good. */
1569
1570 fprintf(stderr,"(%d), ",pageout);
1571
1572 check_page(data+deptr,headers[pageout],&og_de);
1573 deptr+=og_de.body_len;
1574 pageout++;
1575
1576 /* submit it to deconstitution */
1577 ogg_stream_pagein(&os_de,&og_de);
1578
1579 /* packets out? */
1580 while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
1581 ogg_stream_packetpeek(&os_de,NULL);
1582 ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
1583
1584 /* verify peek and out match */
1585 if(memcmp(&op_de,&op_de2,sizeof(op_de))){
1586 fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
1587 depacket);
1588 exit(1);
1589 }
1590
1591 /* verify the packet! */
1592 /* check data */
1593 if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
1594 fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
1595 depacket);
1596 exit(1);
1597 }
1598 /* check bos flag */
1599 if(bosflag==0 && op_de.b_o_s==0){
1600 fprintf(stderr,"b_o_s flag not set on packet!\n");
1601 exit(1);
1602 }
1603 if(bosflag && op_de.b_o_s){
1604 fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
1605 exit(1);
1606 }
1607 bosflag=1;
1608 depacket+=op_de.bytes;
1609
1610 /* check eos flag */
1611 if(eosflag){
1612 fprintf(stderr,"Multiple decoded packets with eos flag!\n");
1613 exit(1);
1614 }
1615
1616 if(op_de.e_o_s)eosflag=1;
1617
1618 /* check granulepos flag */
1619 if(op_de.granulepos!=-1){
1620 fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
1621 }
1622 }
1623 }
1624 }
1625 }
1626 }
1627 }
1628 _ogg_free(data);
1629 if(headers[pageno]!=NULL){
1630 fprintf(stderr,"did not write last page!\n");
1631 exit(1);
1632 }
1633 if(headers[pageout]!=NULL){
1634 fprintf(stderr,"did not decode last page!\n");
1635 exit(1);
1636 }
1637 if(inptr!=outptr){
1638 fprintf(stderr,"encoded page data incomplete!\n");
1639 exit(1);
1640 }
1641 if(inptr!=deptr){
1642 fprintf(stderr,"decoded page data incomplete!\n");
1643 exit(1);
1644 }
1645 if(inptr!=depacket){
1646 fprintf(stderr,"decoded packet data incomplete!\n");
1647 exit(1);
1648 }
1649 if(!eosflag){
1650 fprintf(stderr,"Never got a packet with EOS set!\n");
1651 exit(1);
1652 }
1653 fprintf(stderr,"ok.\n");
1654}
1655
1656int main(void){
1657
1658 ogg_stream_init(&os_en,0x04030201);
1659 ogg_stream_init(&os_de,0x04030201);
1660 ogg_sync_init(&oy);
1661
1662 /* Exercise each code path in the framing code. Also verify that
1663 the checksums are working. */
1664
1665 {
1666 /* 17 only */
1667 const int packets[]={17, -1};
1668 const int *headret[]={head1_0,NULL};
1669
1670 fprintf(stderr,"testing single page encoding... ");
1671 test_pack(packets,headret,0,0,0);
1672 }
1673
1674 {
1675 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1676 const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
1677 const int *headret[]={head1_1,head2_1,NULL};
1678
1679 fprintf(stderr,"testing basic page encoding... ");
1680 test_pack(packets,headret,0,0,0);
1681 }
1682
1683 {
1684 /* nil packets; beginning,middle,end */
1685 const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
1686 const int *headret[]={head1_2,head2_2,NULL};
1687
1688 fprintf(stderr,"testing basic nil packets... ");
1689 test_pack(packets,headret,0,0,0);
1690 }
1691
1692 {
1693 /* large initial packet */
1694 const int packets[]={4345,259,255,-1};
1695 const int *headret[]={head1_3,head2_3,NULL};
1696
1697 fprintf(stderr,"testing initial-packet lacing > 4k... ");
1698 test_pack(packets,headret,0,0,0);
1699 }
1700
1701 {
1702 /* continuing packet test; with page spill expansion, we have to
1703 overflow the lacing table. */
1704 const int packets[]={0,65500,259,255,-1};
1705 const int *headret[]={head1_4,head2_4,head3_4,NULL};
1706
1707 fprintf(stderr,"testing single packet page span... ");
1708 test_pack(packets,headret,0,0,0);
1709 }
1710
1711 {
1712 /* spill expand packet test */
1713 const int packets[]={0,4345,259,255,0,0,-1};
1714 const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
1715
1716 fprintf(stderr,"testing page spill expansion... ");
1717 test_pack(packets,headret,0,0,0);
1718 }
1719
1720 /* page with the 255 segment limit */
1721 {
1722
1723 const int packets[]={0,10,10,10,10,10,10,10,10,
1724 10,10,10,10,10,10,10,10,
1725 10,10,10,10,10,10,10,10,
1726 10,10,10,10,10,10,10,10,
1727 10,10,10,10,10,10,10,10,
1728 10,10,10,10,10,10,10,10,
1729 10,10,10,10,10,10,10,10,
1730 10,10,10,10,10,10,10,10,
1731 10,10,10,10,10,10,10,10,
1732 10,10,10,10,10,10,10,10,
1733 10,10,10,10,10,10,10,10,
1734 10,10,10,10,10,10,10,10,
1735 10,10,10,10,10,10,10,10,
1736 10,10,10,10,10,10,10,10,
1737 10,10,10,10,10,10,10,10,
1738 10,10,10,10,10,10,10,10,
1739 10,10,10,10,10,10,10,10,
1740 10,10,10,10,10,10,10,10,
1741 10,10,10,10,10,10,10,10,
1742 10,10,10,10,10,10,10,10,
1743 10,10,10,10,10,10,10,10,
1744 10,10,10,10,10,10,10,10,
1745 10,10,10,10,10,10,10,10,
1746 10,10,10,10,10,10,10,10,
1747 10,10,10,10,10,10,10,10,
1748 10,10,10,10,10,10,10,10,
1749 10,10,10,10,10,10,10,10,
1750 10,10,10,10,10,10,10,10,
1751 10,10,10,10,10,10,10,10,
1752 10,10,10,10,10,10,10,10,
1753 10,10,10,10,10,10,10,10,
1754 10,10,10,10,10,10,10,50,-1};
1755 const int *headret[]={head1_5,head2_5,head3_5,NULL};
1756
1757 fprintf(stderr,"testing max packet segments... ");
1758 test_pack(packets,headret,0,0,0);
1759 }
1760
1761 {
1762 /* packet that overspans over an entire page */
1763 const int packets[]={0,100,130049,259,255,-1};
1764 const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1765
1766 fprintf(stderr,"testing very large packets... ");
1767 test_pack(packets,headret,0,0,0);
1768 }
1769
1770 {
1771 /* test for the libogg 1.1.1 resync in large continuation bug
1772 found by Josh Coalson) */
1773 const int packets[]={0,100,130049,259,255,-1};
1774 const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1775
1776 fprintf(stderr,"testing continuation resync in very large packets... ");
1777 test_pack(packets,headret,100,2,3);
1778 }
1779
1780 {
1781 /* term only page. why not? */
1782 const int packets[]={0,100,64770,-1};
1783 const int *headret[]={head1_7,head2_7,head3_7,NULL};
1784
1785 fprintf(stderr,"testing zero data page (1 nil packet)... ");
1786 test_pack(packets,headret,0,0,0);
1787 }
1788
1789
1790
1791 {
1792 /* build a bunch of pages for testing */
1793 unsigned char *data=_ogg_malloc(1024*1024);
1794 int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
1795 int inptr=0,i,j;
1796 ogg_page og[5];
1797
1798 ogg_stream_reset(&os_en);
1799
1800 for(i=0;pl[i]!=-1;i++){
1801 ogg_packet op;
1802 int len=pl[i];
1803
1804 op.packet=data+inptr;
1805 op.bytes=len;
1806 op.e_o_s=(pl[i+1]<0?1:0);
1807 op.granulepos=(i+1)*1000;
1808
1809 for(j=0;j<len;j++)data[inptr++]=i+j;
1810 ogg_stream_packetin(&os_en,&op);
1811 }
1812
1813 _ogg_free(data);
1814
1815 /* retrieve finished pages */
1816 for(i=0;i<5;i++){
1817 if(ogg_stream_pageout(&os_en,&og[i])==0){
1818 fprintf(stderr,"Too few pages output building sync tests!\n");
1819 exit(1);
1820 }
1821 copy_page(&og[i]);
1822 }
1823
1824 /* Test lost pages on pagein/packetout: no rollback */
1825 {
1826 ogg_page temp;
1827 ogg_packet test;
1828
1829 fprintf(stderr,"Testing loss of pages... ");
1830
1831 ogg_sync_reset(&oy);
1832 ogg_stream_reset(&os_de);
1833 for(i=0;i<5;i++){
1834 memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1835 og[i].header_len);
1836 ogg_sync_wrote(&oy,og[i].header_len);
1837 memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1838 ogg_sync_wrote(&oy,og[i].body_len);
1839 }
1840
1841 ogg_sync_pageout(&oy,&temp);
1842 ogg_stream_pagein(&os_de,&temp);
1843 ogg_sync_pageout(&oy,&temp);
1844 ogg_stream_pagein(&os_de,&temp);
1845 ogg_sync_pageout(&oy,&temp);
1846 /* skip */
1847 ogg_sync_pageout(&oy,&temp);
1848 ogg_stream_pagein(&os_de,&temp);
1849
1850 /* do we get the expected results/packets? */
1851
1852 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1853 checkpacket(&test,0,0,0);
1854 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1855 checkpacket(&test,1,1,-1);
1856 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1857 checkpacket(&test,1,2,-1);
1858 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1859 checkpacket(&test,98,3,-1);
1860 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1861 checkpacket(&test,4079,4,5000);
1862 if(ogg_stream_packetout(&os_de,&test)!=-1){
1863 fprintf(stderr,"Error: loss of page did not return error\n");
1864 exit(1);
1865 }
1866 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1867 checkpacket(&test,76,9,-1);
1868 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1869 checkpacket(&test,34,10,-1);
1870 fprintf(stderr,"ok.\n");
1871 }
1872
1873 /* Test lost pages on pagein/packetout: rollback with continuation */
1874 {
1875 ogg_page temp;
1876 ogg_packet test;
1877
1878 fprintf(stderr,"Testing loss of pages (rollback required)... ");
1879
1880 ogg_sync_reset(&oy);
1881 ogg_stream_reset(&os_de);
1882 for(i=0;i<5;i++){
1883 memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1884 og[i].header_len);
1885 ogg_sync_wrote(&oy,og[i].header_len);
1886 memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1887 ogg_sync_wrote(&oy,og[i].body_len);
1888 }
1889
1890 ogg_sync_pageout(&oy,&temp);
1891 ogg_stream_pagein(&os_de,&temp);
1892 ogg_sync_pageout(&oy,&temp);
1893 ogg_stream_pagein(&os_de,&temp);
1894 ogg_sync_pageout(&oy,&temp);
1895 ogg_stream_pagein(&os_de,&temp);
1896 ogg_sync_pageout(&oy,&temp);
1897 /* skip */
1898 ogg_sync_pageout(&oy,&temp);
1899 ogg_stream_pagein(&os_de,&temp);
1900
1901 /* do we get the expected results/packets? */
1902
1903 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1904 checkpacket(&test,0,0,0);
1905 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1906 checkpacket(&test,1,1,-1);
1907 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1908 checkpacket(&test,1,2,-1);
1909 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1910 checkpacket(&test,98,3,-1);
1911 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1912 checkpacket(&test,4079,4,5000);
1913 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1914 checkpacket(&test,1,5,-1);
1915 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1916 checkpacket(&test,1,6,-1);
1917 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1918 checkpacket(&test,2954,7,-1);
1919 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1920 checkpacket(&test,2057,8,9000);
1921 if(ogg_stream_packetout(&os_de,&test)!=-1){
1922 fprintf(stderr,"Error: loss of page did not return error\n");
1923 exit(1);
1924 }
1925 if(ogg_stream_packetout(&os_de,&test)!=1)error();
1926 checkpacket(&test,300,17,18000);
1927 fprintf(stderr,"ok.\n");
1928 }
1929
1930 /* the rest only test sync */
1931 {
1932 ogg_page og_de;
1933 /* Test fractional page inputs: incomplete capture */
1934 fprintf(stderr,"Testing sync on partial inputs... ");
1935 ogg_sync_reset(&oy);
1936 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1937 3);
1938 ogg_sync_wrote(&oy,3);
1939 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1940
1941 /* Test fractional page inputs: incomplete fixed header */
1942 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
1943 20);
1944 ogg_sync_wrote(&oy,20);
1945 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1946
1947 /* Test fractional page inputs: incomplete header */
1948 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
1949 5);
1950 ogg_sync_wrote(&oy,5);
1951 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1952
1953 /* Test fractional page inputs: incomplete body */
1954
1955 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
1956 og[1].header_len-28);
1957 ogg_sync_wrote(&oy,og[1].header_len-28);
1958 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1959
1960 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
1961 ogg_sync_wrote(&oy,1000);
1962 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1963
1964 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
1965 og[1].body_len-1000);
1966 ogg_sync_wrote(&oy,og[1].body_len-1000);
1967 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1968
1969 fprintf(stderr,"ok.\n");
1970 }
1971
1972 /* Test fractional page inputs: page + incomplete capture */
1973 {
1974 ogg_page og_de;
1975 fprintf(stderr,"Testing sync on 1+partial inputs... ");
1976 ogg_sync_reset(&oy);
1977
1978 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1979 og[1].header_len);
1980 ogg_sync_wrote(&oy,og[1].header_len);
1981
1982 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1983 og[1].body_len);
1984 ogg_sync_wrote(&oy,og[1].body_len);
1985
1986 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1987 20);
1988 ogg_sync_wrote(&oy,20);
1989 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1990 if(ogg_sync_pageout(&oy,&og_de)>0)error();
1991
1992 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
1993 og[1].header_len-20);
1994 ogg_sync_wrote(&oy,og[1].header_len-20);
1995 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1996 og[1].body_len);
1997 ogg_sync_wrote(&oy,og[1].body_len);
1998 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1999
2000 fprintf(stderr,"ok.\n");
2001 }
2002
2003 /* Test recapture: garbage + page */
2004 {
2005 ogg_page og_de;
2006 fprintf(stderr,"Testing search for capture... ");
2007 ogg_sync_reset(&oy);
2008
2009 /* 'garbage' */
2010 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2011 og[1].body_len);
2012 ogg_sync_wrote(&oy,og[1].body_len);
2013
2014 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2015 og[1].header_len);
2016 ogg_sync_wrote(&oy,og[1].header_len);
2017
2018 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2019 og[1].body_len);
2020 ogg_sync_wrote(&oy,og[1].body_len);
2021
2022 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2023 20);
2024 ogg_sync_wrote(&oy,20);
2025 if(ogg_sync_pageout(&oy,&og_de)>0)error();
2026 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2027 if(ogg_sync_pageout(&oy,&og_de)>0)error();
2028
2029 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
2030 og[2].header_len-20);
2031 ogg_sync_wrote(&oy,og[2].header_len-20);
2032 memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2033 og[2].body_len);
2034 ogg_sync_wrote(&oy,og[2].body_len);
2035 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2036
2037 fprintf(stderr,"ok.\n");
2038 }
2039
2040 /* Test recapture: page + garbage + page */
2041 {
2042 ogg_page og_de;
2043 fprintf(stderr,"Testing recapture... ");
2044 ogg_sync_reset(&oy);
2045
2046 memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2047 og[1].header_len);
2048 ogg_sync_wrote(&oy,og[1].header_len);
2049
2050 memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2051 og[1].body_len);
2052 ogg_sync_wrote(&oy,og[1].body_len);
2053
2054 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2055 og[2].header_len);
2056 ogg_sync_wrote(&oy,og[2].header_len);
2057
2058 memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2059 og[2].header_len);
2060 ogg_sync_wrote(&oy,og[2].header_len);
2061
2062 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2063
2064 memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2065 og[2].body_len-5);
2066 ogg_sync_wrote(&oy,og[2].body_len-5);
2067
2068 memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
2069 og[3].header_len);
2070 ogg_sync_wrote(&oy,og[3].header_len);
2071
2072 memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
2073 og[3].body_len);
2074 ogg_sync_wrote(&oy,og[3].body_len);
2075
2076 if(ogg_sync_pageout(&oy,&og_de)>0)error();
2077 if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2078
2079 fprintf(stderr,"ok.\n");
2080 }
2081
2082 /* Free page data that was previously copied */
2083 {
2084 for(i=0;i<5;i++){
2085 free_page(&og[i]);
2086 }
2087 }
2088 }
2089
2090 return(0);
1066} 2091}
1067 2092
2093#endif
2094
2095
2096
2097
diff --git a/apps/codecs/libtremor/info.c b/apps/codecs/libtremor/info.c
index 9bfa7d03b0..f3ac5f87f6 100644
--- a/apps/codecs/libtremor/info.c
+++ b/apps/codecs/libtremor/info.c
@@ -240,7 +240,7 @@ int vorbis_synthesis_idheader(ogg_packet *op){
240 char buffer[6]; 240 char buffer[6];
241 241
242 if(op){ 242 if(op){
243 oggpack_readinit(&opb,op->packet); 243 oggpack_readinit(&opb,op->packet,op->bytes);
244 244
245 if(!op->b_o_s) 245 if(!op->b_o_s)
246 return(0); /* Not the initial packet */ 246 return(0); /* Not the initial packet */
@@ -268,7 +268,7 @@ int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op)
268 oggpack_buffer opb; 268 oggpack_buffer opb;
269 269
270 if(op){ 270 if(op){
271 oggpack_readinit(&opb,op->packet); 271 oggpack_readinit(&opb,op->packet,op->bytes);
272 272
273 /* Which of the three types of header is this? */ 273 /* Which of the three types of header is this? */
274 /* Also verify header-ness, vorbis */ 274 /* Also verify header-ness, vorbis */
diff --git a/apps/codecs/libtremor/ivorbisfile.h b/apps/codecs/libtremor/ivorbisfile.h
index 39a648961a..1aeb0ca84b 100644
--- a/apps/codecs/libtremor/ivorbisfile.h
+++ b/apps/codecs/libtremor/ivorbisfile.h
@@ -56,7 +56,7 @@ typedef struct OggVorbis_File {
56 int seekable; 56 int seekable;
57 ogg_int64_t offset; 57 ogg_int64_t offset;
58 ogg_int64_t end; 58 ogg_int64_t end;
59 ogg_sync_state *oy; 59 ogg_sync_state oy;
60 60
61 /* If the FILE handle isn't seekable (eg, a pipe), only the current 61 /* If the FILE handle isn't seekable (eg, a pipe), only the current
62 stream appears */ 62 stream appears */
@@ -77,7 +77,7 @@ typedef struct OggVorbis_File {
77 ogg_int64_t bittrack; 77 ogg_int64_t bittrack;
78 ogg_int64_t samptrack; 78 ogg_int64_t samptrack;
79 79
80 ogg_stream_state *os; /* take physical pages, weld into a logical 80 ogg_stream_state os; /* take physical pages, weld into a logical
81 stream of packets */ 81 stream of packets */
82 vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ 82 vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
83 vorbis_block vb; /* local working space for packet->PCM decode */ 83 vorbis_block vb; /* local working space for packet->PCM decode */
@@ -87,13 +87,11 @@ typedef struct OggVorbis_File {
87} OggVorbis_File; 87} OggVorbis_File;
88 88
89extern int ov_clear(OggVorbis_File *vf); 89extern int ov_clear(OggVorbis_File *vf);
90 //extern int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
91extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf, 90extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf,
92 char *initial, long ibytes, ov_callbacks callbacks); 91 const char *initial, long ibytes, ov_callbacks callbacks);
93 92
94 //extern int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
95extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf, 93extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf,
96 char *initial, long ibytes, ov_callbacks callbacks); 94 const char *initial, long ibytes, ov_callbacks callbacks);
97extern int ov_test_open(OggVorbis_File *vf); 95extern int ov_test_open(OggVorbis_File *vf);
98 96
99extern long ov_bitrate(OggVorbis_File *vf,int i); 97extern long ov_bitrate(OggVorbis_File *vf,int i);
diff --git a/apps/codecs/libtremor/ogg.h b/apps/codecs/libtremor/ogg.h
index 15ca46b3cd..da072184b4 100644
--- a/apps/codecs/libtremor/ogg.h
+++ b/apps/codecs/libtremor/ogg.h
@@ -1,17 +1,17 @@
1/******************************************************************** 1/********************************************************************
2 * * 2 * *
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * 3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * *
5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * * 7 * *
9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * 8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * 9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 * * 10 * *
12 ******************************************************************** 11 ********************************************************************
13 12
14 function: subsumed libogg includes 13 function: toplevel libogg include
14 last mod: $Id$
15 15
16 ********************************************************************/ 16 ********************************************************************/
17#ifndef _OGG_H 17#ifndef _OGG_H
@@ -21,241 +21,238 @@
21extern "C" { 21extern "C" {
22#endif 22#endif
23 23
24#include <stddef.h>
24#include "os_types.h" 25#include "os_types.h"
25 26
26typedef struct ogg_buffer_state{ 27extern const unsigned long mask[] ICONST_ATTR;
27 struct ogg_buffer *unused_buffers;
28 struct ogg_reference *unused_references;
29 int outstanding;
30 int shutdown;
31} ogg_buffer_state;
32
33typedef struct ogg_buffer {
34 unsigned char *data;
35 long size;
36 int refcount;
37
38 union {
39 ogg_buffer_state *owner;
40 struct ogg_buffer *next;
41 } ptr;
42} ogg_buffer;
43
44typedef struct ogg_reference {
45 ogg_buffer *buffer;
46 long begin;
47 long length;
48
49 struct ogg_reference *next;
50} ogg_reference;
51
52typedef struct oggpack_buffer {
53 int headbit;
54 unsigned char *headptr;
55 long headend;
56
57 /* memory management */
58 ogg_reference *head;
59 ogg_reference *tail;
60
61 /* render the byte/bit counter API constant time */
62 long count; /* doesn't count the tail */
63} oggpack_buffer;
64 28
65typedef struct oggbyte_buffer { 29typedef struct {
66 ogg_reference *baseref; 30 void *iov_base;
31 size_t iov_len;
32} ogg_iovec_t;
33
34typedef struct {
35 long endbyte;
36 int endbit;
67 37
68 ogg_reference *ref; 38 unsigned char *buffer;
69 unsigned char *ptr; 39 unsigned char *ptr;
70 long pos; 40 long storage;
71 long end; 41} oggpack_buffer;
72} oggbyte_buffer;
73 42
74typedef struct ogg_sync_state { 43/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
75 /* decode memory management pool */
76 ogg_buffer_state *bufferpool;
77 44
78 /* stream buffers */ 45typedef struct {
79 ogg_reference *fifo_head; 46 unsigned char *header;
80 ogg_reference *fifo_tail; 47 long header_len;
81 long fifo_fill; 48 unsigned char *body;
49 long body_len;
50} ogg_page;
82 51
83 /* stream sync management */ 52/* ogg_stream_state contains the current encode/decode state of a logical
84 int unsynced; 53 Ogg bitstream **********************************************************/
85 int headerbytes;
86 int bodybytes;
87 54
88} ogg_sync_state; 55typedef struct {
56 unsigned char *body_data; /* bytes from packet bodies */
57 long body_storage; /* storage elements allocated */
58 long body_fill; /* elements stored; fill mark */
59 long body_returned; /* elements of fill returned */
60
61
62 int *lacing_vals; /* The values that will go to the segment table */
63 ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
64 this way, but it is simple coupled to the
65 lacing fifo */
66 long lacing_storage;
67 long lacing_fill;
68 long lacing_packet;
69 long lacing_returned;
70
71#if 0
72 unsigned char header[282]; /* working space for header encode */
73 int header_fill;
74#endif
75 int e_o_s; /* set when we have buffered the last packet in the
76 logical bitstream */
77 int b_o_s; /* set after we've written the initial page
78 of a logical bitstream */
79 ogg_uint32_t serialno;
80 long pageno;
81 ogg_int64_t packetno; /* sequence number for decode; the framing
82 knows where there's a hole in the data,
83 but we need coupling so that the codec
84 (which is in a separate abstraction
85 layer) also knows about the gap */
86 ogg_int64_t granulepos;
89 87
90typedef struct ogg_stream_state {
91 ogg_reference *header_head;
92 ogg_reference *header_tail;
93 ogg_reference *body_head;
94 ogg_reference *body_tail;
95
96 int e_o_s; /* set when we have buffered the last
97 packet in the logical bitstream */
98 int b_o_s; /* set after we've written the initial page
99 of a logical bitstream */
100 long serialno;
101 long pageno;
102 ogg_int64_t packetno; /* sequence number for decode; the framing
103 knows where there's a hole in the data,
104 but we need coupling so that the codec
105 (which is in a seperate abstraction
106 layer) also knows about the gap */
107 ogg_int64_t granulepos;
108
109 int lacing_fill;
110 ogg_uint32_t body_fill;
111
112 /* decode-side state data */
113 int holeflag;
114 int spanflag;
115 int clearflag;
116 int laceptr;
117 ogg_uint32_t body_fill_next;
118
119} ogg_stream_state; 88} ogg_stream_state;
120 89
90/* ogg_packet is used to encapsulate the data and metadata belonging
91 to a single raw Ogg/Vorbis packet *************************************/
92
121typedef struct { 93typedef struct {
122 ogg_reference *packet; 94 unsigned char *packet;
123 long bytes; 95 long bytes;
124 long b_o_s; 96 long b_o_s;
125 long e_o_s; 97 long e_o_s;
126 ogg_int64_t granulepos; 98
127 ogg_int64_t packetno; /* sequence number for decode; the framing 99 ogg_int64_t granulepos;
128 knows where there's a hole in the data, 100
129 but we need coupling so that the codec 101 ogg_int64_t packetno; /* sequence number for decode; the framing
130 (which is in a seperate abstraction 102 knows where there's a hole in the data,
131 layer) also knows about the gap */ 103 but we need coupling so that the codec
104 (which is in a separate abstraction
105 layer) also knows about the gap */
132} ogg_packet; 106} ogg_packet;
133 107
134typedef struct { 108typedef struct {
135 ogg_reference *header; 109 unsigned char *data;
136 int header_len; 110 int storage;
137 ogg_reference *body; 111 int fill;
138 long body_len; 112 int returned;
139} ogg_page; 113
114 int unsynced;
115 int headerbytes;
116 int bodybytes;
117} ogg_sync_state;
140 118
141/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ 119/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
120/*
121extern void oggpack_writeinit(oggpack_buffer *b);
122extern int oggpack_writecheck(oggpack_buffer *b);
123extern void oggpack_writetrunc(oggpack_buffer *b,long bits);
124extern void oggpack_writealign(oggpack_buffer *b);
125extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
126extern void oggpack_reset(oggpack_buffer *b);
127extern void oggpack_writeclear(oggpack_buffer *b); */
128extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
129/* extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits); */
130
131//extern long oggpack_look(oggpack_buffer *b,int bits);
132static inline long oggpack_look(oggpack_buffer *b,int bits){
133 unsigned long ret;
134 unsigned long m;
135
136 if(bits<0 || bits>32) return -1;
137 m=mask[bits];
138 bits+=b->endbit;
139
140 if(b->endbyte >= b->storage-4){
141 /* not the main path */
142 if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
143 /* special case to avoid reading b->ptr[0], which might be past the end of
144 the buffer; also skips some useless accounting */
145 else if(!bits)return(0L);
146 }
142 147
143extern void oggpack_readinit(oggpack_buffer *b,ogg_reference *r); 148 ret=b->ptr[0]>>b->endbit;
144extern long oggpack_look_full(oggpack_buffer *b,int bits); 149 if(bits>8){
145extern long oggpack_read(oggpack_buffer *b,register int bits); 150 ret|=b->ptr[1]<<(8-b->endbit);
146 151 if(bits>16){
147/* Inline a few, often called functions */ 152 ret|=b->ptr[2]<<(16-b->endbit);
148 153 if(bits>24){
149/* mark read process as having run off the end */ 154 ret|=b->ptr[3]<<(24-b->endbit);
150static inline void _adv_halt(oggpack_buffer *b){ 155 if(bits>32 && b->endbit)
151 b->headptr=b->head->buffer->data+b->head->begin+b->head->length; 156 ret|=b->ptr[4]<<(32-b->endbit);
152 b->headend=-1; 157 }
153 b->headbit=0;
154}
155
156/* spans forward, skipping as many bytes as headend is negative; if
157 headend is zero, simply finds next byte. If we're up to the end
158 of the buffer, leaves headend at zero. If we've read past the end,
159 halt the decode process. */
160static inline void _span(oggpack_buffer *b){
161 while(b->headend<1){
162 if(b->head->next){
163 b->count+=b->head->length;
164 b->head=b->head->next;
165 b->headptr=b->head->buffer->data+b->head->begin-b->headend;
166 b->headend+=b->head->length;
167 }else{
168 /* we've either met the end of decode, or gone past it. halt
169 only if we're past */
170 if(b->headend<0 || b->headbit)
171 /* read has fallen off the end */
172 _adv_halt(b);
173
174 break;
175 } 158 }
176 } 159 }
160 return(m&ret);
177} 161}
178 162
179/* limited to 32 at a time */ 163extern long oggpack_look1(oggpack_buffer *b);
164
165//extern void oggpack_adv(oggpack_buffer *b,int bits);
180static inline void oggpack_adv(oggpack_buffer *b,int bits){ 166static inline void oggpack_adv(oggpack_buffer *b,int bits){
181 bits+=b->headbit; 167 bits+=b->endbit;
182 b->headbit=bits&7;
183 b->headptr+=bits/8;
184 if((b->headend-=((unsigned)bits)/8)<1)_span(b);
185}
186 168
187static inline long oggpack_look(oggpack_buffer *b, int bits){ 169 if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
188 if(bits+b->headbit < b->headend<<3){ 170
189 extern const unsigned long oggpack_mask[]; 171 b->ptr+=bits/8;
190 unsigned long m=oggpack_mask[bits]; 172 b->endbyte+=bits/8;
191 unsigned long ret=-1; 173 b->endbit=bits&7;
192 174 return;
193 bits+=b->headbit; 175
194 ret=b->headptr[0]>>b->headbit; 176 overflow:
195 if(bits>8){ 177 b->ptr=NULL;
196 ret|=b->headptr[1]<<(8-b->headbit); 178 b->endbyte=b->storage;
197 if(bits>16){ 179 b->endbit=1;
198 ret|=b->headptr[2]<<(16-b->headbit);
199 if(bits>24){
200 ret|=b->headptr[3]<<(24-b->headbit);
201 if(bits>32 && b->headbit)
202 ret|=b->headptr[4]<<(32-b->headbit);
203 }
204 }
205 }
206 return ret&m;
207 }else{
208 return oggpack_look_full(b, bits);
209 }
210} 180}
211 181
182extern void oggpack_adv1(oggpack_buffer *b);
183extern long oggpack_read(oggpack_buffer *b,int bits);
184extern long oggpack_read1(oggpack_buffer *b);
185#if 0
186extern long oggpack_bytes(oggpack_buffer *b);
187extern long oggpack_bits(oggpack_buffer *b);
188extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);
189
190extern void oggpackB_writeinit(oggpack_buffer *b);
191extern int oggpackB_writecheck(oggpack_buffer *b);
192extern void oggpackB_writetrunc(oggpack_buffer *b,long bits);
193extern void oggpackB_writealign(oggpack_buffer *b);
194extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits);
195extern void oggpackB_reset(oggpack_buffer *b);
196extern void oggpackB_writeclear(oggpack_buffer *b);
197extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
198extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits);
199extern long oggpackB_look(oggpack_buffer *b,int bits);
200extern long oggpackB_look1(oggpack_buffer *b);
201extern void oggpackB_adv(oggpack_buffer *b,int bits);
202extern void oggpackB_adv1(oggpack_buffer *b);
203extern long oggpackB_read(oggpack_buffer *b,int bits);
204extern long oggpackB_read1(oggpack_buffer *b);
205extern long oggpackB_bytes(oggpack_buffer *b);
206extern long oggpackB_bits(oggpack_buffer *b);
207extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b);
208# endif
209/* Ogg BITSTREAM PRIMITIVES: encoding **************************/
210#if 0
211extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
212extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov,
213 int count, long e_o_s, ogg_int64_t granulepos);
214extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
215extern int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill);
216extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
217#endif
212/* Ogg BITSTREAM PRIMITIVES: decoding **************************/ 218/* Ogg BITSTREAM PRIMITIVES: decoding **************************/
213 219
214extern ogg_sync_state *ogg_sync_create(void); 220extern int ogg_sync_init(ogg_sync_state *oy);
215extern int ogg_sync_destroy(ogg_sync_state *oy); 221extern int ogg_sync_clear(ogg_sync_state *oy);
216extern int ogg_sync_reset(ogg_sync_state *oy); 222extern int ogg_sync_reset(ogg_sync_state *oy);
223extern int ogg_sync_destroy(ogg_sync_state *oy);
224extern int ogg_sync_check(ogg_sync_state *oy);
217 225
218extern unsigned char *ogg_sync_bufferin(ogg_sync_state *oy, long size); 226extern char *ogg_sync_buffer(ogg_sync_state *oy, long size);
219extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); 227extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes);
220extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); 228extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
229extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
221extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); 230extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
222extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); 231extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
223extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); 232extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);
224 233
225/* Ogg BITSTREAM PRIMITIVES: general ***************************/ 234/* Ogg BITSTREAM PRIMITIVES: general ***************************/
226 235
227extern ogg_stream_state *ogg_stream_create(int serialno); 236extern int ogg_stream_init(ogg_stream_state *os,int serialno);
228extern int ogg_stream_destroy(ogg_stream_state *os); 237extern int ogg_stream_clear(ogg_stream_state *os);
229extern int ogg_stream_reset(ogg_stream_state *os); 238extern int ogg_stream_reset(ogg_stream_state *os);
230extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); 239extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
240extern int ogg_stream_destroy(ogg_stream_state *os);
241extern int ogg_stream_check(ogg_stream_state *os);
231extern int ogg_stream_eos(ogg_stream_state *os); 242extern int ogg_stream_eos(ogg_stream_state *os);
232 243
233extern int ogg_page_checksum_set(ogg_page *og); 244extern void ogg_page_checksum_set(ogg_page *og);
234
235extern int ogg_page_version(ogg_page *og);
236extern int ogg_page_continued(ogg_page *og);
237extern int ogg_page_bos(ogg_page *og);
238extern int ogg_page_eos(ogg_page *og);
239extern ogg_int64_t ogg_page_granulepos(ogg_page *og);
240extern ogg_uint32_t ogg_page_serialno(ogg_page *og);
241extern ogg_uint32_t ogg_page_pageno(ogg_page *og);
242extern int ogg_page_getbuffer(ogg_page *og, unsigned char **buffer);
243
244extern int ogg_packet_release(ogg_packet *op);
245extern int ogg_page_release(ogg_page *og);
246
247extern void ogg_page_dup(ogg_page *d, ogg_page *s);
248
249/* Ogg BITSTREAM PRIMITIVES: return codes ***************************/
250 245
251#define OGG_SUCCESS 0 246extern int ogg_page_version(const ogg_page *og);
247extern int ogg_page_continued(const ogg_page *og);
248extern int ogg_page_bos(const ogg_page *og);
249extern int ogg_page_eos(const ogg_page *og);
250extern ogg_int64_t ogg_page_granulepos(const ogg_page *og);
251extern ogg_uint32_t ogg_page_serialno(const ogg_page *og);
252extern long ogg_page_pageno(const ogg_page *og);
253extern int ogg_page_packets(const ogg_page *og);
252 254
253#define OGG_HOLE -10 255extern void ogg_packet_clear(ogg_packet *op);
254#define OGG_SPAN -11
255#define OGG_EVERSION -12
256#define OGG_ESERIAL -13
257#define OGG_EINVAL -14
258#define OGG_EEOS -15
259 256
260 257
261#ifdef __cplusplus 258#ifdef __cplusplus
diff --git a/apps/codecs/libtremor/synthesis.c b/apps/codecs/libtremor/synthesis.c
index 69180b7acf..c47f381592 100644
--- a/apps/codecs/libtremor/synthesis.c
+++ b/apps/codecs/libtremor/synthesis.c
@@ -37,7 +37,7 @@ static inline int _vorbis_synthesis1(vorbis_block *vb,ogg_packet *op,int decodep
37 37
38 /* first things first. Make sure decode is ready */ 38 /* first things first. Make sure decode is ready */
39 _vorbis_block_ripcord(vb); 39 _vorbis_block_ripcord(vb);
40 oggpack_readinit(opb,op->packet); 40 oggpack_readinit(opb,op->packet,op->bytes);
41 41
42 /* Check the packet type */ 42 /* Check the packet type */
43 if(oggpack_read(opb,1)!=0){ 43 if(oggpack_read(opb,1)!=0){
@@ -102,6 +102,8 @@ int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){
102 return _vorbis_synthesis1(vb,op,1); 102 return _vorbis_synthesis1(vb,op,1);
103} 103}
104 104
105/* used to track pcm position without actually performing decode.
106 Useful for sequential 'fast forward' */
105int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){ 107int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){
106 return _vorbis_synthesis1(vb,op,0); 108 return _vorbis_synthesis1(vb,op,0);
107} 109}
@@ -111,7 +113,7 @@ long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
111 oggpack_buffer opb; 113 oggpack_buffer opb;
112 int mode; 114 int mode;
113 115
114 oggpack_readinit(&opb,op->packet); 116 oggpack_readinit(&opb,op->packet,op->bytes);
115 117
116 /* Check the packet type */ 118 /* Check the packet type */
117 if(oggpack_read(&opb,1)!=0){ 119 if(oggpack_read(&opb,1)!=0){
diff --git a/apps/codecs/libtremor/vorbisfile.c b/apps/codecs/libtremor/vorbisfile.c
index 50a57affbd..9365ba344b 100644
--- a/apps/codecs/libtremor/vorbisfile.c
+++ b/apps/codecs/libtremor/vorbisfile.c
@@ -53,18 +53,19 @@
53 we only want coarse navigation through the stream. */ 53 we only want coarse navigation through the stream. */
54 54
55/************************************************************************* 55/*************************************************************************
56 * Many, many internal helpers. The intention is not to be confusing; 56 * Many, many internal helpers. The intention is not to be confusing;
57 * rampant duplication and monolithic function implementation would be 57 * rampant duplication and monolithic function implementation would be
58 * harder to understand anyway. The high level functions are last. Begin 58 * harder to understand anyway. The high level functions are last. Begin
59 * grokking near the end of the file */ 59 * grokking near the end of the file */
60 60
61 61
62/* read a little more data from the file/pipe into the ogg_sync framer */ 62/* read a little more data from the file/pipe into the ogg_sync framer */
63static long _get_data(OggVorbis_File *vf){ 63static long _get_data(OggVorbis_File *vf){
64 if(!(vf->callbacks.read_func))return(-1);
64 if(vf->datasource){ 65 if(vf->datasource){
65 char *buffer=(char *)ogg_sync_bufferin(vf->oy,CHUNKSIZE); 66 char *buffer=ogg_sync_buffer(&vf->oy,CHUNKSIZE);
66 long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource); 67 long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource);
67 if(bytes>0)ogg_sync_wrote(vf->oy,bytes); 68 if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
68 return(bytes); 69 return(bytes);
69 }else 70 }else
70 return(0); 71 return(0);
@@ -77,7 +78,7 @@ static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
77 (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1) 78 (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1)
78 return OV_EREAD; 79 return OV_EREAD;
79 vf->offset=offset; 80 vf->offset=offset;
80 ogg_sync_reset(vf->oy); 81 ogg_sync_reset(&vf->oy);
81 }else{ 82 }else{
82 /* shouldn't happen unless someone writes a broken callback */ 83 /* shouldn't happen unless someone writes a broken callback */
83 return OV_EFAULT; 84 return OV_EFAULT;
@@ -96,9 +97,7 @@ static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
96 n) search for a new page beginning for n bytes 97 n) search for a new page beginning for n bytes
97 98
98 return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD) 99 return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
99 n) found a page at absolute offset n 100 n) found a page at absolute offset n */
100
101 produces a refcounted page */
102 101
103static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og, 102static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
104 ogg_int64_t boundary){ 103 ogg_int64_t boundary){
@@ -107,8 +106,8 @@ static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
107 long more; 106 long more;
108 107
109 if(boundary>0 && vf->offset>=boundary)return(OV_FALSE); 108 if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
110 more=ogg_sync_pageseek(vf->oy,og); 109 more=ogg_sync_pageseek(&vf->oy,og);
111 110
112 if(more<0){ 111 if(more<0){
113 /* skipped n bytes */ 112 /* skipped n bytes */
114 vf->offset-=more; 113 vf->offset-=more;
@@ -127,7 +126,7 @@ static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
127 ogg_int64_t ret=vf->offset; 126 ogg_int64_t ret=vf->offset;
128 vf->offset+=more; 127 vf->offset+=more;
129 return(ret); 128 return(ret);
130 129
131 } 130 }
132 } 131 }
133 } 132 }
@@ -137,8 +136,7 @@ static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
137 position. Much dirtier than the above as Ogg doesn't have any 136 position. Much dirtier than the above as Ogg doesn't have any
138 backward search linkage. no 'readp' as it will certainly have to 137 backward search linkage. no 'readp' as it will certainly have to
139 read. */ 138 read. */
140/* returns offset or OV_EREAD, OV_FAULT and produces a refcounted page */ 139/* returns offset or OV_EREAD, OV_FAULT */
141
142static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){ 140static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
143 ogg_int64_t begin=vf->offset; 141 ogg_int64_t begin=vf->offset;
144 ogg_int64_t end=begin; 142 ogg_int64_t end=begin;
@@ -151,9 +149,10 @@ static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
151 begin=0; 149 begin=0;
152 150
153 ret=_seek_helper(vf,begin); 151 ret=_seek_helper(vf,begin);
154 if(ret)return(ret); 152 if(ret)return(ret);
155 153
156 while(vf->offset<end){ 154 while(vf->offset<end){
155 memset(og,0,sizeof(*og));
157 ret=_get_next_page(vf,og,end-vf->offset); 156 ret=_get_next_page(vf,og,end-vf->offset);
158 if(ret==OV_EREAD)return(OV_EREAD); 157 if(ret==OV_EREAD)return(OV_EREAD);
159 if(ret<0){ 158 if(ret<0){
@@ -168,7 +167,6 @@ static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
168 holding the last page. In multiplexed (or noncompliant streams), 167 holding the last page. In multiplexed (or noncompliant streams),
169 we will probably have to re-read the last page we saw */ 168 we will probably have to re-read the last page we saw */
170 if(og->header_len==0){ 169 if(og->header_len==0){
171 ogg_page_release(og);
172 ret=_seek_helper(vf,offset); 170 ret=_seek_helper(vf,offset);
173 if(ret)return(ret); 171 if(ret)return(ret);
174 172
@@ -219,14 +217,14 @@ static int _lookup_page_serialno(ogg_page *og, ogg_uint32_t *serialno_list, int
219static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf, 217static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
220 ogg_uint32_t *serial_list, int serial_n, 218 ogg_uint32_t *serial_list, int serial_n,
221 int *serialno, ogg_int64_t *granpos){ 219 int *serialno, ogg_int64_t *granpos){
222 ogg_page og={0,0,0,0}; 220 ogg_page og;
223 ogg_int64_t begin=vf->offset; 221 ogg_int64_t begin=vf->offset;
224 ogg_int64_t end=begin; 222 ogg_int64_t end=begin;
225 ogg_int64_t ret; 223 ogg_int64_t ret;
226 224
227 ogg_int64_t prefoffset=-1; 225 ogg_int64_t prefoffset=-1;
228 ogg_int64_t offset=-1; 226 ogg_int64_t offset=-1;
229 ogg_uint32_t ret_serialno=-1; 227 ogg_int64_t ret_serialno=-1;
230 ogg_int64_t ret_gran=-1; 228 ogg_int64_t ret_gran=-1;
231 229
232 while(offset==-1){ 230 while(offset==-1){
@@ -241,13 +239,11 @@ static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
241 ret=_get_next_page(vf,&og,end-vf->offset); 239 ret=_get_next_page(vf,&og,end-vf->offset);
242 if(ret==OV_EREAD)return(OV_EREAD); 240 if(ret==OV_EREAD)return(OV_EREAD);
243 if(ret<0){ 241 if(ret<0){
244 ogg_page_release(&og);
245 break; 242 break;
246 }else{ 243 }else{
247 ret_serialno=ogg_page_serialno(&og); 244 ret_serialno=ogg_page_serialno(&og);
248 ret_gran=ogg_page_granulepos(&og); 245 ret_gran=ogg_page_granulepos(&og);
249 offset=ret; 246 offset=ret;
250 ogg_page_release(&og);
251 247
252 if(ret_serialno == (ogg_uint32_t) *serialno){ 248 if(ret_serialno == (ogg_uint32_t) *serialno){
253 prefoffset=ret; 249 prefoffset=ret;
@@ -276,23 +272,18 @@ static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
276 272
277/* uses the local ogg_stream storage in vf; this is important for 273/* uses the local ogg_stream storage in vf; this is important for
278 non-streaming input sources */ 274 non-streaming input sources */
279/* consumes the page that's passed in (if any) */ 275static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
280 276 ogg_uint32_t **serialno_list, int *serialno_n,
281static int _fetch_headers(OggVorbis_File *vf,
282 vorbis_info *vi,
283 vorbis_comment *vc,
284 ogg_uint32_t **serialno_list,
285 int *serialno_n,
286 ogg_page *og_ptr){ 277 ogg_page *og_ptr){
287 ogg_page og={0,0,0,0}; 278 ogg_page og;
288 ogg_packet op={0,0,0,0,0,0}; 279 ogg_packet op;
289 int i,ret; 280 int i,ret;
290 int allbos=0; 281 int allbos=0;
291 282
292 if(!og_ptr){ 283 if(!og_ptr){
293 ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE); 284 ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
294 if(llret==OV_EREAD)return(OV_EREAD); 285 if(llret==OV_EREAD)return(OV_EREAD);
295 if(llret<0)return OV_ENOTVORBIS; 286 if(llret<0)return(OV_ENOTVORBIS);
296 og_ptr=&og; 287 og_ptr=&og;
297 } 288 }
298 289
@@ -320,10 +311,10 @@ static int _fetch_headers(OggVorbis_File *vf,
320 if(vf->ready_state<STREAMSET){ 311 if(vf->ready_state<STREAMSET){
321 /* we don't have a vorbis stream in this link yet, so begin 312 /* we don't have a vorbis stream in this link yet, so begin
322 prospective stream setup. We need a stream to get packets */ 313 prospective stream setup. We need a stream to get packets */
323 ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr)); 314 ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
324 ogg_stream_pagein(vf->os,og_ptr); 315 ogg_stream_pagein(&vf->os,og_ptr);
325 316
326 if(ogg_stream_packetout(vf->os,&op) > 0 && 317 if(ogg_stream_packetout(&vf->os,&op) > 0 &&
327 vorbis_synthesis_idheader(&op)){ 318 vorbis_synthesis_idheader(&op)){
328 /* vorbis header; continue setup */ 319 /* vorbis header; continue setup */
329 vf->ready_state=STREAMSET; 320 vf->ready_state=STREAMSET;
@@ -348,8 +339,8 @@ static int _fetch_headers(OggVorbis_File *vf,
348 339
349 /* if this page also belongs to our vorbis stream, submit it and break */ 340 /* if this page also belongs to our vorbis stream, submit it and break */
350 if(vf->ready_state==STREAMSET && 341 if(vf->ready_state==STREAMSET &&
351 (ogg_uint32_t) vf->os->serialno == ogg_page_serialno(og_ptr)){ 342 vf->os.serialno == ogg_page_serialno(og_ptr)){
352 ogg_stream_pagein(vf->os,og_ptr); 343 ogg_stream_pagein(&vf->os,og_ptr);
353 break; 344 break;
354 } 345 }
355 } 346 }
@@ -367,7 +358,7 @@ static int _fetch_headers(OggVorbis_File *vf,
367 358
368 while(i<2){ /* get a packet loop */ 359 while(i<2){ /* get a packet loop */
369 360
370 int result=ogg_stream_packetout(vf->os,&op); 361 int result=ogg_stream_packetout(&vf->os,&op);
371 if(result==0)break; 362 if(result==0)break;
372 if(result==-1){ 363 if(result==-1){
373 ret=OV_EBADHEADER; 364 ret=OV_EBADHEADER;
@@ -387,8 +378,8 @@ static int _fetch_headers(OggVorbis_File *vf,
387 } 378 }
388 379
389 /* if this page belongs to the correct stream, go parse it */ 380 /* if this page belongs to the correct stream, go parse it */
390 if((ogg_uint32_t) vf->os->serialno == ogg_page_serialno(og_ptr)){ 381 if(vf->os.serialno == ogg_page_serialno(og_ptr)){
391 ogg_stream_pagein(vf->os,og_ptr); 382 ogg_stream_pagein(&vf->os,og_ptr);
392 break; 383 break;
393 } 384 }
394 385
@@ -406,15 +397,10 @@ static int _fetch_headers(OggVorbis_File *vf,
406 } 397 }
407 } 398 }
408 399
409 ogg_packet_release(&op);
410 ogg_page_release(&og);
411
412 return 0; 400 return 0;
413 } 401 }
414 402
415 bail_header: 403 bail_header:
416 ogg_packet_release(&op);
417 ogg_page_release(&og);
418 vorbis_info_clear(vi); 404 vorbis_info_clear(vi);
419 vorbis_comment_clear(vc); 405 vorbis_comment_clear(vc);
420 vf->ready_state=OPENED; 406 vf->ready_state=OPENED;
@@ -427,25 +413,23 @@ static int _fetch_headers(OggVorbis_File *vf,
427 audio, however this is only called during stream parsing upon 413 audio, however this is only called during stream parsing upon
428 seekable open. */ 414 seekable open. */
429static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){ 415static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
430 ogg_page og={0,0,0,0}; 416 ogg_page og;
431 ogg_int64_t accumulated=0,pos; 417 ogg_int64_t accumulated=0;
432 long lastblock=-1; 418 long lastblock=-1;
433 int result; 419 int result;
434 int serialno = vf->os->serialno; 420 ogg_uint32_t serialno = vf->os.serialno;
435 421
436 while(1){ 422 while(1){
437 ogg_packet op={0,0,0,0,0,0}; 423 ogg_packet op;
438
439 if(_get_next_page(vf,&og,-1)<0) 424 if(_get_next_page(vf,&og,-1)<0)
440 break; /* should not be possible unless the file is truncated/mangled */ 425 break; /* should not be possible unless the file is truncated/mangled */
441 426
442 if(ogg_page_bos(&og)) break; 427 if(ogg_page_bos(&og)) break;
443 if(ogg_page_serialno(&og)!=(ogg_uint32_t) serialno) continue; 428 if(ogg_page_serialno(&og)!= serialno) continue;
444 pos=ogg_page_granulepos(&og);
445 429
446 /* count blocksizes of all frames in the page */ 430 /* count blocksizes of all frames in the page */
447 ogg_stream_pagein(vf->os,&og); 431 ogg_stream_pagein(&vf->os,&og);
448 while((result=ogg_stream_packetout(vf->os,&op))){ 432 while((result=ogg_stream_packetout(&vf->os,&op))){
449 if(result>0){ /* ignore holes */ 433 if(result>0){ /* ignore holes */
450 long thisblock=vorbis_packet_blocksize(vi,&op); 434 long thisblock=vorbis_packet_blocksize(vi,&op);
451 if(lastblock!=-1) 435 if(lastblock!=-1)
@@ -453,11 +437,10 @@ static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
453 lastblock=thisblock; 437 lastblock=thisblock;
454 } 438 }
455 } 439 }
456 ogg_packet_release(&op);
457 440
458 if(pos!=-1){ 441 if(ogg_page_granulepos(&og)!=-1){
459 /* pcm offset of last packet on the first audio page */ 442 /* pcm offset of last packet on the first audio page */
460 accumulated= pos-accumulated; 443 accumulated= ogg_page_granulepos(&og)-accumulated;
461 break; 444 break;
462 } 445 }
463 } 446 }
@@ -466,11 +449,9 @@ static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
466 the beginning, a normal occurrence; set the offset to zero */ 449 the beginning, a normal occurrence; set the offset to zero */
467 if(accumulated<0)accumulated=0; 450 if(accumulated<0)accumulated=0;
468 451
469 ogg_page_release(&og);
470 return accumulated; 452 return accumulated;
471} 453}
472 454
473
474/* finds each bitstream link one at a time using a bisection search 455/* finds each bitstream link one at a time using a bisection search
475 (has to begin by knowing the offset of the lb's initial page). 456 (has to begin by knowing the offset of the lb's initial page).
476 Recurses for each link so it can alloc the link storage after 457 Recurses for each link so it can alloc the link storage after
@@ -484,14 +465,14 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
484 ogg_uint32_t *currentno_list, 465 ogg_uint32_t *currentno_list,
485 int currentnos, 466 int currentnos,
486 long m){ 467 long m){
487
488 ogg_int64_t pcmoffset; 468 ogg_int64_t pcmoffset;
489 ogg_int64_t dataoffset=searched; 469 ogg_int64_t dataoffset=searched;
490 ogg_int64_t endsearched=end; 470 ogg_int64_t endsearched=end;
491 ogg_int64_t next=end; 471 ogg_int64_t next=end;
492 ogg_int64_t searchgran=-1; 472 ogg_int64_t searchgran=-1;
473 ogg_page og;
493 ogg_int64_t ret,last; 474 ogg_int64_t ret,last;
494 int serialno = vf->os->serialno; 475 int serialno = vf->os.serialno;
495 476
496 /* invariants: 477 /* invariants:
497 we have the headers and serialnos for the link beginning at 'begin' 478 we have the headers and serialnos for the link beginning at 'begin'
@@ -538,7 +519,6 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
538 /* the below guards against garbage seperating the last and 519 /* the below guards against garbage seperating the last and
539 first pages of two links. */ 520 first pages of two links. */
540 while(searched<endsearched){ 521 while(searched<endsearched){
541 ogg_page og={0,0,0,0};
542 ogg_int64_t bisect; 522 ogg_int64_t bisect;
543 523
544 if(endsearched-searched<CHUNKSIZE){ 524 if(endsearched-searched<CHUNKSIZE){
@@ -547,8 +527,10 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
547 bisect=(searched+endsearched)/2; 527 bisect=(searched+endsearched)/2;
548 } 528 }
549 529
550 ret=_seek_helper(vf,bisect); 530 if(bisect != vf->offset){
551 if(ret)return(ret); 531 ret=_seek_helper(vf,bisect);
532 if(ret)return(ret);
533 }
552 534
553 last=_get_next_page(vf,&og,-1); 535 last=_get_next_page(vf,&og,-1);
554 if(last==OV_EREAD)return(OV_EREAD); 536 if(last==OV_EREAD)return(OV_EREAD);
@@ -556,9 +538,8 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
556 endsearched=bisect; 538 endsearched=bisect;
557 if(last>=0)next=last; 539 if(last>=0)next=last;
558 }else{ 540 }else{
559 searched=last+og.header_len+og.body_len; 541 searched=vf->offset;
560 } 542 }
561 ogg_page_release(&og);
562 } 543 }
563 544
564 /* Bisection point found */ 545 /* Bisection point found */
@@ -580,7 +561,7 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
580 561
581 ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL); 562 ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL);
582 if(ret)return(ret); 563 if(ret)return(ret);
583 serialno = vf->os->serialno; 564 serialno = vf->os.serialno;
584 dataoffset = vf->offset; 565 dataoffset = vf->offset;
585 566
586 /* this will consume a page, however the next bistection always 567 /* this will consume a page, however the next bistection always
@@ -627,8 +608,8 @@ static int _make_decode_ready(OggVorbis_File *vf){
627 608
628static int _open_seekable2(OggVorbis_File *vf){ 609static int _open_seekable2(OggVorbis_File *vf){
629 ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1; 610 ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1;
630 int endserial=vf->os->serialno; 611 int endserial=vf->os.serialno;
631 int serialno=vf->os->serialno; 612 int serialno=vf->os.serialno;
632 613
633 /* we're partially open and have a first link header state in 614 /* we're partially open and have a first link header state in
634 storage in vf */ 615 storage in vf */
@@ -666,7 +647,7 @@ static int _open_seekable2(OggVorbis_File *vf){
666 return(ov_raw_seek(vf,dataoffset)); 647 return(ov_raw_seek(vf,dataoffset));
667} 648}
668 649
669/* clear out the current logical bitstream decoder */ 650/* clear out the current logical bitstream decoder */
670static void _decode_clear(OggVorbis_File *vf){ 651static void _decode_clear(OggVorbis_File *vf){
671 vorbis_dsp_clear(&vf->vd); 652 vorbis_dsp_clear(&vf->vd);
672 vorbis_block_clear(&vf->vb); 653 vorbis_block_clear(&vf->vb);
@@ -677,74 +658,67 @@ static void _decode_clear(OggVorbis_File *vf){
677 bitstream boundary and dumps the decoding machine. If the decoding 658 bitstream boundary and dumps the decoding machine. If the decoding
678 machine is unloaded, it loads it. It also keeps pcm_offset up to 659 machine is unloaded, it loads it. It also keeps pcm_offset up to
679 date (seek and read both use this. seek uses a special hack with 660 date (seek and read both use this. seek uses a special hack with
680 readp). 661 readp).
681 662
682 return: <0) error, OV_HOLE (lost packet) or OV_EOF 663 return: <0) error, OV_HOLE (lost packet) or OV_EOF
683 0) need more data (only if readp==0) 664 0) need more data (only if readp==0)
684 1) got a packet 665 1) got a packet
685*/ 666*/
686 667
687STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf, 668static int _fetch_and_process_packet(OggVorbis_File *vf,
688 int readp, 669 ogg_packet *op_in,
689 int spanp) ICODE_ATTR_TREMOR_NOT_MDCT;
690STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
691 int readp, 670 int readp,
692 int spanp){ 671 int spanp){
693 ogg_page og={0,0,0,0}; 672 ogg_page og;
694 ogg_packet op={0,0,0,0,0,0};
695 int ret=0;
696 673
697 /* handle one packet. Try to fetch it from current stream state */ 674 /* handle one packet. Try to fetch it from current stream state */
698 /* extract packets from page */ 675 /* extract packets from page */
699 while(1){ 676 while(1){
700 677
701 if(vf->ready_state==STREAMSET){ 678 if(vf->ready_state==STREAMSET){
702 ret=_make_decode_ready(vf); 679 int ret=_make_decode_ready(vf);
703 if(ret<0) goto cleanup; 680 if(ret<0)return ret;
704 } 681 }
705 682
706 /* process a packet if we can. If the machine isn't loaded, 683 /* process a packet if we can. If the machine isn't loaded,
707 neither is a page */ 684 neither is a page */
708 if(vf->ready_state==INITSET){ 685 if(vf->ready_state==INITSET){
709 while(1) { 686 while(1) {
710 int result=ogg_stream_packetout(vf->os,&op); 687 ogg_packet op;
688 ogg_packet *op_ptr=(op_in?op_in:&op);
689 int result=ogg_stream_packetout(&vf->os,op_ptr);
711 ogg_int64_t granulepos; 690 ogg_int64_t granulepos;
712 691
713 if(result==-1){ 692 op_in=NULL;
714 ret=OV_HOLE; /* hole in the data. */ 693 if(result==-1)return(OV_HOLE); /* hole in the data. */
715 goto cleanup;
716 }
717 if(result>0){ 694 if(result>0){
718 /* got a packet. process it */ 695 /* got a packet. process it */
719 granulepos=op.granulepos; 696 granulepos=op_ptr->granulepos;
720 if(!vorbis_synthesis(&vf->vb,&op)){ /* lazy check for lazy 697 if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy
721 header handling. The 698 header handling. The
722 header packets aren't 699 header packets aren't
723 audio, so if/when we 700 audio, so if/when we
724 submit them, 701 submit them,
725 vorbis_synthesis will 702 vorbis_synthesis will
726 reject them */ 703 reject them */
727 704
728 /* suck in the synthesis data and track bitrate */ 705 /* suck in the synthesis data and track bitrate */
729 { 706 {
730 int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL); 707 int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
731 /* for proper use of libvorbis within libvorbisfile, 708 /* for proper use of libvorbis within libvorbisfile,
732 oldsamples will always be zero. */ 709 oldsamples will always be zero. */
733 if(oldsamples){ 710 if(oldsamples)return(OV_EFAULT);
734 ret=OV_EFAULT;
735 goto cleanup;
736 }
737 711
738 vorbis_synthesis_blockin(&vf->vd,&vf->vb); 712 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
739 vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples; 713 vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
740 vf->bittrack+=op.bytes*8; 714 vf->bittrack+=op_ptr->bytes*8;
741 } 715 }
742 716
743 /* update the pcm offset. */ 717 /* update the pcm offset. */
744 if(granulepos!=-1 && !op.e_o_s){ 718 if(granulepos!=-1 && !op_ptr->e_o_s){
745 int link=(vf->seekable?vf->current_link:0); 719 int link=(vf->seekable?vf->current_link:0);
746 int i,samples; 720 int i,samples;
747 721
748 /* this packet has a pcm_offset on it (the last packet 722 /* this packet has a pcm_offset on it (the last packet
749 completed on a page carries the offset) After processing 723 completed on a page carries the offset) After processing
750 (above), we know the pcm position of the *last* sample 724 (above), we know the pcm position of the *last* sample
@@ -755,7 +729,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
755 granulepos declares the last frame in the stream, and the 729 granulepos declares the last frame in the stream, and the
756 last packet of the last page may be a partial frame. 730 last packet of the last page may be a partial frame.
757 So, we need a previous granulepos from an in-sequence page 731 So, we need a previous granulepos from an in-sequence page
758 to have a reference point. Thus the !op.e_o_s clause 732 to have a reference point. Thus the !op_ptr->e_o_s clause
759 above */ 733 above */
760 734
761 if(vf->seekable && link>0) 735 if(vf->seekable && link>0)
@@ -766,23 +740,22 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
766 is very broken */ 740 is very broken */
767 741
768 samples=vorbis_synthesis_pcmout(&vf->vd,NULL); 742 samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
769 743
770 granulepos-=samples; 744 granulepos-=samples;
771 for(i=0;i<link;i++) 745 for(i=0;i<link;i++)
772 granulepos+=vf->pcmlengths[i*2+1]; 746 granulepos+=vf->pcmlengths[i*2+1];
773 vf->pcm_offset=granulepos; 747 vf->pcm_offset=granulepos;
774 } 748 }
775 ret=1; 749 return(1);
776 goto cleanup;
777 } 750 }
778 } 751 }
779 else 752 else
780 break; 753 break;
781 } 754 }
782 } 755 }
783 756
784 if(vf->ready_state>=OPENED){ 757 if(vf->ready_state>=OPENED){
785 ogg_int64_t lret; 758 ogg_int64_t ret;
786 759
787 while(1){ 760 while(1){
788 /* the loop is not strictly necessary, but there's no sense in 761 /* the loop is not strictly necessary, but there's no sense in
@@ -791,13 +764,9 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
791 part of a different logical bitstream; keep reading until 764 part of a different logical bitstream; keep reading until
792 we get one with the correct serialno */ 765 we get one with the correct serialno */
793 766
794 if(!readp){ 767 if(!readp)return(0);
795 ret=0; 768 if((ret=_get_next_page(vf,&og,-1))<0){
796 goto cleanup; 769 return(OV_EOF); /* eof. leave unitialized */
797 }
798 if((lret=_get_next_page(vf,&og,-1))<0){
799 ret=OV_EOF; /* eof. leave unitialized */
800 goto cleanup;
801 } 770 }
802 771
803 /* bitrate tracking; add the header's bytes here, the body bytes 772 /* bitrate tracking; add the header's bytes here, the body bytes
@@ -813,10 +782,8 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
813 782
814 if(ogg_page_bos(&og)){ 783 if(ogg_page_bos(&og)){
815 /* boundary case */ 784 /* boundary case */
816 if(!spanp){ 785 if(!spanp)
817 ret=OV_EOF; 786 return(OV_EOF);
818 goto cleanup;
819 }
820 787
821 _decode_clear(vf); 788 _decode_clear(vf);
822 789
@@ -830,12 +797,13 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
830 continue; /* possibility #2 */ 797 continue; /* possibility #2 */
831 } 798 }
832 } 799 }
800
833 break; 801 break;
834 } 802 }
835 } 803 }
836 804
837 /* Do we need to load a new machine before submitting the page? */ 805 /* Do we need to load a new machine before submitting the page? */
838 /* This is different in the seekable and non-seekable cases. 806 /* This is different in the seekable and non-seekable cases.
839 807
840 In the seekable case, we already have all the header 808 In the seekable case, we already have all the header
841 information loaded and cached; we just initialize the machine 809 information loaded and cached; we just initialize the machine
@@ -846,37 +814,37 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
846 we're now nominally at the header of the next bitstream 814 we're now nominally at the header of the next bitstream
847 */ 815 */
848 816
849 if(vf->ready_state!=INITSET){ 817 if(vf->ready_state!=INITSET){
850 int link; 818 int link;
851 819
852 if(vf->ready_state<STREAMSET){ 820 if(vf->ready_state<STREAMSET){
853 if(vf->seekable){ 821 if(vf->seekable){
854 long serialno=ogg_page_serialno(&og); 822 ogg_uint32_t serialno = ogg_page_serialno(&og);
855 823
856 /* match the serialno to bitstream section. We use this rather than 824 /* match the serialno to bitstream section. We use this rather than
857 offset positions to avoid problems near logical bitstream 825 offset positions to avoid problems near logical bitstream
858 boundaries */ 826 boundaries */
859 827
860 for(link=0;link<vf->links;link++) 828 for(link=0;link<vf->links;link++)
861 if(vf->serialnos[link]==(ogg_uint32_t) serialno)break; 829 if(vf->serialnos[link]==serialno)break;
862 830
863 if(link==vf->links) continue; /* not the desired Vorbis 831 if(link==vf->links) continue; /* not the desired Vorbis
864 bitstream section; keep 832 bitstream section; keep
865 trying */ 833 trying */
866 834
867 vf->current_serialno=serialno; 835 vf->current_serialno=serialno;
868 vf->current_link=link; 836 vf->current_link=link;
869 837
870 ogg_stream_reset_serialno(vf->os,vf->current_serialno); 838 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
871 vf->ready_state=STREAMSET; 839 vf->ready_state=STREAMSET;
872 840
873 }else{ 841 }else{
874 /* we're streaming */ 842 /* we're streaming */
875 /* fetch the three header packets, build the info struct */ 843 /* fetch the three header packets, build the info struct */
876 844
877 int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og); 845 int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og);
878 if(ret) goto cleanup; 846 if(ret)return(ret);
879 vf->current_serialno=vf->os->serialno; 847 vf->current_serialno=vf->os.serialno;
880 vf->current_link++; 848 vf->current_link++;
881 link=0; 849 link=0;
882 } 850 }
@@ -885,17 +853,14 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
885 853
886 /* the buffered page is the data we want, and we're ready for it; 854 /* the buffered page is the data we want, and we're ready for it;
887 add it to the stream state */ 855 add it to the stream state */
888 ogg_stream_pagein(vf->os,&og); 856 ogg_stream_pagein(&vf->os,&og);
857
889 } 858 }
890 cleanup:
891 ogg_packet_release(&op);
892 ogg_page_release(&og);
893 return ret;
894} 859}
895 860
896static int _ov_open1(void *f,OggVorbis_File *vf,char *initial, 861static int _ov_open1(void *f,OggVorbis_File *vf,const char *initial,
897 long ibytes, ov_callbacks callbacks){ 862 long ibytes, ov_callbacks callbacks){
898 int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1); 863 int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1);
899 ogg_uint32_t *serialno_list=NULL; 864 ogg_uint32_t *serialno_list=NULL;
900 int serialno_list_size=0; 865 int serialno_list_size=0;
901 int ret; 866 int ret;
@@ -905,16 +870,16 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
905 vf->callbacks = callbacks; 870 vf->callbacks = callbacks;
906 871
907 /* init the framing state */ 872 /* init the framing state */
908 vf->oy=ogg_sync_create(); 873 ogg_sync_init(&vf->oy);
909 874
910 /* perhaps some data was previously read into a buffer for testing 875 /* perhaps some data was previously read into a buffer for testing
911 against other stream types. Allow initialization from this 876 against other stream types. Allow initialization from this
912 previously read data (especially as we may be reading from a 877 previously read data (especially as we may be reading from a
913 non-seekable stream) */ 878 non-seekable stream) */
914 if(initial){ 879 if(initial){
915 unsigned char *buffer=ogg_sync_bufferin(vf->oy,ibytes); 880 char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
916 memcpy(buffer,initial,ibytes); 881 memcpy(buffer,initial,ibytes);
917 ogg_sync_wrote(vf->oy,ibytes); 882 ogg_sync_wrote(&vf->oy,ibytes);
918 } 883 }
919 884
920 /* can we seek? Stevens suggests the seek test was portable */ 885 /* can we seek? Stevens suggests the seek test was portable */
@@ -925,7 +890,7 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
925 vf->links=1; 890 vf->links=1;
926 vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi)); 891 vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
927 vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc)); 892 vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
928 vf->os=ogg_stream_create(-1); /* fill in the serialno later */ 893 ogg_stream_init(&vf->os,-1); /* fill in the serialno later */
929 894
930 /* Fetch all BOS pages, store the vorbis header and all seen serial 895 /* Fetch all BOS pages, store the vorbis header and all seen serial
931 numbers, load subsequent vorbis setup headers */ 896 numbers, load subsequent vorbis setup headers */
@@ -945,7 +910,7 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
945 vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets)); 910 vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets));
946 vf->offsets[0]=0; 911 vf->offsets[0]=0;
947 vf->dataoffsets[0]=vf->offset; 912 vf->dataoffsets[0]=vf->offset;
948 vf->current_serialno=vf->os->serialno; 913 vf->current_serialno=vf->os.serialno;
949 914
950 vf->ready_state=PARTOPEN; 915 vf->ready_state=PARTOPEN;
951 } 916 }
@@ -954,8 +919,8 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
954} 919}
955 920
956static int _ov_open2(OggVorbis_File *vf){ 921static int _ov_open2(OggVorbis_File *vf){
957 if(vf->ready_state < OPENED) 922 if(vf->ready_state != PARTOPEN) return OV_EINVAL;
958 vf->ready_state=OPENED; 923 vf->ready_state=OPENED;
959 if(vf->seekable){ 924 if(vf->seekable){
960 int ret=_open_seekable2(vf); 925 int ret=_open_seekable2(vf);
961 if(ret){ 926 if(ret){
@@ -963,7 +928,9 @@ static int _ov_open2(OggVorbis_File *vf){
963 ov_clear(vf); 928 ov_clear(vf);
964 } 929 }
965 return(ret); 930 return(ret);
966 } 931 }else
932 vf->ready_state=STREAMSET;
933
967 return 0; 934 return 0;
968} 935}
969 936
@@ -973,8 +940,8 @@ int ov_clear(OggVorbis_File *vf){
973 if(vf){ 940 if(vf){
974 vorbis_block_clear(&vf->vb); 941 vorbis_block_clear(&vf->vb);
975 vorbis_dsp_clear(&vf->vd); 942 vorbis_dsp_clear(&vf->vd);
976 ogg_stream_destroy(vf->os); 943 ogg_stream_clear(&vf->os);
977 944
978 if(vf->vi && vf->links){ 945 if(vf->vi && vf->links){
979 int i; 946 int i;
980 for(i=0;i<vf->links;i++){ 947 for(i=0;i<vf->links;i++){
@@ -988,8 +955,7 @@ int ov_clear(OggVorbis_File *vf){
988 if(vf->pcmlengths)_ogg_free(vf->pcmlengths); 955 if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
989 if(vf->serialnos)_ogg_free(vf->serialnos); 956 if(vf->serialnos)_ogg_free(vf->serialnos);
990 if(vf->offsets)_ogg_free(vf->offsets); 957 if(vf->offsets)_ogg_free(vf->offsets);
991 ogg_sync_destroy(vf->oy); 958 ogg_sync_clear(&vf->oy);
992
993 if(vf->datasource && vf->callbacks.close_func) 959 if(vf->datasource && vf->callbacks.close_func)
994 (vf->callbacks.close_func)(vf->datasource); 960 (vf->callbacks.close_func)(vf->datasource);
995 memset(vf,0,sizeof(*vf)); 961 memset(vf,0,sizeof(*vf));
@@ -1002,14 +968,14 @@ int ov_clear(OggVorbis_File *vf){
1002 968
1003/* inspects the OggVorbis file and finds/documents all the logical 969/* inspects the OggVorbis file and finds/documents all the logical
1004 bitstreams contained in it. Tries to be tolerant of logical 970 bitstreams contained in it. Tries to be tolerant of logical
1005 bitstream sections that are truncated/woogie. 971 bitstream sections that are truncated/woogie.
1006 972
1007 return: -1) error 973 return: -1) error
1008 0) OK 974 0) OK
1009*/ 975*/
1010 976
1011int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes, 977int ov_open_callbacks(void *f,OggVorbis_File *vf,
1012 ov_callbacks callbacks){ 978 const char *initial,long ibytes,ov_callbacks callbacks){
1013 #if defined(CPU_COLDFIRE) 979 #if defined(CPU_COLDFIRE)
1014 /* this seems to be the closest we get to an init function, let's init emac 980 /* this seems to be the closest we get to an init function, let's init emac
1015 here. rounding is disabled because of MULT31_SHIFT15, which will be 981 here. rounding is disabled because of MULT31_SHIFT15, which will be
@@ -1067,9 +1033,7 @@ ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){
1067 returns zero on success, nonzero on failure */ 1033 returns zero on success, nonzero on failure */
1068 1034
1069int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){ 1035int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1070 ogg_stream_state *work_os=NULL; 1036 ogg_stream_state work_os;
1071 ogg_page og={0,0,0,0};
1072 ogg_packet op={0,0,0,0,0,0};
1073 int ret; 1037 int ret;
1074 1038
1075 if(vf->ready_state<OPENED)return(OV_EINVAL); 1039 if(vf->ready_state<OPENED)return(OV_EINVAL);
@@ -1078,15 +1042,21 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1078 1042
1079 if(pos<0 || pos>vf->end)return(OV_EINVAL); 1043 if(pos<0 || pos>vf->end)return(OV_EINVAL);
1080 1044
1045 /* is the seek position outside our current link [if any]? */
1046 if(vf->ready_state>=STREAMSET){
1047 if(pos<vf->offsets[vf->current_link] || pos>=vf->offsets[vf->current_link+1])
1048 _decode_clear(vf); /* clear out stream state */
1049 }
1050
1081 /* don't yet clear out decoding machine (if it's initialized), in 1051 /* don't yet clear out decoding machine (if it's initialized), in
1082 the case we're in the same link. Restart the decode lapping, and 1052 the case we're in the same link. Restart the decode lapping, and
1083 let _fetch_and_process_packet deal with a potential bitstream 1053 let _fetch_and_process_packet deal with a potential bitstream
1084 boundary */ 1054 boundary */
1085 vf->pcm_offset=-1; 1055 vf->pcm_offset=-1;
1086 ogg_stream_reset_serialno(vf->os, 1056 ogg_stream_reset_serialno(&vf->os,
1087 vf->current_serialno); /* must set serialno */ 1057 vf->current_serialno); /* must set serialno */
1088 vorbis_synthesis_restart(&vf->vd); 1058 vorbis_synthesis_restart(&vf->vd);
1089 1059
1090 ret=_seek_helper(vf,pos); 1060 ret=_seek_helper(vf,pos);
1091 if(ret)goto seek_error; 1061 if(ret)goto seek_error;
1092 1062
@@ -1097,55 +1067,61 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1097 1067
1098 So, a hack. We use two stream states; a local scratch state and 1068 So, a hack. We use two stream states; a local scratch state and
1099 the shared vf->os stream state. We use the local state to 1069 the shared vf->os stream state. We use the local state to
1100 scan, and the shared state as a buffer for later decode. 1070 scan, and the shared state as a buffer for later decode.
1101 1071
1102 Unfortuantely, on the last page we still advance to last packet 1072 Unfortuantely, on the last page we still advance to last packet
1103 because the granulepos on the last page is not necessarily on a 1073 because the granulepos on the last page is not necessarily on a
1104 packet boundary, and we need to make sure the granpos is 1074 packet boundary, and we need to make sure the granpos is
1105 correct. 1075 correct.
1106 */ 1076 */
1107 1077
1108 { 1078 {
1079 ogg_page og;
1080 ogg_packet op;
1109 int lastblock=0; 1081 int lastblock=0;
1110 int accblock=0; 1082 int accblock=0;
1111 int thisblock; 1083 int thisblock=0;
1112 int lastflag=0; 1084 int lastflag=0;
1113 int firstflag=0; 1085 int firstflag=0;
1114 ogg_int64_t pagepos=-1; 1086 ogg_int64_t pagepos=-1;
1115 1087
1116 work_os=ogg_stream_create(vf->current_serialno); /* get the memory ready */ 1088 ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */
1089 ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE
1090 return from not necessarily
1091 starting from the beginning */
1092
1117 while(1){ 1093 while(1){
1118 if(vf->ready_state>=STREAMSET){ 1094 if(vf->ready_state>=STREAMSET){
1119 /* snarf/scan a packet if we can */ 1095 /* snarf/scan a packet if we can */
1120 int result=ogg_stream_packetout(work_os,&op); 1096 int result=ogg_stream_packetout(&work_os,&op);
1121 1097
1122 if(result>0){ 1098 if(result>0){
1123 1099
1124 if(vf->vi[vf->current_link].codec_setup){ 1100 if(vf->vi[vf->current_link].codec_setup){
1125 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); 1101 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1126 if(thisblock<0){ 1102 if(thisblock<0){
1127 ogg_stream_packetout(vf->os,NULL); 1103 ogg_stream_packetout(&vf->os,NULL);
1128 thisblock=0; 1104 thisblock=0;
1129 }else{ 1105 }else{
1130 1106
1131 /* We can't get a guaranteed correct pcm position out of the 1107 /* We can't get a guaranteed correct pcm position out of the
1132 last page in a stream because it might have a 'short' 1108 last page in a stream because it might have a 'short'
1133 granpos, which can only be detected in the presence of a 1109 granpos, which can only be detected in the presence of a
1134 preceeding page. However, if the last page is also the first 1110 preceding page. However, if the last page is also the first
1135 page, the granpos rules of a first page take precedence. Not 1111 page, the granpos rules of a first page take precedence. Not
1136 only that, but for first==last, the EOS page must be treated 1112 only that, but for first==last, the EOS page must be treated
1137 as if its a normal first page for the stream to open/play. */ 1113 as if its a normal first page for the stream to open/play. */
1138 if(lastflag && !firstflag) 1114 if(lastflag && !firstflag)
1139 ogg_stream_packetout(vf->os,NULL); 1115 ogg_stream_packetout(&vf->os,NULL);
1140 else 1116 else
1141 if(lastblock)accblock+=(lastblock+thisblock)>>2; 1117 if(lastblock)accblock+=(lastblock+thisblock)>>2;
1142 } 1118 }
1143 1119
1144 if(op.granulepos!=-1){ 1120 if(op.granulepos!=-1){
1145 int i,link=vf->current_link; 1121 int i,link=vf->current_link;
1146 ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2]; 1122 ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
1147 if(granulepos<0)granulepos=0; 1123 if(granulepos<0)granulepos=0;
1148 1124
1149 for(i=0;i<link;i++) 1125 for(i=0;i<link;i++)
1150 granulepos+=vf->pcmlengths[i*2+1]; 1126 granulepos+=vf->pcmlengths[i*2+1];
1151 vf->pcm_offset=granulepos-accblock; 1127 vf->pcm_offset=granulepos-accblock;
@@ -1155,10 +1131,10 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1155 lastblock=thisblock; 1131 lastblock=thisblock;
1156 continue; 1132 continue;
1157 }else 1133 }else
1158 ogg_stream_packetout(vf->os,NULL); 1134 ogg_stream_packetout(&vf->os,NULL);
1159 } 1135 }
1160 } 1136 }
1161 1137
1162 if(!lastblock){ 1138 if(!lastblock){
1163 pagepos=_get_next_page(vf,&og,-1); 1139 pagepos=_get_next_page(vf,&og,-1);
1164 if(pagepos<0){ 1140 if(pagepos<0){
@@ -1170,10 +1146,11 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1170 vf->pcm_offset=-1; 1146 vf->pcm_offset=-1;
1171 break; 1147 break;
1172 } 1148 }
1173 1149
1174 /* has our decoding just traversed a bitstream boundary? */ 1150 /* has our decoding just traversed a bitstream boundary? */
1175 if(vf->ready_state>=STREAMSET){ 1151 if(vf->ready_state>=STREAMSET){
1176 if(vf->current_serialno!=ogg_page_serialno(&og)){ 1152 if(vf->current_serialno!=ogg_page_serialno(&og)){
1153
1177 /* two possibilities: 1154 /* two possibilities:
1178 1) our decoding just traversed a bitstream boundary 1155 1) our decoding just traversed a bitstream boundary
1179 2) another stream is multiplexed into this logical section? */ 1156 2) another stream is multiplexed into this logical section? */
@@ -1181,53 +1158,45 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1181 if(ogg_page_bos(&og)){ 1158 if(ogg_page_bos(&og)){
1182 /* we traversed */ 1159 /* we traversed */
1183 _decode_clear(vf); /* clear out stream state */ 1160 _decode_clear(vf); /* clear out stream state */
1184 ogg_stream_destroy(work_os); 1161 ogg_stream_clear(&work_os);
1185 } /* else, do nothing; next loop will scoop another page */ 1162 } /* else, do nothing; next loop will scoop another page */
1186 } 1163 }
1187 } 1164 }
1188 1165
1189 if(vf->ready_state<STREAMSET){ 1166 if(vf->ready_state<STREAMSET){
1190 int link; 1167 int link;
1191 long serialno = ogg_page_serialno(&og); 1168 ogg_uint32_t serialno = ogg_page_serialno(&og);
1192 1169
1193 for(link=0;link<vf->links;link++) 1170 for(link=0;link<vf->links;link++)
1194 if(vf->serialnos[link]==vf->current_serialno)break; 1171 if(vf->serialnos[link]==serialno)break;
1195 1172
1196 if(link==vf->links) continue; /* not the desired Vorbis 1173 if(link==vf->links) continue; /* not the desired Vorbis
1197 bitstream section; keep 1174 bitstream section; keep
1198 trying */ 1175 trying */
1199 vf->current_link=link; 1176 vf->current_link=link;
1200 vf->current_serialno=serialno; 1177 vf->current_serialno=serialno;
1201 ogg_stream_reset_serialno(vf->os,vf->current_serialno); 1178 ogg_stream_reset_serialno(&vf->os,serialno);
1202 ogg_stream_reset_serialno(work_os,vf->current_serialno); 1179 ogg_stream_reset_serialno(&work_os,serialno);
1203 vf->ready_state=STREAMSET; 1180 vf->ready_state=STREAMSET;
1204 firstflag=(pagepos<=vf->dataoffsets[link]); 1181 firstflag=(pagepos<=vf->dataoffsets[link]);
1205 } 1182 }
1206 1183
1207 { 1184 ogg_stream_pagein(&vf->os,&og);
1208 ogg_page dup; 1185 ogg_stream_pagein(&work_os,&og);
1209 ogg_page_dup(&dup,&og); 1186 lastflag=ogg_page_eos(&og);
1210 lastflag=ogg_page_eos(&og); 1187
1211 ogg_stream_pagein(vf->os,&og);
1212 ogg_stream_pagein(work_os,&dup);
1213 }
1214 } 1188 }
1215 } 1189 }
1216 1190
1217 ogg_packet_release(&op); 1191 ogg_stream_clear(&work_os);
1218 ogg_page_release(&og);
1219 ogg_stream_destroy(work_os);
1220 vf->bittrack=0; 1192 vf->bittrack=0;
1221 vf->samptrack=0; 1193 vf->samptrack=0;
1222 return(0); 1194 return(0);
1223 1195
1224 seek_error: 1196 seek_error:
1225 ogg_packet_release(&op);
1226 ogg_page_release(&og);
1227
1228 /* dump the machine so we're in a known state */ 1197 /* dump the machine so we're in a known state */
1229 vf->pcm_offset=-1; 1198 vf->pcm_offset=-1;
1230 ogg_stream_destroy(work_os); 1199 ogg_stream_clear(&work_os);
1231 _decode_clear(vf); 1200 _decode_clear(vf);
1232 return OV_EBADLINK; 1201 return OV_EBADLINK;
1233} 1202}
@@ -1235,20 +1204,19 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1235/* Page granularity seek (faster than sample granularity because we 1204/* Page granularity seek (faster than sample granularity because we
1236 don't do the last bit of decode to find a specific sample). 1205 don't do the last bit of decode to find a specific sample).
1237 1206
1238 Seek to the last [granule marked] page preceeding the specified pos 1207 Seek to the last [granule marked] page preceding the specified pos
1239 location, such that decoding past the returned point will quickly 1208 location, such that decoding past the returned point will quickly
1240 arrive at the requested position. */ 1209 arrive at the requested position. */
1241int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){ 1210int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1242 int link=-1; 1211 int link=-1;
1243 ogg_int64_t result=0; 1212 ogg_int64_t result=0;
1244 ogg_int64_t total=ov_pcm_total(vf,-1); 1213 ogg_int64_t total=ov_pcm_total(vf,-1);
1245 ogg_page og={0,0,0,0};
1246 ogg_packet op={0,0,0,0,0,0};
1247 1214
1248 if(vf->ready_state<OPENED)return(OV_EINVAL); 1215 if(vf->ready_state<OPENED)return(OV_EINVAL);
1249 if(!vf->seekable)return(OV_ENOSEEK); 1216 if(!vf->seekable)return(OV_ENOSEEK);
1217
1250 if(pos<0 || pos>total)return(OV_EINVAL); 1218 if(pos<0 || pos>total)return(OV_EINVAL);
1251 1219
1252 /* which bitstream section does this pcm offset occur in? */ 1220 /* which bitstream section does this pcm offset occur in? */
1253 for(link=vf->links-1;link>=0;link--){ 1221 for(link=vf->links-1;link>=0;link--){
1254 total-=vf->pcmlengths[link*2+1]; 1222 total-=vf->pcmlengths[link*2+1];
@@ -1256,7 +1224,7 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1256 } 1224 }
1257 1225
1258 /* search within the logical bitstream for the page with the highest 1226 /* search within the logical bitstream for the page with the highest
1259 pcm_pos preceeding (or equal to) pos. There is a danger here; 1227 pcm_pos preceding (or equal to) pos. There is a danger here;
1260 missing pages or incorrect frame number information in the 1228 missing pages or incorrect frame number information in the
1261 bitstream could make our task impossible. Account for that (it 1229 bitstream could make our task impossible. Account for that (it
1262 would be an error condition) */ 1230 would be an error condition) */
@@ -1269,22 +1237,26 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1269 ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime; 1237 ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
1270 ogg_int64_t target=pos-total+begintime; 1238 ogg_int64_t target=pos-total+begintime;
1271 ogg_int64_t best=begin; 1239 ogg_int64_t best=begin;
1272 1240
1241 ogg_page og;
1273 while(begin<end){ 1242 while(begin<end){
1274 ogg_int64_t bisect; 1243 ogg_int64_t bisect;
1275 1244
1276 if(end-begin<CHUNKSIZE){ 1245 if(end-begin<CHUNKSIZE){
1277 bisect=begin; 1246 bisect=begin;
1278 }else{ 1247 }else{
1279 /* take a (pretty decent) guess. */ 1248 /* take a (pretty decent) guess. */
1280 bisect=begin + 1249 bisect=begin +
1281 (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE; 1250 (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
1282 if(bisect<=begin) 1251 if(bisect<begin+CHUNKSIZE)
1283 bisect=begin+1; 1252 bisect=begin;
1284 } 1253 }
1285 1254
1286 _seek_helper(vf,bisect); 1255 if(bisect!=vf->offset){
1287 1256 result=_seek_helper(vf,bisect);
1257 if(result) goto seek_error;
1258 }
1259
1288 while(begin<end){ 1260 while(begin<end){
1289 result=_get_next_page(vf,&og,end-vf->offset); 1261 result=_get_next_page(vf,&og,end-vf->offset);
1290 if(result==OV_EREAD) goto seek_error; 1262 if(result==OV_EREAD) goto seek_error;
@@ -1295,16 +1267,23 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1295 if(bisect==0) goto seek_error; 1267 if(bisect==0) goto seek_error;
1296 bisect-=CHUNKSIZE; 1268 bisect-=CHUNKSIZE;
1297 if(bisect<=begin)bisect=begin+1; 1269 if(bisect<=begin)bisect=begin+1;
1298 _seek_helper(vf,bisect); 1270 result=_seek_helper(vf,bisect);
1271 if(result) goto seek_error;
1299 } 1272 }
1300 }else{ 1273 }else{
1301 ogg_int64_t granulepos=ogg_page_granulepos(&og); 1274 ogg_int64_t granulepos;
1275
1276 if(ogg_page_serialno(&og)!=vf->serialnos[link])
1277 continue;
1278
1279 granulepos=ogg_page_granulepos(&og);
1302 if(granulepos==-1)continue; 1280 if(granulepos==-1)continue;
1281
1303 if(granulepos<target){ 1282 if(granulepos<target){
1304 best=result; /* raw offset of packet with granulepos */ 1283 best=result; /* raw offset of packet with granulepos */
1305 begin=vf->offset; /* raw offset of next page */ 1284 begin=vf->offset; /* raw offset of next page */
1306 begintime=granulepos; 1285 begintime=granulepos;
1307 1286
1308 if(target-begintime>44100)break; 1287 if(target-begintime>44100)break;
1309 bisect=begin; /* *not* begin + 1 */ 1288 bisect=begin; /* *not* begin + 1 */
1310 }else{ 1289 }else{
@@ -1315,9 +1294,10 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1315 end=result; 1294 end=result;
1316 bisect-=CHUNKSIZE; /* an endless loop otherwise. */ 1295 bisect-=CHUNKSIZE; /* an endless loop otherwise. */
1317 if(bisect<=begin)bisect=begin+1; 1296 if(bisect<=begin)bisect=begin+1;
1318 _seek_helper(vf,bisect); 1297 result=_seek_helper(vf,bisect);
1298 if(result) goto seek_error;
1319 }else{ 1299 }else{
1320 end=result; 1300 end=bisect;
1321 endtime=granulepos; 1301 endtime=granulepos;
1322 break; 1302 break;
1323 } 1303 }
@@ -1328,9 +1308,11 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1328 } 1308 }
1329 1309
1330 /* found our page. seek to it, update pcm offset. Easier case than 1310 /* found our page. seek to it, update pcm offset. Easier case than
1331 raw_seek, don't keep packets preceeding granulepos. */ 1311 raw_seek, don't keep packets preceding granulepos. */
1332 { 1312 {
1333 1313 ogg_page og;
1314 ogg_packet op;
1315
1334 /* seek */ 1316 /* seek */
1335 result=_seek_helper(vf,best); 1317 result=_seek_helper(vf,best);
1336 vf->pcm_offset=-1; 1318 vf->pcm_offset=-1;
@@ -1340,28 +1322,28 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1340 1322
1341 if(link!=vf->current_link){ 1323 if(link!=vf->current_link){
1342 /* Different link; dump entire decode machine */ 1324 /* Different link; dump entire decode machine */
1343 _decode_clear(vf); 1325 _decode_clear(vf);
1344 1326
1345 vf->current_link=link; 1327 vf->current_link=link;
1346 vf->current_serialno=ogg_page_serialno(&og); 1328 vf->current_serialno=vf->serialnos[link];
1347 vf->ready_state=STREAMSET; 1329 vf->ready_state=STREAMSET;
1348 1330
1349 }else{ 1331 }else{
1350 vorbis_synthesis_restart(&vf->vd); 1332 vorbis_synthesis_restart(&vf->vd);
1351 } 1333 }
1352 1334
1353 ogg_stream_reset_serialno(vf->os,vf->current_serialno); 1335 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
1354 ogg_stream_pagein(vf->os,&og); 1336 ogg_stream_pagein(&vf->os,&og);
1355 1337
1356 /* pull out all but last packet; the one with granulepos */ 1338 /* pull out all but last packet; the one with granulepos */
1357 while(1){ 1339 while(1){
1358 result=ogg_stream_packetpeek(vf->os,&op); 1340 result=ogg_stream_packetpeek(&vf->os,&op);
1359 if(result==0){ 1341 if(result==0){
1360 /* !!! the packet finishing this page originated on a 1342 /* !!! the packet finishing this page originated on a
1361 preceeding page. Keep fetching previous pages until we 1343 preceding page. Keep fetching previous pages until we
1362 get one with a granulepos or without the 'continued' flag 1344 get one with a granulepos or without the 'continued' flag
1363 set. Then just use raw_seek for simplicity. */ 1345 set. Then just use raw_seek for simplicity. */
1364 1346
1365 result=_seek_helper(vf,best); 1347 result=_seek_helper(vf,best);
1366 if(result<0) goto seek_error; 1348 if(result<0) goto seek_error;
1367 1349
@@ -1377,7 +1359,7 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1377 } 1359 }
1378 } 1360 }
1379 if(result<0){ 1361 if(result<0){
1380 result = OV_EBADPACKET; 1362 result = OV_EBADPACKET;
1381 goto seek_error; 1363 goto seek_error;
1382 } 1364 }
1383 if(op.granulepos!=-1){ 1365 if(op.granulepos!=-1){
@@ -1386,11 +1368,11 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1386 vf->pcm_offset+=total; 1368 vf->pcm_offset+=total;
1387 break; 1369 break;
1388 }else 1370 }else
1389 result=ogg_stream_packetout(vf->os,NULL); 1371 result=ogg_stream_packetout(&vf->os,NULL);
1390 } 1372 }
1391 } 1373 }
1392 } 1374 }
1393 1375
1394 /* verify result */ 1376 /* verify result */
1395 if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){ 1377 if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1396 result=OV_EFAULT; 1378 result=OV_EFAULT;
@@ -1398,60 +1380,53 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1398 } 1380 }
1399 vf->bittrack=0; 1381 vf->bittrack=0;
1400 vf->samptrack=0; 1382 vf->samptrack=0;
1401
1402 ogg_page_release(&og);
1403 ogg_packet_release(&op);
1404 return(0); 1383 return(0);
1405
1406 seek_error:
1407
1408 ogg_page_release(&og);
1409 ogg_packet_release(&op);
1410 1384
1385 seek_error:
1411 /* dump machine so we're in a known state */ 1386 /* dump machine so we're in a known state */
1412 vf->pcm_offset=-1; 1387 vf->pcm_offset=-1;
1413 _decode_clear(vf); 1388 _decode_clear(vf);
1414 return (int)result; 1389 return (int)result;
1415} 1390}
1416 1391
1417/* seek to a sample offset relative to the decompressed pcm stream 1392/* seek to a sample offset relative to the decompressed pcm stream
1418 returns zero on success, nonzero on failure */ 1393 returns zero on success, nonzero on failure */
1419 1394
1420int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){ 1395int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1421 ogg_packet op={0,0,0,0,0,0};
1422 ogg_page og={0,0,0,0};
1423 int thisblock,lastblock=0; 1396 int thisblock,lastblock=0;
1424 int ret=ov_pcm_seek_page(vf,pos); 1397 int ret=ov_pcm_seek_page(vf,pos);
1425 if(ret<0)return(ret); 1398 if(ret<0)return(ret);
1426 _make_decode_ready(vf); 1399 if((ret=_make_decode_ready(vf)))return ret;
1427 1400
1428 /* discard leading packets we don't need for the lapping of the 1401 /* discard leading packets we don't need for the lapping of the
1429 position we want; don't decode them */ 1402 position we want; don't decode them */
1430 1403
1431 while(1){ 1404 while(1){
1405 ogg_packet op;
1406 ogg_page og;
1432 1407
1433 int ret=ogg_stream_packetpeek(vf->os,&op); 1408 int ret=ogg_stream_packetpeek(&vf->os,&op);
1434 if(ret>0){ 1409 if(ret>0){
1435 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); 1410 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1436 if(thisblock<0){ 1411 if(thisblock<0){
1437 ogg_stream_packetout(vf->os,NULL); 1412 ogg_stream_packetout(&vf->os,NULL);
1438 continue; /* non audio packet */ 1413 continue; /* non audio packet */
1439 } 1414 }
1440 if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2; 1415 if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1441 1416
1442 if(vf->pcm_offset+((thisblock+ 1417 if(vf->pcm_offset+((thisblock+
1443 vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break; 1418 vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
1444 1419
1445 /* remove the packet from packet queue and track its granulepos */ 1420 /* remove the packet from packet queue and track its granulepos */
1446 ogg_stream_packetout(vf->os,NULL); 1421 ogg_stream_packetout(&vf->os,NULL);
1447 vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with 1422 vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with
1448 only tracking, no 1423 only tracking, no
1449 pcm_decode */ 1424 pcm_decode */
1450 vorbis_synthesis_blockin(&vf->vd,&vf->vb); 1425 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
1451 1426
1452 /* end of logical stream case is hard, especially with exact 1427 /* end of logical stream case is hard, especially with exact
1453 length positioning. */ 1428 length positioning. */
1454 1429
1455 if(op.granulepos>-1){ 1430 if(op.granulepos>-1){
1456 int i; 1431 int i;
1457 /* always believe the stream markers */ 1432 /* always believe the stream markers */
@@ -1460,20 +1435,20 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1460 for(i=0;i<vf->current_link;i++) 1435 for(i=0;i<vf->current_link;i++)
1461 vf->pcm_offset+=vf->pcmlengths[i*2+1]; 1436 vf->pcm_offset+=vf->pcmlengths[i*2+1];
1462 } 1437 }
1463 1438
1464 lastblock=thisblock; 1439 lastblock=thisblock;
1465 1440
1466 }else{ 1441 }else{
1467 if(ret<0 && ret!=OV_HOLE)break; 1442 if(ret<0 && ret!=OV_HOLE)break;
1468 1443
1469 /* suck in a new page */ 1444 /* suck in a new page */
1470 if(_get_next_page(vf,&og,-1)<0)break; 1445 if(_get_next_page(vf,&og,-1)<0)break;
1471 if(ogg_page_bos(&og))_decode_clear(vf); 1446 if(ogg_page_bos(&og))_decode_clear(vf);
1472 1447
1473 if(vf->ready_state<STREAMSET){ 1448 if(vf->ready_state<STREAMSET){
1474 long serialno=ogg_page_serialno(&og); 1449 long serialno=ogg_page_serialno(&og);
1475 int link; 1450 int link;
1476 1451
1477 for(link=0;link<vf->links;link++) 1452 for(link=0;link<vf->links;link++)
1478 if(vf->serialnos[link]==(ogg_uint32_t) serialno)break; 1453 if(vf->serialnos[link]==(ogg_uint32_t) serialno)break;
1479 if(link==vf->links) continue; 1454 if(link==vf->links) continue;
@@ -1481,17 +1456,13 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1481 1456
1482 vf->ready_state=STREAMSET; 1457 vf->ready_state=STREAMSET;
1483 vf->current_serialno=ogg_page_serialno(&og); 1458 vf->current_serialno=ogg_page_serialno(&og);
1484 ogg_stream_reset_serialno(vf->os,serialno); 1459 ogg_stream_reset_serialno(&vf->os,serialno);
1485 ret=_make_decode_ready(vf); 1460 ret=_make_decode_ready(vf);
1486 if(ret){ 1461 if(ret)return ret;
1487 ogg_page_release(&og);
1488 ogg_packet_release(&op);
1489 return ret;
1490 }
1491 lastblock=0; 1462 lastblock=0;
1492 } 1463 }
1493 1464
1494 ogg_stream_pagein(vf->os,&og); 1465 ogg_stream_pagein(&vf->os,&og);
1495 } 1466 }
1496 } 1467 }
1497 1468
@@ -1506,18 +1477,15 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1506 if(samples>target)samples=target; 1477 if(samples>target)samples=target;
1507 vorbis_synthesis_read(&vf->vd,samples); 1478 vorbis_synthesis_read(&vf->vd,samples);
1508 vf->pcm_offset+=samples; 1479 vf->pcm_offset+=samples;
1509 1480
1510 if(samples<target) 1481 if(samples<target)
1511 if(_fetch_and_process_packet(vf,1,1)<=0) 1482 if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
1512 vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */ 1483 vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1513 } 1484 }
1514
1515 ogg_page_release(&og);
1516 ogg_packet_release(&op);
1517 return 0; 1485 return 0;
1518} 1486}
1519 1487
1520/* seek to a playback time relative to the decompressed pcm stream 1488/* seek to a playback time relative to the decompressed pcm stream
1521 returns zero on success, nonzero on failure */ 1489 returns zero on success, nonzero on failure */
1522int ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){ 1490int ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){
1523 /* translate time to PCM position and call ov_pcm_seek */ 1491 /* translate time to PCM position and call ov_pcm_seek */
@@ -1529,7 +1497,7 @@ int ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){
1529 if(vf->ready_state<OPENED)return(OV_EINVAL); 1497 if(vf->ready_state<OPENED)return(OV_EINVAL);
1530 if(!vf->seekable)return(OV_ENOSEEK); 1498 if(!vf->seekable)return(OV_ENOSEEK);
1531 if(milliseconds<0)return(OV_EINVAL); 1499 if(milliseconds<0)return(OV_EINVAL);
1532 1500
1533 /* which bitstream section does this time offset occur in? */ 1501 /* which bitstream section does this time offset occur in? */
1534 for(link=0;link<vf->links;link++){ 1502 for(link=0;link<vf->links;link++){
1535 ogg_int64_t addsec = ov_time_total(vf,link); 1503 ogg_int64_t addsec = ov_time_total(vf,link);
@@ -1559,7 +1527,7 @@ ogg_int64_t ov_time_tell(OggVorbis_File *vf){
1559 int link=0; 1527 int link=0;
1560 ogg_int64_t pcm_total=0; 1528 ogg_int64_t pcm_total=0;
1561 ogg_int64_t time_total=0; 1529 ogg_int64_t time_total=0;
1562 1530
1563 if(vf->ready_state<OPENED)return(OV_EINVAL); 1531 if(vf->ready_state<OPENED)return(OV_EINVAL);
1564 if(vf->seekable){ 1532 if(vf->seekable){
1565 pcm_total=ov_pcm_total(vf,-1); 1533 pcm_total=ov_pcm_total(vf,-1);
@@ -1579,7 +1547,7 @@ ogg_int64_t ov_time_tell(OggVorbis_File *vf){
1579/* link: -1) return the vorbis_info struct for the bitstream section 1547/* link: -1) return the vorbis_info struct for the bitstream section
1580 currently being decoded 1548 currently being decoded
1581 0-n) to request information for a specific bitstream section 1549 0-n) to request information for a specific bitstream section
1582 1550
1583 In the case of a non-seekable bitstream, any call returns the 1551 In the case of a non-seekable bitstream, any call returns the
1584 current bitstream. NULL in the case that the machine is not 1552 current bitstream. NULL in the case that the machine is not
1585 initialized */ 1553 initialized */
@@ -1634,9 +1602,12 @@ long ov_read_fixed(OggVorbis_File *vf,ogg_int32_t ***pcm_channels,int length,
1634 1602
1635 /* suck in another packet */ 1603 /* suck in another packet */
1636 { 1604 {
1637 int ret=_fetch_and_process_packet(vf,1,1); 1605 int ret=_fetch_and_process_packet(vf,NULL,1,1);
1638 if(ret==OV_EOF)return(0); 1606 if(ret==OV_EOF)
1639 if(ret<=0)return(ret); 1607 return(0);
1608 if(ret<=0)
1609 return(ret);
1640 } 1610 }
1641 } 1611 }
1642} 1612}
1613