|
@@ -5,13 +5,13 @@
|
|
* 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 SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
|
|
|
|
|
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015 *
|
|
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
|
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
|
* *
|
|
* *
|
|
********************************************************************
|
|
********************************************************************
|
|
|
|
|
|
function: stdio-based convenience library for opening/seeking/decoding
|
|
function: stdio-based convenience library for opening/seeking/decoding
|
|
- last mod: $Id: vorbisfile.c 17573 2010-10-27 14:53:59Z xiphmont $
|
|
|
|
|
|
+ last mod: $Id: vorbisfile.c 19457 2015-03-03 00:15:29Z giles $
|
|
|
|
|
|
********************************************************************/
|
|
********************************************************************/
|
|
|
|
|
|
@@ -80,11 +80,14 @@ static long _get_data(OggVorbis_File *vf){
|
|
/* save a tiny smidge of verbosity to make the code more readable */
|
|
/* save a tiny smidge of verbosity to make the code more readable */
|
|
static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
|
|
static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
|
|
if(vf->datasource){
|
|
if(vf->datasource){
|
|
- if(!(vf->callbacks.seek_func)||
|
|
|
|
- (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1)
|
|
|
|
- return OV_EREAD;
|
|
|
|
- vf->offset=offset;
|
|
|
|
- ogg_sync_reset(&vf->oy);
|
|
|
|
|
|
+ /* only seek if the file position isn't already there */
|
|
|
|
+ if(vf->offset != offset){
|
|
|
|
+ if(!(vf->callbacks.seek_func)||
|
|
|
|
+ (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1)
|
|
|
|
+ return OV_EREAD;
|
|
|
|
+ vf->offset=offset;
|
|
|
|
+ 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;
|
|
@@ -138,14 +141,12 @@ static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-/* find the latest page beginning before the current stream cursor
|
|
|
|
- position. Much dirtier than the above as Ogg doesn't have any
|
|
|
|
- backward search linkage. no 'readp' as it will certainly have to
|
|
|
|
- read. */
|
|
|
|
|
|
+/* find the latest page beginning before the passed in 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 */
|
|
/* 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;
|
|
|
|
|
|
+static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_int64_t begin,ogg_page *og){
|
|
|
|
+ ogg_int64_t end = begin;
|
|
ogg_int64_t ret;
|
|
ogg_int64_t ret;
|
|
ogg_int64_t offset=-1;
|
|
ogg_int64_t offset=-1;
|
|
|
|
|
|
@@ -220,11 +221,10 @@ static int _lookup_page_serialno(ogg_page *og, long *serialno_list, int n){
|
|
info of last page of the matching serial number instead of the very
|
|
info of last page of the matching serial number instead of the very
|
|
last page. If no page of the specified serialno is seen, it will
|
|
last page. If no page of the specified serialno is seen, it will
|
|
return the info of last page and alter *serialno. */
|
|
return the info of last page and alter *serialno. */
|
|
-static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
|
|
|
|
|
|
+static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf, ogg_int64_t begin,
|
|
long *serial_list, int serial_n,
|
|
long *serial_list, int serial_n,
|
|
int *serialno, ogg_int64_t *granpos){
|
|
int *serialno, ogg_int64_t *granpos){
|
|
ogg_page og;
|
|
ogg_page og;
|
|
- ogg_int64_t begin=vf->offset;
|
|
|
|
ogg_int64_t end=begin;
|
|
ogg_int64_t end=begin;
|
|
ogg_int64_t ret;
|
|
ogg_int64_t ret;
|
|
|
|
|
|
@@ -438,9 +438,11 @@ static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
|
|
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)
|
|
|
|
- accumulated+=(lastblock+thisblock)>>2;
|
|
|
|
- lastblock=thisblock;
|
|
|
|
|
|
+ if(thisblock>=0){
|
|
|
|
+ if(lastblock!=-1)
|
|
|
|
+ accumulated+=(lastblock+thisblock)>>2;
|
|
|
|
+ lastblock=thisblock;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -494,10 +496,10 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
|
|
down to (or just started with) a single link. Now we need to
|
|
down to (or just started with) a single link. Now we need to
|
|
find the last vorbis page belonging to the first vorbis stream
|
|
find the last vorbis page belonging to the first vorbis stream
|
|
for this link. */
|
|
for this link. */
|
|
-
|
|
|
|
|
|
+ searched = end;
|
|
while(endserial != serialno){
|
|
while(endserial != serialno){
|
|
endserial = serialno;
|
|
endserial = serialno;
|
|
- vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&endserial,&endgran);
|
|
|
|
|
|
+ searched=_get_prev_page_serial(vf,searched,currentno_list,currentnos,&endserial,&endgran);
|
|
}
|
|
}
|
|
|
|
|
|
vf->links=m+1;
|
|
vf->links=m+1;
|
|
@@ -518,10 +520,15 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
|
|
|
|
|
|
}else{
|
|
}else{
|
|
|
|
|
|
|
|
+ /* last page is not in the starting stream's serial number list,
|
|
|
|
+ so we have multiple links. Find where the stream that begins
|
|
|
|
+ our bisection ends. */
|
|
|
|
+
|
|
long *next_serialno_list=NULL;
|
|
long *next_serialno_list=NULL;
|
|
int next_serialnos=0;
|
|
int next_serialnos=0;
|
|
vorbis_info vi;
|
|
vorbis_info vi;
|
|
vorbis_comment vc;
|
|
vorbis_comment vc;
|
|
|
|
+ int testserial = serialno+1;
|
|
|
|
|
|
/* 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. */
|
|
@@ -534,10 +541,8 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
|
|
bisect=(searched+endsearched)/2;
|
|
bisect=(searched+endsearched)/2;
|
|
}
|
|
}
|
|
|
|
|
|
- if(bisect != vf->offset){
|
|
|
|
- ret=_seek_helper(vf,bisect);
|
|
|
|
- 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);
|
|
@@ -550,28 +555,22 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
|
|
}
|
|
}
|
|
|
|
|
|
/* Bisection point found */
|
|
/* Bisection point found */
|
|
-
|
|
|
|
/* for the time being, fetch end PCM offset the simple way */
|
|
/* for the time being, fetch end PCM offset the simple way */
|
|
- {
|
|
|
|
- int testserial = serialno+1;
|
|
|
|
- vf->offset = next;
|
|
|
|
- while(testserial != serialno){
|
|
|
|
- testserial = serialno;
|
|
|
|
- vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&testserial,&searchgran);
|
|
|
|
- }
|
|
|
|
|
|
+ searched = next;
|
|
|
|
+ while(testserial != serialno){
|
|
|
|
+ testserial = serialno;
|
|
|
|
+ searched = _get_prev_page_serial(vf,searched,currentno_list,currentnos,&testserial,&searchgran);
|
|
}
|
|
}
|
|
|
|
|
|
- if(vf->offset!=next){
|
|
|
|
- ret=_seek_helper(vf,next);
|
|
|
|
- if(ret)return(ret);
|
|
|
|
- }
|
|
|
|
|
|
+ ret=_seek_helper(vf,next);
|
|
|
|
+ if(ret)return(ret);
|
|
|
|
|
|
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 bisection always
|
|
starts with a raw seek */
|
|
starts with a raw seek */
|
|
pcmoffset = _initial_pcmoffset(vf,&vi);
|
|
pcmoffset = _initial_pcmoffset(vf,&vi);
|
|
|
|
|
|
@@ -638,11 +637,11 @@ static int _open_seekable2(OggVorbis_File *vf){
|
|
/* Get the offset of the last page of the physical bitstream, or, if
|
|
/* Get the offset of the last page of the physical bitstream, or, if
|
|
we're lucky the last vorbis page of this link as most OggVorbis
|
|
we're lucky the last vorbis page of this link as most OggVorbis
|
|
files will contain a single logical bitstream */
|
|
files will contain a single logical bitstream */
|
|
- end=_get_prev_page_serial(vf,vf->serialnos+2,vf->serialnos[1],&endserial,&endgran);
|
|
|
|
|
|
+ end=_get_prev_page_serial(vf,vf->end,vf->serialnos+2,vf->serialnos[1],&endserial,&endgran);
|
|
if(end<0)return(end);
|
|
if(end<0)return(end);
|
|
|
|
|
|
/* now determine bitstream structure recursively */
|
|
/* now determine bitstream structure recursively */
|
|
- if(_bisect_forward_serialno(vf,0,dataoffset,vf->offset,endgran,endserial,
|
|
|
|
|
|
+ if(_bisect_forward_serialno(vf,0,dataoffset,end,endgran,endserial,
|
|
vf->serialnos+2,vf->serialnos[1],0)<0)return(OV_EREAD);
|
|
vf->serialnos+2,vf->serialnos[1],0)<0)return(OV_EREAD);
|
|
|
|
|
|
vf->offsets[0]=0;
|
|
vf->offsets[0]=0;
|
|
@@ -1055,7 +1054,11 @@ int ov_halfrate_p(OggVorbis_File *vf){
|
|
/* Only partially open the vorbis file; test for Vorbisness, and load
|
|
/* Only partially open the vorbis file; test for Vorbisness, and load
|
|
the headers for the first chain. Do not seek (although test for
|
|
the headers for the first chain. Do not seek (although test for
|
|
seekability). Use ov_test_open to finish opening the file, else
|
|
seekability). Use ov_test_open to finish opening the file, else
|
|
- ov_clear to close/free it. Same return codes as open. */
|
|
|
|
|
|
+ ov_clear to close/free it. Same return codes as open.
|
|
|
|
+
|
|
|
|
+ Note that vorbisfile does _not_ take ownership of the file if the
|
|
|
|
+ call fails; the calling applicaiton is responsible for closing the file
|
|
|
|
+ if this call returns an error. */
|
|
|
|
|
|
int ov_test_callbacks(void *f,OggVorbis_File *vf,
|
|
int ov_test_callbacks(void *f,OggVorbis_File *vf,
|
|
const char *initial,long ibytes,ov_callbacks callbacks)
|
|
const char *initial,long ibytes,ov_callbacks callbacks)
|
|
@@ -1417,22 +1420,41 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|
if(pos>=total)break;
|
|
if(pos>=total)break;
|
|
}
|
|
}
|
|
|
|
|
|
- /* search within the logical bitstream for the page with the highest
|
|
|
|
- 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) */
|
|
|
|
|
|
+ /* Search within the logical bitstream for the page with the highest
|
|
|
|
+ pcm_pos preceding pos. If we're looking for a position on the
|
|
|
|
+ first page, bisection will halt without finding our position as
|
|
|
|
+ it's before the first explicit granulepos fencepost. That case is
|
|
|
|
+ handled separately below.
|
|
|
|
+
|
|
|
|
+ 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) */
|
|
|
|
+
|
|
|
|
+ /* new search algorithm originally by HB (Nicholas Vinen) */
|
|
|
|
|
|
- /* new search algorithm by HB (Nicholas Vinen) */
|
|
|
|
{
|
|
{
|
|
ogg_int64_t end=vf->offsets[link+1];
|
|
ogg_int64_t end=vf->offsets[link+1];
|
|
- ogg_int64_t begin=vf->offsets[link];
|
|
|
|
|
|
+ ogg_int64_t begin=vf->dataoffsets[link];
|
|
ogg_int64_t begintime = vf->pcmlengths[link*2];
|
|
ogg_int64_t begintime = vf->pcmlengths[link*2];
|
|
ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
|
|
ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
|
|
ogg_int64_t target=pos-total+begintime;
|
|
ogg_int64_t target=pos-total+begintime;
|
|
- ogg_int64_t best=begin;
|
|
|
|
|
|
+ ogg_int64_t best=-1;
|
|
|
|
+ int got_page=0;
|
|
|
|
|
|
ogg_page og;
|
|
ogg_page og;
|
|
|
|
+
|
|
|
|
+ /* if we have only one page, there will be no bisection. Grab the page here */
|
|
|
|
+ if(begin==end){
|
|
|
|
+ result=_seek_helper(vf,begin);
|
|
|
|
+ if(result) goto seek_error;
|
|
|
|
+
|
|
|
|
+ result=_get_next_page(vf,&og,1);
|
|
|
|
+ if(result<0) goto seek_error;
|
|
|
|
+
|
|
|
|
+ got_page=1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* bisection loop */
|
|
while(begin<end){
|
|
while(begin<end){
|
|
ogg_int64_t bisect;
|
|
ogg_int64_t bisect;
|
|
|
|
|
|
@@ -1447,51 +1469,80 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|
bisect=begin;
|
|
bisect=begin;
|
|
}
|
|
}
|
|
|
|
|
|
- if(bisect!=vf->offset){
|
|
|
|
- result=_seek_helper(vf,bisect);
|
|
|
|
- if(result) goto seek_error;
|
|
|
|
- }
|
|
|
|
|
|
+ result=_seek_helper(vf,bisect);
|
|
|
|
+ if(result) goto seek_error;
|
|
|
|
|
|
|
|
+ /* read loop within the bisection loop */
|
|
while(begin<end){
|
|
while(begin<end){
|
|
result=_get_next_page(vf,&og,end-vf->offset);
|
|
result=_get_next_page(vf,&og,end-vf->offset);
|
|
if(result==OV_EREAD) goto seek_error;
|
|
if(result==OV_EREAD) goto seek_error;
|
|
if(result<0){
|
|
if(result<0){
|
|
|
|
+ /* there is no next page! */
|
|
if(bisect<=begin+1)
|
|
if(bisect<=begin+1)
|
|
- end=begin; /* found it */
|
|
|
|
|
|
+ /* No bisection left to perform. We've either found the
|
|
|
|
+ best candidate already or failed. Exit loop. */
|
|
|
|
+ end=begin;
|
|
else{
|
|
else{
|
|
|
|
+ /* We tried to load a fraction of the last page; back up a
|
|
|
|
+ bit and try to get the whole last page */
|
|
if(bisect==0) goto seek_error;
|
|
if(bisect==0) goto seek_error;
|
|
bisect-=CHUNKSIZE;
|
|
bisect-=CHUNKSIZE;
|
|
|
|
+
|
|
|
|
+ /* don't repeat/loop on a read we've already performed */
|
|
if(bisect<=begin)bisect=begin+1;
|
|
if(bisect<=begin)bisect=begin+1;
|
|
|
|
+
|
|
|
|
+ /* seek and cntinue bisection */
|
|
result=_seek_helper(vf,bisect);
|
|
result=_seek_helper(vf,bisect);
|
|
if(result) goto seek_error;
|
|
if(result) goto seek_error;
|
|
}
|
|
}
|
|
}else{
|
|
}else{
|
|
ogg_int64_t granulepos;
|
|
ogg_int64_t granulepos;
|
|
|
|
+ got_page=1;
|
|
|
|
|
|
|
|
+ /* got a page. analyze it */
|
|
|
|
+ /* only consider pages from primary vorbis stream */
|
|
if(ogg_page_serialno(&og)!=vf->serialnos[link])
|
|
if(ogg_page_serialno(&og)!=vf->serialnos[link])
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
+ /* only consider pages with the granulepos set */
|
|
granulepos=ogg_page_granulepos(&og);
|
|
granulepos=ogg_page_granulepos(&og);
|
|
if(granulepos==-1)continue;
|
|
if(granulepos==-1)continue;
|
|
|
|
|
|
if(granulepos<target){
|
|
if(granulepos<target){
|
|
|
|
+ /* this page is a successful candidate! Set state */
|
|
|
|
+
|
|
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 */
|
|
begintime=granulepos;
|
|
begintime=granulepos;
|
|
|
|
|
|
|
|
+ /* if we're before our target but within a short distance,
|
|
|
|
+ don't bisect; read forward */
|
|
if(target-begintime>44100)break;
|
|
if(target-begintime>44100)break;
|
|
- bisect=begin; /* *not* begin + 1 */
|
|
|
|
|
|
+
|
|
|
|
+ bisect=begin; /* *not* begin + 1 as above */
|
|
}else{
|
|
}else{
|
|
- if(bisect<=begin+1)
|
|
|
|
- end=begin; /* found it */
|
|
|
|
- else{
|
|
|
|
- if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
|
|
|
|
|
|
+
|
|
|
|
+ /* This is one of our pages, but the granpos is
|
|
|
|
+ post-target; it is not a bisection return
|
|
|
|
+ candidate. (The only way we'd use it is if it's the
|
|
|
|
+ first page in the stream; we handle that case later
|
|
|
|
+ outside the bisection) */
|
|
|
|
+ if(bisect<=begin+1){
|
|
|
|
+ /* No bisection left to perform. We've either found the
|
|
|
|
+ best candidate already or failed. Exit loop. */
|
|
|
|
+ end=begin;
|
|
|
|
+ }else{
|
|
|
|
+ if(end==vf->offset){
|
|
|
|
+ /* bisection read to the end; use the known page
|
|
|
|
+ boundary (result) to update bisection, back up a
|
|
|
|
+ little bit, and try again */
|
|
end=result;
|
|
end=result;
|
|
- bisect-=CHUNKSIZE; /* an endless loop otherwise. */
|
|
|
|
|
|
+ bisect-=CHUNKSIZE;
|
|
if(bisect<=begin)bisect=begin+1;
|
|
if(bisect<=begin)bisect=begin+1;
|
|
result=_seek_helper(vf,bisect);
|
|
result=_seek_helper(vf,bisect);
|
|
if(result) goto seek_error;
|
|
if(result) goto seek_error;
|
|
}else{
|
|
}else{
|
|
|
|
+ /* Normal bisection */
|
|
end=bisect;
|
|
end=bisect;
|
|
endtime=granulepos;
|
|
endtime=granulepos;
|
|
break;
|
|
break;
|
|
@@ -1502,9 +1553,46 @@ 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 preceding granulepos. */
|
|
|
|
- {
|
|
|
|
|
|
+ /* Out of bisection: did it 'fail?' */
|
|
|
|
+ if(best == -1){
|
|
|
|
+
|
|
|
|
+ /* Check the 'looking for data in first page' special case;
|
|
|
|
+ bisection would 'fail' because our search target was before the
|
|
|
|
+ first PCM granule position fencepost. */
|
|
|
|
+
|
|
|
|
+ if(got_page &&
|
|
|
|
+ begin == vf->dataoffsets[link] &&
|
|
|
|
+ ogg_page_serialno(&og)==vf->serialnos[link]){
|
|
|
|
+
|
|
|
|
+ /* Yes, this is the beginning-of-stream case. We already have
|
|
|
|
+ our page, right at the beginning of PCM data. Set state
|
|
|
|
+ and return. */
|
|
|
|
+
|
|
|
|
+ vf->pcm_offset=total;
|
|
|
|
+
|
|
|
|
+ if(link!=vf->current_link){
|
|
|
|
+ /* Different link; dump entire decode machine */
|
|
|
|
+ _decode_clear(vf);
|
|
|
|
+
|
|
|
|
+ vf->current_link=link;
|
|
|
|
+ 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);
|
|
|
|
+
|
|
|
|
+ }else
|
|
|
|
+ goto seek_error;
|
|
|
|
+
|
|
|
|
+ }else{
|
|
|
|
+
|
|
|
|
+ /* Bisection found our page. seek to it, update pcm offset. Easier case than
|
|
|
|
+ raw_seek, don't keep packets preceding granulepos. */
|
|
|
|
+
|
|
ogg_page og;
|
|
ogg_page og;
|
|
ogg_packet op;
|
|
ogg_packet op;
|
|
|
|
|
|
@@ -1534,23 +1622,23 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|
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
|
|
|
|
- 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;
|
|
|
|
-
|
|
|
|
- while(1){
|
|
|
|
- result=_get_prev_page(vf,&og);
|
|
|
|
|
|
+ /* No packet returned; we exited the bisection with 'best'
|
|
|
|
+ pointing to a page with a granule position, so the packet
|
|
|
|
+ finishing this page ('best') originated on a 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. */
|
|
|
|
+ /* Do not rewind past the beginning of link data; if we do,
|
|
|
|
+ it's either a bug or a broken stream */
|
|
|
|
+ result=best;
|
|
|
|
+ while(result>vf->dataoffsets[link]){
|
|
|
|
+ result=_get_prev_page(vf,result,&og);
|
|
if(result<0) goto seek_error;
|
|
if(result<0) goto seek_error;
|
|
if(ogg_page_serialno(&og)==vf->current_serialno &&
|
|
if(ogg_page_serialno(&og)==vf->current_serialno &&
|
|
(ogg_page_granulepos(&og)>-1 ||
|
|
(ogg_page_granulepos(&og)>-1 ||
|
|
!ogg_page_continued(&og))){
|
|
!ogg_page_continued(&og))){
|
|
return ov_raw_seek(vf,result);
|
|
return ov_raw_seek(vf,result);
|
|
}
|
|
}
|
|
- vf->offset=result;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(result<0){
|
|
if(result<0){
|
|
@@ -2054,14 +2142,14 @@ long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-extern float *vorbis_window(vorbis_dsp_state *v,int W);
|
|
|
|
|
|
+extern const float *vorbis_window(vorbis_dsp_state *v,int W);
|
|
|
|
|
|
static void _ov_splice(float **pcm,float **lappcm,
|
|
static void _ov_splice(float **pcm,float **lappcm,
|
|
int n1, int n2,
|
|
int n1, int n2,
|
|
int ch1, int ch2,
|
|
int ch1, int ch2,
|
|
- float *w1, float *w2){
|
|
|
|
|
|
+ const float *w1, const float *w2){
|
|
int i,j;
|
|
int i,j;
|
|
- float *w=w1;
|
|
|
|
|
|
+ const float *w=w1;
|
|
int n=n1;
|
|
int n=n1;
|
|
|
|
|
|
if(n1>n2){
|
|
if(n1>n2){
|
|
@@ -2169,7 +2257,7 @@ int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){
|
|
vorbis_info *vi1,*vi2;
|
|
vorbis_info *vi1,*vi2;
|
|
float **lappcm;
|
|
float **lappcm;
|
|
float **pcm;
|
|
float **pcm;
|
|
- float *w1,*w2;
|
|
|
|
|
|
+ const float *w1,*w2;
|
|
int n1,n2,i,ret,hs1,hs2;
|
|
int n1,n2,i,ret,hs1,hs2;
|
|
|
|
|
|
if(vf1==vf2)return(0); /* degenerate case */
|
|
if(vf1==vf2)return(0); /* degenerate case */
|
|
@@ -2223,7 +2311,7 @@ static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos,
|
|
vorbis_info *vi;
|
|
vorbis_info *vi;
|
|
float **lappcm;
|
|
float **lappcm;
|
|
float **pcm;
|
|
float **pcm;
|
|
- float *w1,*w2;
|
|
|
|
|
|
+ const float *w1,*w2;
|
|
int n1,n2,ch1,ch2,hs;
|
|
int n1,n2,ch1,ch2,hs;
|
|
int i,ret;
|
|
int i,ret;
|
|
|
|
|
|
@@ -2284,7 +2372,7 @@ static int _ov_d_seek_lap(OggVorbis_File *vf,double pos,
|
|
vorbis_info *vi;
|
|
vorbis_info *vi;
|
|
float **lappcm;
|
|
float **lappcm;
|
|
float **pcm;
|
|
float **pcm;
|
|
- float *w1,*w2;
|
|
|
|
|
|
+ const float *w1,*w2;
|
|
int n1,n2,ch1,ch2,hs;
|
|
int n1,n2,ch1,ch2,hs;
|
|
int i,ret;
|
|
int i,ret;
|
|
|
|
|