summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <xiphmont@xiph.org>2009-04-09 16:35:52 +0000
committerMonty <xiphmont@xiph.org>2009-04-09 16:35:52 +0000
commit8ab5ace478ce4c64f9bf718f34787318f87bd759 (patch)
treee26ad6805cdd79ed7d1bf9efeeb5883312d03dd2
parent4f57ae39f6cb216fbf5fe55ae734a584a8466c4d (diff)
downloadlibvorbis-git-8ab5ace478ce4c64f9bf718f34787318f87bd759.tar.gz
Correct another setup bug; extremely short links could get 'shadowed'
in the preferred serialno lookup if a backwards seek to find a preceeding page goes back too far and lands in an entirely different link. svn path=/trunk/vorbis/; revision=15930
-rw-r--r--include/vorbis/vorbisfile.h3
-rw-r--r--lib/vorbisfile.c76
2 files changed, 43 insertions, 36 deletions
diff --git a/include/vorbis/vorbisfile.h b/include/vorbis/vorbisfile.h
index 7c6cbc4d..e128fe88 100644
--- a/include/vorbis/vorbisfile.h
+++ b/include/vorbis/vorbisfile.h
@@ -48,12 +48,9 @@ typedef struct {
* ov_open() to avoid problems with incompatable crt.o version linking
* issues. */
-#include <stdio.h>
static int _ov_header_fseek_wrap(FILE *f,ogg_int64_t off,int whence){
if(f==NULL)return(-1);
- fprintf(stderr,"seek: %s %ld\n",(whence==SEEK_END?"END":(whence==SEEK_SET?"SET":"CUR")), (long)off);
-
#ifdef __MINGW32__
return fseeko64(f,off,whence);
#elif defined (_WIN32)
diff --git a/lib/vorbisfile.c b/lib/vorbisfile.c
index 4560ec57..99131993 100644
--- a/lib/vorbisfile.c
+++ b/lib/vorbisfile.c
@@ -181,13 +181,44 @@ static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
return(offset);
}
+static void _add_serialno(ogg_page *og,long **serialno_list, int *n){
+ long s = ogg_page_serialno(og);
+ (*n)++;
+
+ if(serialno_list){
+ *serialno_list = _ogg_realloc(*serialno_list, sizeof(*serialno_list)*(*n));
+ }else{
+ *serialno_list = _ogg_malloc(sizeof(**serialno_list));
+ }
+
+ (*serialno_list)[(*n)-1] = s;
+}
+
+/* returns nonzero if found */
+static int _lookup_serialno(long s, long *serialno_list, int n){
+ if(serialno_list){
+ while(n--){
+ if(*serialno_list == s) return 1;
+ serialno_list++;
+ }
+ }
+ return 0;
+}
+
+static int _lookup_page_serialno(ogg_page *og, long *serialno_list, int n){
+ long s = ogg_page_serialno(og);
+ return _lookup_serialno(s,serialno_list,n);
+}
+
/* performs the same search as _get_prev_page, but prefers pages of
the specified serial number. If a page of the specified serialno is
spotted during the seek-back-and-read-forward, it will return the
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
return the info of last page and alter *serialno. */
-static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,int *serialno, ogg_int64_t *granpos){
+static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
+ long *serial_list, int serial_n,
+ int *serialno, ogg_int64_t *granpos){
ogg_page og;
ogg_int64_t begin=vf->offset;
ogg_int64_t end=begin;
@@ -220,6 +251,14 @@ static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,int *serialno, ogg_i
prefoffset=ret;
*granpos=ret_gran;
}
+
+ if(!_lookup_serialno(ret_serialno,serial_list,serial_n)){
+ /* we fell off the end of the link, which means we seeked
+ back too far and shouldn't have been looking in that link
+ to begin with. If we found the preferred serial number,
+ forget that we saw it. */
+ prefoffset=-1;
+ }
}
}
}
@@ -233,35 +272,6 @@ static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,int *serialno, ogg_i
}
-static void _add_serialno(ogg_page *og,long **serialno_list, int *n){
- long s = ogg_page_serialno(og);
- (*n)++;
-
- if(serialno_list){
- *serialno_list = _ogg_realloc(*serialno_list, sizeof(*serialno_list)*(*n));
- }else{
- *serialno_list = _ogg_malloc(sizeof(**serialno_list));
- }
-
- (*serialno_list)[(*n)-1] = s;
-}
-
-/* returns nonzero if found */
-static int _lookup_serialno(long s, long *serialno_list, int n){
- if(serialno_list){
- while(n--){
- if(*serialno_list == s) return 1;
- serialno_list++;
- }
- }
- return 0;
-}
-
-static int _lookup_page_serialno(ogg_page *og, long *serialno_list, int n){
- long s = ogg_page_serialno(og);
- return _lookup_serialno(s,serialno_list,n);
-}
-
/* uses the local ogg_stream storage in vf; this is important for
non-streaming input sources */
static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
@@ -482,7 +492,7 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
while(endserial != serialno){
endserial = serialno;
- vf->offset=_get_prev_page_serial(vf,&endserial,&endgran);
+ vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&endserial,&endgran);
}
vf->links=m+1;
@@ -540,7 +550,7 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
vf->offset = next;
while(testserial != serialno){
testserial = serialno;
- vf->offset=_get_prev_page_serial(vf,&testserial,&searchgran);
+ vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&testserial,&searchgran);
}
}
@@ -621,7 +631,7 @@ static int _open_seekable2(OggVorbis_File *vf){
/* 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
files will contain a single logical bitstream */
- end=_get_prev_page_serial(vf,&endserial,&endgran);
+ end=_get_prev_page_serial(vf,vf->serialnos+2,vf->serialnos[1],&endserial,&endgran);
if(end<0)return(end);
/* now determine bitstream structure recursively */