aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar diego <diego@b3059339-0415-0410-9bf9-f77b7e298cf2>2007-08-15 11:47:22 +0000
committerGravatar diego <diego@b3059339-0415-0410-9bf9-f77b7e298cf2>2007-08-15 11:47:22 +0000
commit80dee3f8ac591919a1f78724d31049f5b4472f42 (patch)
tree03c83643049579a36c79840a2a2b0ab01f20da91
parent5d9b793edd1a692816c3c7a8d4dd8549f18fd1af (diff)
Sync libdvdread with version 0.9.5 (functional changes).
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@24067 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r--Changelog1
-rw-r--r--Copyright2
-rwxr-xr-xconfigure3
-rw-r--r--dvdread/Makefile1
-rw-r--r--dvdread/bswap.h14
-rw-r--r--dvdread/dvd_input.c104
-rw-r--r--dvdread/dvd_input.h7
-rw-r--r--dvdread/dvd_reader.c436
-rw-r--r--dvdread/dvd_reader.h44
-rw-r--r--dvdread/dvd_udf.c282
-rw-r--r--dvdread/dvd_udf.h6
-rw-r--r--dvdread/dvdread_internal.h4
-rw-r--r--dvdread/ifo_print.c91
-rw-r--r--dvdread/ifo_read.c246
-rw-r--r--dvdread/ifo_types.h62
-rw-r--r--dvdread/nav_print.c8
-rw-r--r--dvdread/nav_read.c4
-rw-r--r--dvdread/nav_types.h3
-rw-r--r--stream/stream_dvd_common.c1
19 files changed, 1086 insertions, 233 deletions
diff --git a/Changelog b/Changelog
index ce5f0319b1..2359e96e8d 100644
--- a/Changelog
+++ b/Changelog
@@ -112,6 +112,7 @@ MPlayer (1.0)
* 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
diff --git a/Copyright b/Copyright
index eb235db438..4ca0aba441 100644
--- a/Copyright
+++ b/Copyright
@@ -49,7 +49,7 @@ Copyright: 1998-2006 VideoLAN
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>
diff --git a/configure b/configure
index 5935be5d2e..4e37e6814b 100755
--- a/configure
+++ b/configure
@@ -7744,6 +7744,9 @@ $_def_fast_inttypes
#define HAVE_MEMCPY 1
#define HAVE_STRCHR 1
+/* libdvdread */
+#define HAVE_UINTPTR_T 1
+
/* name of messages charset */
$_def_charset
diff --git a/dvdread/Makefile b/dvdread/Makefile
index 77f2e1c2ee..c79375e755 100644
--- a/dvdread/Makefile
+++ b/dvdread/Makefile
@@ -10,6 +10,7 @@ SRCS_COMMON = dvd_input.c \
nav_print.c \
nav_read.c \
md5.c \
+ cmd_print.c \
CFLAGS = -D__USE_UNIX98 -D_GNU_SOURCE
diff --git a/dvdread/bswap.h b/dvdread/bswap.h
index c612025b31..a5296b82cd 100644
--- a/dvdread/bswap.h
+++ b/dvdread/bswap.h
@@ -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 @@ inline static unsigned long long int bswap_64(unsigned long long int x)
* 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))
diff --git a/dvdread/dvd_input.c b/dvdread/dvd_input.c
index 341c9882d4..dcd5307862 100644
--- a/dvdread/dvd_input.c
+++ b/dvdread/dvd_input.c
@@ -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 @@ static dvd_input_t css_open(const char *target)
/* 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 @@ static int css_close(dvd_input_t dev)
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 int css_close(dvd_input_t dev)
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 char *file_error(dvd_input_t dev)
*/
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 @@ static int file_read(dvd_input_t dev, void *buffer, int blocks, int flags)
{
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 @@ static int file_read(dvd_input_t dev, void *buffer, int blocks, int flags)
return (int) (bytes / DVD_VIDEO_LB_LEN);
}
+ buf+=ret;
len -= ret;
}
@@ -262,13 +283,49 @@ static int file_close(dvd_input_t dev)
}
+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 @@ int dvdinput_setup(void)
dvdcss_version = &dvdcss_interface_2;
#else
- /* dlopening libdvdcss */
+
dvdcss_library = dlopen("libdvdcss.so.2", RTLD_LAZY);
if(dvdcss_library != NULL) {
@@ -302,33 +359,39 @@ int dvdinput_setup(void)
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 @@ int dvdinput_setup(void)
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;
diff --git a/dvdread/dvd_input.h b/dvdread/dvd_input.h
index e9e84917ea..0f05c97952 100644
--- a/dvdread/dvd_input.h
+++ b/dvdread/dvd_input.h
@@ -40,6 +40,13 @@ extern int (*dvdinput_read) (dvd_input_t, void *, int, int);
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);
diff --git a/dvdread/dvd_reader.c b/dvdread/dvd_reader.c
index d944696c15..92d202b8d9 100644
--- a/dvdread/dvd_reader.c
+++ b/dvdread/dvd_reader.c
@@ -60,11 +60,13 @@ static void gettimeofday(struct timeval* t,void* timezone){
}
#endif
-#include "dvd_udf.h"
-#include "dvd_input.h"
#include "dvd_reader.h"
+#include "dvd_input.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 @@ struct dvd_reader_s {
/* 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 @@ struct dvd_file_s {
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 @@ void SetUDFCacheHandle(dvd_reader_t *device, void *cache)
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 @@ static int initAllCSSKeys( dvd_reader_t *dvd )
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 @@ static int initAllCSSKeys( dvd_reader_t *dvd )
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 @@ static int initAllCSSKeys( dvd_reader_t *dvd )
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 @@ static int initAllCSSKeys( dvd_reader_t *dvd )
/**
* 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 @@ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css )
}
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 @@ static dvd_reader_t *DVDOpenPath( const char *path_root )
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 @@ dvd_reader_t *DVDOpen( const char *path )
{
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 @@ dvd_reader_t *DVDOpen( const char *path )
{
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 @@ dvd_reader_t *DVDOpen( const char *path )
/* 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 @@ dvd_reader_t *DVDOpen( const char *path )
*/
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 @@ dvd_reader_t *DVDOpen( const char *path )
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 @@ dvd_reader_t *DVDOpen( const char *path )
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 @@ dvd_reader_t *DVDOpen( const char *path )
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 @@ dvd_reader_t *DVDOpen( const char *path )
/**
* 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 @@ dvd_reader_t *DVDOpen( const char *path )
}
/* 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 @@ void DVDClose( dvd_reader_t *dvd )
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 @@ static int findDirFile( const char *path, const char *file, char *filename )
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 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
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 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu )
}
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 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu )
}
if( stat( full_path, &fileinfo ) < 0 ) {
+ if(dvd->verbose >= 1) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
+ }
break;
}
@@ -746,8 +948,10 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
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 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
}
break;
default:
+ if(dvd->verbose >= 1) {
fprintf( stderr, "libdvdread: Invalid domain for file open.\n" );
+ }
+ errno = EINVAL;
return NULL;
}
@@ -811,7 +1018,20 @@ void DVDCloseFile( dvd_file_t *dvd_file )
}
}
-/* 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 UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
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 UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
(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 @@ static int DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t 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'.
+ * 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 @@ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset,
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 @@ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset,
/* 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 @@ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset,
/* 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 @@ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset,
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 @@ int DVDFileSeek( dvd_file_t *dvd_file, int offset )
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 @@ ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
}
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 @@ int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid )
{
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 @@ int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid )
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 @@ int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid )
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 @@ int DVDISOVolumeInfo( dvd_reader_t *dvd,
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 == NULL ) {
+ errno = EINVAL;
+ return -1;
+ }
if( dvd->dev == NULL ) {
/* No block access, so no ISO... */
+ 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" );
+ 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 @@ int DVDISOVolumeInfo( dvd_reader_t *dvd,
}
memcpy(volsetid, &buffer[190], volsetid_size);
}
+ free(buffer_start);
+
return 0;
}
diff --git a/dvdread/dvd_reader.h b/dvdread/dvd_reader.h
index cc4ba54895..25b0370279 100644
--- a/dvdread/dvd_reader.h
+++ b/dvdread/dvd_reader.h
@@ -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 @@ typedef struct dvd_file_s dvd_file_t;
* @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 @@ dvd_reader_t *DVDOpen( const char * );
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 @@ void DVDCloseFile( dvd_file_t * );
* @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);
diff --git a/dvdread/dvd_udf.c b/dvdread/dvd_udf.c
index 56682e7405..19b69560cf 100644
--- a/dvdread/dvd_udf.c
+++ b/dvdread/dvd_udf.c
@@ -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 @@ typedef enum {
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 UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristics,
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 @@ static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType,
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 @@ static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType,
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 @@ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
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 @@ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
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 @@ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
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 @@ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
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 @@ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
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 UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
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 @@ static int UDFGetAVDP( dvd_reader_t *device,
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 @@ static int UDFGetAVDP( dvd_reader_t *device,
}
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 @@ static int UDFGetAVDP( dvd_reader_t *device,
lbnum = lastsector - 256;
} else {
/* Unable to find last sector */
+ dvdalign_lbfree(device, Anchor);
+ errno = EMEDIUMTYPE;
return 0;
}
}
@@ -708,6 +889,7 @@ static int UDFGetAVDP( dvd_reader_t *device,
SetUDFCache(device, AVDPCache, 0, avdp);
+ dvdalign_lbfree(device, Anchor);
return 1;
}
@@ -719,7 +901,7 @@ static int UDFGetAVDP( dvd_reader_t *device,
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 @@ static int UDFFindPartition( dvd_reader_t *device, int partnum,
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 @@ static int UDFFindPartition( dvd_reader_t *device, int partnum,
}
} 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 @@ static int UDFFindPartition( dvd_reader_t *device, int partnum,
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 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
char *token;
uint8_t filetype;
+ if(filesize) {
*filesize = 0;
+ }
tokenline[0] = '\0';
strcat( tokenline, filename );
@@ -798,9 +987,15 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
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 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
} 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 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
}
/* 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 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
* 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 @@ static int UDFGetDescriptor( dvd_reader_t *device, int id,
}
} 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 @@ static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd)
memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128);
SetUDFCache(device, PVDCache, 0, pvd);
+ dvdalign_lbfree(device, pvd_buf);
+
return 1;
}
diff --git a/dvdread/dvd_udf.h b/dvdread/dvd_udf.h
index b600983d9a..0e2e8b0df4 100644
--- a/dvdread/dvd_udf.h
+++ b/dvdread/dvd_udf.h
@@ -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 @@ extern "C" {
*/
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,
diff --git a/dvdread/dvdread_internal.h b/dvdread/dvdread_internal.h
index 5c8a535cc0..fbd87b48ce 100644
--- a/dvdread/dvdread_internal.h
+++ b/dvdread/dvdread_internal.h
@@ -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 */
diff --git a/dvdread/ifo_print.c b/dvdread/ifo_print.c
index 17820c77a4..47938f6aba 100644
--- a/dvdread/ifo_print.c
+++ b/dvdread/ifo_print.c
@@ -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 @@ static void ifoPrint_time(dvd_time_t *dtime) {
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 @@ static void ifoPrint_audio_attributes(audio_attr_t *attr) {
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 @@ static void ifoPrint_audio_attributes(audio_attr_t *attr) {
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 @@ static void ifoPrint_audio_attributes(audio_attr_t *attr) {
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 @@ static void ifoPrint_audio_attributes(audio_attr_t *attr) {
printf("48kHz ");
break;
case 1:
- printf("??kHz ");
+ printf("96kHz ");
break;
default:
printf("sample_frequency %i (please send a bug report) ",
@@ -387,10 +414,9 @@ static void ifoPrint_subp_attributes(subp_attr_t *attr) {
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 @@ static void ifoPrint_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) {
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 @@ static void ifoPrint_CELL_POSITION(cell_position_t *cell_position, int nr) {
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 @@ void ifoPrint_PGC(pgc_t *pgc) {
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 @@ void ifoPrint_C_ADT(c_adt_t *c_adt) {
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 @@ void ifoPrint(dvd_reader_t *dvd, int title) {
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 @@ void ifoPrint(dvd_reader_t *dvd, int title) {
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");
diff --git a/dvdread/ifo_read.c b/dvdread/ifo_read.c
index 8ad7baeea1..34ce32f41e 100644
--- a/dvdread/ifo_read.c
+++ b/dvdread/ifo_read.c
@@ -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(pgc_t *pgc);
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 @@ ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) {
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 @@ ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) {
/* 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 @@ ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) {
/* 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 @@ ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) {
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 @@ ifo_handle_t *ifoOpenVMGI(dvd_reader_t *dvd) {
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 @@ ifo_handle_t *ifoOpenVTSI(dvd_reader_t *dvd, int title) {
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 @@ void ifoClose(ifo_handle_t *ifofile) {
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_VTS(ifo_handle_t *ifofile) {
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 @@ static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,
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 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) {
}
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 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) {
} 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 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) {
} 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 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) {
} else {
pgc->cell_position = NULL;
}
+ } else {
+ pgc->cell_position = NULL;
+ }
return 1;
}
@@ -813,7 +940,9 @@ int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
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 @@ int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
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 @@ int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
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 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
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 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
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 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
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 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
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 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
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 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
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 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
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 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
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 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
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 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
}
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 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
}
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 @@ static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile,
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 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
}
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 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
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 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
free(pgcit->pgci_srp[j].pgc);
}
free(pgcit->pgci_srp);
+ pgcit->pgci_srp = NULL;
return 0;
}
}
@@ -1663,8 +1817,10 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
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 @@ int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) {
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;
diff --git a/dvdread/ifo_types.h b/dvdread/ifo_types.h
index 6f66957349..3e11adece2 100644
--- a/dvdread/ifo_types.h
+++ b/dvdread/ifo_types.h
@@ -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 {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
uint16_t next_pgc_nr;
uint16_t prev_pgc_nr;
uint16_t goup_pgc_nr;
- uint8_t still_time;
uint8_t pg_playback_mode;
+ uint8_t still_time;
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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
diff --git a/dvdread/nav_print.c b/dvdread/nav_print.c
index 6df3dc8310..8a8518bd6d 100644
--- a/dvdread/nav_print.c
+++ b/dvdread/nav_print.c
@@ -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 @@ static void navPrint_BTNIT(btni_t *btni_table, int btngr_ns, int btn_ns) {
printf("left %d, ", btni->left);
printf("right %d\n", btni->right);
- // ifoPrint_COMMAND(&btni->cmd);
+ cmdPrint_CMD(0, &btni->cmd);
printf("\n");
}
}
diff --git a/dvdread/nav_read.c b/dvdread/nav_read.c
index 1a907f9dfe..2de0b859b7 100644
--- a/dvdread/nav_read.c
+++ b/dvdread/nav_read.c
@@ -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"
diff --git a/dvdread/nav_types.h b/dvdread/nav_types.h
index c9fc3da60f..de962ac2e4 100644
--- a/dvdread/nav_types.h
+++ b/dvdread/nav_types.h
@@ -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
diff --git a/stream/stream_dvd_common.c b/stream/stream_dvd_common.c
index 63a00c1cff..895db3a567 100644
--- a/stream/stream_dvd_common.c
+++ b/stream/stream_dvd_common.c
@@ -1,3 +1,4 @@
+#include <inttypes.h>
#include <dvdread/ifo_types.h>
#include "stream_dvd_common.h"