From 431033df2571df5bdd1ec1253cf04921b6d01368 Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Sun, 2 Mar 2008 22:48:39 +0000 Subject: libdvdread - Uses UDF provided length as authoritative libdvdread uses the file length provided by the UDF fs of the title set IFO files authoritative. I got a DVD which have parts of this file mapped outside of the provided file size and according to my memory only the offsets in the files matters in the standard. This patch adjusts the internal knowledge of the filesize accordingly and at least allows mplayer to play the dvd. (Imported from Debian libdvdread 0.9.7-8) --- src/input/libdvdnav/dvd_reader.c | 24 +++++++++++++++++++++++- src/input/libdvdnav/dvd_reader.h | 2 ++ src/input/libdvdnav/ifo_read.c | 6 +++++- 3 files changed, 30 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/input/libdvdnav/dvd_reader.c b/src/input/libdvdnav/dvd_reader.c index 200a1dbec..eff1977fc 100644 --- a/src/input/libdvdnav/dvd_reader.c +++ b/src/input/libdvdnav/dvd_reader.c @@ -1037,6 +1037,28 @@ int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset ) return offset; } +int32_t DVDFileSeekForce( dvd_file_t *dvd_file, int offset, int force_size ) +{ + /* Check arguments. */ + if( dvd_file == NULL || offset < 0 ) + return -1; + + if( dvd_file->dvd->isImageFile ) { + if( force_size < 0 ) + force_size = (offset - 1) / DVD_VIDEO_LB_LEN + 1; + if( dvd_file->filesize < force_size) { + dvd_file->filesize = force_size; + fprintf(stderr, "libdvdread: Ignored UDF provided size of file.\n"); + } + } + + if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) { + return -1; + } + dvd_file->seek_pos = (uint32_t) offset; + return offset; +} + ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) { unsigned char *secbuf_base, *secbuf; @@ -1077,7 +1099,7 @@ ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) memcpy( data, &(secbuf[ seek_byte ]), byte_size ); free( secbuf_base ); - dvd_file->seek_pos += byte_size; + DVDFileSeekForce(dvd_file, dvd_file->seek_pos + byte_size, -1); return byte_size; } diff --git a/src/input/libdvdnav/dvd_reader.h b/src/input/libdvdnav/dvd_reader.h index bb3f5053b..e1b051c00 100644 --- a/src/input/libdvdnav/dvd_reader.h +++ b/src/input/libdvdnav/dvd_reader.h @@ -171,6 +171,8 @@ ssize_t DVDReadBlocks( dvd_file_t *, int, size_t, unsigned char * ); */ int32_t DVDFileSeek( dvd_file_t *, int32_t ); +int32_t DVDFileSeekForce( dvd_file_t *, int, int ); + /** * Reads the given number of bytes from the file. This call can only be used * on the information files, and may not be used for reading from a VOB. This diff --git a/src/input/libdvdnav/ifo_read.c b/src/input/libdvdnav/ifo_read.c index 8f47d2a54..bc1ba580b 100644 --- a/src/input/libdvdnav/ifo_read.c +++ b/src/input/libdvdnav/ifo_read.c @@ -93,6 +93,10 @@ static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) { return (DVDFileSeek(dvd_file, (int)offset) == (int)offset); } +static inline int32_t DVDFileSeekForce_( dvd_file_t *dvd_file, uint32_t offset, int force_size ) { + return (DVDFileSeekForce(dvd_file, (int)offset, force_size) == (int)offset); +} + ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) { ifo_handle_t *ifofile; @@ -1507,7 +1511,7 @@ static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, unsigned int i; int info_length; - if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) + if(!DVDFileSeekForce_(ifofile->file, sector * DVD_BLOCK_LEN, sector)) return 0; if(!(DVDReadBytes(ifofile->file, vobu_admap, VOBU_ADMAP_SIZE))) -- cgit v1.2.3