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;
while (bufptr<bufend) {
if (b->headend > 8) {
if(b->endbyte < b->storage - 8) {
ogg_uint32_t *ptr;
unsigned long bit, bitend;
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 char *book_dec_codelengths = book->dec_codelengths;
adr = (unsigned long)b->headptr;
bit = (adr&3)*8+b->headbit;
adr = (unsigned long)b->ptr;
bit = (adr&3)*8+b->endbit;
ptr = (ogg_uint32_t*)(adr&~3);
bitend = ((adr&3)+b->headend)*8;
bitend = ((adr&3)+(b->storage-b->endbyte))*8;
while (bufptr<bufend){
if (UNLIKELY(cachesize<book_dec_maxlength)) {
if (bit-cachesize+32>=bitend)
@ -323,11 +323,11 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
cache >>= l;
}
adr=(unsigned long)b->headptr;
adr=(unsigned long)b->ptr;
bit-=(adr&3)*8+cachesize;
b->headend-=(bit/8);
b->headptr+=bit/8;
b->headbit=bit%8;
b->endbyte+=bit/8;
b->ptr+=bit/8;
b->endbit=bit&7;
} else {
long r = decode_packed_entry_number(book, b);
if (r == -1) return bufptr-buf;
@ -337,7 +337,6 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
return n;
}
/* Decode side is specced and easier, because we don't need to find
matches using different criteria; we simply read and map. There are
two things we need to do 'depending':
@ -570,3 +569,4 @@ long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,
}
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];
if(op){
oggpack_readinit(&opb,op->packet);
oggpack_readinit(&opb,op->packet,op->bytes);
if(!op->b_o_s)
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;
if(op){
oggpack_readinit(&opb,op->packet);
oggpack_readinit(&opb,op->packet,op->bytes);
/* Which of the three types of header is this? */
/* Also verify header-ness, vorbis */

View file

@ -56,7 +56,7 @@ typedef struct OggVorbis_File {
int seekable;
ogg_int64_t offset;
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
stream appears */
@ -77,7 +77,7 @@ typedef struct OggVorbis_File {
ogg_int64_t bittrack;
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 */
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
vorbis_block vb; /* local working space for packet->PCM decode */
@ -87,13 +87,11 @@ typedef struct OggVorbis_File {
} OggVorbis_File;
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,
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,
char *initial, long ibytes, ov_callbacks callbacks);
const char *initial, long ibytes, ov_callbacks callbacks);
extern int ov_test_open(OggVorbis_File *vf);
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 *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 *
* BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: subsumed libogg includes
function: toplevel libogg include
last mod: $Id$
********************************************************************/
#ifndef _OGG_H
@ -21,241 +21,238 @@
extern "C" {
#endif
#include <stddef.h>
#include "os_types.h"
typedef struct ogg_buffer_state{
struct ogg_buffer *unused_buffers;
struct ogg_reference *unused_references;
int outstanding;
int shutdown;
} ogg_buffer_state;
extern const unsigned long mask[] ICONST_ATTR;
typedef struct ogg_buffer {
unsigned char *data;
long size;
int refcount;
typedef struct {
void *iov_base;
size_t iov_len;
} ogg_iovec_t;
union {
ogg_buffer_state *owner;
struct ogg_buffer *next;
} ptr;
} ogg_buffer;
typedef struct {
long endbyte;
int endbit;
typedef struct ogg_reference {
ogg_buffer *buffer;
long begin;
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 */
unsigned char *buffer;
unsigned char *ptr;
long storage;
} oggpack_buffer;
typedef struct oggbyte_buffer {
ogg_reference *baseref;
/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
ogg_reference *ref;
unsigned char *ptr;
long pos;
long end;
} oggbyte_buffer;
typedef struct {
unsigned char *header;
long header_len;
unsigned char *body;
long body_len;
} ogg_page;
typedef struct ogg_sync_state {
/* decode memory management pool */
ogg_buffer_state *bufferpool;
/* ogg_stream_state contains the current encode/decode state of a logical
Ogg bitstream **********************************************************/
/* stream buffers */
ogg_reference *fifo_head;
ogg_reference *fifo_tail;
long fifo_fill;
typedef struct {
unsigned char *body_data; /* bytes from packet bodies */
long body_storage; /* storage elements allocated */
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 {
ogg_reference *header_head;
ogg_reference *header_tail;
ogg_reference *body_head;
ogg_reference *body_tail;
int e_o_s; /* set when we have buffered the last
packet in the logical bitstream */
#if 0
unsigned char header[282]; /* working space for header encode */
int header_fill;
#endif
int e_o_s; /* set when we have buffered the last packet in the
logical bitstream */
int b_o_s; /* set after we've written the initial page
of a logical bitstream */
long serialno;
ogg_uint32_t serialno;
long pageno;
ogg_int64_t packetno; /* sequence number for decode; the framing
knows where there's a hole in the data,
but we need coupling so that the codec
(which is in a seperate abstraction
(which is in a separate abstraction
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_packet is used to encapsulate the data and metadata belonging
to a single raw Ogg/Vorbis packet *************************************/
typedef struct {
ogg_reference *packet;
unsigned char *packet;
long bytes;
long b_o_s;
long e_o_s;
ogg_int64_t granulepos;
ogg_int64_t packetno; /* sequence number for decode; the framing
knows where there's a hole in the data,
but we need coupling so that the codec
(which is in a seperate abstraction
(which is in a separate abstraction
layer) also knows about the gap */
} ogg_packet;
typedef struct {
ogg_reference *header;
int header_len;
ogg_reference *body;
long body_len;
} ogg_page;
unsigned char *data;
int storage;
int fill;
int returned;
int unsynced;
int headerbytes;
int bodybytes;
} ogg_sync_state;
/* 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_full(oggpack_buffer *b,int bits);
extern long oggpack_read(oggpack_buffer *b,register int bits);
//extern long oggpack_look(oggpack_buffer *b,int bits);
static inline long oggpack_look(oggpack_buffer *b,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 */
static inline void _adv_halt(oggpack_buffer *b){
b->headptr=b->head->buffer->data+b->head->begin+b->head->length;
b->headend=-1;
b->headbit=0;
}
/* 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;
if(b->endbyte >= b->storage-4){
/* not the main path */
if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
/* special case to avoid reading b->ptr[0], which might be past the end of
the buffer; also skips some useless accounting */
else if(!bits)return(0L);
}
}
}
/* limited to 32 at a time */
static inline void oggpack_adv(oggpack_buffer *b,int bits){
bits+=b->headbit;
b->headbit=bits&7;
b->headptr+=bits/8;
if((b->headend-=((unsigned)bits)/8)<1)_span(b);
}
static inline long oggpack_look(oggpack_buffer *b, int bits){
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;
ret=b->ptr[0]>>b->endbit;
if(bits>8){
ret|=b->headptr[1]<<(8-b->headbit);
ret|=b->ptr[1]<<(8-b->endbit);
if(bits>16){
ret|=b->headptr[2]<<(16-b->headbit);
ret|=b->ptr[2]<<(16-b->endbit);
if(bits>24){
ret|=b->headptr[3]<<(24-b->headbit);
if(bits>32 && b->headbit)
ret|=b->headptr[4]<<(32-b->headbit);
ret|=b->ptr[3]<<(24-b->endbit);
if(bits>32 && b->endbit)
ret|=b->ptr[4]<<(32-b->endbit);
}
}
}
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 **************************/
extern ogg_sync_state *ogg_sync_create(void);
extern int ogg_sync_destroy(ogg_sync_state *oy);
extern int ogg_sync_init(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_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 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_packetout(ogg_stream_state *os,ogg_packet *op);
extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);
/* Ogg BITSTREAM PRIMITIVES: general ***************************/
extern ogg_stream_state *ogg_stream_create(int serialno);
extern int ogg_stream_destroy(ogg_stream_state *os);
extern int ogg_stream_init(ogg_stream_state *os,int serialno);
extern int ogg_stream_clear(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_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_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_continued(ogg_page *og);
extern int ogg_page_bos(ogg_page *og);
extern int ogg_page_eos(ogg_page *og);
extern ogg_int64_t ogg_page_granulepos(ogg_page *og);
extern ogg_uint32_t ogg_page_serialno(ogg_page *og);
extern ogg_uint32_t ogg_page_pageno(ogg_page *og);
extern int ogg_page_getbuffer(ogg_page *og, unsigned char **buffer);
extern int ogg_page_version(const ogg_page *og);
extern int ogg_page_continued(const ogg_page *og);
extern int ogg_page_bos(const ogg_page *og);
extern int ogg_page_eos(const ogg_page *og);
extern ogg_int64_t ogg_page_granulepos(const ogg_page *og);
extern ogg_uint32_t ogg_page_serialno(const ogg_page *og);
extern long ogg_page_pageno(const ogg_page *og);
extern int ogg_page_packets(const ogg_page *og);
extern int ogg_packet_release(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
extern void ogg_packet_clear(ogg_packet *op);
#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 */
_vorbis_block_ripcord(vb);
oggpack_readinit(opb,op->packet);
oggpack_readinit(opb,op->packet,op->bytes);
/* Check the packet type */
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);
}
/* used to track pcm position without actually performing decode.
Useful for sequential 'fast forward' */
int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){
return _vorbis_synthesis1(vb,op,0);
}
@ -111,7 +113,7 @@ long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
oggpack_buffer opb;
int mode;
oggpack_readinit(&opb,op->packet);
oggpack_readinit(&opb,op->packet,op->bytes);
/* Check the packet type */
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 */
static long _get_data(OggVorbis_File *vf){
if(!(vf->callbacks.read_func))return(-1);
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);
if(bytes>0)ogg_sync_wrote(vf->oy,bytes);
if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
return(bytes);
}else
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)
return OV_EREAD;
vf->offset=offset;
ogg_sync_reset(vf->oy);
ogg_sync_reset(&vf->oy);
}else{
/* shouldn't happen unless someone writes a broken callback */
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
return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
n) found a page at absolute offset n
produces a refcounted page */
n) found a page at absolute offset n */
static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
ogg_int64_t boundary){
@ -107,7 +106,7 @@ static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
long more;
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){
/* 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
backward search linkage. no 'readp' as it will certainly have to
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){
ogg_int64_t begin=vf->offset;
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);
while(vf->offset<end){
memset(og,0,sizeof(*og));
ret=_get_next_page(vf,og,end-vf->offset);
if(ret==OV_EREAD)return(OV_EREAD);
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),
we will probably have to re-read the last page we saw */
if(og->header_len==0){
ogg_page_release(og);
ret=_seek_helper(vf,offset);
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,
ogg_uint32_t *serial_list, int serial_n,
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 end=begin;
ogg_int64_t ret;
ogg_int64_t prefoffset=-1;
ogg_int64_t offset=-1;
ogg_uint32_t ret_serialno=-1;
ogg_int64_t ret_serialno=-1;
ogg_int64_t ret_gran=-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);
if(ret==OV_EREAD)return(OV_EREAD);
if(ret<0){
ogg_page_release(&og);
break;
}else{
ret_serialno=ogg_page_serialno(&og);
ret_gran=ogg_page_granulepos(&og);
offset=ret;
ogg_page_release(&og);
if(ret_serialno == (ogg_uint32_t) *serialno){
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
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={0,0,0,0};
ogg_packet op={0,0,0,0,0,0};
ogg_page og;
ogg_packet op;
int i,ret;
int allbos=0;
if(!og_ptr){
ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
if(llret==OV_EREAD)return(OV_EREAD);
if(llret<0)return OV_ENOTVORBIS;
if(llret<0)return(OV_ENOTVORBIS);
og_ptr=&og;
}
@ -320,10 +311,10 @@ static int _fetch_headers(OggVorbis_File *vf,
if(vf->ready_state<STREAMSET){
/* we don't have a vorbis stream in this link yet, so begin
prospective stream setup. We need a stream to get packets */
ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr));
ogg_stream_pagein(vf->os,og_ptr);
ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(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 header; continue setup */
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(vf->ready_state==STREAMSET &&
(ogg_uint32_t) vf->os->serialno == ogg_page_serialno(og_ptr)){
ogg_stream_pagein(vf->os,og_ptr);
vf->os.serialno == ogg_page_serialno(og_ptr)){
ogg_stream_pagein(&vf->os,og_ptr);
break;
}
}
@ -367,7 +358,7 @@ static int _fetch_headers(OggVorbis_File *vf,
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==-1){
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((ogg_uint32_t) vf->os->serialno == ogg_page_serialno(og_ptr)){
ogg_stream_pagein(vf->os,og_ptr);
if(vf->os.serialno == ogg_page_serialno(og_ptr)){
ogg_stream_pagein(&vf->os,og_ptr);
break;
}
@ -406,15 +397,10 @@ static int _fetch_headers(OggVorbis_File *vf,
}
}
ogg_packet_release(&op);
ogg_page_release(&og);
return 0;
}
bail_header:
ogg_packet_release(&op);
ogg_page_release(&og);
vorbis_info_clear(vi);
vorbis_comment_clear(vc);
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
seekable open. */
static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
ogg_page og={0,0,0,0};
ogg_int64_t accumulated=0,pos;
ogg_page og;
ogg_int64_t accumulated=0;
long lastblock=-1;
int result;
int serialno = vf->os->serialno;
ogg_uint32_t serialno = vf->os.serialno;
while(1){
ogg_packet op={0,0,0,0,0,0};
ogg_packet op;
if(_get_next_page(vf,&og,-1)<0)
break; /* should not be possible unless the file is truncated/mangled */
if(ogg_page_bos(&og)) break;
if(ogg_page_serialno(&og)!=(ogg_uint32_t) serialno) continue;
pos=ogg_page_granulepos(&og);
if(ogg_page_serialno(&og)!= serialno) continue;
/* count blocksizes of all frames in the page */
ogg_stream_pagein(vf->os,&og);
while((result=ogg_stream_packetout(vf->os,&op))){
ogg_stream_pagein(&vf->os,&og);
while((result=ogg_stream_packetout(&vf->os,&op))){
if(result>0){ /* ignore holes */
long thisblock=vorbis_packet_blocksize(vi,&op);
if(lastblock!=-1)
@ -453,11 +437,10 @@ static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
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 */
accumulated= pos-accumulated;
accumulated= ogg_page_granulepos(&og)-accumulated;
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 */
if(accumulated<0)accumulated=0;
ogg_page_release(&og);
return accumulated;
}
/* 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).
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,
int currentnos,
long m){
ogg_int64_t pcmoffset;
ogg_int64_t dataoffset=searched;
ogg_int64_t endsearched=end;
ogg_int64_t next=end;
ogg_int64_t searchgran=-1;
ogg_page og;
ogg_int64_t ret,last;
int serialno = vf->os->serialno;
int serialno = vf->os.serialno;
/* invariants:
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
first pages of two links. */
while(searched<endsearched){
ogg_page og={0,0,0,0};
ogg_int64_t bisect;
if(endsearched-searched<CHUNKSIZE){
@ -547,8 +527,10 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
bisect=(searched+endsearched)/2;
}
if(bisect != vf->offset){
ret=_seek_helper(vf,bisect);
if(ret)return(ret);
}
last=_get_next_page(vf,&og,-1);
if(last==OV_EREAD)return(OV_EREAD);
@ -556,9 +538,8 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
endsearched=bisect;
if(last>=0)next=last;
}else{
searched=last+og.header_len+og.body_len;
searched=vf->offset;
}
ogg_page_release(&og);
}
/* 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);
if(ret)return(ret);
serialno = vf->os->serialno;
serialno = vf->os.serialno;
dataoffset = vf->offset;
/* 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){
ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1;
int endserial=vf->os->serialno;
int serialno=vf->os->serialno;
int endserial=vf->os.serialno;
int serialno=vf->os.serialno;
/* we're partially open and have a first link header state in
storage in vf */
@ -684,40 +665,36 @@ static void _decode_clear(OggVorbis_File *vf){
1) got a packet
*/
STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
int readp,
int spanp) ICODE_ATTR_TREMOR_NOT_MDCT;
STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
static int _fetch_and_process_packet(OggVorbis_File *vf,
ogg_packet *op_in,
int readp,
int spanp){
ogg_page og={0,0,0,0};
ogg_packet op={0,0,0,0,0,0};
int ret=0;
ogg_page og;
/* handle one packet. Try to fetch it from current stream state */
/* extract packets from page */
while(1){
if(vf->ready_state==STREAMSET){
ret=_make_decode_ready(vf);
if(ret<0) goto cleanup;
int ret=_make_decode_ready(vf);
if(ret<0)return ret;
}
/* process a packet if we can. If the machine isn't loaded,
neither is a page */
if(vf->ready_state==INITSET){
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;
if(result==-1){
ret=OV_HOLE; /* hole in the data. */
goto cleanup;
}
op_in=NULL;
if(result==-1)return(OV_HOLE); /* hole in the data. */
if(result>0){
/* got a packet. process it */
granulepos=op.granulepos;
if(!vorbis_synthesis(&vf->vb,&op)){ /* lazy check for lazy
granulepos=op_ptr->granulepos;
if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy
header handling. The
header packets aren't
audio, so if/when we
@ -730,18 +707,15 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
/* for proper use of libvorbis within libvorbisfile,
oldsamples will always be zero. */
if(oldsamples){
ret=OV_EFAULT;
goto cleanup;
}
if(oldsamples)return(OV_EFAULT);
vorbis_synthesis_blockin(&vf->vd,&vf->vb);
vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
vf->bittrack+=op.bytes*8;
vf->bittrack+=op_ptr->bytes*8;
}
/* 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 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
last packet of the last page may be a partial frame.
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 */
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];
vf->pcm_offset=granulepos;
}
ret=1;
goto cleanup;
return(1);
}
}
else
@ -782,7 +755,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
}
if(vf->ready_state>=OPENED){
ogg_int64_t lret;
ogg_int64_t ret;
while(1){
/* 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
we get one with the correct serialno */
if(!readp){
ret=0;
goto cleanup;
}
if((lret=_get_next_page(vf,&og,-1))<0){
ret=OV_EOF; /* eof. leave unitialized */
goto cleanup;
if(!readp)return(0);
if((ret=_get_next_page(vf,&og,-1))<0){
return(OV_EOF); /* eof. leave unitialized */
}
/* 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)){
/* boundary case */
if(!spanp){
ret=OV_EOF;
goto cleanup;
}
if(!spanp)
return(OV_EOF);
_decode_clear(vf);
@ -830,6 +797,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
continue; /* possibility #2 */
}
}
break;
}
}
@ -851,14 +819,14 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
if(vf->ready_state<STREAMSET){
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
offset positions to avoid problems near logical bitstream
boundaries */
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
bitstream section; keep
@ -867,7 +835,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
vf->current_serialno=serialno;
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;
}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 */
int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og);
if(ret) goto cleanup;
vf->current_serialno=vf->os->serialno;
if(ret)return(ret);
vf->current_serialno=vf->os.serialno;
vf->current_link++;
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;
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){
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;
int serialno_list_size=0;
int ret;
@ -905,16 +870,16 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
vf->callbacks = callbacks;
/* 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
against other stream types. Allow initialization from this
previously read data (especially as we may be reading from a
non-seekable stream) */
if(initial){
unsigned char *buffer=ogg_sync_bufferin(vf->oy,ibytes);
char *buffer=ogg_sync_buffer(&vf->oy,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 */
@ -925,7 +890,7 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
vf->links=1;
vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
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
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->offsets[0]=0;
vf->dataoffsets[0]=vf->offset;
vf->current_serialno=vf->os->serialno;
vf->current_serialno=vf->os.serialno;
vf->ready_state=PARTOPEN;
}
@ -954,7 +919,7 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
}
static int _ov_open2(OggVorbis_File *vf){
if(vf->ready_state < OPENED)
if(vf->ready_state != PARTOPEN) return OV_EINVAL;
vf->ready_state=OPENED;
if(vf->seekable){
int ret=_open_seekable2(vf);
@ -963,7 +928,9 @@ static int _ov_open2(OggVorbis_File *vf){
ov_clear(vf);
}
return(ret);
}
}else
vf->ready_state=STREAMSET;
return 0;
}
@ -973,7 +940,7 @@ int ov_clear(OggVorbis_File *vf){
if(vf){
vorbis_block_clear(&vf->vb);
vorbis_dsp_clear(&vf->vd);
ogg_stream_destroy(vf->os);
ogg_stream_clear(&vf->os);
if(vf->vi && vf->links){
int i;
@ -988,8 +955,7 @@ int ov_clear(OggVorbis_File *vf){
if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
if(vf->serialnos)_ogg_free(vf->serialnos);
if(vf->offsets)_ogg_free(vf->offsets);
ogg_sync_destroy(vf->oy);
ogg_sync_clear(&vf->oy);
if(vf->datasource && vf->callbacks.close_func)
(vf->callbacks.close_func)(vf->datasource);
memset(vf,0,sizeof(*vf));
@ -1008,8 +974,8 @@ int ov_clear(OggVorbis_File *vf){
0) OK
*/
int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
ov_callbacks callbacks){
int ov_open_callbacks(void *f,OggVorbis_File *vf,
const char *initial,long ibytes,ov_callbacks callbacks){
#if defined(CPU_COLDFIRE)
/* 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
@ -1067,9 +1033,7 @@ ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){
returns zero on success, nonzero on failure */
int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
ogg_stream_state *work_os=NULL;
ogg_page og={0,0,0,0};
ogg_packet op={0,0,0,0,0,0};
ogg_stream_state work_os;
int ret;
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);
/* 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
the case we're in the same link. Restart the decode lapping, and
let _fetch_and_process_packet deal with a potential bitstream
boundary */
vf->pcm_offset=-1;
ogg_stream_reset_serialno(vf->os,
ogg_stream_reset_serialno(&vf->os,
vf->current_serialno); /* must set serialno */
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 accblock=0;
int thisblock;
int thisblock=0;
int lastflag=0;
int firstflag=0;
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){
if(vf->ready_state>=STREAMSET){
/* 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(vf->vi[vf->current_link].codec_setup){
thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
if(thisblock<0){
ogg_stream_packetout(vf->os,NULL);
ogg_stream_packetout(&vf->os,NULL);
thisblock=0;
}else{
/* We can't get a guaranteed correct pcm position out of the
last page in a stream because it might have a 'short'
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
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. */
if(lastflag && !firstflag)
ogg_stream_packetout(vf->os,NULL);
ogg_stream_packetout(&vf->os,NULL);
else
if(lastblock)accblock+=(lastblock+thisblock)>>2;
}
@ -1155,7 +1131,7 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
lastblock=thisblock;
continue;
}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? */
if(vf->ready_state>=STREAMSET){
if(vf->current_serialno!=ogg_page_serialno(&og)){
/* two possibilities:
1) our decoding just traversed a bitstream boundary
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)){
/* we traversed */
_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 */
}
}
if(vf->ready_state<STREAMSET){
int link;
long serialno = ogg_page_serialno(&og);
ogg_uint32_t serialno = ogg_page_serialno(&og);
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
bitstream section; keep
trying */
vf->current_link=link;
vf->current_serialno=serialno;
ogg_stream_reset_serialno(vf->os,vf->current_serialno);
ogg_stream_reset_serialno(work_os,vf->current_serialno);
ogg_stream_reset_serialno(&vf->os,serialno);
ogg_stream_reset_serialno(&work_os,serialno);
vf->ready_state=STREAMSET;
firstflag=(pagepos<=vf->dataoffsets[link]);
}
{
ogg_page dup;
ogg_page_dup(&dup,&og);
ogg_stream_pagein(&vf->os,&og);
ogg_stream_pagein(&work_os,&og);
lastflag=ogg_page_eos(&og);
ogg_stream_pagein(vf->os,&og);
ogg_stream_pagein(work_os,&dup);
}
}
}
ogg_packet_release(&op);
ogg_page_release(&og);
ogg_stream_destroy(work_os);
ogg_stream_clear(&work_os);
vf->bittrack=0;
vf->samptrack=0;
return(0);
seek_error:
ogg_packet_release(&op);
ogg_page_release(&og);
/* dump the machine so we're in a known state */
vf->pcm_offset=-1;
ogg_stream_destroy(work_os);
ogg_stream_clear(&work_os);
_decode_clear(vf);
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
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
arrive at the requested position. */
int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
int link=-1;
ogg_int64_t result=0;
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->seekable)return(OV_ENOSEEK);
if(pos<0 || pos>total)return(OV_EINVAL);
/* 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
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
bitstream could make our task impossible. Account for that (it
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 best=begin;
ogg_page og;
while(begin<end){
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. */
bisect=begin +
(target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
if(bisect<=begin)
bisect=begin+1;
if(bisect<begin+CHUNKSIZE)
bisect=begin;
}
_seek_helper(vf,bisect);
if(bisect!=vf->offset){
result=_seek_helper(vf,bisect);
if(result) goto seek_error;
}
while(begin<end){
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;
bisect-=CHUNKSIZE;
if(bisect<=begin)bisect=begin+1;
_seek_helper(vf,bisect);
result=_seek_helper(vf,bisect);
if(result) goto seek_error;
}
}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<target){
best=result; /* raw offset of packet with granulepos */
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;
bisect-=CHUNKSIZE; /* an endless loop otherwise. */
if(bisect<=begin)bisect=begin+1;
_seek_helper(vf,bisect);
result=_seek_helper(vf,bisect);
if(result) goto seek_error;
}else{
end=result;
end=bisect;
endtime=granulepos;
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
raw_seek, don't keep packets preceeding granulepos. */
raw_seek, don't keep packets preceding granulepos. */
{
ogg_page og;
ogg_packet op;
/* seek */
result=_seek_helper(vf,best);
@ -1343,22 +1325,22 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
_decode_clear(vf);
vf->current_link=link;
vf->current_serialno=ogg_page_serialno(&og);
vf->current_serialno=vf->serialnos[link];
vf->ready_state=STREAMSET;
}else{
vorbis_synthesis_restart(&vf->vd);
}
ogg_stream_reset_serialno(vf->os,vf->current_serialno);
ogg_stream_pagein(vf->os,&og);
ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
ogg_stream_pagein(&vf->os,&og);
/* pull out all but last packet; the one with granulepos */
while(1){
result=ogg_stream_packetpeek(vf->os,&op);
result=ogg_stream_packetpeek(&vf->os,&op);
if(result==0){
/* !!! 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
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;
break;
}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->samptrack=0;
ogg_page_release(&og);
ogg_packet_release(&op);
return(0);
seek_error:
ogg_page_release(&og);
ogg_packet_release(&op);
/* dump machine so we're in a known state */
vf->pcm_offset=-1;
_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 */
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 ret=ov_pcm_seek_page(vf,pos);
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
position we want; don't decode them */
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){
thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
if(thisblock<0){
ogg_stream_packetout(vf->os,NULL);
ogg_stream_packetout(&vf->os,NULL);
continue; /* non audio packet */
}
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;
/* 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
only tracking, no
pcm_decode */
@ -1481,17 +1456,13 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
vf->ready_state=STREAMSET;
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);
if(ret){
ogg_page_release(&og);
ogg_packet_release(&op);
return ret;
}
if(ret)return ret;
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;
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 */
}
ogg_page_release(&og);
ogg_packet_release(&op);
return 0;
}
@ -1634,9 +1602,12 @@ long ov_read_fixed(OggVorbis_File *vf,ogg_int32_t ***pcm_channels,int length,
/* suck in another packet */
{
int ret=_fetch_and_process_packet(vf,1,1);
if(ret==OV_EOF)return(0);
if(ret<=0)return(ret);
int ret=_fetch_and_process_packet(vf,NULL,1,1);
if(ret==OV_EOF)
return(0);
if(ret<=0)
return(ret);
}
}
}