summaryrefslogtreecommitdiff
path: root/apps/codecs/libtremor/vorbisfile.c
diff options
context:
space:
mode:
authorNils Wallménius <nils@rockbox.org>2010-12-06 14:36:52 +0000
committerNils Wallménius <nils@rockbox.org>2010-12-06 14:36:52 +0000
commit67efbc13870ee87ce3df442f7c396c13481921ec (patch)
treeeaf63d36c5bf2d41a6b3bb2addecb4d3c05f7eef /apps/codecs/libtremor/vorbisfile.c
parent1f64b7fb1fa5058e3b7871078055156eac0c511d (diff)
downloadrockbox-67efbc13870ee87ce3df442f7c396c13481921ec.zip
rockbox-67efbc13870ee87ce3df442f7c396c13481921ec.tar.gz
rockbox-67efbc13870ee87ce3df442f7c396c13481921ec.tar.bz2
rockbox-67efbc13870ee87ce3df442f7c396c13481921ec.tar.xz
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
Diffstat (limited to 'apps/codecs/libtremor/vorbisfile.c')
-rw-r--r--apps/codecs/libtremor/vorbisfile.c509
1 files changed, 240 insertions, 269 deletions
diff --git a/apps/codecs/libtremor/vorbisfile.c b/apps/codecs/libtremor/vorbisfile.c
index 50a57af..9365ba3 100644
--- a/apps/codecs/libtremor/vorbisfile.c
+++ b/apps/codecs/libtremor/vorbisfile.c
@@ -53,18 +53,19 @@
we only want coarse navigation through the stream. */
/*************************************************************************
- * Many, many internal helpers. The intention is not to be confusing;
- * rampant duplication and monolithic function implementation would be
+ * Many, many internal helpers. The intention is not to be confusing;
+ * rampant duplication and monolithic function implementation would be
* harder to understand anyway. The high level functions are last. Begin
* grokking near the end of the file */
/* 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,8 +106,8 @@ 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 */
vf->offset-=more;
@@ -127,7 +126,7 @@ static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
ogg_int64_t ret=vf->offset;
vf->offset+=more;
return(ret);
-
+
}
}
}
@@ -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;
@@ -151,9 +149,10 @@ static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
begin=0;
ret=_seek_helper(vf,begin);
- if(ret)return(ret);
+ 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;
}
- ret=_seek_helper(vf,bisect);
- if(ret)return(ret);
+ 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 */
@@ -666,7 +647,7 @@ static int _open_seekable2(OggVorbis_File *vf){
return(ov_raw_seek(vf,dataoffset));
}
-/* clear out the current logical bitstream decoder */
+/* clear out the current logical bitstream decoder */
static void _decode_clear(OggVorbis_File *vf){
vorbis_dsp_clear(&vf->vd);
vorbis_block_clear(&vf->vb);
@@ -677,74 +658,67 @@ static void _decode_clear(OggVorbis_File *vf){
bitstream boundary and dumps the decoding machine. If the decoding
machine is unloaded, it loads it. It also keeps pcm_offset up to
date (seek and read both use this. seek uses a special hack with
- readp).
+ readp).
return: <0) error, OV_HOLE (lost packet) or OV_EOF
0) need more data (only if readp==0)
- 1) got a packet
+ 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
- header handling. The
- header packets aren't
- audio, so if/when we
- submit them,
- vorbis_synthesis will
- reject them */
+ 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
+ submit them,
+ vorbis_synthesis will
+ reject them */
/* suck in the synthesis data and track bitrate */
{
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;
-
+
/* this packet has a pcm_offset on it (the last packet
completed on a page carries the offset) After processing
(above), we know the pcm position of the *last* sample
@@ -755,7 +729,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
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)
@@ -766,23 +740,22 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
is very broken */
samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
-
+
granulepos-=samples;
for(i=0;i<link;i++)
granulepos+=vf->pcmlengths[i*2+1];
vf->pcm_offset=granulepos;
}
- ret=1;
- goto cleanup;
+ return(1);
}
}
- else
+ else
break;
}
}
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,12 +797,13 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
continue; /* possibility #2 */
}
}
+
break;
}
}
/* Do we need to load a new machine before submitting the page? */
- /* This is different in the seekable and non-seekable cases.
+ /* This is different in the seekable and non-seekable cases.
In the seekable case, we already have all the header
information loaded and cached; we just initialize the machine
@@ -846,37 +814,37 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
we're now nominally at the header of the next bitstream
*/
- if(vf->ready_state!=INITSET){
+ if(vf->ready_state!=INITSET){
int link;
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
- trying */
+ if(link==vf->links) continue; /* not the desired Vorbis
+ bitstream section; keep
+ trying */
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{
/* we're streaming */
/* 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,8 +919,8 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
}
static int _ov_open2(OggVorbis_File *vf){
- if(vf->ready_state < OPENED)
- vf->ready_state=OPENED;
+ if(vf->ready_state != PARTOPEN) return OV_EINVAL;
+ vf->ready_state=OPENED;
if(vf->seekable){
int ret=_open_seekable2(vf);
if(ret){
@@ -963,7 +928,9 @@ static int _ov_open2(OggVorbis_File *vf){
ov_clear(vf);
}
return(ret);
- }
+ }else
+ vf->ready_state=STREAMSET;
+
return 0;
}
@@ -973,8 +940,8 @@ 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;
for(i=0;i<vf->links;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));
@@ -1002,14 +968,14 @@ int ov_clear(OggVorbis_File *vf){
/* inspects the OggVorbis file and finds/documents all the logical
bitstreams contained in it. Tries to be tolerant of logical
- bitstream sections that are truncated/woogie.
+ bitstream sections that are truncated/woogie.
return: -1) error
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,15 +1042,21 @@ 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);
-
+
ret=_seek_helper(vf,pos);
if(ret)goto seek_error;
@@ -1097,55 +1067,61 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
So, a hack. We use two stream states; a local scratch state and
the shared vf->os stream state. We use the local state to
- scan, and the shared state as a buffer for later decode.
+ scan, and the shared state as a buffer for later decode.
Unfortuantely, on the last page we still advance to last packet
because the granulepos on the last page is not necessarily on a
packet boundary, and we need to make sure the granpos is
- correct.
+ correct.
*/
{
+ 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;
- }
+ }
if(op.granulepos!=-1){
int i,link=vf->current_link;
ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
if(granulepos<0)granulepos=0;
-
+
for(i=0;i<link;i++)
granulepos+=vf->pcmlengths[i*2+1];
vf->pcm_offset=granulepos-accblock;
@@ -1155,10 +1131,10 @@ 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);
}
}
-
+
if(!lastblock){
pagepos=_get_next_page(vf,&og,-1);
if(pagepos<0){
@@ -1170,10 +1146,11 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
vf->pcm_offset=-1;
break;
}
-
+
/* 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);
- lastflag=ogg_page_eos(&og);
- ogg_stream_pagein(vf->os,&og);
- ogg_stream_pagein(work_os,&dup);
- }
+
+ ogg_stream_pagein(&vf->os,&og);
+ ogg_stream_pagein(&work_os,&og);
+ lastflag=ogg_page_eos(&og);
+
}
}
- 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,20 +1204,19 @@ 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? */
for(link=vf->links-1;link>=0;link--){
total-=vf->pcmlengths[link*2+1];
@@ -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) */
@@ -1269,22 +1237,26 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
ogg_int64_t target=pos-total+begintime;
ogg_int64_t best=begin;
-
+
+ ogg_page og;
while(begin<end){
ogg_int64_t bisect;
-
+
if(end-begin<CHUNKSIZE){
bisect=begin;
}else{
/* take a (pretty decent) guess. */
- bisect=begin +
+ 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);
if(result==OV_EREAD) goto seek_error;
@@ -1295,16 +1267,23 @@ 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 */
+ best=result; /* raw offset of packet with granulepos */
begin=vf->offset; /* raw offset of next page */
begintime=granulepos;
-
+
if(target-begintime>44100)break;
bisect=begin; /* *not* begin + 1 */
}else{
@@ -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,9 +1308,11 @@ 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);
vf->pcm_offset=-1;
@@ -1340,28 +1322,28 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
if(link!=vf->current_link){
/* Different link; dump entire decode machine */
- _decode_clear(vf);
-
+ _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. */
-
+
result=_seek_helper(vf,best);
if(result<0) goto seek_error;
@@ -1377,7 +1359,7 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
}
}
if(result<0){
- result = OV_EBADPACKET;
+ result = OV_EBADPACKET;
goto seek_error;
}
if(op.granulepos!=-1){
@@ -1386,11 +1368,11 @@ 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);
}
}
}
-
+
/* verify result */
if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
result=OV_EFAULT;
@@ -1398,60 +1380,53 @@ 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);
+ seek_error:
/* dump machine so we're in a known state */
vf->pcm_offset=-1;
_decode_clear(vf);
return (int)result;
}
-/* seek to a sample offset relative to the decompressed pcm stream
+/* seek to a sample offset relative to the decompressed pcm stream
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;
-
+
if(vf->pcm_offset+((thisblock+
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 */
- vorbis_synthesis_blockin(&vf->vd,&vf->vb);
-
+ vorbis_synthesis_blockin(&vf->vd,&vf->vb);
+
/* end of logical stream case is hard, especially with exact
length positioning. */
-
+
if(op.granulepos>-1){
int i;
/* always believe the stream markers */
@@ -1460,20 +1435,20 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
for(i=0;i<vf->current_link;i++)
vf->pcm_offset+=vf->pcmlengths[i*2+1];
}
-
+
lastblock=thisblock;
-
+
}else{
if(ret<0 && ret!=OV_HOLE)break;
-
+
/* suck in a new page */
if(_get_next_page(vf,&og,-1)<0)break;
if(ogg_page_bos(&og))_decode_clear(vf);
-
+
if(vf->ready_state<STREAMSET){
- long serialno=ogg_page_serialno(&og);
+ long serialno=ogg_page_serialno(&og);
int link;
-
+
for(link=0;link<vf->links;link++)
if(vf->serialnos[link]==(ogg_uint32_t) serialno)break;
if(link==vf->links) continue;
@@ -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);
}
}
@@ -1506,18 +1477,15 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
if(samples>target)samples=target;
vorbis_synthesis_read(&vf->vd,samples);
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;
}
-/* seek to a playback time relative to the decompressed pcm stream
+/* seek to a playback time relative to the decompressed pcm stream
returns zero on success, nonzero on failure */
int ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){
/* translate time to PCM position and call ov_pcm_seek */
@@ -1529,7 +1497,7 @@ int ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){
if(vf->ready_state<OPENED)return(OV_EINVAL);
if(!vf->seekable)return(OV_ENOSEEK);
if(milliseconds<0)return(OV_EINVAL);
-
+
/* which bitstream section does this time offset occur in? */
for(link=0;link<vf->links;link++){
ogg_int64_t addsec = ov_time_total(vf,link);
@@ -1559,7 +1527,7 @@ ogg_int64_t ov_time_tell(OggVorbis_File *vf){
int link=0;
ogg_int64_t pcm_total=0;
ogg_int64_t time_total=0;
-
+
if(vf->ready_state<OPENED)return(OV_EINVAL);
if(vf->seekable){
pcm_total=ov_pcm_total(vf,-1);
@@ -1579,7 +1547,7 @@ ogg_int64_t ov_time_tell(OggVorbis_File *vf){
/* link: -1) return the vorbis_info struct for the bitstream section
currently being decoded
0-n) to request information for a specific bitstream section
-
+
In the case of a non-seekable bitstream, any call returns the
current bitstream. NULL in the case that the machine is not
initialized */
@@ -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);
}
}
}
+