diff options
author | Monty <xiphmont@xiph.org> | 2009-04-09 16:35:52 +0000 |
---|---|---|
committer | Monty <xiphmont@xiph.org> | 2009-04-09 16:35:52 +0000 |
commit | 8ab5ace478ce4c64f9bf718f34787318f87bd759 (patch) | |
tree | e26ad6805cdd79ed7d1bf9efeeb5883312d03dd2 | |
parent | 4f57ae39f6cb216fbf5fe55ae734a584a8466c4d (diff) | |
download | libvorbis-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.h | 3 | ||||
-rw-r--r-- | lib/vorbisfile.c | 76 |
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 */ |