Commit 85b6663a authored by Thomas Guillem's avatar Thomas Guillem Committed by Jean-Baptiste Kempf

dvd_reader: cache IFO and BUP files (only for images files)

It reduces the number of read/seek accesses
Signed-off-by: Jean-Baptiste Kempf's avatarJean-Baptiste Kempf <jb@videolan.org>
parent af446d46
...@@ -118,6 +118,10 @@ struct dvd_file_s { ...@@ -118,6 +118,10 @@ struct dvd_file_s {
/* Calculated at open-time, size in blocks. */ /* Calculated at open-time, size in blocks. */
ssize_t filesize; ssize_t filesize;
/* Cache of the dvd_file. If not NULL, the cache corresponds to the whole
* dvd_file. Used only for IFO and BUP. */
unsigned char *cache;
}; };
int InternalUDFReadBlocksRaw( const dvd_reader_t *device, uint32_t lb_number, int InternalUDFReadBlocksRaw( const dvd_reader_t *device, uint32_t lb_number,
...@@ -647,7 +651,8 @@ void DVDClose( dvd_reader_t *dvd ) ...@@ -647,7 +651,8 @@ void DVDClose( dvd_reader_t *dvd )
/** /**
* Open an unencrypted file on a DVD image file. * Open an unencrypted file on a DVD image file.
*/ */
static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename ) static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename,
int do_cache )
{ {
uint32_t start, len; uint32_t start, len;
dvd_file_t *dvd_file; dvd_file_t *dvd_file;
...@@ -669,6 +674,25 @@ static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename ) ...@@ -669,6 +674,25 @@ static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename )
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN; dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
dvd_file->cache = NULL;
/* Read the whole file in cache (unencrypted) if asked and if it doesn't
* exceed 128KB */
if( do_cache && len < 64 * DVD_VIDEO_LB_LEN ) {
int ret;
dvd_file->cache = malloc( len );
if( !dvd_file->cache )
return dvd_file;
ret = InternalUDFReadBlocksRaw( dvd, dvd_file->lb_start,
dvd_file->filesize, dvd_file->cache,
DVDINPUT_NOFLAGS );
if( ret != dvd_file->filesize ) {
free( dvd_file->cache );
dvd_file->cache = NULL;
}
}
return dvd_file; return dvd_file;
} }
...@@ -766,6 +790,7 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename ) ...@@ -766,6 +790,7 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = 0; dvd_file->filesize = 0;
dvd_file->cache = NULL;
if( stat( full_path, &fileinfo ) < 0 ) { if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
...@@ -803,6 +828,7 @@ static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu ) ...@@ -803,6 +828,7 @@ static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu )
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN; dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
dvd_file->cache = NULL;
/* Calculate the complete file size for every file in the VOBS */ /* Calculate the complete file size for every file in the VOBS */
if( !menu ) { if( !menu ) {
...@@ -845,6 +871,7 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu ) ...@@ -845,6 +871,7 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu )
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = 0; dvd_file->filesize = 0;
dvd_file->cache = NULL;
if( menu ) { if( menu ) {
dvd_input_t dev; dvd_input_t dev;
...@@ -909,6 +936,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum, ...@@ -909,6 +936,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
dvd_read_domain_t domain ) dvd_read_domain_t domain )
{ {
char filename[ MAX_UDF_FILE_NAME_LEN ]; char filename[ MAX_UDF_FILE_NAME_LEN ];
int do_cache = 0;
/* Check arguments. */ /* Check arguments. */
if( dvd == NULL || titlenum < 0 ) if( dvd == NULL || titlenum < 0 )
...@@ -921,6 +949,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum, ...@@ -921,6 +949,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
} else { } else {
sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum ); sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum );
} }
do_cache = 1;
break; break;
case DVD_READ_INFO_BACKUP_FILE: case DVD_READ_INFO_BACKUP_FILE:
if( titlenum == 0 ) { if( titlenum == 0 ) {
...@@ -928,6 +957,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum, ...@@ -928,6 +957,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
} else { } else {
sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum ); sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum );
} }
do_cache = 1;
break; break;
case DVD_READ_MENU_VOBS: case DVD_READ_MENU_VOBS:
if( dvd->isImageFile ) { if( dvd->isImageFile ) {
...@@ -950,7 +980,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum, ...@@ -950,7 +980,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
} }
if( dvd->isImageFile ) { if( dvd->isImageFile ) {
return DVDOpenFileUDF( dvd, filename ); return DVDOpenFileUDF( dvd, filename, do_cache );
} else { } else {
return DVDOpenFilePath( dvd, filename ); return DVDOpenFilePath( dvd, filename );
} }
...@@ -969,6 +999,7 @@ void DVDCloseFile( dvd_file_t *dvd_file ) ...@@ -969,6 +999,7 @@ void DVDCloseFile( dvd_file_t *dvd_file )
} }
} }
free( dvd_file->cache );
free( dvd_file ); free( dvd_file );
dvd_file = NULL; dvd_file = NULL;
} }
...@@ -1182,8 +1213,25 @@ static int DVDReadBlocksUDF( const dvd_file_t *dvd_file, uint32_t offset, ...@@ -1182,8 +1213,25 @@ static int DVDReadBlocksUDF( const dvd_file_t *dvd_file, uint32_t offset,
size_t block_count, unsigned char *data, size_t block_count, unsigned char *data,
int encrypted ) int encrypted )
{ {
return InternalUDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset, /* If the cache is present and we don't need to decrypt, use the cache to
block_count, data, encrypted ); * feed the data */
if( dvd_file->cache && (encrypted & DVDINPUT_READ_DECRYPT) == 0 ) {
/* Check if we don't exceed the cache (or file) size */
if( block_count + offset > (size_t) dvd_file->filesize )
return 0;
/* Copy the cache at a specified offset into data. offset and block_count
* must be converted into bytes */
memcpy( data, dvd_file->cache + (off_t)offset * (off_t)DVD_VIDEO_LB_LEN,
(off_t)block_count * (off_t)DVD_VIDEO_LB_LEN );
/* return the amount of blocks copied */
return block_count;
} else {
/* use dvdinput access */
return InternalUDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset,
block_count, data, encrypted );
}
} }
/* This is using possibly several inputs and starting from an offset of '0'. /* This is using possibly several inputs and starting from an offset of '0'.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment