Mercurial > mplayer.hg
changeset 24047:de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
author | diego |
---|---|
date | Wed, 15 Aug 2007 11:47:22 +0000 |
parents | 7e2808fb1807 |
children | fe3043a8552c |
files | Changelog Copyright configure dvdread/Makefile dvdread/bswap.h dvdread/dvd_input.c dvdread/dvd_input.h dvdread/dvd_reader.c dvdread/dvd_reader.h dvdread/dvd_udf.c dvdread/dvd_udf.h dvdread/dvdread_internal.h dvdread/ifo_print.c dvdread/ifo_read.c dvdread/ifo_types.h dvdread/nav_print.c dvdread/nav_read.c dvdread/nav_types.h stream/stream_dvd_common.c |
diffstat | 19 files changed, 1089 insertions(+), 236 deletions(-) [+] |
line wrap: on
line diff
--- a/Changelog Wed Aug 15 10:34:53 2007 +0000 +++ b/Changelog Wed Aug 15 11:47:22 2007 +0000 @@ -112,6 +112,7 @@ * ability to change subtitle size during playback * ability to turn loop on/off during playback * Apple Remote support + * libdvdread updated to 0.9.5 rc1: "Codename intentionally left blank" October 22, 2006
--- a/Copyright Wed Aug 15 10:34:53 2007 +0000 +++ b/Copyright Wed Aug 15 11:47:22 2007 +0000 @@ -49,7 +49,7 @@ License: GNU General Public License Name: libdvdread -Version: 0.9.4 + patches +Version: 0.9.5 + patches Homepage: http://www.dtek.chalmers.se/groups/dvd/development.shtml Directory: dvdread Copyright: 1998, 1999 Eric Smith <eric@brouhaha.com>
--- a/configure Wed Aug 15 10:34:53 2007 +0000 +++ b/configure Wed Aug 15 11:47:22 2007 +0000 @@ -7744,6 +7744,9 @@ #define HAVE_MEMCPY 1 #define HAVE_STRCHR 1 +/* libdvdread */ +#define HAVE_UINTPTR_T 1 + /* name of messages charset */ $_def_charset
--- a/dvdread/Makefile Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/Makefile Wed Aug 15 11:47:22 2007 +0000 @@ -10,6 +10,7 @@ nav_print.c \ nav_read.c \ md5.c \ + cmd_print.c \ CFLAGS = -D__USE_UNIX98 -D_GNU_SOURCE
--- a/dvdread/bswap.h Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/bswap.h Wed Aug 15 11:47:22 2007 +0000 @@ -61,7 +61,19 @@ #include <sys/endian.h> #define B2N_16(x) x = be16toh(x) #define B2N_32(x) x = be32toh(x) +#if __FreeBSD_version >= 500000 #define B2N_64(x) x = be64toh(x) +#else +#define B2N_64(x) \ + x = ((((x) & 0xff00000000000000) >> 56) | \ + (((x) & 0x00ff000000000000) >> 40) | \ + (((x) & 0x0000ff0000000000) >> 24) | \ + (((x) & 0x000000ff00000000) >> 8) | \ + (((x) & 0x00000000ff000000) << 8) | \ + (((x) & 0x0000000000ff0000) << 24) | \ + (((x) & 0x000000000000ff00) << 40) | \ + (((x) & 0x00000000000000ff) << 56)) +#endif /* _FreeBSD_version >= 500000 */ #elif defined(__DragonFly__) #include <sys/endian.h> @@ -113,7 +125,7 @@ * functionality! */ -#elif defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__) || defined(__CYGWIN__) +#elif defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__) || defined(WIN32) || defined(__BEOS__) || defined(__INTERIX) || defined(__CYGWIN__) #define B2N_16(x) \ x = ((((x) & 0xff00) >> 8) | \ (((x) & 0x00ff) << 8))
--- a/dvdread/dvd_input.c Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/dvd_input.c Wed Aug 15 11:47:22 2007 +0000 @@ -25,18 +25,26 @@ #include <stdio.h> #include <stdlib.h> +#define __USE_GNU /* to get O_DIRECT in linux */ #include <fcntl.h> #include <unistd.h> #include "dvd_reader.h" #include "dvd_input.h" +#include "dvdread_internal.h" + /* The function pointers that is the exported interface of this file. */ dvd_input_t (*dvdinput_open) (const char *); int (*dvdinput_close) (dvd_input_t); int (*dvdinput_seek) (dvd_input_t, int); int (*dvdinput_title) (dvd_input_t, int); +/** + * pointer must be aligned to 2048 bytes + * if reading from a raw/O_DIRECT file + */ int (*dvdinput_read) (dvd_input_t, void *, int, int); + char * (*dvdinput_error) (dvd_input_t); #ifdef HAVE_DVDCSS_DVDCSS_H @@ -80,16 +88,15 @@ /* Allocate the handle structure */ dev = (dvd_input_t) malloc(sizeof(struct dvd_input_s)); if(dev == NULL) { - fprintf(stderr, "libdvdread: Could not allocate memory.\n"); + /* malloc has set errno to ENOMEM */ return NULL; } /* Really open it with libdvdcss */ dev->dvdcss = DVDcss_open(target); if(dev->dvdcss == 0) { - fprintf(stderr, "libdvdread: Could not open %s with libdvdcss.\n", target); free(dev); - return NULL; + dev = NULL; } return dev; @@ -145,10 +152,14 @@ return 0; } - - - - +/* Need to use O_BINARY for WIN32 */ +#ifndef O_BINARY +#ifdef _O_BINARY +#define O_BINARY _O_BINARY +#else +#define O_BINARY 0 +#endif +#endif /** * initialize and open a DVD device or file. @@ -156,18 +167,26 @@ static dvd_input_t file_open(const char *target) { dvd_input_t dev; + char *use_odirect; + int oflags; + oflags = O_RDONLY | O_BINARY; + use_odirect = getenv("DVDREAD_USE_DIRECT"); + if(use_odirect) { +#ifndef O_DIRECT +#define O_DIRECT 0 +#endif + oflags |= O_DIRECT; + } /* Allocate the library structure */ dev = (dvd_input_t) malloc(sizeof(struct dvd_input_s)); if(dev == NULL) { - fprintf(stderr, "libdvdread: Could not allocate memory.\n"); return NULL; } /* Open the device */ - dev->fd = open(target, O_RDONLY); + dev->fd = open(target, oflags); if(dev->fd < 0) { - perror("libdvdread: Could not open input"); free(dev); return NULL; } @@ -189,9 +208,9 @@ */ static int file_seek(dvd_input_t dev, int blocks) { - off_t pos; + off_t pos = (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN; - pos = lseek(dev->fd, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_SET); + pos = lseek(dev->fd, pos, SEEK_SET); if(pos < 0) { return pos; } @@ -214,12 +233,13 @@ { size_t len; ssize_t ret; + unsigned char *buf = buffer; len = (size_t)blocks * DVD_VIDEO_LB_LEN; while(len > 0) { - ret = read(dev->fd, buffer, len); + ret = read(dev->fd, buf, len); if(ret < 0) { /* One of the reads failed, too bad. We won't even bother @@ -238,6 +258,7 @@ return (int) (bytes / DVD_VIDEO_LB_LEN); } + buf+=ret; len -= ret; } @@ -262,13 +283,49 @@ } +static void *dvdcss_library = NULL; +static int dvdcss_library_init = 0; + +/** + * Free any objects allocated by dvdinput_setup. + * Should only be called when libdvdread is not to be used any more. + * Closes dlopened libraries. + */ +void dvdinput_free(void) +{ +#ifdef HAVE_DVDCSS_DVDCSS_H + /* linked statically, nothing to free */ + return; +#else + if(dvdcss_library) { + dlclose(dvdcss_library); + dvdcss_library = NULL; + } + dvdcss_library_init = 0; + return; +#endif +} + + /** * Setup read functions with either libdvdcss or minimal DVD access. */ int dvdinput_setup(void) { - void *dvdcss_library = NULL; char **dvdcss_version = NULL; + int verbose; + + /* dlopening libdvdcss */ + if(dvdcss_library_init) { + /* libdvdcss is already dlopened, function ptrs set */ + if(dvdcss_library) { + return 1; /* css available */ + } else { + return 0; /* css not available */ + } + } + + verbose = get_verbose(); #ifdef HAVE_DVDCSS_DVDCSS_H /* linking to libdvdcss */ @@ -277,7 +334,7 @@ dvdcss_version = &dvdcss_interface_2; #else - /* dlopening libdvdcss */ + dvdcss_library = dlopen("libdvdcss.so.2", RTLD_LAZY); if(dvdcss_library != NULL) { @@ -302,33 +359,39 @@ dvdcss_version = (char **)dlsym(dvdcss_library, U_S "dvdcss_interface_2"); if(dlsym(dvdcss_library, U_S "dvdcss_crack")) { + if(verbose >= 0) { fprintf(stderr, "libdvdread: Old (pre-0.0.2) version of libdvdcss found.\n" "libdvdread: You should get the latest version from " "http://www.videolan.org/\n" ); + } dlclose(dvdcss_library); dvdcss_library = NULL; } else if(!DVDcss_open || !DVDcss_close || !DVDcss_title || !DVDcss_seek || !DVDcss_read || !DVDcss_error || !dvdcss_version) { + if(verbose >= 0) { fprintf(stderr, "libdvdread: Missing symbols in libdvdcss.so.2, " "this shouldn't happen !\n"); + } dlclose(dvdcss_library); + dvdcss_library = NULL; } } #endif /* HAVE_DVDCSS_DVDCSS_H */ - if(dvdcss_library != NULL) { + dvdcss_library_init = 1; + + if(dvdcss_library) { /* char *psz_method = getenv( "DVDCSS_METHOD" ); char *psz_verbose = getenv( "DVDCSS_VERBOSE" ); fprintf(stderr, "DVDCSS_METHOD %s\n", psz_method); fprintf(stderr, "DVDCSS_VERBOSE %s\n", psz_verbose); */ - /* + if(verbose >= 1) { fprintf(stderr, "libdvdread: Using libdvdcss version %s for DVD access\n", *dvdcss_version); - */ - + } /* libdvdcss wrapper functions */ dvdinput_open = css_open; dvdinput_close = css_close; @@ -339,8 +402,9 @@ return 1; } else { + if(verbose >= 1) { fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n"); - + } /* libdvdcss replacement functions */ dvdinput_open = file_open; dvdinput_close = file_close;
--- a/dvdread/dvd_input.h Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/dvd_input.h Wed Aug 15 11:47:22 2007 +0000 @@ -40,6 +40,13 @@ extern char * (*dvdinput_error) (dvd_input_t); /** + * Free any objects allocated by dvdinput_setup. + * Should only be called when libdvdread is not to be used any more. + * Closes dlopened libraries. + */ +void dvdinput_free(void); + +/** * Setup function accessed by dvd_reader.c. Returns 1 if there is CSS support. */ int dvdinput_setup(void);
--- a/dvdread/dvd_reader.c Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/dvd_reader.c Wed Aug 15 11:47:22 2007 +0000 @@ -60,11 +60,13 @@ } #endif -#include "dvd_udf.h" +#include "dvd_reader.h" #include "dvd_input.h" -#include "dvd_reader.h" +#include "dvd_udf.h" #include "md5.h" +#include "dvdread_internal.h" + #define DEFAULT_UDF_CACHE_LEVEL 0 struct dvd_reader_s { @@ -85,6 +87,12 @@ /* Filesystem cache */ int udfcache_level; /* 0 - turned off, 1 - on */ void *udfcache; + + /* block aligned malloc */ + void *align; + + /* error message verbosity level */ + int verbose; }; struct dvd_file_s { @@ -106,6 +114,42 @@ ssize_t filesize; }; + +#define DVDREAD_VERBOSE_DEFAULT 0 + +int get_verbose(void) +{ + char *dvdread_verbose; + int verbose; + + dvdread_verbose = getenv("DVDREAD_VERBOSE"); + if(dvdread_verbose) { + verbose = (int)strtol(dvdread_verbose, NULL, 0); + } else { + verbose = DVDREAD_VERBOSE_DEFAULT; + } + return verbose; +} + +int dvdread_verbose(dvd_reader_t *dvd) +{ + return dvd->verbose; +} + +dvd_reader_t *device_of_file(dvd_file_t *file) +{ + return file->dvd; +} + +/** + * Returns the compiled version. (DVDREAD_VERSION as an int) + */ +int DVDVersion(void) +{ + return DVDREAD_VERSION; +} + + /** * Set the level of caching on udf * level = 0 (no caching) @@ -140,6 +184,31 @@ dev->udfcache = cache; } +void *GetAlignHandle(dvd_reader_t *device) +{ + struct dvd_reader_s *dev = (struct dvd_reader_s *)device; + + return dev->align; +} + +void SetAlignHandle(dvd_reader_t *device, void *align) +{ + struct dvd_reader_s *dev = (struct dvd_reader_s *)device; + + dev->align = align; +} + +#ifdef WIN32 /* replacement gettimeofday implementation */ +#include <sys/timeb.h> +static int gettimeofday( struct timeval *tv, void *tz ) +{ + struct timeb t; + ftime( &t ); + tv->tv_sec = t.time; + tv->tv_usec = t.millitm * 1000; + return 0; +} +#endif /* Loop over all titles and call dvdcss_title to crack the keys. */ @@ -155,11 +224,12 @@ if(nokeys_str != NULL) return 0; + if(dvd->verbose >= 1) { fprintf( stderr, "\n" ); fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" ); fprintf( stderr, "libdvdread: This can take a _long_ time, " "please be patient\n\n" ); - + } gettimeofday(&all_s, NULL); for( title = 0; title < 100; title++ ) { @@ -172,15 +242,21 @@ start = UDFFindFile( dvd, filename, &len ); if( start != 0 && len != 0 ) { /* Perform CSS key cracking for this title. */ + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", filename, start ); + } if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { + if(dvd->verbose >= 0) { fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start); } + } gettimeofday( &t_e, NULL ); + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Elapsed time %ld\n", (long int) t_e.tv_sec - t_s.tv_sec ); } + } if( title == 0 ) continue; @@ -190,22 +266,31 @@ if( start == 0 || len == 0 ) break; /* Perform CSS key cracking for this title. */ + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", filename, start ); + } if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { + if(dvd->verbose >= 0) { fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start); } + } gettimeofday( &t_e, NULL ); + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Elapsed time %ld\n", (long int) t_e.tv_sec - t_s.tv_sec ); } + } title--; + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Found %d VTS's\n", title ); + } gettimeofday(&all_e, NULL); + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Elapsed time %ld\n", (long int) all_e.tv_sec - all_s.tv_sec ); - + } return 0; } @@ -213,27 +298,43 @@ /** * Open a DVD image or block device file. + * Checks if the root directory in the udf image file can be found. + * If not it assumes this isn't a valid udf image and returns NULL */ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) { dvd_reader_t *dvd; dvd_input_t dev; + int verbose; + + verbose = get_verbose(); dev = dvdinput_open( location ); if( !dev ) { - fprintf( stderr, "libdvdread: Can't open %s for reading\n", location ); - return 0; + if(verbose >= 1) { + fprintf( stderr, "libdvdread: Can't open '%s' for reading: %s\n", + location, strerror(errno)); + } + return NULL; } dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); - if( !dvd ) return 0; + if( !dvd ) { + int tmp_errno = errno; + dvdinput_close(dev); + errno = tmp_errno; + return NULL; + } + dvd->verbose = verbose; dvd->isImageFile = 1; dvd->dev = dev; - dvd->path_root = 0; + dvd->path_root = NULL; dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; dvd->udfcache = NULL; + dvd->align = NULL; + if( have_css ) { /* Only if DVDCSS_METHOD = title, a bit if it's disc or if * DVDCSS_METHOD = key but region missmatch. Unfortunaly we @@ -243,6 +344,20 @@ } dvd->css_title = 0; + /* sanity check, is it a valid UDF image, can we find the root dir */ + if(!UDFFindFile(dvd, "/", NULL)) { + dvdinput_close(dvd->dev); + if(dvd->udfcache) { + FreeUDFCache(dvd, dvd->udfcache); + } + if(dvd->align) { + if(dvd->verbose >= 0) { + fprintf(stderr, "libdvdread: DVDOpenImageFile(): Memory leak in align functions 1\n"); + } + } + free(dvd); + return NULL; + } return dvd; } @@ -251,14 +366,22 @@ dvd_reader_t *dvd; dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); - if( !dvd ) return 0; + if( !dvd ) { + return NULL; + } + dvd->verbose = get_verbose(); dvd->isImageFile = 0; dvd->dev = 0; dvd->path_root = strdup( path_root ); - + if(!dvd->path_root) { + free(dvd); + return 0; + } dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; dvd->udfcache = NULL; + dvd->align = NULL; + dvd->css_state = 0; /* Only used in the UDF path */ dvd->css_title = 0; /* Only matters in the UDF path */ @@ -320,10 +443,16 @@ { struct stat fileinfo; int ret, have_css; - char *dev_name = 0; + char *dev_name = NULL; + int internal_errno = 0; + int verbose; - if( path == NULL ) - return 0; + if( path == NULL ) { + errno = EINVAL; + return NULL; + } + + verbose = get_verbose(); #ifdef WIN32 /* Stat doesn't work on devices under mingwin/cygwin. */ @@ -337,10 +466,14 @@ { ret = stat( path, &fileinfo ); if( ret < 0 ) { + int tmp_errno = errno; /* If we can't stat the file, give up */ - fprintf( stderr, "libdvdread: Can't stat %s\n", path ); - perror(""); - return 0; + if(verbose >= 1) { + fprintf( stderr, "libdvdread: Can't stat '%s': %s\n", + path, strerror(errno)); + } + errno = tmp_errno; + return NULL; } } @@ -375,24 +508,38 @@ /* XXX: We should scream real loud here. */ if( !(path_copy = strdup( path ) ) ) return 0; +#ifndef WIN32 /* don't have fchdir, and getcwd( NULL, ... ) is strange */ /* Resolve any symlinks and get the absolut dir name. */ { char *new_path; - int cdir = open( ".", O_RDONLY ); + char *current_path; - if( cdir >= 0 ) { + current_path = malloc(PATH_MAX); + if(current_path) { + if(!getcwd(current_path, PATH_MAX)) { + free(current_path); + current_path = NULL; + } + } + if(current_path) { chdir( path_copy ); - new_path = getcwd( NULL, PATH_MAX ); -#ifndef __MINGW32__ - fchdir( cdir ); -#endif - close( cdir ); + new_path = malloc(PATH_MAX); + if(new_path) { + if(!getcwd(new_path, PATH_MAX )) { + free(new_path); + new_path = NULL; + } + } + + chdir(current_path); + free(current_path); if( new_path ) { free( path_copy ); path_copy = new_path; } } } +#endif /** * If we're being asked to open a directory, check if that directory @@ -400,26 +547,37 @@ */ if( strlen( path_copy ) > 1 ) { - if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) + if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) { path_copy[ strlen( path_copy ) - 1 ] = '\0'; } + } - if( strlen( path_copy ) > 9 ) { + if( strlen( path_copy ) >= 9 ) { if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]), "/video_ts" ) ) { path_copy[ strlen( path_copy ) - 9 ] = '\0'; + if(path_copy[0] == '\0') { + path_copy[0] = '/'; + path_copy[1] = '\0'; + } } } #if defined(SYS_BSD) if( ( fe = getfsfile( path_copy ) ) ) { dev_name = bsd_block2char( fe->fs_spec ); + if(verbose >= 1) { fprintf( stderr, "libdvdread: Attempting to use device %s" - " mounted on %s for CSS authentication\n", + " mounted on %s%s\n", dev_name, - fe->fs_file ); + fe->fs_file, + have_css ? " for CSS authentication" : ""); + } auth_drive = DVDOpenImageFile( dev_name, have_css ); + if(!auth_drive) { + internal_errno = errno; + } } #elif defined(__sun) mntfile = fopen( MNTTAB, "r" ); @@ -430,12 +588,18 @@ while( ( res = getmntent( mntfile, &mp ) ) != -1 ) { if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) { dev_name = sun_block2char( mp.mnt_special ); + if(verbose >= 1) { fprintf( stderr, "libdvdread: Attempting to use device %s" - " mounted on %s for CSS authentication\n", + " mounted on %s%s\n", dev_name, - mp.mnt_mountp ); + mp.mnt_mountp, + have_css ? " for CSS authentication" : ""); + } auth_drive = DVDOpenImageFile( dev_name, have_css ); + if(!auth_drive) { + internal_errno = errno; + } break; } } @@ -448,12 +612,18 @@ while( ( me = getmntent( mntfile ) ) ) { if( !strcmp( me->mnt_dir, path_copy ) ) { + if(verbose >= 1) { fprintf( stderr, "libdvdread: Attempting to use device %s" - " mounted on %s for CSS authentication\n", + " mounted on %s%s\n", me->mnt_fsname, - me->mnt_dir ); + me->mnt_dir, + have_css ? " for CSS authentication" : ""); + } auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css ); + if(!auth_drive) { + internal_errno = errno; + } dev_name = strdup(me->mnt_fsname); break; } @@ -465,10 +635,16 @@ auth_drive = DVDOpenImageFile( path, have_css ); #endif if( !dev_name ) { + if(verbose >= 1) { fprintf( stderr, "libdvdread: Couldn't find device name.\n" ); + } } else if( !auth_drive ) { - fprintf( stderr, "libdvdread: Device %s inaccessible, " - "CSS authentication not available.\n", dev_name ); + if(verbose >= 1) { + fprintf( stderr, "libdvdread: Device %s inaccessible%s: %s\n", + dev_name, + have_css ? ", CSS authentication not available" : "", + strerror(internal_errno)); + } } free( dev_name ); @@ -477,8 +653,9 @@ /** * If we've opened a drive, just use that. */ - if( auth_drive ) return auth_drive; - + if( auth_drive ) { + return auth_drive; + } /** * Otherwise, we now try to open the directory tree instead. */ @@ -486,7 +663,9 @@ } /* If it's none of the above, screw it. */ + if(verbose >= 1) { fprintf( stderr, "libdvdread: Could not open %s\n", path ); + } return 0; } @@ -495,11 +674,27 @@ if( dvd ) { if( dvd->dev ) dvdinput_close( dvd->dev ); if( dvd->path_root ) free( dvd->path_root ); - if( dvd->udfcache ) FreeUDFCache( dvd->udfcache ); + if( dvd->udfcache ) FreeUDFCache( dvd, dvd->udfcache ); + if(dvd->align) { + if(dvd->verbose >= 0) { + fprintf(stderr, "libdvdread: DVDClose(): Memory leak in align functions\n"); + } + } + dvdinput_free(); free( dvd ); } } +void DVDInit(void) +{ + dvdinput_setup(); +} + +void DVDFinish(void) +{ + dvdinput_free(); +} + /** * Open an unencrypted file on a DVD image file. */ @@ -542,10 +737,11 @@ sprintf( filename, "%s%s%s", path, ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ), ent->d_name ); + closedir(dir); return 0; } } - + closedir(dir); return -1; } @@ -606,7 +802,9 @@ dvd_file->filesize = 0; if( stat( full_path, &fileinfo ) < 0 ) { + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); + } free( dvd_file ); return 0; } @@ -704,7 +902,9 @@ } if( stat( full_path, &fileinfo ) < 0 ) { + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); + } free( dvd_file ); return 0; } @@ -722,7 +922,9 @@ } if( stat( full_path, &fileinfo ) < 0 ) { + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); + } break; } @@ -746,8 +948,10 @@ char filename[ MAX_UDF_FILE_NAME_LEN ]; /* Check arguments. */ - if( dvd == NULL || titlenum < 0 ) + if( dvd == NULL || titlenum < 0 ) { + errno = EINVAL; return NULL; + } switch( domain ) { case DVD_READ_INFO_FILE: @@ -780,7 +984,10 @@ } break; default: + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: Invalid domain for file open.\n" ); + } + errno = EINVAL; return NULL; } @@ -811,7 +1018,20 @@ } } -/* Internal, but used from dvd_udf.c */ +/** + * Internal, but used from dvd_udf.c + * + * @param device A read handle. + * @param lb_number Logical block number to start read from. + * @param block_count Number of logical blocks to read. + * @param data Pointer to buffer where read data should be stored. + * This buffer must be large enough to hold lb_number*2048 bytes. + * The pointer must be aligned to the logical block size when + * reading from a raw/O_DIRECT device. + * @param encrypted 0 if no decryption shall be performed, + * 1 if decryption shall be performed + * @param return Returns number of blocks read on success, negative on error + */ int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ) @@ -819,13 +1039,19 @@ int ret; if( !device->dev ) { + if(device->verbose >= 1) { fprintf( stderr, "libdvdread: Fatal error in block read.\n" ); + } return 0; } ret = dvdinput_seek( device->dev, (int) lb_number ); if( ret != (int) lb_number ) { - fprintf( stderr, "libdvdread: Can't seek to block %u\n", lb_number ); + if(device->verbose >= 1) { + fprintf( stderr, + "libdvdread: UDFReadBlocksRaw: Can't seek to block %u\n", + lb_number ); + } return 0; } @@ -833,12 +1059,20 @@ (int) block_count, encrypted ); } -/* This is using a single input and starting from 'dvd_file->lb_start' offset. +/** + * This is using a single input and starting from 'dvd_file->lb_start' offset. * * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' * into the buffer located at 'data' and if 'encrypted' is set * descramble the data if it's encrypted. Returning either an - * negative error or the number of blocks read. */ + * negative error or the number of blocks read. + * + * @param data Pointer to buffer where read data should be placed. + * This buffer must be large enough to hold block_count*2048 bytes. + * The pointer must be aligned to 2048 bytes when reading from + * a raw/O_DIRECT device. + * @return Returns the number of blocks read on success or a negative error. + */ static int DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset, size_t block_count, unsigned char *data, int encrypted ) @@ -847,12 +1081,19 @@ 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'. + * data must be aligned to logical block size (2048 bytes) of the device + * for raw/O_DIRECT devices to work * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' * into the buffer located at 'data' and if 'encrypted' is set * descramble the data if it's encrypted. Returning either an - * negative error or the number of blocks read. */ + * negative error or the number of blocks read. + * + * @param dvd_file A file read handle. + * @param offset Block offset from start of file. + * @return Returns number of blocks read on success, negative on error. + */ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset, size_t block_count, unsigned char *data, int encrypted ) @@ -869,8 +1110,10 @@ if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) { off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); if( off < 0 || off != (int)offset ) { - fprintf( stderr, "libdvdread: Can't seek to block %d\n", + if(dvd_file->dvd->verbose >= 1) { + fprintf( stderr, "libdvdread: DVDReadBlocksPath1: Can't seek to block %d\n", offset ); + } return off < 0 ? off : 0; } ret = dvdinput_read( dvd_file->title_devs[ i ], data, @@ -884,8 +1127,10 @@ /* Read part 1 */ off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); if( off < 0 || off != (int)offset ) { - fprintf( stderr, "libdvdread: Can't seek to block %d\n", + if(dvd_file->dvd->verbose >= 1) { + fprintf( stderr, "libdvdread: DVDReadBlocksPath2: Can't seek to block %d\n", offset ); + } return off < 0 ? off : 0; } ret = dvdinput_read( dvd_file->title_devs[ i ], data, @@ -900,8 +1145,9 @@ /* Read part 2 */ off = dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 ); if( off < 0 || off != 0 ) { - fprintf( stderr, "libdvdread: Can't seek to block %d\n", - 0 ); + if(dvd_file->dvd->verbose >= 1) { + fprintf( stderr, "libdvdread: DVDReadBlocksPath3: Can't seek to block %d\n", 0 ); + } return off < 0 ? off : 0; } ret2 = dvdinput_read( dvd_file->title_devs[ i + 1 ], @@ -920,7 +1166,9 @@ return ret + ret2; } -/* This is broken reading more than 2Gb at a time is ssize_t is 32-bit. */ +/** + * This is broken reading more than 2Gb at a time if ssize_t is 32-bit. + */ ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset, size_t block_count, unsigned char *data ) { @@ -966,29 +1214,41 @@ return offset; } +#ifndef HAVE_UINTPTR_T +#warning "Assuming that (unsigned long) can hold (void *)" +typedef unsigned long uintptr_t; +#endif + +#define DVD_ALIGN(ptr) (void *)((((uintptr_t)(ptr)) + (DVD_VIDEO_LB_LEN-1)) \ + / DVD_VIDEO_LB_LEN * DVD_VIDEO_LB_LEN) + ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) { - unsigned char *secbuf; + unsigned char *secbuf_start; + unsigned char *secbuf; //must be aligned to 2048-bytes for raw/O_DIRECT unsigned int numsec, seek_sector, seek_byte; int ret; /* Check arguments. */ - if( dvd_file == NULL || data == NULL ) + if( dvd_file == NULL || data == NULL ) { + errno = EINVAL; return -1; - + } seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN; seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN; numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + ( ( ( seek_byte + byte_size ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 ); - secbuf = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN ); - if( !secbuf ) { - fprintf( stderr, "libdvdread: Can't allocate memory " - "for file read!\n" ); - return 0; + /* must align to 2048 bytes if we are reading from raw/O_DIRECT */ + secbuf_start = (unsigned char *) malloc( (numsec+1) * DVD_VIDEO_LB_LEN ); + if( !secbuf_start ) { + /* errno will be set to ENOMEM by malloc */ + return -1; } + secbuf = DVD_ALIGN(secbuf_start); + if( dvd_file->dvd->isImageFile ) { ret = DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector, (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); @@ -998,12 +1258,12 @@ } if( ret != (int) numsec ) { - free( secbuf ); + free( secbuf_start ); return ret < 0 ? ret : 0; } memcpy( data, &(secbuf[ seek_byte ]), byte_size ); - free( secbuf ); + free( secbuf_start ); dvd_file->seek_pos += byte_size; return byte_size; @@ -1022,11 +1282,14 @@ { struct md5_ctx ctx; int title; - + int nr_of_files = 0; + int tmp_errno; + int nofiles_errno = ENOENT; /* Check arguments. */ - if( dvd == NULL || discid == NULL ) - return 0; - + if( dvd == NULL || discid == NULL ) { + errno = EINVAL; + return -1; + } /* Go through the first 10 IFO:s, in order, * and md5sum them, i.e VIDEO_TS.IFO and VTS_0?_0.IFO */ md5_init_ctx( &ctx ); @@ -1037,16 +1300,23 @@ size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN; char *buffer = malloc( file_size ); + nr_of_files++; + if( buffer == NULL ) { - fprintf( stderr, "libdvdread: DVDDiscId, failed to " - "allocate memory for file read!\n" ); + /* errno will be set to ENOMEM by malloc */ return -1; } + bytes_read = DVDReadBytes( dvd_file, buffer, file_size ); if( bytes_read != file_size ) { + tmp_errno = errno; + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: DVDDiscId read returned %d bytes" - ", wanted %d\n", bytes_read, file_size ); + ", wanted %d\n", (int)bytes_read, (int)file_size ); + } + free(buffer); DVDCloseFile( dvd_file ); + errno = tmp_errno; return -1; } @@ -1054,10 +1324,17 @@ DVDCloseFile( dvd_file ); free( buffer ); + } else { + if(errno != ENOENT) { + nofiles_errno = errno; + } } } md5_finish_ctx( &ctx, discid ); - + if(nr_of_files == 0) { + errno = nofiles_errno; + return -1; + } return 0; } @@ -1066,29 +1343,36 @@ char *volid, unsigned int volid_size, unsigned char *volsetid, unsigned int volsetid_size ) { - unsigned char *buffer; + unsigned char *buffer; /* must be aligned to 2048 for raw/O_DIRECT */ + unsigned char *buffer_start; int ret; /* Check arguments. */ - if( dvd == NULL ) - return 0; - - if( dvd->dev == NULL ) { - /* No block access, so no ISO... */ + if( dvd == NULL ) { + errno = EINVAL; return -1; } - buffer = malloc( DVD_VIDEO_LB_LEN ); - if( buffer == NULL ) { - fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " - "allocate memory for file read!\n" ); + if( dvd->dev == NULL ) { + /* No block access, so no ISO... */ + errno = EINVAL; + return -1; + } + + buffer_start = malloc( 2 * DVD_VIDEO_LB_LEN ); + if( buffer_start == NULL ) { return -1; } + buffer = DVD_ALIGN(buffer_start); + ret = UDFReadBlocksRaw( dvd, 16, 1, buffer, 0 ); if( ret != 1 ) { + if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " "read ISO9660 Primary Volume Descriptor!\n" ); + } + free(buffer_start); return -1; } @@ -1114,6 +1398,8 @@ } memcpy(volsetid, &buffer[190], volsetid_size); } + free(buffer_start); + return 0; }
--- a/dvdread/dvd_reader.h Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/dvd_reader.h Wed Aug 15 11:47:22 2007 +0000 @@ -31,9 +31,14 @@ */ /** - * The current version. + * The current version. (0.9.4 => 904, 1.2.3 => 10203) */ -#define DVDREAD_VERSION 904 +#define DVDREAD_VERSION 905 + +/** + * Returns the compiled version. (DVDREAD_VERSION as an int) + */ +int DVDVersion(void); /** * The length of one Logical Block of a DVD. @@ -80,6 +85,10 @@ * @return If successful a a read handle is returned. Otherwise 0 is returned. * * dvd = DVDOpen(path); + * + * Threads: this function uses chdir() and getcwd(). + * The current working directory is global to all threads, + * so using chdir/getcwd in another thread could give unexpected results. */ dvd_reader_t *DVDOpen( const char * ); @@ -95,6 +104,35 @@ void DVDClose( dvd_reader_t * ); /** + * Initializes libdvdread to be used with multithreading apps. + * + * You must call this function before using any other functions of libdvdread + * if you are going to use libdvdread in multiple threads in your program. + * If you are not using threads, or using libdvdread from just one thread, + * you do not need to call this, but you are allowed to do so anyway. + * + * There are several restrictions on how you can use libdvdread in + * multithreading apps, see further documentation. + * + * If you have called DVDFinish() you need to call DVDInit again to use + * libdvdread in multiple threads. + * + * DVDInit(void); + */ +void DVDInit(void); + +/** + * frees any dlopened objects. + * + * You must DVDClose all handles opened with DVDOpen before calling this. + * Use this function if you need to close the dlopened libs and any other + * objects that have been dynamically allocated by libdvdread. + * + * DVDFinish(void); + */ +void DVDFinish(void); + +/** * */ typedef enum { @@ -141,6 +179,8 @@ * @param offset Block offset from the start of the file to start reading at. * @param block_count Number of block to read. * @param data Pointer to a buffer to write the data into. + * It must be aligned to the logical block size of the device when + * reading from a raw/O_DIRECT device (2048 bytes for DVD) * @return Returns number of blocks read on success, -1 on error. * * blocks_read = DVDReadBlocks(dvd_file, offset, block_count, data);
--- a/dvdread/dvd_udf.c Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/dvd_udf.c Wed Aug 15 11:47:22 2007 +0000 @@ -37,23 +37,173 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#ifndef __MINGW32__ -#include <sys/ioctl.h> -#endif + #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +#include <errno.h> + +#if defined(HAVE_INTTYPES_H) #include <inttypes.h> +#elif defined(HAVE_STDINT_H) +#include <stdint.h> +#endif #include "dvd_reader.h" #include "dvd_udf.h" +#include "dvdread_internal.h" + +#ifndef EMEDIUMTYPE +#define EMEDIUMTYPE ENOENT +#endif + +#ifndef HAVE_UINTPTR_T +#warning "Assuming that (unsigned long) can hold (void *)" +typedef unsigned long uintptr_t; +#endif + +#define DVD_ALIGN(ptr) (void *)((((uintptr_t)(ptr)) + (DVD_VIDEO_LB_LEN-1)) \ + / DVD_VIDEO_LB_LEN * DVD_VIDEO_LB_LEN) + +typedef struct { + void *start; + void *aligned; +} dvdalign_ptrs_t; + +typedef struct { + dvdalign_ptrs_t *ptrs; + uint32_t ptrs_in_use; + uint32_t ptrs_max; +} dvdalign_t; + +extern void *GetAlignHandle(dvd_reader_t *device); +extern void SetAlignHandle(dvd_reader_t *device, void *align); + +/** + * Allocates aligned memory (for use with reads from raw/O_DIRECT devices). + * This memory must be freed with dvdalign_free() + * The size of the memory that is allocate is num_lbs*2048 bytes. + * The memory will be suitably aligned for use with + * block reads from raw/O_DIRECT device. + * @param num_lbs Number of logical blocks (2048 bytes) to allocate. + * @return Returns pointer to allocated memory, or NULL on failure + * This isn't supposed to be fast/efficient, if that is needed + * this function should be rewritten to use posix_memalign or similar. + * It's just needed for aligning memory for small block reads from + * raw/O_DIRECT devices. + * We assume that 2048 is enough alignment for all systems at the moment. + * Not thread safe. Only use this from one thread. + * Depends on sizeof(unsigned long) being at least as large as sizeof(void *) + */ +static void *dvdalign_lbmalloc(dvd_reader_t *device, uint32_t num_lbs) +{ + void *m; + int n; + dvdalign_t *a; + + m = malloc((num_lbs+1)*DVD_VIDEO_LB_LEN); + if(m == NULL) { + return m; + } + a = (dvdalign_t *)GetAlignHandle(device); + if(a == NULL) { + a = malloc(sizeof(dvdalign_t)); + if(a == NULL) { + return a; + } + a->ptrs = NULL; + a->ptrs_in_use = 0; + a->ptrs_max = 0; + SetAlignHandle(device, (void *)a); + } + + if(a->ptrs_in_use >= a->ptrs_max) { + a->ptrs = realloc(a->ptrs, (a->ptrs_max+10)*sizeof(dvdalign_ptrs_t)); + if(a->ptrs == NULL) { + free(m); + return NULL; + } + a->ptrs_max+=10; + for(n = a->ptrs_in_use; n < a->ptrs_max; n++) { + a->ptrs[n].start = NULL; + a->ptrs[n].aligned = NULL; + } + n = a->ptrs_in_use; + } else { + for(n = 0; n < a->ptrs_max; n++) { + if(a->ptrs[n].start == NULL) { + break; + } + } + } + + a->ptrs[n].start = m; + a->ptrs[n].aligned = DVD_ALIGN(m); + + a->ptrs_in_use++; + + /* If this function starts to be used too much print a warning. + Either there is a memory leak somewhere or we need to rewrite this to + a more efficient version. + */ + if(a->ptrs_in_use > 50) { + if(dvdread_verbose(device) >= 0) { + fprintf(stderr, "libdvdread: dvdalign_lbmalloc(), more allocs than supposed: %u\n", a->ptrs_in_use); + } + } + + return a->ptrs[n].aligned; +} + +/** + * Frees memory allocated with dvdalign_lbmemory() + * @param ptr Pointer to memory space to free + * Not thread safe. + */ +static void dvdalign_lbfree(dvd_reader_t *device, void *ptr) +{ + int n; + dvdalign_t *a; + + a = (dvdalign_t *)GetAlignHandle(device); + if(a && a->ptrs) { + for(n = 0; n < a->ptrs_max; n++) { + if(a->ptrs[n].aligned == ptr) { + free(a->ptrs[n].start); + a->ptrs[n].start = NULL; + a->ptrs[n].aligned = NULL; + a->ptrs_in_use--; + if(a->ptrs_in_use == 0) { + free(a->ptrs); + a->ptrs = NULL; + a->ptrs_max = 0; + free(a); + a = NULL; + SetAlignHandle(device, (void *)a); + } + return; + } + } + } + if(dvdread_verbose(device) >= 0) { + fprintf(stderr, "libdvdread: dvdalign_lbfree(), error trying to free mem: %08lx (%u)\n", (unsigned long)ptr, a ? a->ptrs_in_use : 0); + } +} + /* Private but located in/shared with dvd_reader.c */ extern int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ); -/* It's required to either fail or deliver all the blocks asked for. */ +/** @internal + * Its required to either fail or deliver all the blocks asked for. + * + * @param data Pointer to a buffer where data is returned. This must be large + * enough to hold lb_number*2048 bytes. + * It must be aligned to system specific (2048) logical blocks size when + * reading from raw/O_DIRECT device. + */ static int DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ) @@ -149,12 +299,24 @@ extern void *GetUDFCacheHandle(dvd_reader_t *device); extern void SetUDFCacheHandle(dvd_reader_t *device, void *cache); -void FreeUDFCache(void *cache) + +void FreeUDFCache(dvd_reader_t *device, void *cache) { + int n; + struct udf_cache *c = (struct udf_cache *)cache; if(c == NULL) { return; } + + for(n = 0; n < c->lb_num; n++) { + if(c->lbs[n].data) { + /* free data */ + dvdalign_lbfree(device, c->lbs[n].data); + } + } + c->lb_num = 0; + if(c->lbs) { free(c->lbs); } @@ -493,7 +655,7 @@ static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType, struct Partition *partition, struct AD *File ) { - uint8_t LogBlock[DVD_VIDEO_LB_LEN]; + uint8_t *LogBlock; uint32_t lbnum; uint16_t TagID; struct icbmap tmpmap; @@ -506,6 +668,11 @@ return 1; } + LogBlock = dvdalign_lbmalloc(device, 1); + if(!LogBlock) { + return 0; + } + do { if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { TagID = 0; @@ -518,11 +685,13 @@ tmpmap.file = *File; tmpmap.filetype = *FileType; SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap); + dvdalign_lbfree(device, LogBlock); return 1; }; } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 ) / DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) ); + dvdalign_lbfree(device, LogBlock); return 0; } @@ -537,7 +706,7 @@ int cache_file_info) { char filename[ MAX_UDF_FILE_NAME_LEN ]; - uint8_t directory[ 2 * DVD_VIDEO_LB_LEN ]; + uint8_t *directory; uint32_t lbnum; uint16_t TagID; uint8_t filechar; @@ -556,19 +725,13 @@ if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) { dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN; - if((cached_dir = malloc(dir_lba * DVD_VIDEO_LB_LEN)) == NULL) { + if((cached_dir = dvdalign_lbmalloc(device, dir_lba)) == NULL) { return 0; } if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) { - free(cached_dir); + dvdalign_lbfree(device, cached_dir); cached_dir = NULL; } - /* - if(cached_dir) { - fprintf(stderr, "malloc dir: %d\n", - dir_lba * DVD_VIDEO_LB_LEN); - } - */ SetUDFCache(device, LBUDFCache, lbnum, &cached_dir); } else { in_cache = 1; @@ -615,7 +778,12 @@ return 0; } + directory = dvdalign_lbmalloc(device, 2); + if(!directory) { + return 0; + } if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { + dvdalign_lbfree(device, directory); return 0; } @@ -626,6 +794,7 @@ p -= DVD_VIDEO_LB_LEN; Dir.Length -= DVD_VIDEO_LB_LEN; if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { + dvdalign_lbfree(device, directory); return 0; } } @@ -634,13 +803,16 @@ p += UDFFileIdentifier( &directory[ p ], &filechar, filename, FileICB ); if( !strcasecmp( FileName, filename ) ) { + dvdalign_lbfree(device, directory); return 1; } } else { + dvdalign_lbfree(device, directory); return 0; } } + dvdalign_lbfree(device, directory); return 0; } @@ -648,7 +820,7 @@ static int UDFGetAVDP( dvd_reader_t *device, struct avdp_t *avdp) { - uint8_t Anchor[ DVD_VIDEO_LB_LEN ]; + uint8_t *Anchor; uint32_t lbnum, MVDS_location, MVDS_length; uint16_t TagID; uint32_t lastsector; @@ -664,6 +836,10 @@ lbnum = 256; /* Try #1, prime anchor */ terminate = 0; + Anchor = dvdalign_lbmalloc(device, 1); + if(!Anchor) { + return 0; + } for(;;) { if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) { UDFDescriptor( Anchor, &TagID ); @@ -672,10 +848,13 @@ } if (TagID != 2) { /* Not an anchor */ - if( terminate ) return 0; /* Final try failed */ + if( terminate ) { + dvdalign_lbfree(device, Anchor); + errno = EMEDIUMTYPE; + return 0; /* Final try failed */ + } if( lastsector ) { - /* We already found the last sector. Try #3, alternative * backup anchor. If that fails, don't try again. */ @@ -688,6 +867,8 @@ lbnum = lastsector - 256; } else { /* Unable to find last sector */ + dvdalign_lbfree(device, Anchor); + errno = EMEDIUMTYPE; return 0; } } @@ -708,6 +889,7 @@ SetUDFCache(device, AVDPCache, 0, avdp); + dvdalign_lbfree(device, Anchor); return 1; } @@ -719,7 +901,7 @@ static int UDFFindPartition( dvd_reader_t *device, int partnum, struct Partition *part ) { - uint8_t LogBlock[ DVD_VIDEO_LB_LEN ]; + uint8_t *LogBlock; uint32_t lbnum, MVDS_location, MVDS_length; uint16_t TagID; int i, volvalid; @@ -730,6 +912,10 @@ return 0; } + LogBlock = dvdalign_lbmalloc(device, 1); + if(!LogBlock) { + return 0; + } /* Main volume descriptor */ MVDS_location = avdp.mvds.location; MVDS_length = avdp.mvds.length; @@ -774,6 +960,7 @@ } } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) ); + dvdalign_lbfree(device, LogBlock); /* We only care for the partition, not the volume */ return part->valid; } @@ -781,7 +968,7 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *filesize ) { - uint8_t LogBlock[ DVD_VIDEO_LB_LEN ]; + uint8_t *LogBlock; uint32_t lbnum; uint16_t TagID; struct Partition partition; @@ -790,7 +977,9 @@ char *token; uint8_t filetype; + if(filesize) { *filesize = 0; + } tokenline[0] = '\0'; strcat( tokenline, filename ); @@ -798,9 +987,15 @@ if(!(GetUDFCache(device, PartitionCache, 0, &partition) && GetUDFCache(device, RootICBCache, 0, &RootICB))) { /* Find partition, 0 is the standard location for DVD Video.*/ - if( !UDFFindPartition( device, 0, &partition ) ) return 0; + if( !UDFFindPartition( device, 0, &partition ) ) { + return 0; + } SetUDFCache(device, PartitionCache, 0, &partition); + LogBlock = dvdalign_lbmalloc(device, 1); + if(!LogBlock) { + return 0; + } /* Find root dir ICB */ lbnum = partition.Start; do { @@ -817,16 +1012,25 @@ } while( ( lbnum < partition.Start + partition.Length ) && ( TagID != 8 ) && ( TagID != 256 ) ); + dvdalign_lbfree(device, LogBlock); + /* Sanity checks. */ - if( TagID != 256 ) return 0; - if( RootICB.Partition != 0 ) return 0; + if( TagID != 256 ) { + return 0; + } + if( RootICB.Partition != 0 ) { + return 0; + } SetUDFCache(device, RootICBCache, 0, &RootICB); } /* Find root dir */ - if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) return 0; - if( filetype != 4 ) return 0; /* Root dir should be dir */ - + if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) { + return 0; + } + if( filetype != 4 ) { + return 0; /* Root dir should be dir */ + } { int cache_file_info = 0; /* Tokenize filepath */ @@ -849,15 +1053,20 @@ } /* Sanity check. */ - if( File.Partition != 0 ) return 0; + if( File.Partition != 0 ) { + return 0; + } + if(filesize) { *filesize = File.Length; + } /* Hack to not return partition.Start for empty files. */ - if( !File.Location ) + if( !File.Location ) { return 0; - else + } else { return partition.Start + File.Location; } +} @@ -865,7 +1074,8 @@ * Gets a Descriptor . * Returns 1 if descriptor found, 0 on error. * id, tagid of descriptor - * bufsize, size of BlockBuf (must be >= DVD_VIDEO_LB_LEN). + * bufsize, size of BlockBuf (must be >= DVD_VIDEO_LB_LEN) + * and aligned for raw/O_DIRECT read. */ static int UDFGetDescriptor( dvd_reader_t *device, int id, uint8_t *descriptor, int bufsize) @@ -919,19 +1129,25 @@ } } while( i-- && ( !desc_found ) ); + return desc_found; } static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd) { - uint8_t pvd_buf[DVD_VIDEO_LB_LEN]; + uint8_t *pvd_buf; if(GetUDFCache(device, PVDCache, 0, pvd)) { return 1; } - if(!UDFGetDescriptor( device, 1, pvd_buf, sizeof(pvd_buf))) { + pvd_buf = dvdalign_lbmalloc(device, 1); + if(!pvd_buf) { + return 0; + } + if(!UDFGetDescriptor( device, 1, pvd_buf, 1*DVD_VIDEO_LB_LEN)) { + dvdalign_lbfree(device, pvd_buf); return 0; } @@ -939,6 +1155,8 @@ memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128); SetUDFCache(device, PVDCache, 0, pvd); + dvdalign_lbfree(device, pvd_buf); + return 1; }
--- a/dvdread/dvd_udf.h Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/dvd_udf.h Wed Aug 15 11:47:22 2007 +0000 @@ -31,7 +31,11 @@ * http://www.gnu.org/copyleft/gpl.html */ +#if defined(HAVE_INTTYPES_H) #include <inttypes.h> +#elif defined(HAVE_STDINT_H) +#include <stdint.h> +#endif #include "dvd_reader.h" @@ -48,7 +52,7 @@ */ uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *size ); -void FreeUDFCache(void *cache); +void FreeUDFCache(dvd_reader_t *device, void *cache); int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid, unsigned int volid_size); int UDFGetVolumeSetIdentifier(dvd_reader_t *device,
--- a/dvdread/dvdread_internal.h Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/dvdread_internal.h Wed Aug 15 11:47:22 2007 +0000 @@ -5,4 +5,8 @@ #define CHECK_VALUE(arg) +int get_verbose(void); +int dvdread_verbose(dvd_reader_t *dvd); +dvd_reader_t *device_of_file(dvd_file_t *file); + #endif /* DVDREAD_INTERNAL_H */
--- a/dvdread/ifo_print.c Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/ifo_print.c Wed Aug 15 11:47:22 2007 +0000 @@ -27,13 +27,19 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> -#include <inttypes.h> #include <string.h> #include <ctype.h> +#if defined(HAVE_INTTYPES_H) +#include <inttypes.h> +#elif defined(HAVE_STDINT_H) +#include <stdint.h> +#endif + #include "ifo_types.h" #include "ifo_read.h" #include "ifo_print.h" +#include "cmd_print.h" #include "dvdread_internal.h" /* Put this in some other file / package? It's used in nav_print too. */ @@ -67,20 +73,6 @@ printf(" @ %s fps", rate); } -/* Put this in some other file / package? It's used in nav_print too. - Possibly also by the vm / navigator. */ -static void ifoPrint_CMD(int row, vm_cmd_t *command) { - int i; - - printf("(%03d) ", row + 1); - for(i=0;i<8;i++) - printf("%02x ", command->bytes[i]); - printf("| "); - - //vmcmd(command); - printf("\n"); -} - static void ifoPrint_video_attributes(video_attr_t *attr) { /* The following test is shorter but not correct ISO C, @@ -261,6 +253,9 @@ case 1: printf("%c%c (%c) ", attr->lang_code>>8, attr->lang_code & 0xff, attr->lang_extension ? attr->lang_extension : ' '); + if(attr->lang_extension) { + printf("(please send a bug report) lang_extension != 0"); + } break; default: printf("(please send a bug report) "); @@ -280,6 +275,29 @@ printf("(please send a bug report) "); } + switch(attr->audio_format) { + case 0: //ac3 + if(attr->quantization != 3) { + printf("(please send a bug report) ac3 quant/drc not 3 (%d)", + attr->quantization); + } + break; + case 2: //mpeg 1 or mpeg 2 without extension stream + case 3: //mpeg 2 with extension stream + switch(attr->quantization) { + case 0: //no drc + printf("no drc "); + break; + case 1: + printf("drc "); + break; + default: + printf("(please send a bug report) mpeg reserved quant/drc (%d)", + attr->quantization); + break; + } + break; + case 4: switch(attr->quantization) { case 0: printf("16bit "); @@ -291,10 +309,19 @@ printf("24bit "); break; case 3: - printf("drc "); + printf("(please send a bug report) lpcm reserved quant/drc (%d)", + attr->quantization); + break; + } + break; + case 6: //dts + if(attr->quantization != 3) { + printf("(please send a bug report) dts quant/drc not 3 (%d)", + attr->quantization); + } break; default: - printf("(please send a bug report) "); + break; } switch(attr->sample_frequency) { @@ -302,7 +329,7 @@ printf("48kHz "); break; case 1: - printf("??kHz "); + printf("96kHz "); break; default: printf("sample_frequency %i (please send a bug report) ", @@ -387,10 +414,9 @@ printf("%d ", attr->zero1); printf("%d ", attr->zero2); - printf("%d ", attr->code_extension); + printf("%d ", attr->lang_extension); - /* Is this correct? should it not be subp_code_ext here instead? */ - switch(attr->lang_extension) { + switch(attr->code_extension) { case 0: printf("Not specified "); break; @@ -640,17 +666,17 @@ printf("Number of Pre commands: %i\n", cmd_tbl->nr_of_pre); for(i = 0; i < cmd_tbl->nr_of_pre; i++) { - ifoPrint_CMD(i, &cmd_tbl->pre_cmds[i]); + cmdPrint_CMD(i, &cmd_tbl->pre_cmds[i]); } printf("Number of Post commands: %i\n", cmd_tbl->nr_of_post); for(i = 0; i < cmd_tbl->nr_of_post; i++) { - ifoPrint_CMD(i, &cmd_tbl->post_cmds[i]); + cmdPrint_CMD(i, &cmd_tbl->post_cmds[i]); } printf("Number of Cell commands: %i\n", cmd_tbl->nr_of_cell); for(i = 0; i < cmd_tbl->nr_of_cell; i++) { - ifoPrint_CMD(i, &cmd_tbl->cell_cmds[i]); + cmdPrint_CMD(i, &cmd_tbl->cell_cmds[i]); } } @@ -754,6 +780,11 @@ void ifoPrint_PGC(pgc_t *pgc) { int i; + if(pgc == NULL) { + printf("Error: No PGC present\n"); + return; + } + printf("Number of Programs: %i\n", pgc->nr_of_programs); printf("Number of Cells: %i\n", pgc->nr_of_cells); /* Check that time is 0:0:0:0 also if nr_of_programs==0 */ @@ -765,14 +796,14 @@ ifoPrint_USER_OPS(&pgc->prohibited_ops); for(i = 0; i < 8; i++) { - if(pgc->audio_control[i].present) { + if(pgc->audio_control[i].present) { /* The 'is present' bit */ printf("Audio stream %i control: %04x\n", i, pgc->audio_control[i]); } } for(i = 0; i < 32; i++) { - if(pgc->subp_control[i].present) { + if(pgc->subp_control[i].present) { /* The 'is present' bit */ printf("Subpicture stream %2i control: %08x\n", i, pgc->subp_control[i]); } @@ -918,7 +949,7 @@ printf("Number of VOBs in this VOBS: %i\n", c_adt->nr_of_vobs); //entries = c_adt->nr_of_vobs; - entries = (c_adt->last_byte + 1 - C_ADT_SIZE)/sizeof(c_adt_t); + entries = (c_adt->last_byte + 1 - C_ADT_SIZE)/sizeof(cell_adr_t); for(i = 0; i < entries; i++) { printf("VOB ID: %3i, Cell ID: %3i ", @@ -1030,7 +1061,9 @@ ifohandle = ifoOpen(dvd, title); if(!ifohandle) { + if(dvdread_verbose(dvd) >= 0) { fprintf(stderr, "Can't open info file for title %d\n", title); + } return; } @@ -1041,7 +1074,11 @@ ifoPrint_VMGI_MAT(ifohandle->vmgi_mat); printf("\nFirst Play PGC\n--------------\n"); + if(ifohandle->first_play_pgc) { ifoPrint_PGC(ifohandle->first_play_pgc); + } else { + printf("No First Play PGC present\n"); + } printf("\nTitle Track search pointer table\n"); printf( "------------------------------------------------\n");
--- a/dvdread/ifo_read.c Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/ifo_read.c Wed Aug 15 11:47:22 2007 +0000 @@ -26,8 +26,15 @@ #include <stdio.h> #include <stdlib.h> + +#if defined(HAVE_INTTYPES_H) #include <inttypes.h> +#elif defined(HAVE_STDINT_H) +#include <stdint.h> +#endif + #include <string.h> +#include <errno.h> #include "bswap.h" #include "ifo_types.h" @@ -92,6 +99,11 @@ static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl); static void ifoFree_PGCIT_internal(pgcit_t *pgcit); +static ifo_handle_t *ifoOpen_File(ifo_handle_t *ifofile, int title, + char *suffix); +static ifo_handle_t *ifoOpenVMGI_File(ifo_handle_t *ifofile, char *suffix); +static ifo_handle_t *ifoOpenVTSI_File(ifo_handle_t *ifofile, int title, + char *suffix); static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) { return (DVDFileSeek(dvd_file, (int)offset) == (int)offset); @@ -103,21 +115,52 @@ ifofile = malloc(sizeof(ifo_handle_t)); if(!ifofile) - return 0; + return NULL; memset(ifofile, 0, sizeof(ifo_handle_t)); ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE); - if(!ifofile->file) /* Should really catch any error and try to fallback */ + if(!ifoOpen_File(ifofile, title, "IFO")) { + if(title) { + if(dvdread_verbose(dvd) >= 1) { + fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.%s.\n", + title, "IFO"); + } + } else { + if(dvdread_verbose(dvd) >= 1) { + fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.%s.\n", "IFO"); + } + } + /* lower functions free the pointer, reallocate */ + ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t)); + if(!ifofile) + return NULL; + + memset(ifofile, 0, sizeof(ifo_handle_t)); + ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE); - if(!ifofile->file) { + if(!ifoOpen_File(ifofile, title, "BUP")) { if(title) { - fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title); + if(dvdread_verbose(dvd) >= 1) { + fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.%s.\n", + title, "BUP"); + } } else { - fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n"); + if(dvdread_verbose(dvd) >= 1) { + fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.%s.\n", "BUP"); + } + } + return NULL; + } } + return ifofile; +} + +static ifo_handle_t *ifoOpen_File(ifo_handle_t *ifofile, int title, + char *suffix) { + if(!ifofile->file) { free(ifofile); - return 0; + return NULL; } /* First check if this is a VMGI file. */ @@ -125,9 +168,12 @@ /* These are both mandatory. */ if(!ifoRead_FP_PGC(ifofile) || !ifoRead_TT_SRPT(ifofile)) { - fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IFO).\n"); + if(dvdread_verbose(device_of_file(ifofile->file)) >= 0) { + fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.%s).\n", + suffix); + } ifoClose(ifofile); - return 0; + return NULL; } ifoRead_PGCI_UT(ifofile); @@ -135,9 +181,12 @@ /* This is also mandatory. */ if(!ifoRead_VTS_ATRT(ifofile)) { - fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IFO).\n"); + if(dvdread_verbose(device_of_file(ifofile->file)) >= 0) { + fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.%s).\n", + suffix); + } ifoClose(ifofile); - return 0; + return NULL; } ifoRead_TXTDT_MGI(ifofile); @@ -150,36 +199,44 @@ if(ifoRead_VTS(ifofile)) { if(!ifoRead_VTS_PTT_SRPT(ifofile) || !ifoRead_PGCIT(ifofile)) { - fprintf(stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.IFO).\n", - title); + if(dvdread_verbose(device_of_file(ifofile->file)) >= 0) { + fprintf(stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.%s).\n", + title, suffix); + } ifoClose(ifofile); - return 0; + return NULL; } - ifoRead_PGCI_UT(ifofile); ifoRead_VTS_TMAPT(ifofile); ifoRead_C_ADT(ifofile); ifoRead_VOBU_ADMAP(ifofile); if(!ifoRead_TITLE_C_ADT(ifofile) || !ifoRead_TITLE_VOBU_ADMAP(ifofile)) { - fprintf(stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.IFO).\n", - title); + if(dvdread_verbose(device_of_file(ifofile->file)) >= 0) { + fprintf(stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.%s).\n", + title, suffix); + } ifoClose(ifofile); - return 0; + return NULL; } return ifofile; } if(title) { - fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.IFO).\n", - title, title); + if(dvdread_verbose(device_of_file(ifofile->file)) >= 0) { + fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.%s).\n", + title, title, suffix); + } } else { - fprintf(stderr, "libdvdread: Invalid IFO for VMGM (VIDEO_TS.IFO).\n"); + if(dvdread_verbose(device_of_file(ifofile->file)) >= 0) { + fprintf(stderr, "libdvdread: Invalid IFO for VMGM (VIDEO_TS.%s).\n", + suffix); + } } ifoClose(ifofile); - return 0; + return NULL; } @@ -188,25 +245,50 @@ ifofile = malloc(sizeof(ifo_handle_t)); if(!ifofile) - return 0; + return NULL; memset(ifofile, 0, sizeof(ifo_handle_t)); ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_FILE); - if(!ifofile->file) /* Should really catch any error and try to fallback */ + if(!ifoOpenVMGI_File(ifofile, "IFO")) { + if(dvdread_verbose(dvd) >= 1) { + fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO: %s\n", + strerror(errno)); + } + + /* lower functions free the pointer, reallocate */ + ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t)); + if(!ifofile) + return NULL; + + memset(ifofile, 0, sizeof(ifo_handle_t)); + ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_BACKUP_FILE); + if(!ifoOpenVMGI_File(ifofile, "BUP")) + if(dvdread_verbose(dvd) >= 1) { + fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.BUP: %s\n", + strerror(errno)); + } + return NULL; + } + return ifofile; +} + +static ifo_handle_t *ifoOpenVMGI_File(ifo_handle_t *ifofile, char *suffix) { if(!ifofile->file) { - fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n"); free(ifofile); - return 0; + return NULL; } if(ifoRead_VMG(ifofile)) return ifofile; - fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IFO).\n"); + if(dvdread_verbose(device_of_file(ifofile->file)) >= 0) { + fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.%s).\n", + suffix); + } ifoClose(ifofile); - return 0; + return NULL; } @@ -215,33 +297,57 @@ ifofile = malloc(sizeof(ifo_handle_t)); if(!ifofile) - return 0; + return NULL; memset(ifofile, 0, sizeof(ifo_handle_t)); if(title <= 0 || title > 99) { + if(dvdread_verbose(dvd) >= 0) { fprintf(stderr, "libdvdread: ifoOpenVTSI invalid title (%d).\n", title); + } free(ifofile); - return 0; + errno = EINVAL; + return NULL; } ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE); - if(!ifofile->file) /* Should really catch any error and try to fallback */ + if(!ifoOpenVTSI_File(ifofile, title, "IFO")) { + if(dvdread_verbose(dvd) >= 1) { + fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.%s.\n", title, "IFO"); + } + /* lower functions free the pointer, reallocate */ + ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t)); + if(!ifofile) + return NULL; + + memset(ifofile, 0, sizeof(ifo_handle_t)); + ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE); + if(!ifoOpenVTSI_File(ifofile, title, "BUP")) + if(dvdread_verbose(dvd) >= 1) { + fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.%s.\n", title, "BUP"); + } + return NULL; + } + return ifofile; +} + +static ifo_handle_t *ifoOpenVTSI_File(ifo_handle_t* ifofile, int title, char *suffix) { if(!ifofile->file) { - fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title); free(ifofile); - return 0; + return NULL; } ifoRead_VTS(ifofile); if(ifofile->vtsi_mat) return ifofile; - fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.IFO).\n", - title, title); + if(dvdread_verbose(device_of_file(ifofile->file)) >= 0) { + fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.%s).\n", + title, title, suffix); + } ifoClose(ifofile); - return 0; + return NULL; } @@ -261,6 +367,7 @@ ifoFree_FP_PGC(ifofile); ifoFree_PGCIT(ifofile); ifoFree_VTS_PTT_SRPT(ifofile); + ifoFree_VTS_TMAPT(ifofile); if(ifofile->vmgi_mat) free(ifofile->vmgi_mat); @@ -480,6 +587,7 @@ static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile, pgc_command_tbl_t *cmd_tbl, unsigned int offset) { + unsigned int total; memset(cmd_tbl, 0, sizeof(pgc_command_tbl_t)); @@ -492,8 +600,12 @@ B2N_16(cmd_tbl->nr_of_pre); B2N_16(cmd_tbl->nr_of_post); B2N_16(cmd_tbl->nr_of_cell); + B2N_16(cmd_tbl->last_byte); - CHECK_VALUE(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255); + total = cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell; + CHECK_VALUE(PGC_COMMAND_TBL_SIZE + total * COMMAND_DATA_SIZE + <= cmd_tbl->last_byte + 1U); + CHECK_VALUE(total <= 255); if(cmd_tbl->nr_of_pre != 0) { unsigned int pre_cmds_size = cmd_tbl->nr_of_pre * COMMAND_DATA_SIZE; @@ -684,6 +796,8 @@ } if(pgc->program_map_offset != 0) { + if(pgc->nr_of_programs != 0) { + pgc->program_map = malloc(pgc->nr_of_programs * sizeof(pgc_program_map_t)); if(!pgc->program_map) { ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); @@ -698,8 +812,13 @@ } else { pgc->program_map = NULL; } + } else { + pgc->program_map = NULL; + } if(pgc->cell_playback_offset != 0) { + if(pgc->nr_of_cells != 0) { + pgc->cell_playback = malloc(pgc->nr_of_cells * sizeof(cell_playback_t)); if(!pgc->cell_playback) { ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); @@ -719,8 +838,13 @@ } else { pgc->cell_playback = NULL; } + } else { + pgc->cell_playback = NULL; + } if(pgc->cell_position_offset != 0) { + if(pgc->nr_of_cells != 0) { + pgc->cell_position = malloc(pgc->nr_of_cells * sizeof(cell_position_t)); if(!pgc->cell_position) { ifoFree_PGC(pgc); @@ -735,6 +859,9 @@ } else { pgc->cell_position = NULL; } + } else { + pgc->cell_position = NULL; + } return 1; } @@ -813,7 +940,9 @@ ifofile->tt_srpt = tt_srpt; if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n"); + } free(tt_srpt); return 0; } @@ -830,7 +959,9 @@ return 0; } if(!(DVDReadBytes(ifofile->file, tt_srpt->title, info_length))) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n"); + } ifoFree_TT_SRPT(ifofile); return 0; } @@ -845,7 +976,7 @@ CHECK_ZERO(tt_srpt->zero_1); CHECK_VALUE(tt_srpt->nr_of_srpts != 0); CHECK_VALUE(tt_srpt->nr_of_srpts < 100); // ?? - CHECK_VALUE((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); + CHECK_VALUE(tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); for(i = 0; i < tt_srpt->nr_of_srpts; i++) { CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0); @@ -915,7 +1046,9 @@ ifofile->vts_ptt_srpt = vts_ptt_srpt; if(!(DVDReadBytes(ifofile->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read PTT search table.\n"); + } free(vts_ptt_srpt); return 0; } @@ -936,7 +1069,9 @@ return 0; } if(!(DVDReadBytes(ifofile->file, data, info_length))) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read PTT search table.\n"); + } free(vts_ptt_srpt); free(data); ifofile->vts_ptt_srpt = 0; @@ -1080,7 +1215,9 @@ for(i = 0; i < ptl_mait->nr_of_countries; i++) { if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n"); + } free(ptl_mait->countries); free(ptl_mait); ifofile->ptl_mait = 0; @@ -1096,8 +1233,8 @@ for(i = 0; i < ptl_mait->nr_of_countries; i++) { CHECK_ZERO(ptl_mait->countries[i].zero_1); CHECK_ZERO(ptl_mait->countries[i].zero_2); - CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte - + 8*2 * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1); + CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte + + 16U * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1U); } for(i = 0; i < ptl_mait->nr_of_countries; i++) { @@ -1106,7 +1243,9 @@ if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN + ptl_mait->countries[i].pf_ptl_mai_start_byte)) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to seak PTL_MAIT table.\n"); + } free(ptl_mait->countries); free(ptl_mait); return 0; @@ -1122,7 +1261,9 @@ return 0; } if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table.\n"); + } free(pf_temp); for(j = 0; j < i ; j++) { free(ptl_mait->countries[j].pf_ptl_mai); @@ -1187,9 +1328,9 @@ if(!ifofile->vtsi_mat) return 0; - if(ifofile->vtsi_mat->vts_tmapt == 0) { /* optional(?) */ + /* Seems to be optional, at least when there are no OneSequencial Titles */ + if(ifofile->vtsi_mat->vts_tmapt == 0) { ifofile->vts_tmapt = NULL; - fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n"); return 1; } @@ -1205,7 +1346,9 @@ ifofile->vts_tmapt = vts_tmapt; if(!(DVDReadBytes(ifofile->file, vts_tmapt, VTS_TMAPT_SIZE))) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); + } free(vts_tmapt); ifofile->vts_tmapt = NULL; return 0; @@ -1228,7 +1371,9 @@ vts_tmapt->tmap_offset = vts_tmap_srp; if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); + } free(vts_tmap_srp); free(vts_tmapt); ifofile->vts_tmapt = NULL; @@ -1259,7 +1404,9 @@ } if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n"); + } ifoFree_VTS_TMAPT(ifofile); return 0; } @@ -1281,7 +1428,9 @@ } if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n"); + } ifoFree_VTS_TMAPT(ifofile); return 0; } @@ -1392,7 +1541,9 @@ Enemy of the State region 2 (de) has Titles where nr_of_vobs field is to high, they high ones are never referenced though. */ if(info_length / sizeof(cell_adr_t) < c_adt->nr_of_vobs) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: *C_ADT nr_of_vobs > avaiable info entries\n"); + } c_adt->nr_of_vobs = info_length / sizeof(cell_adr_t); } @@ -1624,8 +1775,8 @@ } ptr = data; for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { - memcpy(&pgcit->pgci_srp[i], ptr, PGCI_LU_SIZE); - ptr += PGCI_LU_SIZE; + memcpy(&pgcit->pgci_srp[i], ptr, PGCI_SRP_SIZE); + ptr += PGCI_SRP_SIZE; B2N_16(pgcit->pgci_srp[i].ptl_id_mask); B2N_32(pgcit->pgci_srp[i].pgc_start_byte); CHECK_VALUE(pgcit->pgci_srp[i].unknown1 == 0); @@ -1643,6 +1794,8 @@ ifoFree_PGC(pgcit->pgci_srp[j].pgc); free(pgcit->pgci_srp[j].pgc); } + free(pgcit->pgci_srp); + pgcit->pgci_srp = NULL; return 0; } if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc, @@ -1653,6 +1806,7 @@ free(pgcit->pgci_srp[j].pgc); } free(pgcit->pgci_srp); + pgcit->pgci_srp = NULL; return 0; } } @@ -1663,8 +1817,10 @@ static void ifoFree_PGCIT_internal(pgcit_t *pgcit) { if(pgcit) { int i; - for(i = 0; i < pgcit->nr_of_pgci_srp; i++) + for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { ifoFree_PGC(pgcit->pgci_srp[i].pgc); + free(pgcit->pgci_srp[i].pgc); + } free(pgcit->pgci_srp); } } @@ -2000,7 +2156,9 @@ ifofile->txtdt_mgi = txtdt_mgi; if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) { + if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n"); + } free(txtdt_mgi); ifofile->txtdt_mgi = 0; return 0;
--- a/dvdread/ifo_types.h Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/ifo_types.h Wed Aug 15 11:47:22 2007 +0000 @@ -24,9 +24,17 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <inttypes.h> #include <dvdread/dvd_reader.h> +#if defined(__BEOS__) +#if !defined(_INTTYPES_H_) && !defined(_INTTYPES_H) && !defined(_STDINT_H_) && !defined(_STDINT_H) +#error "Must include <inttypes.h> or <stdint.h> before any libdvdread header." +#endif +#else +#if !defined(UINT8_MAX) || !defined(UINT16_MAX) || !defined(INT32_MAX) +#error "Must include <inttypes.h> or <stdint.h> before any libdvdread header." +#endif +#endif #undef ATTRIBUTE_PACKED #undef PRAGMA_PACK_BEGIN @@ -72,7 +80,7 @@ typedef struct { uint8_t bytes[8]; } ATTRIBUTE_PACKED vm_cmd_t; -#define COMMAND_DATA_SIZE 8 +#define COMMAND_DATA_SIZE 8U /** @@ -140,7 +148,7 @@ uint8_t code_extension; uint8_t unknown3; union { - struct ATTRIBUTE_PACKED { + struct { #ifdef WORDS_BIGENDIAN unsigned int unknown4 : 1; unsigned int channel_assignment : 3; @@ -154,8 +162,8 @@ unsigned int channel_assignment : 3; unsigned int unknown4 : 1; #endif - } karaoke; - struct ATTRIBUTE_PACKED { + } ATTRIBUTE_PACKED karaoke; + struct { #ifdef WORDS_BIGENDIAN unsigned int unknown5 : 4; unsigned int dolby_encoded : 1; /* suitable for surround decoding */ @@ -165,7 +173,7 @@ unsigned int dolby_encoded : 1; unsigned int unknown5 : 4; #endif - } surround; + } ATTRIBUTE_PACKED surround; } app_info; } ATTRIBUTE_PACKED audio_attr_t; @@ -265,12 +273,12 @@ uint16_t nr_of_pre; uint16_t nr_of_post; uint16_t nr_of_cell; - uint16_t zero_1; + uint16_t last_byte; vm_cmd_t *pre_cmds; vm_cmd_t *post_cmds; vm_cmd_t *cell_cmds; } ATTRIBUTE_PACKED pgc_command_tbl_t; -#define PGC_COMMAND_TBL_SIZE 8 +#define PGC_COMMAND_TBL_SIZE 8U /** * PGC Program Map @@ -460,8 +468,8 @@ uint16_t next_pgc_nr; uint16_t prev_pgc_nr; uint16_t goup_pgc_nr; + uint8_t pg_playback_mode; uint8_t still_time; - uint8_t pg_playback_mode; uint32_t palette[16]; /* New type struct {zero_1, Y, Cr, Cb} ? */ uint16_t command_tbl_offset; uint16_t program_map_offset; @@ -472,7 +480,7 @@ cell_playback_t *cell_playback; cell_position_t *cell_position; } ATTRIBUTE_PACKED pgc_t; -#define PGC_SIZE 236 +#define PGC_SIZE 236U /** * Program Chain Information Search Pointer. @@ -492,7 +500,7 @@ uint32_t pgc_start_byte; pgc_t *pgc; } ATTRIBUTE_PACKED pgci_srp_t; -#define PGCI_SRP_SIZE 8 +#define PGCI_SRP_SIZE 8U /** * Program Chain Information Table. @@ -503,7 +511,7 @@ uint32_t last_byte; pgci_srp_t *pgci_srp; } ATTRIBUTE_PACKED pgcit_t; -#define PGCIT_SIZE 8 +#define PGCIT_SIZE 8U /** * Menu PGCI Language Unit. @@ -515,7 +523,7 @@ uint32_t lang_start_byte; pgcit_t *pgcit; } ATTRIBUTE_PACKED pgci_lu_t; -#define PGCI_LU_SIZE 8 +#define PGCI_LU_SIZE 8U /** * Menu PGCI Unit Table. @@ -526,7 +534,7 @@ uint32_t last_byte; pgci_lu_t *lu; } ATTRIBUTE_PACKED pgci_ut_t; -#define PGCI_UT_SIZE 8 +#define PGCI_UT_SIZE 8U /** * Cell Address Information. @@ -548,7 +556,7 @@ uint32_t last_byte; cell_adr_t *cell_adr_table; /* No explicit size given. */ } ATTRIBUTE_PACKED c_adt_t; -#define C_ADT_SIZE 8 +#define C_ADT_SIZE 8U /** * VOBU Address Map. @@ -557,7 +565,7 @@ uint32_t last_byte; uint32_t *vobu_start_sectors; } ATTRIBUTE_PACKED vobu_admap_t; -#define VOBU_ADMAP_SIZE 4 +#define VOBU_ADMAP_SIZE 4U @@ -655,7 +663,7 @@ uint32_t last_byte; title_info_t *title; } ATTRIBUTE_PACKED tt_srpt_t; -#define TT_SRPT_SIZE 8 +#define TT_SRPT_SIZE 8U /** @@ -674,7 +682,7 @@ uint16_t zero_2; pf_level_t *pf_ptl_mai; /* table of (nr_of_vtss + 1), video_ts is first */ } ATTRIBUTE_PACKED ptl_mait_country_t; -#define PTL_MAIT_COUNTRY_SIZE 8 +#define PTL_MAIT_COUNTRY_SIZE 8U /** * Parental Management Information Table. @@ -685,7 +693,7 @@ uint32_t last_byte; ptl_mait_country_t *countries; } ATTRIBUTE_PACKED ptl_mait_t; -#define PTL_MAIT_SIZE 8 +#define PTL_MAIT_SIZE 8U /** * Video Title Set Attributes. @@ -716,8 +724,8 @@ uint8_t nr_of_vtstt_subp_streams; subp_attr_t vtstt_subp_attr[32]; } ATTRIBUTE_PACKED vts_attributes_t; -#define VTS_ATTRIBUTES_SIZE 542 -#define VTS_ATTRIBUTES_MIN_SIZE 356 +#define VTS_ATTRIBUTES_SIZE 542U +#define VTS_ATTRIBUTES_MIN_SIZE 356U /** * Video Title Set Attribute Table. @@ -729,7 +737,7 @@ vts_attributes_t *vts; uint32_t *vts_atrt_offsets; /* offsets table for each vts_attributes */ } ATTRIBUTE_PACKED vts_atrt_t; -#define VTS_ATRT_SIZE 8 +#define VTS_ATRT_SIZE 8U /** * Text Data. (Incomplete) @@ -762,7 +770,7 @@ uint32_t txtdt_start_byte; /* prt, rel start of vmg_txtdt_mgi */ txtdt_t *txtdt; } ATTRIBUTE_PACKED txtdt_lu_t; -#define TXTDT_LU_SIZE 8 +#define TXTDT_LU_SIZE 8U /** * Text Data Manager Information. (Incomplete) @@ -773,7 +781,7 @@ uint32_t last_byte; txtdt_lu_t *lu; } ATTRIBUTE_PACKED txtdt_mgi_t; -#define TXTDT_MGI_SIZE 20 +#define TXTDT_MGI_SIZE 20U /** @@ -865,7 +873,7 @@ ttu_t *title; uint32_t *ttu_offset; /* offset table for each ttu */ } ATTRIBUTE_PACKED vts_ptt_srpt_t; -#define VTS_PTT_SRPT_SIZE 8 +#define VTS_PTT_SRPT_SIZE 8U /** @@ -883,7 +891,7 @@ uint16_t nr_of_entries; map_ent_t *map_ent; } ATTRIBUTE_PACKED vts_tmap_t; -#define VTS_TMAP_SIZE 4 +#define VTS_TMAP_SIZE 4U /** * Time Map Table. @@ -895,7 +903,7 @@ vts_tmap_t *tmap; uint32_t *tmap_offset; /* offset table for each tmap */ } ATTRIBUTE_PACKED vts_tmapt_t; -#define VTS_TMAPT_SIZE 8 +#define VTS_TMAPT_SIZE 8U #if PRAGMA_PACK
--- a/dvdread/nav_print.c Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/nav_print.c Wed Aug 15 11:47:22 2007 +0000 @@ -26,10 +26,16 @@ #include "config.h" #include <stdio.h> + +#if defined(HAVE_INTTYPES_H) #include <inttypes.h> +#elif defined(HAVE_STDINT_H) +#include <stdint.h> +#endif #include "nav_types.h" #include "nav_print.h" +#include "cmd_print.h" #include "dvdread_internal.h" static void print_time(dvd_time_t *dtime) { @@ -167,7 +173,7 @@ printf("left %d, ", btni->left); printf("right %d\n", btni->right); - // ifoPrint_COMMAND(&btni->cmd); + cmdPrint_CMD(0, &btni->cmd); printf("\n"); } }
--- a/dvdread/nav_read.c Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/nav_read.c Wed Aug 15 11:47:22 2007 +0000 @@ -20,7 +20,11 @@ #include <stdio.h> #include <string.h> +#if defined(HAVE_INTTYPES_H) #include <inttypes.h> +#elif defined(HAVE_STDINT_H) +#include <stdint.h> +#endif #include "bswap.h" #include "nav_types.h"
--- a/dvdread/nav_types.h Wed Aug 15 10:34:53 2007 +0000 +++ b/dvdread/nav_types.h Wed Aug 15 11:47:22 2007 +0000 @@ -29,9 +29,8 @@ * USA */ -#include <inttypes.h> #include <dvdread/ifo_types.h> /* only dvd_time_t, vm_cmd_t and user_ops_t */ - +/* If it's ever removed add a uintX_t test. */ #undef ATTRIBUTE_PACKED #undef PRAGMA_PACK_BEGIN