1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Nils Wallménius 2010-12-06 14:36:52 +00:00
parent 1f64b7fb1f
commit 67efbc1387
8 changed files with 3153 additions and 1504 deletions

File diff suppressed because it is too large Load diff

View file

@ -279,7 +279,7 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
long *bufend = buf + n; long *bufend = buf + n;
while (bufptr<bufend) { while (bufptr<bufend) {
if (b->headend > 8) { if(b->endbyte < b->storage - 8) {
ogg_uint32_t *ptr; ogg_uint32_t *ptr;
unsigned long bit, bitend; unsigned long bit, bitend;
unsigned long adr; unsigned long adr;
@ -292,10 +292,10 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
const ogg_uint32_t *book_codelist = book->codelist; const ogg_uint32_t *book_codelist = book->codelist;
const char *book_dec_codelengths = book->dec_codelengths; const char *book_dec_codelengths = book->dec_codelengths;
adr = (unsigned long)b->headptr; adr = (unsigned long)b->ptr;
bit = (adr&3)*8+b->headbit; bit = (adr&3)*8+b->endbit;
ptr = (ogg_uint32_t*)(adr&~3); ptr = (ogg_uint32_t*)(adr&~3);
bitend = ((adr&3)+b->headend)*8; bitend = ((adr&3)+(b->storage-b->endbyte))*8;
while (bufptr<bufend){ while (bufptr<bufend){
if (UNLIKELY(cachesize<book_dec_maxlength)) { if (UNLIKELY(cachesize<book_dec_maxlength)) {
if (bit-cachesize+32>=bitend) if (bit-cachesize+32>=bitend)
@ -323,11 +323,11 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
cache >>= l; cache >>= l;
} }
adr=(unsigned long)b->headptr; adr=(unsigned long)b->ptr;
bit-=(adr&3)*8+cachesize; bit-=(adr&3)*8+cachesize;
b->headend-=(bit/8); b->endbyte+=bit/8;
b->headptr+=bit/8; b->ptr+=bit/8;
b->headbit=bit%8; b->endbit=bit&7;
} else { } else {
long r = decode_packed_entry_number(book, b); long r = decode_packed_entry_number(book, b);
if (r == -1) return bufptr-buf; if (r == -1) return bufptr-buf;
@ -337,7 +337,6 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
return n; return n;
} }
/* Decode side is specced and easier, because we don't need to find /* Decode side is specced and easier, because we don't need to find
matches using different criteria; we simply read and map. There are matches using different criteria; we simply read and map. There are
two things we need to do 'depending': two things we need to do 'depending':
@ -570,3 +569,4 @@ long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,
} }
return(0); return(0);
} }

File diff suppressed because it is too large Load diff

View file

@ -240,7 +240,7 @@ int vorbis_synthesis_idheader(ogg_packet *op){
char buffer[6]; char buffer[6];
if(op){ if(op){
oggpack_readinit(&opb,op->packet); oggpack_readinit(&opb,op->packet,op->bytes);
if(!op->b_o_s) if(!op->b_o_s)
return(0); /* Not the initial packet */ return(0); /* Not the initial packet */
@ -268,7 +268,7 @@ int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op)
oggpack_buffer opb; oggpack_buffer opb;
if(op){ if(op){
oggpack_readinit(&opb,op->packet); oggpack_readinit(&opb,op->packet,op->bytes);
/* Which of the three types of header is this? */ /* Which of the three types of header is this? */
/* Also verify header-ness, vorbis */ /* Also verify header-ness, vorbis */

View file

@ -56,7 +56,7 @@ typedef struct OggVorbis_File {
int seekable; int seekable;
ogg_int64_t offset; ogg_int64_t offset;
ogg_int64_t end; ogg_int64_t end;
ogg_sync_state *oy; ogg_sync_state oy;
/* If the FILE handle isn't seekable (eg, a pipe), only the current /* If the FILE handle isn't seekable (eg, a pipe), only the current
stream appears */ stream appears */
@ -77,7 +77,7 @@ typedef struct OggVorbis_File {
ogg_int64_t bittrack; ogg_int64_t bittrack;
ogg_int64_t samptrack; ogg_int64_t samptrack;
ogg_stream_state *os; /* take physical pages, weld into a logical ogg_stream_state os; /* take physical pages, weld into a logical
stream of packets */ stream of packets */
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
vorbis_block vb; /* local working space for packet->PCM decode */ vorbis_block vb; /* local working space for packet->PCM decode */
@ -87,13 +87,11 @@ typedef struct OggVorbis_File {
} OggVorbis_File; } OggVorbis_File;
extern int ov_clear(OggVorbis_File *vf); extern int ov_clear(OggVorbis_File *vf);
//extern int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf, extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf,
char *initial, long ibytes, ov_callbacks callbacks); const char *initial, long ibytes, ov_callbacks callbacks);
//extern int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf, extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf,
char *initial, long ibytes, ov_callbacks callbacks); const char *initial, long ibytes, ov_callbacks callbacks);
extern int ov_test_open(OggVorbis_File *vf); extern int ov_test_open(OggVorbis_File *vf);
extern long ov_bitrate(OggVorbis_File *vf,int i); extern long ov_bitrate(OggVorbis_File *vf,int i);

View file

@ -1,17 +1,17 @@
/******************************************************************** /********************************************************************
* * * *
* THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* * * *
* THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
* BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * by the Xiph.Org Foundation http://www.xiph.org/ *
* * * *
******************************************************************** ********************************************************************
function: subsumed libogg includes function: toplevel libogg include
last mod: $Id$
********************************************************************/ ********************************************************************/
#ifndef _OGG_H #ifndef _OGG_H
@ -21,241 +21,238 @@
extern "C" { extern "C" {
#endif #endif
#include <stddef.h>
#include "os_types.h" #include "os_types.h"
typedef struct ogg_buffer_state{ extern const unsigned long mask[] ICONST_ATTR;
struct ogg_buffer *unused_buffers;
struct ogg_reference *unused_references;
int outstanding;
int shutdown;
} ogg_buffer_state;
typedef struct ogg_buffer { typedef struct {
unsigned char *data; void *iov_base;
long size; size_t iov_len;
int refcount; } ogg_iovec_t;
union { typedef struct {
ogg_buffer_state *owner; long endbyte;
struct ogg_buffer *next; int endbit;
} ptr;
} ogg_buffer;
typedef struct ogg_reference { unsigned char *buffer;
ogg_buffer *buffer; unsigned char *ptr;
long begin; long storage;
long length;
struct ogg_reference *next;
} ogg_reference;
typedef struct oggpack_buffer {
int headbit;
unsigned char *headptr;
long headend;
/* memory management */
ogg_reference *head;
ogg_reference *tail;
/* render the byte/bit counter API constant time */
long count; /* doesn't count the tail */
} oggpack_buffer; } oggpack_buffer;
typedef struct oggbyte_buffer { /* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
ogg_reference *baseref;
ogg_reference *ref; typedef struct {
unsigned char *ptr; unsigned char *header;
long pos; long header_len;
long end; unsigned char *body;
} oggbyte_buffer; long body_len;
} ogg_page;
typedef struct ogg_sync_state { /* ogg_stream_state contains the current encode/decode state of a logical
/* decode memory management pool */ Ogg bitstream **********************************************************/
ogg_buffer_state *bufferpool;
/* stream buffers */ typedef struct {
ogg_reference *fifo_head; unsigned char *body_data; /* bytes from packet bodies */
ogg_reference *fifo_tail; long body_storage; /* storage elements allocated */
long fifo_fill; long body_fill; /* elements stored; fill mark */
long body_returned; /* elements of fill returned */
/* stream sync management */
int unsynced;
int headerbytes;
int bodybytes;
} ogg_sync_state; int *lacing_vals; /* The values that will go to the segment table */
ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
this way, but it is simple coupled to the
lacing fifo */
long lacing_storage;
long lacing_fill;
long lacing_packet;
long lacing_returned;
typedef struct ogg_stream_state { #if 0
ogg_reference *header_head; unsigned char header[282]; /* working space for header encode */
ogg_reference *header_tail; int header_fill;
ogg_reference *body_head; #endif
ogg_reference *body_tail; int e_o_s; /* set when we have buffered the last packet in the
logical bitstream */
int e_o_s; /* set when we have buffered the last int b_o_s; /* set after we've written the initial page
packet in the logical bitstream */ of a logical bitstream */
int b_o_s; /* set after we've written the initial page ogg_uint32_t serialno;
of a logical bitstream */ long pageno;
long serialno; ogg_int64_t packetno; /* sequence number for decode; the framing
long pageno; knows where there's a hole in the data,
ogg_int64_t packetno; /* sequence number for decode; the framing but we need coupling so that the codec
knows where there's a hole in the data, (which is in a separate abstraction
but we need coupling so that the codec layer) also knows about the gap */
(which is in a seperate abstraction ogg_int64_t granulepos;
layer) also knows about the gap */
ogg_int64_t granulepos;
int lacing_fill;
ogg_uint32_t body_fill;
/* decode-side state data */
int holeflag;
int spanflag;
int clearflag;
int laceptr;
ogg_uint32_t body_fill_next;
} ogg_stream_state; } ogg_stream_state;
/* ogg_packet is used to encapsulate the data and metadata belonging
to a single raw Ogg/Vorbis packet *************************************/
typedef struct { typedef struct {
ogg_reference *packet; unsigned char *packet;
long bytes; long bytes;
long b_o_s; long b_o_s;
long e_o_s; long e_o_s;
ogg_int64_t granulepos;
ogg_int64_t packetno; /* sequence number for decode; the framing ogg_int64_t granulepos;
knows where there's a hole in the data,
but we need coupling so that the codec ogg_int64_t packetno; /* sequence number for decode; the framing
(which is in a seperate abstraction knows where there's a hole in the data,
layer) also knows about the gap */ but we need coupling so that the codec
(which is in a separate abstraction
layer) also knows about the gap */
} ogg_packet; } ogg_packet;
typedef struct { typedef struct {
ogg_reference *header; unsigned char *data;
int header_len; int storage;
ogg_reference *body; int fill;
long body_len; int returned;
} ogg_page;
int unsynced;
int headerbytes;
int bodybytes;
} ogg_sync_state;
/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ /* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
/*
extern void oggpack_writeinit(oggpack_buffer *b);
extern int oggpack_writecheck(oggpack_buffer *b);
extern void oggpack_writetrunc(oggpack_buffer *b,long bits);
extern void oggpack_writealign(oggpack_buffer *b);
extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
extern void oggpack_reset(oggpack_buffer *b);
extern void oggpack_writeclear(oggpack_buffer *b); */
extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
/* extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits); */
extern void oggpack_readinit(oggpack_buffer *b,ogg_reference *r); //extern long oggpack_look(oggpack_buffer *b,int bits);
extern long oggpack_look_full(oggpack_buffer *b,int bits); static inline long oggpack_look(oggpack_buffer *b,int bits){
extern long oggpack_read(oggpack_buffer *b,register int bits); unsigned long ret;
unsigned long m;
/* Inline a few, often called functions */ if(bits<0 || bits>32) return -1;
m=mask[bits];
bits+=b->endbit;
/* mark read process as having run off the end */ if(b->endbyte >= b->storage-4){
static inline void _adv_halt(oggpack_buffer *b){ /* not the main path */
b->headptr=b->head->buffer->data+b->head->begin+b->head->length; if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
b->headend=-1; /* special case to avoid reading b->ptr[0], which might be past the end of
b->headbit=0; the buffer; also skips some useless accounting */
} else if(!bits)return(0L);
/* spans forward, skipping as many bytes as headend is negative; if
headend is zero, simply finds next byte. If we're up to the end
of the buffer, leaves headend at zero. If we've read past the end,
halt the decode process. */
static inline void _span(oggpack_buffer *b){
while(b->headend<1){
if(b->head->next){
b->count+=b->head->length;
b->head=b->head->next;
b->headptr=b->head->buffer->data+b->head->begin-b->headend;
b->headend+=b->head->length;
}else{
/* we've either met the end of decode, or gone past it. halt
only if we're past */
if(b->headend<0 || b->headbit)
/* read has fallen off the end */
_adv_halt(b);
break;
}
} }
}
/* limited to 32 at a time */ ret=b->ptr[0]>>b->endbit;
static inline void oggpack_adv(oggpack_buffer *b,int bits){ if(bits>8){
bits+=b->headbit; ret|=b->ptr[1]<<(8-b->endbit);
b->headbit=bits&7; if(bits>16){
b->headptr+=bits/8; ret|=b->ptr[2]<<(16-b->endbit);
if((b->headend-=((unsigned)bits)/8)<1)_span(b); if(bits>24){
} ret|=b->ptr[3]<<(24-b->endbit);
if(bits>32 && b->endbit)
static inline long oggpack_look(oggpack_buffer *b, int bits){ ret|=b->ptr[4]<<(32-b->endbit);
if(bits+b->headbit < b->headend<<3){
extern const unsigned long oggpack_mask[];
unsigned long m=oggpack_mask[bits];
unsigned long ret=-1;
bits+=b->headbit;
ret=b->headptr[0]>>b->headbit;
if(bits>8){
ret|=b->headptr[1]<<(8-b->headbit);
if(bits>16){
ret|=b->headptr[2]<<(16-b->headbit);
if(bits>24){
ret|=b->headptr[3]<<(24-b->headbit);
if(bits>32 && b->headbit)
ret|=b->headptr[4]<<(32-b->headbit);
}
} }
} }
return ret&m;
}else{
return oggpack_look_full(b, bits);
} }
return(m&ret);
} }
extern long oggpack_look1(oggpack_buffer *b);
//extern void oggpack_adv(oggpack_buffer *b,int bits);
static inline void oggpack_adv(oggpack_buffer *b,int bits){
bits+=b->endbit;
if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
b->ptr+=bits/8;
b->endbyte+=bits/8;
b->endbit=bits&7;
return;
overflow:
b->ptr=NULL;
b->endbyte=b->storage;
b->endbit=1;
}
extern void oggpack_adv1(oggpack_buffer *b);
extern long oggpack_read(oggpack_buffer *b,int bits);
extern long oggpack_read1(oggpack_buffer *b);
#if 0
extern long oggpack_bytes(oggpack_buffer *b);
extern long oggpack_bits(oggpack_buffer *b);
extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);
extern void oggpackB_writeinit(oggpack_buffer *b);
extern int oggpackB_writecheck(oggpack_buffer *b);
extern void oggpackB_writetrunc(oggpack_buffer *b,long bits);
extern void oggpackB_writealign(oggpack_buffer *b);
extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits);
extern void oggpackB_reset(oggpack_buffer *b);
extern void oggpackB_writeclear(oggpack_buffer *b);
extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits);
extern long oggpackB_look(oggpack_buffer *b,int bits);
extern long oggpackB_look1(oggpack_buffer *b);
extern void oggpackB_adv(oggpack_buffer *b,int bits);
extern void oggpackB_adv1(oggpack_buffer *b);
extern long oggpackB_read(oggpack_buffer *b,int bits);
extern long oggpackB_read1(oggpack_buffer *b);
extern long oggpackB_bytes(oggpack_buffer *b);
extern long oggpackB_bits(oggpack_buffer *b);
extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b);
# endif
/* Ogg BITSTREAM PRIMITIVES: encoding **************************/
#if 0
extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov,
int count, long e_o_s, ogg_int64_t granulepos);
extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
extern int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill);
extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
#endif
/* Ogg BITSTREAM PRIMITIVES: decoding **************************/ /* Ogg BITSTREAM PRIMITIVES: decoding **************************/
extern ogg_sync_state *ogg_sync_create(void); extern int ogg_sync_init(ogg_sync_state *oy);
extern int ogg_sync_destroy(ogg_sync_state *oy); extern int ogg_sync_clear(ogg_sync_state *oy);
extern int ogg_sync_reset(ogg_sync_state *oy); extern int ogg_sync_reset(ogg_sync_state *oy);
extern int ogg_sync_destroy(ogg_sync_state *oy);
extern int ogg_sync_check(ogg_sync_state *oy);
extern unsigned char *ogg_sync_bufferin(ogg_sync_state *oy, long size); extern char *ogg_sync_buffer(ogg_sync_state *oy, long size);
extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes);
extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);
/* Ogg BITSTREAM PRIMITIVES: general ***************************/ /* Ogg BITSTREAM PRIMITIVES: general ***************************/
extern ogg_stream_state *ogg_stream_create(int serialno); extern int ogg_stream_init(ogg_stream_state *os,int serialno);
extern int ogg_stream_destroy(ogg_stream_state *os); extern int ogg_stream_clear(ogg_stream_state *os);
extern int ogg_stream_reset(ogg_stream_state *os); extern int ogg_stream_reset(ogg_stream_state *os);
extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
extern int ogg_stream_destroy(ogg_stream_state *os);
extern int ogg_stream_check(ogg_stream_state *os);
extern int ogg_stream_eos(ogg_stream_state *os); extern int ogg_stream_eos(ogg_stream_state *os);
extern int ogg_page_checksum_set(ogg_page *og); extern void ogg_page_checksum_set(ogg_page *og);
extern int ogg_page_version(ogg_page *og); extern int ogg_page_version(const ogg_page *og);
extern int ogg_page_continued(ogg_page *og); extern int ogg_page_continued(const ogg_page *og);
extern int ogg_page_bos(ogg_page *og); extern int ogg_page_bos(const ogg_page *og);
extern int ogg_page_eos(ogg_page *og); extern int ogg_page_eos(const ogg_page *og);
extern ogg_int64_t ogg_page_granulepos(ogg_page *og); extern ogg_int64_t ogg_page_granulepos(const ogg_page *og);
extern ogg_uint32_t ogg_page_serialno(ogg_page *og); extern ogg_uint32_t ogg_page_serialno(const ogg_page *og);
extern ogg_uint32_t ogg_page_pageno(ogg_page *og); extern long ogg_page_pageno(const ogg_page *og);
extern int ogg_page_getbuffer(ogg_page *og, unsigned char **buffer); extern int ogg_page_packets(const ogg_page *og);
extern int ogg_packet_release(ogg_packet *op); extern void ogg_packet_clear(ogg_packet *op);
extern int ogg_page_release(ogg_page *og);
extern void ogg_page_dup(ogg_page *d, ogg_page *s);
/* Ogg BITSTREAM PRIMITIVES: return codes ***************************/
#define OGG_SUCCESS 0
#define OGG_HOLE -10
#define OGG_SPAN -11
#define OGG_EVERSION -12
#define OGG_ESERIAL -13
#define OGG_EINVAL -14
#define OGG_EEOS -15
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -37,7 +37,7 @@ static inline int _vorbis_synthesis1(vorbis_block *vb,ogg_packet *op,int decodep
/* first things first. Make sure decode is ready */ /* first things first. Make sure decode is ready */
_vorbis_block_ripcord(vb); _vorbis_block_ripcord(vb);
oggpack_readinit(opb,op->packet); oggpack_readinit(opb,op->packet,op->bytes);
/* Check the packet type */ /* Check the packet type */
if(oggpack_read(opb,1)!=0){ if(oggpack_read(opb,1)!=0){
@ -102,6 +102,8 @@ int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){
return _vorbis_synthesis1(vb,op,1); return _vorbis_synthesis1(vb,op,1);
} }
/* used to track pcm position without actually performing decode.
Useful for sequential 'fast forward' */
int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){ int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){
return _vorbis_synthesis1(vb,op,0); return _vorbis_synthesis1(vb,op,0);
} }
@ -111,7 +113,7 @@ long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
oggpack_buffer opb; oggpack_buffer opb;
int mode; int mode;
oggpack_readinit(&opb,op->packet); oggpack_readinit(&opb,op->packet,op->bytes);
/* Check the packet type */ /* Check the packet type */
if(oggpack_read(&opb,1)!=0){ if(oggpack_read(&opb,1)!=0){

View file

@ -61,10 +61,11 @@
/* read a little more data from the file/pipe into the ogg_sync framer */ /* read a little more data from the file/pipe into the ogg_sync framer */
static long _get_data(OggVorbis_File *vf){ static long _get_data(OggVorbis_File *vf){
if(!(vf->callbacks.read_func))return(-1);
if(vf->datasource){ if(vf->datasource){
char *buffer=(char *)ogg_sync_bufferin(vf->oy,CHUNKSIZE); char *buffer=ogg_sync_buffer(&vf->oy,CHUNKSIZE);
long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource); long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource);
if(bytes>0)ogg_sync_wrote(vf->oy,bytes); if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
return(bytes); return(bytes);
}else }else
return(0); return(0);
@ -77,7 +78,7 @@ static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
(vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1) (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1)
return OV_EREAD; return OV_EREAD;
vf->offset=offset; vf->offset=offset;
ogg_sync_reset(vf->oy); ogg_sync_reset(&vf->oy);
}else{ }else{
/* shouldn't happen unless someone writes a broken callback */ /* shouldn't happen unless someone writes a broken callback */
return OV_EFAULT; return OV_EFAULT;
@ -96,9 +97,7 @@ static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
n) search for a new page beginning for n bytes n) search for a new page beginning for n bytes
return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD) return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
n) found a page at absolute offset n n) found a page at absolute offset n */
produces a refcounted page */
static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og, static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
ogg_int64_t boundary){ ogg_int64_t boundary){
@ -107,7 +106,7 @@ static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
long more; long more;
if(boundary>0 && vf->offset>=boundary)return(OV_FALSE); if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
more=ogg_sync_pageseek(vf->oy,og); more=ogg_sync_pageseek(&vf->oy,og);
if(more<0){ if(more<0){
/* skipped n bytes */ /* skipped n bytes */
@ -137,8 +136,7 @@ static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
position. Much dirtier than the above as Ogg doesn't have any position. Much dirtier than the above as Ogg doesn't have any
backward search linkage. no 'readp' as it will certainly have to backward search linkage. no 'readp' as it will certainly have to
read. */ read. */
/* returns offset or OV_EREAD, OV_FAULT and produces a refcounted page */ /* returns offset or OV_EREAD, OV_FAULT */
static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){ static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
ogg_int64_t begin=vf->offset; ogg_int64_t begin=vf->offset;
ogg_int64_t end=begin; ogg_int64_t end=begin;
@ -154,6 +152,7 @@ static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
if(ret)return(ret); if(ret)return(ret);
while(vf->offset<end){ while(vf->offset<end){
memset(og,0,sizeof(*og));
ret=_get_next_page(vf,og,end-vf->offset); ret=_get_next_page(vf,og,end-vf->offset);
if(ret==OV_EREAD)return(OV_EREAD); if(ret==OV_EREAD)return(OV_EREAD);
if(ret<0){ if(ret<0){
@ -168,7 +167,6 @@ static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
holding the last page. In multiplexed (or noncompliant streams), holding the last page. In multiplexed (or noncompliant streams),
we will probably have to re-read the last page we saw */ we will probably have to re-read the last page we saw */
if(og->header_len==0){ if(og->header_len==0){
ogg_page_release(og);
ret=_seek_helper(vf,offset); ret=_seek_helper(vf,offset);
if(ret)return(ret); if(ret)return(ret);
@ -219,14 +217,14 @@ static int _lookup_page_serialno(ogg_page *og, ogg_uint32_t *serialno_list, int
static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf, static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
ogg_uint32_t *serial_list, int serial_n, ogg_uint32_t *serial_list, int serial_n,
int *serialno, ogg_int64_t *granpos){ int *serialno, ogg_int64_t *granpos){
ogg_page og={0,0,0,0}; ogg_page og;
ogg_int64_t begin=vf->offset; ogg_int64_t begin=vf->offset;
ogg_int64_t end=begin; ogg_int64_t end=begin;
ogg_int64_t ret; ogg_int64_t ret;
ogg_int64_t prefoffset=-1; ogg_int64_t prefoffset=-1;
ogg_int64_t offset=-1; ogg_int64_t offset=-1;
ogg_uint32_t ret_serialno=-1; ogg_int64_t ret_serialno=-1;
ogg_int64_t ret_gran=-1; ogg_int64_t ret_gran=-1;
while(offset==-1){ while(offset==-1){
@ -241,13 +239,11 @@ static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
ret=_get_next_page(vf,&og,end-vf->offset); ret=_get_next_page(vf,&og,end-vf->offset);
if(ret==OV_EREAD)return(OV_EREAD); if(ret==OV_EREAD)return(OV_EREAD);
if(ret<0){ if(ret<0){
ogg_page_release(&og);
break; break;
}else{ }else{
ret_serialno=ogg_page_serialno(&og); ret_serialno=ogg_page_serialno(&og);
ret_gran=ogg_page_granulepos(&og); ret_gran=ogg_page_granulepos(&og);
offset=ret; offset=ret;
ogg_page_release(&og);
if(ret_serialno == (ogg_uint32_t) *serialno){ if(ret_serialno == (ogg_uint32_t) *serialno){
prefoffset=ret; prefoffset=ret;
@ -276,23 +272,18 @@ static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
/* uses the local ogg_stream storage in vf; this is important for /* uses the local ogg_stream storage in vf; this is important for
non-streaming input sources */ non-streaming input sources */
/* consumes the page that's passed in (if any) */ static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
ogg_uint32_t **serialno_list, int *serialno_n,
static int _fetch_headers(OggVorbis_File *vf,
vorbis_info *vi,
vorbis_comment *vc,
ogg_uint32_t **serialno_list,
int *serialno_n,
ogg_page *og_ptr){ ogg_page *og_ptr){
ogg_page og={0,0,0,0}; ogg_page og;
ogg_packet op={0,0,0,0,0,0}; ogg_packet op;
int i,ret; int i,ret;
int allbos=0; int allbos=0;
if(!og_ptr){ if(!og_ptr){
ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE); ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
if(llret==OV_EREAD)return(OV_EREAD); if(llret==OV_EREAD)return(OV_EREAD);
if(llret<0)return OV_ENOTVORBIS; if(llret<0)return(OV_ENOTVORBIS);
og_ptr=&og; og_ptr=&og;
} }
@ -320,10 +311,10 @@ static int _fetch_headers(OggVorbis_File *vf,
if(vf->ready_state<STREAMSET){ if(vf->ready_state<STREAMSET){
/* we don't have a vorbis stream in this link yet, so begin /* we don't have a vorbis stream in this link yet, so begin
prospective stream setup. We need a stream to get packets */ prospective stream setup. We need a stream to get packets */
ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr)); ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
ogg_stream_pagein(vf->os,og_ptr); ogg_stream_pagein(&vf->os,og_ptr);
if(ogg_stream_packetout(vf->os,&op) > 0 && if(ogg_stream_packetout(&vf->os,&op) > 0 &&
vorbis_synthesis_idheader(&op)){ vorbis_synthesis_idheader(&op)){
/* vorbis header; continue setup */ /* vorbis header; continue setup */
vf->ready_state=STREAMSET; vf->ready_state=STREAMSET;
@ -348,8 +339,8 @@ static int _fetch_headers(OggVorbis_File *vf,
/* if this page also belongs to our vorbis stream, submit it and break */ /* if this page also belongs to our vorbis stream, submit it and break */
if(vf->ready_state==STREAMSET && if(vf->ready_state==STREAMSET &&
(ogg_uint32_t) vf->os->serialno == ogg_page_serialno(og_ptr)){ vf->os.serialno == ogg_page_serialno(og_ptr)){
ogg_stream_pagein(vf->os,og_ptr); ogg_stream_pagein(&vf->os,og_ptr);
break; break;
} }
} }
@ -367,7 +358,7 @@ static int _fetch_headers(OggVorbis_File *vf,
while(i<2){ /* get a packet loop */ while(i<2){ /* get a packet loop */
int result=ogg_stream_packetout(vf->os,&op); int result=ogg_stream_packetout(&vf->os,&op);
if(result==0)break; if(result==0)break;
if(result==-1){ if(result==-1){
ret=OV_EBADHEADER; ret=OV_EBADHEADER;
@ -387,8 +378,8 @@ static int _fetch_headers(OggVorbis_File *vf,
} }
/* if this page belongs to the correct stream, go parse it */ /* if this page belongs to the correct stream, go parse it */
if((ogg_uint32_t) vf->os->serialno == ogg_page_serialno(og_ptr)){ if(vf->os.serialno == ogg_page_serialno(og_ptr)){
ogg_stream_pagein(vf->os,og_ptr); ogg_stream_pagein(&vf->os,og_ptr);
break; break;
} }
@ -406,15 +397,10 @@ static int _fetch_headers(OggVorbis_File *vf,
} }
} }
ogg_packet_release(&op);
ogg_page_release(&og);
return 0; return 0;
} }
bail_header: bail_header:
ogg_packet_release(&op);
ogg_page_release(&og);
vorbis_info_clear(vi); vorbis_info_clear(vi);
vorbis_comment_clear(vc); vorbis_comment_clear(vc);
vf->ready_state=OPENED; vf->ready_state=OPENED;
@ -427,25 +413,23 @@ static int _fetch_headers(OggVorbis_File *vf,
audio, however this is only called during stream parsing upon audio, however this is only called during stream parsing upon
seekable open. */ seekable open. */
static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){ static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
ogg_page og={0,0,0,0}; ogg_page og;
ogg_int64_t accumulated=0,pos; ogg_int64_t accumulated=0;
long lastblock=-1; long lastblock=-1;
int result; int result;
int serialno = vf->os->serialno; ogg_uint32_t serialno = vf->os.serialno;
while(1){ while(1){
ogg_packet op={0,0,0,0,0,0}; ogg_packet op;
if(_get_next_page(vf,&og,-1)<0) if(_get_next_page(vf,&og,-1)<0)
break; /* should not be possible unless the file is truncated/mangled */ break; /* should not be possible unless the file is truncated/mangled */
if(ogg_page_bos(&og)) break; if(ogg_page_bos(&og)) break;
if(ogg_page_serialno(&og)!=(ogg_uint32_t) serialno) continue; if(ogg_page_serialno(&og)!= serialno) continue;
pos=ogg_page_granulepos(&og);
/* count blocksizes of all frames in the page */ /* count blocksizes of all frames in the page */
ogg_stream_pagein(vf->os,&og); ogg_stream_pagein(&vf->os,&og);
while((result=ogg_stream_packetout(vf->os,&op))){ while((result=ogg_stream_packetout(&vf->os,&op))){
if(result>0){ /* ignore holes */ if(result>0){ /* ignore holes */
long thisblock=vorbis_packet_blocksize(vi,&op); long thisblock=vorbis_packet_blocksize(vi,&op);
if(lastblock!=-1) if(lastblock!=-1)
@ -453,11 +437,10 @@ static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
lastblock=thisblock; lastblock=thisblock;
} }
} }
ogg_packet_release(&op);
if(pos!=-1){ if(ogg_page_granulepos(&og)!=-1){
/* pcm offset of last packet on the first audio page */ /* pcm offset of last packet on the first audio page */
accumulated= pos-accumulated; accumulated= ogg_page_granulepos(&og)-accumulated;
break; break;
} }
} }
@ -466,11 +449,9 @@ static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
the beginning, a normal occurrence; set the offset to zero */ the beginning, a normal occurrence; set the offset to zero */
if(accumulated<0)accumulated=0; if(accumulated<0)accumulated=0;
ogg_page_release(&og);
return accumulated; return accumulated;
} }
/* finds each bitstream link one at a time using a bisection search /* finds each bitstream link one at a time using a bisection search
(has to begin by knowing the offset of the lb's initial page). (has to begin by knowing the offset of the lb's initial page).
Recurses for each link so it can alloc the link storage after Recurses for each link so it can alloc the link storage after
@ -484,14 +465,14 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
ogg_uint32_t *currentno_list, ogg_uint32_t *currentno_list,
int currentnos, int currentnos,
long m){ long m){
ogg_int64_t pcmoffset; ogg_int64_t pcmoffset;
ogg_int64_t dataoffset=searched; ogg_int64_t dataoffset=searched;
ogg_int64_t endsearched=end; ogg_int64_t endsearched=end;
ogg_int64_t next=end; ogg_int64_t next=end;
ogg_int64_t searchgran=-1; ogg_int64_t searchgran=-1;
ogg_page og;
ogg_int64_t ret,last; ogg_int64_t ret,last;
int serialno = vf->os->serialno; int serialno = vf->os.serialno;
/* invariants: /* invariants:
we have the headers and serialnos for the link beginning at 'begin' we have the headers and serialnos for the link beginning at 'begin'
@ -538,7 +519,6 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
/* the below guards against garbage seperating the last and /* the below guards against garbage seperating the last and
first pages of two links. */ first pages of two links. */
while(searched<endsearched){ while(searched<endsearched){
ogg_page og={0,0,0,0};
ogg_int64_t bisect; ogg_int64_t bisect;
if(endsearched-searched<CHUNKSIZE){ if(endsearched-searched<CHUNKSIZE){
@ -547,8 +527,10 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
bisect=(searched+endsearched)/2; bisect=(searched+endsearched)/2;
} }
ret=_seek_helper(vf,bisect); if(bisect != vf->offset){
if(ret)return(ret); ret=_seek_helper(vf,bisect);
if(ret)return(ret);
}
last=_get_next_page(vf,&og,-1); last=_get_next_page(vf,&og,-1);
if(last==OV_EREAD)return(OV_EREAD); if(last==OV_EREAD)return(OV_EREAD);
@ -556,9 +538,8 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
endsearched=bisect; endsearched=bisect;
if(last>=0)next=last; if(last>=0)next=last;
}else{ }else{
searched=last+og.header_len+og.body_len; searched=vf->offset;
} }
ogg_page_release(&og);
} }
/* Bisection point found */ /* Bisection point found */
@ -580,7 +561,7 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL); ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL);
if(ret)return(ret); if(ret)return(ret);
serialno = vf->os->serialno; serialno = vf->os.serialno;
dataoffset = vf->offset; dataoffset = vf->offset;
/* this will consume a page, however the next bistection always /* this will consume a page, however the next bistection always
@ -627,8 +608,8 @@ static int _make_decode_ready(OggVorbis_File *vf){
static int _open_seekable2(OggVorbis_File *vf){ static int _open_seekable2(OggVorbis_File *vf){
ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1; ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1;
int endserial=vf->os->serialno; int endserial=vf->os.serialno;
int serialno=vf->os->serialno; int serialno=vf->os.serialno;
/* we're partially open and have a first link header state in /* we're partially open and have a first link header state in
storage in vf */ storage in vf */
@ -684,64 +665,57 @@ static void _decode_clear(OggVorbis_File *vf){
1) got a packet 1) got a packet
*/ */
STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf, static int _fetch_and_process_packet(OggVorbis_File *vf,
int readp, ogg_packet *op_in,
int spanp) ICODE_ATTR_TREMOR_NOT_MDCT;
STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
int readp, int readp,
int spanp){ int spanp){
ogg_page og={0,0,0,0}; ogg_page og;
ogg_packet op={0,0,0,0,0,0};
int ret=0;
/* handle one packet. Try to fetch it from current stream state */ /* handle one packet. Try to fetch it from current stream state */
/* extract packets from page */ /* extract packets from page */
while(1){ while(1){
if(vf->ready_state==STREAMSET){ if(vf->ready_state==STREAMSET){
ret=_make_decode_ready(vf); int ret=_make_decode_ready(vf);
if(ret<0) goto cleanup; if(ret<0)return ret;
} }
/* process a packet if we can. If the machine isn't loaded, /* process a packet if we can. If the machine isn't loaded,
neither is a page */ neither is a page */
if(vf->ready_state==INITSET){ if(vf->ready_state==INITSET){
while(1) { while(1) {
int result=ogg_stream_packetout(vf->os,&op); ogg_packet op;
ogg_packet *op_ptr=(op_in?op_in:&op);
int result=ogg_stream_packetout(&vf->os,op_ptr);
ogg_int64_t granulepos; ogg_int64_t granulepos;
if(result==-1){ op_in=NULL;
ret=OV_HOLE; /* hole in the data. */ if(result==-1)return(OV_HOLE); /* hole in the data. */
goto cleanup;
}
if(result>0){ if(result>0){
/* got a packet. process it */ /* got a packet. process it */
granulepos=op.granulepos; granulepos=op_ptr->granulepos;
if(!vorbis_synthesis(&vf->vb,&op)){ /* lazy check for lazy if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy
header handling. The header handling. The
header packets aren't header packets aren't
audio, so if/when we audio, so if/when we
submit them, submit them,
vorbis_synthesis will vorbis_synthesis will
reject them */ reject them */
/* suck in the synthesis data and track bitrate */ /* suck in the synthesis data and track bitrate */
{ {
int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL); int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
/* for proper use of libvorbis within libvorbisfile, /* for proper use of libvorbis within libvorbisfile,
oldsamples will always be zero. */ oldsamples will always be zero. */
if(oldsamples){ if(oldsamples)return(OV_EFAULT);
ret=OV_EFAULT;
goto cleanup;
}
vorbis_synthesis_blockin(&vf->vd,&vf->vb); vorbis_synthesis_blockin(&vf->vd,&vf->vb);
vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples; vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
vf->bittrack+=op.bytes*8; vf->bittrack+=op_ptr->bytes*8;
} }
/* update the pcm offset. */ /* update the pcm offset. */
if(granulepos!=-1 && !op.e_o_s){ if(granulepos!=-1 && !op_ptr->e_o_s){
int link=(vf->seekable?vf->current_link:0); int link=(vf->seekable?vf->current_link:0);
int i,samples; int i,samples;
@ -755,7 +729,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
granulepos declares the last frame in the stream, and the granulepos declares the last frame in the stream, and the
last packet of the last page may be a partial frame. last packet of the last page may be a partial frame.
So, we need a previous granulepos from an in-sequence page So, we need a previous granulepos from an in-sequence page
to have a reference point. Thus the !op.e_o_s clause to have a reference point. Thus the !op_ptr->e_o_s clause
above */ above */
if(vf->seekable && link>0) if(vf->seekable && link>0)
@ -772,8 +746,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
granulepos+=vf->pcmlengths[i*2+1]; granulepos+=vf->pcmlengths[i*2+1];
vf->pcm_offset=granulepos; vf->pcm_offset=granulepos;
} }
ret=1; return(1);
goto cleanup;
} }
} }
else else
@ -782,7 +755,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
} }
if(vf->ready_state>=OPENED){ if(vf->ready_state>=OPENED){
ogg_int64_t lret; ogg_int64_t ret;
while(1){ while(1){
/* the loop is not strictly necessary, but there's no sense in /* 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,
part of a different logical bitstream; keep reading until part of a different logical bitstream; keep reading until
we get one with the correct serialno */ we get one with the correct serialno */
if(!readp){ if(!readp)return(0);
ret=0; if((ret=_get_next_page(vf,&og,-1))<0){
goto cleanup; return(OV_EOF); /* eof. leave unitialized */
}
if((lret=_get_next_page(vf,&og,-1))<0){
ret=OV_EOF; /* eof. leave unitialized */
goto cleanup;
} }
/* bitrate tracking; add the header's bytes here, the body bytes /* 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,
if(ogg_page_bos(&og)){ if(ogg_page_bos(&og)){
/* boundary case */ /* boundary case */
if(!spanp){ if(!spanp)
ret=OV_EOF; return(OV_EOF);
goto cleanup;
}
_decode_clear(vf); _decode_clear(vf);
@ -830,6 +797,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
continue; /* possibility #2 */ continue; /* possibility #2 */
} }
} }
break; break;
} }
} }
@ -851,23 +819,23 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
if(vf->ready_state<STREAMSET){ if(vf->ready_state<STREAMSET){
if(vf->seekable){ if(vf->seekable){
long serialno=ogg_page_serialno(&og); ogg_uint32_t serialno = ogg_page_serialno(&og);
/* match the serialno to bitstream section. We use this rather than /* match the serialno to bitstream section. We use this rather than
offset positions to avoid problems near logical bitstream offset positions to avoid problems near logical bitstream
boundaries */ boundaries */
for(link=0;link<vf->links;link++) for(link=0;link<vf->links;link++)
if(vf->serialnos[link]==(ogg_uint32_t) serialno)break; if(vf->serialnos[link]==serialno)break;
if(link==vf->links) continue; /* not the desired Vorbis if(link==vf->links) continue; /* not the desired Vorbis
bitstream section; keep bitstream section; keep
trying */ trying */
vf->current_serialno=serialno; vf->current_serialno=serialno;
vf->current_link=link; vf->current_link=link;
ogg_stream_reset_serialno(vf->os,vf->current_serialno); ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
vf->ready_state=STREAMSET; vf->ready_state=STREAMSET;
}else{ }else{
@ -875,8 +843,8 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
/* fetch the three header packets, build the info struct */ /* fetch the three header packets, build the info struct */
int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og); int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og);
if(ret) goto cleanup; if(ret)return(ret);
vf->current_serialno=vf->os->serialno; vf->current_serialno=vf->os.serialno;
vf->current_link++; vf->current_link++;
link=0; link=0;
} }
@ -885,17 +853,14 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
/* the buffered page is the data we want, and we're ready for it; /* the buffered page is the data we want, and we're ready for it;
add it to the stream state */ add it to the stream state */
ogg_stream_pagein(vf->os,&og); ogg_stream_pagein(&vf->os,&og);
} }
cleanup:
ogg_packet_release(&op);
ogg_page_release(&og);
return ret;
} }
static int _ov_open1(void *f,OggVorbis_File *vf,char *initial, static int _ov_open1(void *f,OggVorbis_File *vf,const char *initial,
long ibytes, ov_callbacks callbacks){ long ibytes, ov_callbacks callbacks){
int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1); int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1);
ogg_uint32_t *serialno_list=NULL; ogg_uint32_t *serialno_list=NULL;
int serialno_list_size=0; int serialno_list_size=0;
int ret; int ret;
@ -905,16 +870,16 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
vf->callbacks = callbacks; vf->callbacks = callbacks;
/* init the framing state */ /* init the framing state */
vf->oy=ogg_sync_create(); ogg_sync_init(&vf->oy);
/* perhaps some data was previously read into a buffer for testing /* perhaps some data was previously read into a buffer for testing
against other stream types. Allow initialization from this against other stream types. Allow initialization from this
previously read data (especially as we may be reading from a previously read data (especially as we may be reading from a
non-seekable stream) */ non-seekable stream) */
if(initial){ if(initial){
unsigned char *buffer=ogg_sync_bufferin(vf->oy,ibytes); char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
memcpy(buffer,initial,ibytes); memcpy(buffer,initial,ibytes);
ogg_sync_wrote(vf->oy,ibytes); ogg_sync_wrote(&vf->oy,ibytes);
} }
/* can we seek? Stevens suggests the seek test was portable */ /* 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,
vf->links=1; vf->links=1;
vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi)); vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc)); vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
vf->os=ogg_stream_create(-1); /* fill in the serialno later */ ogg_stream_init(&vf->os,-1); /* fill in the serialno later */
/* Fetch all BOS pages, store the vorbis header and all seen serial /* Fetch all BOS pages, store the vorbis header and all seen serial
numbers, load subsequent vorbis setup headers */ numbers, load subsequent vorbis setup headers */
@ -945,7 +910,7 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets)); vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets));
vf->offsets[0]=0; vf->offsets[0]=0;
vf->dataoffsets[0]=vf->offset; vf->dataoffsets[0]=vf->offset;
vf->current_serialno=vf->os->serialno; vf->current_serialno=vf->os.serialno;
vf->ready_state=PARTOPEN; vf->ready_state=PARTOPEN;
} }
@ -954,8 +919,8 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
} }
static int _ov_open2(OggVorbis_File *vf){ static int _ov_open2(OggVorbis_File *vf){
if(vf->ready_state < OPENED) if(vf->ready_state != PARTOPEN) return OV_EINVAL;
vf->ready_state=OPENED; vf->ready_state=OPENED;
if(vf->seekable){ if(vf->seekable){
int ret=_open_seekable2(vf); int ret=_open_seekable2(vf);
if(ret){ if(ret){
@ -963,7 +928,9 @@ static int _ov_open2(OggVorbis_File *vf){
ov_clear(vf); ov_clear(vf);
} }
return(ret); return(ret);
} }else
vf->ready_state=STREAMSET;
return 0; return 0;
} }
@ -973,7 +940,7 @@ int ov_clear(OggVorbis_File *vf){
if(vf){ if(vf){
vorbis_block_clear(&vf->vb); vorbis_block_clear(&vf->vb);
vorbis_dsp_clear(&vf->vd); vorbis_dsp_clear(&vf->vd);
ogg_stream_destroy(vf->os); ogg_stream_clear(&vf->os);
if(vf->vi && vf->links){ if(vf->vi && vf->links){
int i; int i;
@ -988,8 +955,7 @@ int ov_clear(OggVorbis_File *vf){
if(vf->pcmlengths)_ogg_free(vf->pcmlengths); if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
if(vf->serialnos)_ogg_free(vf->serialnos); if(vf->serialnos)_ogg_free(vf->serialnos);
if(vf->offsets)_ogg_free(vf->offsets); if(vf->offsets)_ogg_free(vf->offsets);
ogg_sync_destroy(vf->oy); ogg_sync_clear(&vf->oy);
if(vf->datasource && vf->callbacks.close_func) if(vf->datasource && vf->callbacks.close_func)
(vf->callbacks.close_func)(vf->datasource); (vf->callbacks.close_func)(vf->datasource);
memset(vf,0,sizeof(*vf)); memset(vf,0,sizeof(*vf));
@ -1008,8 +974,8 @@ int ov_clear(OggVorbis_File *vf){
0) OK 0) OK
*/ */
int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes, int ov_open_callbacks(void *f,OggVorbis_File *vf,
ov_callbacks callbacks){ const char *initial,long ibytes,ov_callbacks callbacks){
#if defined(CPU_COLDFIRE) #if defined(CPU_COLDFIRE)
/* this seems to be the closest we get to an init function, let's init emac /* this seems to be the closest we get to an init function, let's init emac
here. rounding is disabled because of MULT31_SHIFT15, which will be 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){
returns zero on success, nonzero on failure */ returns zero on success, nonzero on failure */
int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
ogg_stream_state *work_os=NULL; ogg_stream_state work_os;
ogg_page og={0,0,0,0};
ogg_packet op={0,0,0,0,0,0};
int ret; int ret;
if(vf->ready_state<OPENED)return(OV_EINVAL); if(vf->ready_state<OPENED)return(OV_EINVAL);
@ -1078,12 +1042,18 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
if(pos<0 || pos>vf->end)return(OV_EINVAL); if(pos<0 || pos>vf->end)return(OV_EINVAL);
/* is the seek position outside our current link [if any]? */
if(vf->ready_state>=STREAMSET){
if(pos<vf->offsets[vf->current_link] || pos>=vf->offsets[vf->current_link+1])
_decode_clear(vf); /* clear out stream state */
}
/* don't yet clear out decoding machine (if it's initialized), in /* don't yet clear out decoding machine (if it's initialized), in
the case we're in the same link. Restart the decode lapping, and the case we're in the same link. Restart the decode lapping, and
let _fetch_and_process_packet deal with a potential bitstream let _fetch_and_process_packet deal with a potential bitstream
boundary */ boundary */
vf->pcm_offset=-1; vf->pcm_offset=-1;
ogg_stream_reset_serialno(vf->os, ogg_stream_reset_serialno(&vf->os,
vf->current_serialno); /* must set serialno */ vf->current_serialno); /* must set serialno */
vorbis_synthesis_restart(&vf->vd); vorbis_synthesis_restart(&vf->vd);
@ -1106,37 +1076,43 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
*/ */
{ {
ogg_page og;
ogg_packet op;
int lastblock=0; int lastblock=0;
int accblock=0; int accblock=0;
int thisblock; int thisblock=0;
int lastflag=0; int lastflag=0;
int firstflag=0; int firstflag=0;
ogg_int64_t pagepos=-1; ogg_int64_t pagepos=-1;
work_os=ogg_stream_create(vf->current_serialno); /* get the memory ready */ ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */
ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE
return from not necessarily
starting from the beginning */
while(1){ while(1){
if(vf->ready_state>=STREAMSET){ if(vf->ready_state>=STREAMSET){
/* snarf/scan a packet if we can */ /* snarf/scan a packet if we can */
int result=ogg_stream_packetout(work_os,&op); int result=ogg_stream_packetout(&work_os,&op);
if(result>0){ if(result>0){
if(vf->vi[vf->current_link].codec_setup){ if(vf->vi[vf->current_link].codec_setup){
thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
if(thisblock<0){ if(thisblock<0){
ogg_stream_packetout(vf->os,NULL); ogg_stream_packetout(&vf->os,NULL);
thisblock=0; thisblock=0;
}else{ }else{
/* We can't get a guaranteed correct pcm position out of the /* We can't get a guaranteed correct pcm position out of the
last page in a stream because it might have a 'short' last page in a stream because it might have a 'short'
granpos, which can only be detected in the presence of a granpos, which can only be detected in the presence of a
preceeding page. However, if the last page is also the first preceding page. However, if the last page is also the first
page, the granpos rules of a first page take precedence. Not page, the granpos rules of a first page take precedence. Not
only that, but for first==last, the EOS page must be treated only that, but for first==last, the EOS page must be treated
as if its a normal first page for the stream to open/play. */ as if its a normal first page for the stream to open/play. */
if(lastflag && !firstflag) if(lastflag && !firstflag)
ogg_stream_packetout(vf->os,NULL); ogg_stream_packetout(&vf->os,NULL);
else else
if(lastblock)accblock+=(lastblock+thisblock)>>2; if(lastblock)accblock+=(lastblock+thisblock)>>2;
} }
@ -1155,7 +1131,7 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
lastblock=thisblock; lastblock=thisblock;
continue; continue;
}else }else
ogg_stream_packetout(vf->os,NULL); ogg_stream_packetout(&vf->os,NULL);
} }
} }
@ -1174,6 +1150,7 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
/* has our decoding just traversed a bitstream boundary? */ /* has our decoding just traversed a bitstream boundary? */
if(vf->ready_state>=STREAMSET){ if(vf->ready_state>=STREAMSET){
if(vf->current_serialno!=ogg_page_serialno(&og)){ if(vf->current_serialno!=ogg_page_serialno(&og)){
/* two possibilities: /* two possibilities:
1) our decoding just traversed a bitstream boundary 1) our decoding just traversed a bitstream boundary
2) another stream is multiplexed into this logical section? */ 2) another stream is multiplexed into this logical section? */
@ -1181,53 +1158,45 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
if(ogg_page_bos(&og)){ if(ogg_page_bos(&og)){
/* we traversed */ /* we traversed */
_decode_clear(vf); /* clear out stream state */ _decode_clear(vf); /* clear out stream state */
ogg_stream_destroy(work_os); ogg_stream_clear(&work_os);
} /* else, do nothing; next loop will scoop another page */ } /* else, do nothing; next loop will scoop another page */
} }
} }
if(vf->ready_state<STREAMSET){ if(vf->ready_state<STREAMSET){
int link; int link;
long serialno = ogg_page_serialno(&og); ogg_uint32_t serialno = ogg_page_serialno(&og);
for(link=0;link<vf->links;link++) for(link=0;link<vf->links;link++)
if(vf->serialnos[link]==vf->current_serialno)break; if(vf->serialnos[link]==serialno)break;
if(link==vf->links) continue; /* not the desired Vorbis if(link==vf->links) continue; /* not the desired Vorbis
bitstream section; keep bitstream section; keep
trying */ trying */
vf->current_link=link; vf->current_link=link;
vf->current_serialno=serialno; vf->current_serialno=serialno;
ogg_stream_reset_serialno(vf->os,vf->current_serialno); ogg_stream_reset_serialno(&vf->os,serialno);
ogg_stream_reset_serialno(work_os,vf->current_serialno); ogg_stream_reset_serialno(&work_os,serialno);
vf->ready_state=STREAMSET; vf->ready_state=STREAMSET;
firstflag=(pagepos<=vf->dataoffsets[link]); firstflag=(pagepos<=vf->dataoffsets[link]);
} }
{ ogg_stream_pagein(&vf->os,&og);
ogg_page dup; ogg_stream_pagein(&work_os,&og);
ogg_page_dup(&dup,&og); lastflag=ogg_page_eos(&og);
lastflag=ogg_page_eos(&og);
ogg_stream_pagein(vf->os,&og);
ogg_stream_pagein(work_os,&dup);
}
} }
} }
ogg_packet_release(&op); ogg_stream_clear(&work_os);
ogg_page_release(&og);
ogg_stream_destroy(work_os);
vf->bittrack=0; vf->bittrack=0;
vf->samptrack=0; vf->samptrack=0;
return(0); return(0);
seek_error: seek_error:
ogg_packet_release(&op);
ogg_page_release(&og);
/* dump the machine so we're in a known state */ /* dump the machine so we're in a known state */
vf->pcm_offset=-1; vf->pcm_offset=-1;
ogg_stream_destroy(work_os); ogg_stream_clear(&work_os);
_decode_clear(vf); _decode_clear(vf);
return OV_EBADLINK; return OV_EBADLINK;
} }
@ -1235,18 +1204,17 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
/* Page granularity seek (faster than sample granularity because we /* Page granularity seek (faster than sample granularity because we
don't do the last bit of decode to find a specific sample). don't do the last bit of decode to find a specific sample).
Seek to the last [granule marked] page preceeding the specified pos Seek to the last [granule marked] page preceding the specified pos
location, such that decoding past the returned point will quickly location, such that decoding past the returned point will quickly
arrive at the requested position. */ arrive at the requested position. */
int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
int link=-1; int link=-1;
ogg_int64_t result=0; ogg_int64_t result=0;
ogg_int64_t total=ov_pcm_total(vf,-1); ogg_int64_t total=ov_pcm_total(vf,-1);
ogg_page og={0,0,0,0};
ogg_packet op={0,0,0,0,0,0};
if(vf->ready_state<OPENED)return(OV_EINVAL); if(vf->ready_state<OPENED)return(OV_EINVAL);
if(!vf->seekable)return(OV_ENOSEEK); if(!vf->seekable)return(OV_ENOSEEK);
if(pos<0 || pos>total)return(OV_EINVAL); if(pos<0 || pos>total)return(OV_EINVAL);
/* which bitstream section does this pcm offset occur in? */ /* which bitstream section does this pcm offset occur in? */
@ -1256,7 +1224,7 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
} }
/* search within the logical bitstream for the page with the highest /* search within the logical bitstream for the page with the highest
pcm_pos preceeding (or equal to) pos. There is a danger here; pcm_pos preceding (or equal to) pos. There is a danger here;
missing pages or incorrect frame number information in the missing pages or incorrect frame number information in the
bitstream could make our task impossible. Account for that (it bitstream could make our task impossible. Account for that (it
would be an error condition) */ would be an error condition) */
@ -1270,6 +1238,7 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
ogg_int64_t target=pos-total+begintime; ogg_int64_t target=pos-total+begintime;
ogg_int64_t best=begin; ogg_int64_t best=begin;
ogg_page og;
while(begin<end){ while(begin<end){
ogg_int64_t bisect; ogg_int64_t bisect;
@ -1279,11 +1248,14 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
/* take a (pretty decent) guess. */ /* take a (pretty decent) guess. */
bisect=begin + bisect=begin +
(target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE; (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
if(bisect<=begin) if(bisect<begin+CHUNKSIZE)
bisect=begin+1; bisect=begin;
} }
_seek_helper(vf,bisect); if(bisect!=vf->offset){
result=_seek_helper(vf,bisect);
if(result) goto seek_error;
}
while(begin<end){ while(begin<end){
result=_get_next_page(vf,&og,end-vf->offset); result=_get_next_page(vf,&og,end-vf->offset);
@ -1295,11 +1267,18 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
if(bisect==0) goto seek_error; if(bisect==0) goto seek_error;
bisect-=CHUNKSIZE; bisect-=CHUNKSIZE;
if(bisect<=begin)bisect=begin+1; if(bisect<=begin)bisect=begin+1;
_seek_helper(vf,bisect); result=_seek_helper(vf,bisect);
if(result) goto seek_error;
} }
}else{ }else{
ogg_int64_t granulepos=ogg_page_granulepos(&og); ogg_int64_t granulepos;
if(ogg_page_serialno(&og)!=vf->serialnos[link])
continue;
granulepos=ogg_page_granulepos(&og);
if(granulepos==-1)continue; if(granulepos==-1)continue;
if(granulepos<target){ if(granulepos<target){
best=result; /* raw offset of packet with granulepos */ best=result; /* raw offset of packet with granulepos */
begin=vf->offset; /* raw offset of next page */ begin=vf->offset; /* raw offset of next page */
@ -1315,9 +1294,10 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
end=result; end=result;
bisect-=CHUNKSIZE; /* an endless loop otherwise. */ bisect-=CHUNKSIZE; /* an endless loop otherwise. */
if(bisect<=begin)bisect=begin+1; if(bisect<=begin)bisect=begin+1;
_seek_helper(vf,bisect); result=_seek_helper(vf,bisect);
if(result) goto seek_error;
}else{ }else{
end=result; end=bisect;
endtime=granulepos; endtime=granulepos;
break; break;
} }
@ -1328,8 +1308,10 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
} }
/* found our page. seek to it, update pcm offset. Easier case than /* found our page. seek to it, update pcm offset. Easier case than
raw_seek, don't keep packets preceeding granulepos. */ raw_seek, don't keep packets preceding granulepos. */
{ {
ogg_page og;
ogg_packet op;
/* seek */ /* seek */
result=_seek_helper(vf,best); result=_seek_helper(vf,best);
@ -1343,22 +1325,22 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
_decode_clear(vf); _decode_clear(vf);
vf->current_link=link; vf->current_link=link;
vf->current_serialno=ogg_page_serialno(&og); vf->current_serialno=vf->serialnos[link];
vf->ready_state=STREAMSET; vf->ready_state=STREAMSET;
}else{ }else{
vorbis_synthesis_restart(&vf->vd); vorbis_synthesis_restart(&vf->vd);
} }
ogg_stream_reset_serialno(vf->os,vf->current_serialno); ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
ogg_stream_pagein(vf->os,&og); ogg_stream_pagein(&vf->os,&og);
/* pull out all but last packet; the one with granulepos */ /* pull out all but last packet; the one with granulepos */
while(1){ while(1){
result=ogg_stream_packetpeek(vf->os,&op); result=ogg_stream_packetpeek(&vf->os,&op);
if(result==0){ if(result==0){
/* !!! the packet finishing this page originated on a /* !!! the packet finishing this page originated on a
preceeding page. Keep fetching previous pages until we preceding page. Keep fetching previous pages until we
get one with a granulepos or without the 'continued' flag get one with a granulepos or without the 'continued' flag
set. Then just use raw_seek for simplicity. */ set. Then just use raw_seek for simplicity. */
@ -1386,7 +1368,7 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
vf->pcm_offset+=total; vf->pcm_offset+=total;
break; break;
}else }else
result=ogg_stream_packetout(vf->os,NULL); result=ogg_stream_packetout(&vf->os,NULL);
} }
} }
} }
@ -1398,16 +1380,9 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
} }
vf->bittrack=0; vf->bittrack=0;
vf->samptrack=0; vf->samptrack=0;
ogg_page_release(&og);
ogg_packet_release(&op);
return(0); return(0);
seek_error: seek_error:
ogg_page_release(&og);
ogg_packet_release(&op);
/* dump machine so we're in a known state */ /* dump machine so we're in a known state */
vf->pcm_offset=-1; vf->pcm_offset=-1;
_decode_clear(vf); _decode_clear(vf);
@ -1418,23 +1393,23 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
returns zero on success, nonzero on failure */ returns zero on success, nonzero on failure */
int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
ogg_packet op={0,0,0,0,0,0};
ogg_page og={0,0,0,0};
int thisblock,lastblock=0; int thisblock,lastblock=0;
int ret=ov_pcm_seek_page(vf,pos); int ret=ov_pcm_seek_page(vf,pos);
if(ret<0)return(ret); if(ret<0)return(ret);
_make_decode_ready(vf); if((ret=_make_decode_ready(vf)))return ret;
/* discard leading packets we don't need for the lapping of the /* discard leading packets we don't need for the lapping of the
position we want; don't decode them */ position we want; don't decode them */
while(1){ while(1){
ogg_packet op;
ogg_page og;
int ret=ogg_stream_packetpeek(vf->os,&op); int ret=ogg_stream_packetpeek(&vf->os,&op);
if(ret>0){ if(ret>0){
thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
if(thisblock<0){ if(thisblock<0){
ogg_stream_packetout(vf->os,NULL); ogg_stream_packetout(&vf->os,NULL);
continue; /* non audio packet */ continue; /* non audio packet */
} }
if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2; if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
@ -1443,7 +1418,7 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break; vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
/* remove the packet from packet queue and track its granulepos */ /* remove the packet from packet queue and track its granulepos */
ogg_stream_packetout(vf->os,NULL); ogg_stream_packetout(&vf->os,NULL);
vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with
only tracking, no only tracking, no
pcm_decode */ pcm_decode */
@ -1481,17 +1456,13 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
vf->ready_state=STREAMSET; vf->ready_state=STREAMSET;
vf->current_serialno=ogg_page_serialno(&og); vf->current_serialno=ogg_page_serialno(&og);
ogg_stream_reset_serialno(vf->os,serialno); ogg_stream_reset_serialno(&vf->os,serialno);
ret=_make_decode_ready(vf); ret=_make_decode_ready(vf);
if(ret){ if(ret)return ret;
ogg_page_release(&og);
ogg_packet_release(&op);
return ret;
}
lastblock=0; lastblock=0;
} }
ogg_stream_pagein(vf->os,&og); ogg_stream_pagein(&vf->os,&og);
} }
} }
@ -1508,12 +1479,9 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
vf->pcm_offset+=samples; vf->pcm_offset+=samples;
if(samples<target) if(samples<target)
if(_fetch_and_process_packet(vf,1,1)<=0) if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */ vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
} }
ogg_page_release(&og);
ogg_packet_release(&op);
return 0; return 0;
} }
@ -1634,9 +1602,12 @@ long ov_read_fixed(OggVorbis_File *vf,ogg_int32_t ***pcm_channels,int length,
/* suck in another packet */ /* suck in another packet */
{ {
int ret=_fetch_and_process_packet(vf,1,1); int ret=_fetch_and_process_packet(vf,NULL,1,1);
if(ret==OV_EOF)return(0); if(ret==OV_EOF)
if(ret<=0)return(ret); return(0);
if(ret<=0)
return(ret);
} }
} }
} }