diff --git a/dvdread/Makefile.am b/dvdread/Makefile.am deleted file mode 100644 index 5c9fddf..0000000 --- a/dvdread/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ - -METASOURCES = AUTO -noinst_LTLIBRARIES = libdvdread.la -libdvdread_la_LDFLAGS = $(all_libraries) -libdvdread_la_SOURCES = dvd_input.c dvd_reader.c dvd_udf.c ifo_read.c md5.c \ - nav_read.c -noinst_HEADERS = bswap.h dvd_input.h dvd_reader.h dvd_udf.h dvdread_internal.h \ - ifo_read.h ifo_types.h md5.h nav_read.h nav_types.h diff --git a/dvdread/bswap.h b/dvdread/bswap.h deleted file mode 100644 index 11c9774..0000000 --- a/dvdread/bswap.h +++ /dev/null @@ -1,126 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -#ifndef BSWAP_H_INCLUDED -#define BSWAP_H_INCLUDED - -/* - * Copyright (C) 2000, 2001 Billy Biggs , - * Håkan Hjort - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#if defined(WORDS_BIGENDIAN) -/* All bigendian systems are fine, just ignore the swaps. */ -#define B2N_16(x) (void)(x) -#define B2N_32(x) (void)(x) -#define B2N_64(x) (void)(x) - -#else - -/* For __FreeBSD_version */ -#if defined(HAVE_SYS_PARAM_H) -#include -#endif - -#if defined(__linux__) -#include -#define B2N_16(x) x = bswap_16(x) -#define B2N_32(x) x = bswap_32(x) -#define B2N_64(x) x = bswap_64(x) - -#elif defined(__NetBSD__) -#include -#define B2N_16(x) BE16TOH(x) -#define B2N_32(x) BE32TOH(x) -#define B2N_64(x) BE64TOH(x) - -#elif defined(__OpenBSD__) -#include -#define B2N_16(x) x = swap16(x) -#define B2N_32(x) x = swap32(x) -#define B2N_64(x) x = swap64(x) - -#elif defined(__FreeBSD__) && __FreeBSD_version >= 470000 -#include -#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 -#define B2N_16(x) x = be16toh(x) -#define B2N_32(x) x = be32toh(x) -#define B2N_64(x) x = be64toh(x) - - -#elif defined(__APPLE__) || defined(__DARWIN__) -#include -#define B2N_16(x) x = OSSwapBigToHostConstInt16(x) -#define B2N_32(x) x = OSSwapBigToHostConstInt32(x) -#define B2N_64(x) x = OSSwapBigToHostConstInt64(x) - -#else -#if defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__) || defined(WIN32) || defined(__BEOS__) || defined(__INTERIX) -/* These systems don't have swap macros */ -#else -/* If there isn't a header provided with your system with this functionality - * add the relevant || define( ) to the list above. - */ -#warning "You should add endian swap macros for your system" -#endif - -/* This is a slow but portable implementation, it has multiple evaluation - * problems so beware. - * Old FreeBSD's and Solaris don't have or any other such - * functionality! - */ - -#define B2N_16(x) \ - x = ((((x) & 0xff00) >> 8) | \ - (((x) & 0x00ff) << 8)) -#define B2N_32(x) \ - x = ((((x) & 0xff000000) >> 24) | \ - (((x) & 0x00ff0000) >> 8) | \ - (((x) & 0x0000ff00) << 8) | \ - (((x) & 0x000000ff) << 24)) -#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 - -#endif /* WORDS_BIGENDIAN */ - -#endif /* BSWAP_H_INCLUDED */ diff --git a/dvdread/dvd_input.c b/dvdread/dvd_input.c deleted file mode 100644 index 99ddd2d..0000000 --- a/dvdread/dvd_input.c +++ /dev/null @@ -1,414 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -/* - * Copyright (C) 2002 Samuel Hocevar , - * Håkan Hjort - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. - */ - -#include "config.h" - -#include -#include -#define __USE_GNU /* to get O_DIRECT in linux */ -#include -#include - -#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 -/* linking to libdvdcss */ -#include -#define DVDcss_open(a) dvdcss_open((char*)(a)) -#define DVDcss_close dvdcss_close -#define DVDcss_seek dvdcss_seek -#define DVDcss_title dvdcss_title -#define DVDcss_read dvdcss_read -#define DVDcss_error dvdcss_error -#else -/* dlopening libdvdcss */ -#include -typedef struct dvdcss_s *dvdcss_handle; -static dvdcss_handle (*DVDcss_open) (const char *); -static int (*DVDcss_close) (dvdcss_handle); -static int (*DVDcss_seek) (dvdcss_handle, int, int); -static int (*DVDcss_title) (dvdcss_handle, int); -static int (*DVDcss_read) (dvdcss_handle, void *, int, int); -static char * (*DVDcss_error) (dvdcss_handle); -#endif - -/* The DVDinput handle, add stuff here for new input methods. */ -struct dvd_input_s { - /* libdvdcss handle */ - dvdcss_handle dvdcss; - - /* dummy file input */ - int fd; -}; - - -/** - * initialize and open a DVD device or file. - */ -static dvd_input_t css_open(const char *target) -{ - dvd_input_t dev; - - /* Allocate the handle structure */ - dev = (dvd_input_t) malloc(sizeof(struct dvd_input_s)); - if(dev == NULL) { - /* malloc has set errno to ENOMEM */ - return NULL; - } - - /* Really open it with libdvdcss */ - dev->dvdcss = DVDcss_open(target); - if(dev->dvdcss == 0) { - free(dev); - dev = NULL; - } - - return dev; -} - -/** - * return the last error message - */ -static char *css_error(dvd_input_t dev) -{ - return DVDcss_error(dev->dvdcss); -} - -/** - * seek into the device. - */ -static int css_seek(dvd_input_t dev, int blocks) -{ - /* DVDINPUT_NOFLAGS should match the DVDCSS_NOFLAGS value. */ - return DVDcss_seek(dev->dvdcss, blocks, DVDINPUT_NOFLAGS); -} - -/** - * set the block for the begining of a new title (key). - */ -static int css_title(dvd_input_t dev, int block) -{ - return DVDcss_title(dev->dvdcss, block); -} - -/** - * read data from the device. - */ -static int css_read(dvd_input_t dev, void *buffer, int blocks, int flags) -{ - return DVDcss_read(dev->dvdcss, buffer, blocks, flags); -} - -/** - * close the DVD device and clean up the library. - */ -static int css_close(dvd_input_t dev) -{ - int ret; - - ret = DVDcss_close(dev->dvdcss); - - if(ret < 0) - return ret; - - free(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. - */ -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) { - return NULL; - } - - /* Open the device */ - dev->fd = open(target, oflags); - if(dev->fd < 0) { - free(dev); - return NULL; - } - - return dev; -} - -/** - * return the last error message - */ -static char *file_error(dvd_input_t dev) -{ - /* use strerror(errno)? */ - return (char *)"unknown error"; -} - -/** - * seek into the device. - */ -static int file_seek(dvd_input_t dev, int blocks) -{ - off_t pos = (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN; - - pos = lseek(dev->fd, pos, SEEK_SET); - if(pos < 0) { - return pos; - } - /* assert pos % DVD_VIDEO_LB_LEN == 0 */ - return (int) (pos / DVD_VIDEO_LB_LEN); -} - -/** - * set the block for the begining of a new title (key). - */ -static int file_title(dvd_input_t dev, int block) -{ - return -1; -} - -/** - * read data from the device. - */ -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, buf, len); - - if(ret < 0) { - /* One of the reads failed, too bad. We won't even bother - * returning the reads that went ok, and as in the posix spec - * the file postition is left unspecified after a failure. */ - return ret; - } - - if(ret == 0) { - /* Nothing more to read. Return the whole blocks, if any, that we got. - and adjust the file possition back to the previous block boundary. */ - size_t bytes = (size_t)blocks * DVD_VIDEO_LB_LEN - len; - off_t over_read = -(bytes % DVD_VIDEO_LB_LEN); - /*off_t pos =*/ lseek(dev->fd, over_read, SEEK_CUR); - /* should have pos % 2048 == 0 */ - return (int) (bytes / DVD_VIDEO_LB_LEN); - } - - buf+=ret; - len -= ret; - } - - return blocks; -} - -/** - * close the DVD device and clean up. - */ -static int file_close(dvd_input_t dev) -{ - int ret; - - ret = close(dev->fd); - - if(ret < 0) - return ret; - - free(dev); - - return 0; -} - - -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) -{ - 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 */ - dvdcss_library = &dvdcss_library; /* Give it some value != NULL */ - /* the DVDcss_* functions have been #defined at the top */ - dvdcss_version = &dvdcss_interface_2; - -#else - - dvdcss_library = dlopen("libdvdcss.so.2", RTLD_LAZY); - - if(dvdcss_library != NULL) { -#if defined(__OpenBSD__) && !defined(__ELF__) -#define U_S "_" -#else -#define U_S -#endif - DVDcss_open = (dvdcss_handle (*)(const char*)) - dlsym(dvdcss_library, U_S "dvdcss_open"); - DVDcss_close = (int (*)(dvdcss_handle)) - dlsym(dvdcss_library, U_S "dvdcss_close"); - DVDcss_title = (int (*)(dvdcss_handle, int)) - dlsym(dvdcss_library, U_S "dvdcss_title"); - DVDcss_seek = (int (*)(dvdcss_handle, int, int)) - dlsym(dvdcss_library, U_S "dvdcss_seek"); - DVDcss_read = (int (*)(dvdcss_handle, void*, int, int)) - dlsym(dvdcss_library, U_S "dvdcss_read"); - DVDcss_error = (char* (*)(dvdcss_handle)) - dlsym(dvdcss_library, U_S "dvdcss_error"); - - 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 */ - - 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; - dvdinput_seek = css_seek; - dvdinput_title = css_title; - dvdinput_read = css_read; - dvdinput_error = css_error; - 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; - dvdinput_seek = file_seek; - dvdinput_title = file_title; - dvdinput_read = file_read; - dvdinput_error = file_error; - return 0; - } -} diff --git a/dvdread/dvd_input.h b/dvdread/dvd_input.h deleted file mode 100644 index bc9544d..0000000 --- a/dvdread/dvd_input.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -#ifndef DVD_INPUT_H_INCLUDED -#define DVD_INPUT_H_INCLUDED - -/* - * Copyright (C) 2001, 2002 Samuel Hocevar , - * Håkan Hjort - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. - */ - -/** - * Defines and flags. Make sure they fit the libdvdcss API! - */ -#define DVDINPUT_NOFLAGS 0 - -#define DVDINPUT_READ_DECRYPT (1 << 0) - -typedef struct dvd_input_s *dvd_input_t; - -/** - * Pointers which will be filled either the input methods functions. - */ -extern dvd_input_t (*dvdinput_open) (const char *); -extern int (*dvdinput_close) (dvd_input_t); -extern int (*dvdinput_seek) (dvd_input_t, int); -extern int (*dvdinput_title) (dvd_input_t, int); -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); - -#endif /* DVD_INPUT_H_INCLUDED */ diff --git a/dvdread/dvd_reader.c b/dvdread/dvd_reader.c deleted file mode 100644 index e07b757..0000000 --- a/dvdread/dvd_reader.c +++ /dev/null @@ -1,1614 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -/* - * Copyright (C) 2001, 2002, 2003 Billy Biggs , - * Håkan Hjort , - * Björn Englund - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. - */ - -#include "config.h" - -#include -#include -#include /* For the timing of dvdcss_title crack. */ -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__) || defined(__DARWIN__) || defined(__DragonFly__) -#define SYS_BSD 1 -#endif - -#if defined(__sun) -#include -#elif defined(SYS_BSD) -#include -#elif defined(__linux__) -#include -#endif - -#include "dvd_reader.h" -#include "dvd_input.h" -#include "dvd_udf.h" -#include "md5.h" - -#include "dvdread_internal.h" - -#define DEFAULT_UDF_CACHE_LEVEL 1 - -struct dvd_reader_s { - /* Basic information. */ - int isImageFile; - - /* Hack for keeping track of the css status. - * 0: no css, 1: perhaps (need init of keys), 2: have done init */ - int css_state; - int css_title; /* Last title that we have called dvdinpute_title for. */ - - /* Information required for an image file. */ - dvd_input_t dev; - - /* Information required for a directory path drive. */ - char *path_root; - - /* 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 { - /* Basic information. */ - dvd_reader_t *dvd; - - /* Hack for selecting the right css title. */ - int css_title; - - /* Information required for an image file. */ - uint32_t lb_start; - uint32_t seek_pos; - - /* Information required for a directory path drive. */ - size_t title_sizes[ 9 ]; - dvd_input_t title_devs[ 9 ]; - - /* Calculated at open-time, size in blocks. */ - 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) - * level = 1 (caching filesystem info) - */ -int DVDUDFCacheLevel(dvd_reader_t *device, int level) -{ - struct dvd_reader_s *dev = (struct dvd_reader_s *)device; - - if(level > 0) { - level = 1; - } else if(level < 0) { - return dev->udfcache_level; - } - - dev->udfcache_level = level; - - return level; -} - -void *GetUDFCacheHandle(dvd_reader_t *device) -{ - struct dvd_reader_s *dev = (struct dvd_reader_s *)device; - - return dev->udfcache; -} - -void SetUDFCacheHandle(dvd_reader_t *device, void *cache) -{ - struct dvd_reader_s *dev = (struct dvd_reader_s *)device; - - 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 -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. */ -static int initAllCSSKeys( dvd_reader_t *dvd ) -{ - struct timeval all_s, all_e; - struct timeval t_s, t_e; - char filename[ MAX_UDF_FILE_NAME_LEN ]; - uint32_t start, len; - int title; - - char *nokeys_str = getenv("DVDREAD_NOKEYS"); - 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++ ) { - gettimeofday( &t_s, NULL ); - if( title == 0 ) { - sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); - } else { - sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 ); - } - 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; - - gettimeofday( &t_s, NULL ); - sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 ); - start = UDFFindFile( dvd, filename, &len ); - 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; -} - - - -/** - * 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 ) { - 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 ) { - int tmp_errno = errno; - dvdinput_close(dev); - errno = tmp_errno; - return NULL; - } - dvd->verbose = verbose; - dvd->isImageFile = 1; - dvd->dev = dev; - 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 - * don't have that information. */ - - dvd->css_state = 1; /* Need key init. */ - } - 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; -} - -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 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 */ - - return dvd; -} - -#if defined(__sun) -/* /dev/rdsk/c0t6d0s0 (link to /devices/...) - /vol/dev/rdsk/c0t6d0/?? - /vol/rdsk/ */ -static char *sun_block2char( const char *path ) -{ - char *new_path; - - /* Must contain "/dsk/" */ - if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path ); - - /* Replace "/dsk/" with "/rdsk/" */ - new_path = malloc( strlen(path) + 2 ); - strcpy( new_path, path ); - strcpy( strstr( new_path, "/dsk/" ), "" ); - strcat( new_path, "/rdsk/" ); - strcat( new_path, strstr( path, "/dsk/" ) + strlen( "/dsk/" ) ); - - return new_path; -} -#endif - -#if defined(SYS_BSD) -/* FreeBSD /dev/(r)(a)cd0c (a is for atapi), recomended to _not_ use r - update: FreeBSD and DragonFly no longer uses the prefix so don't add it. - - OpenBSD /dev/rcd0c, it needs to be the raw device - NetBSD /dev/rcd0[d|c|..] d for x86, c (for non x86), perhaps others - Darwin /dev/rdisk0, it needs to be the raw device - BSD/OS /dev/sr0c (if not mounted) or /dev/rsr0c ('c' any letter will do) - - returns a string allocated with strdup which should be free()'d when - no longer used. -*/ -static char *bsd_block2char( const char *path ) -{ -#if defined(__FreeBSD__) || defined(__DragonFly__) - return (char *) strdup( path ); -#else - char *new_path; - - /* If it doesn't start with "/dev/" or does start with "/dev/r" exit */ - if( strncmp( path, "/dev/", 5 ) || !strncmp( path, "/dev/r", 6 ) ) - return (char *) strdup( path ); - - /* Replace "/dev/" with "/dev/r" */ - new_path = malloc( strlen(path) + 2 ); - strcpy( new_path, "/dev/r" ); - strcat( new_path, path + strlen( "/dev/" ) ); - - return new_path; -#endif /* __FreeBSD__ || __DragonFly__ */ -} -#endif - - -dvd_reader_t *DVDOpen( const char *path ) -{ - struct stat fileinfo; - int ret, have_css; - char *dev_name = NULL; - int internal_errno = 0; - int verbose; - - if( path == NULL ) { - errno = EINVAL; - return NULL; - } - - verbose = get_verbose(); - -#ifdef WIN32 - /* Stat doesn't work on devices under mingwin/cygwin. */ - if( path[0] && path[1] == ':' && path[2] == '\0' ) - { - /* Don't try to stat the file */ - fileinfo.st_mode = S_IFBLK; - } - else -#endif - { - ret = stat( path, &fileinfo ); - if( ret < 0 ) { - int tmp_errno = errno; - /* If we can't stat the file, give up */ - if(verbose >= 1) { - fprintf( stderr, "libdvdread: Can't stat '%s': %s\n", - path, strerror(errno)); - } - errno = tmp_errno; - return NULL; - } - } - - /* Try to open libdvdcss or fall back to standard functions */ - have_css = dvdinput_setup(); - - /* First check if this is a block/char device or a file*/ - if( S_ISBLK( fileinfo.st_mode ) || - S_ISCHR( fileinfo.st_mode ) || - S_ISREG( fileinfo.st_mode ) ) { - /** - * Block devices and regular files are assumed to be DVD-Video images. - */ - dvd_reader_t *dvd = NULL; -#if defined(__sun) - dev_name = sun_block2char( path ); -#elif defined(SYS_BSD) - dev_name = bsd_block2char( path ); -#else - dev_name = strdup( path ); -#endif - dvd = DVDOpenImageFile( dev_name, have_css ); - free( dev_name ); - - return dvd; - } else if( S_ISDIR( fileinfo.st_mode ) ) { - dvd_reader_t *auth_drive = 0; - char *path_copy; -#if defined(SYS_BSD) - struct fstab* fe; -#elif defined(__sun) || defined(__linux__) - FILE *mntfile; -#endif - - /* 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; - char *current_path; - - 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 = 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 - * is the mountpoint for a DVD-ROM which we can use instead. - */ - - if( strlen( path_copy ) > 1 ) { - if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) { - path_copy[ strlen( path_copy ) - 1 ] = '\0'; - } - } - - 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%s\n", - dev_name, - 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" ); - if( mntfile ) { - struct mnttab mp; - int res; - - 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%s\n", - dev_name, - mp.mnt_mountp, - have_css ? " for CSS authentication" : ""); - } - auth_drive = DVDOpenImageFile( dev_name, have_css ); - if(!auth_drive) { - internal_errno = errno; - } - break; - } - } - fclose( mntfile ); - } -#elif defined(__linux__) - mntfile = fopen( MOUNTED, "r" ); - if( mntfile ) { - struct mntent *me; - - 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%s\n", - me->mnt_fsname, - 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; - } - } - fclose( mntfile ); - } -#endif - if( !dev_name ) { - if(verbose >= 1) { - fprintf( stderr, "libdvdread: Couldn't find device name.\n" ); - } - } else if( !auth_drive ) { - 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 ); - free( path_copy ); - - /** - * If we've opened a drive, just use that. - */ - if( auth_drive ) { - return auth_drive; - } - /** - * Otherwise, we now try to open the directory tree instead. - */ - return DVDOpenPath( path ); - } - - /* If it's none of the above, screw it. */ - if(verbose >= 1) { - fprintf( stderr, "libdvdread: Could not open %s\n", path ); - } - return 0; -} - -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, dvd->udfcache ); - if(dvd->align) { - if(dvd->verbose >= 0) { - fprintf(stderr, "libdvdread: DVDClose(): Memory leak in align functions\n"); - } - } - - free( dvd ); - } -} - -void DVDInit(void) -{ - dvdinput_setup(); -} - -void DVDFinish(void) -{ - dvdinput_free(); -} - -/** - * Open an unencrypted file on a DVD image file. - */ -static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename ) -{ - uint32_t start, len; - dvd_file_t *dvd_file; - - start = UDFFindFile( dvd, filename, &len ); - if( !start ) return 0; - - dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); - if( !dvd_file ) return 0; - dvd_file->dvd = dvd; - dvd_file->lb_start = start; - dvd_file->seek_pos = 0; - memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); - memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); - dvd_file->filesize = len / DVD_VIDEO_LB_LEN; - - return dvd_file; -} - -/** - * Searches for in directory , ignoring case. - * Returns 0 and full filename in . - * or -1 on file not found. - * or -2 on path not found. - */ -static int findDirFile( const char *path, const char *file, char *filename ) -{ - DIR *dir; - struct dirent *ent; - - dir = opendir( path ); - if( !dir ) return -2; - - while( ( ent = readdir( dir ) ) != NULL ) { - if( !strcasecmp( ent->d_name, file ) ) { - sprintf( filename, "%s%s%s", path, - ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ), - ent->d_name ); - closedir(dir); - return 0; - } - } - closedir(dir); - return -1; -} - -static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename ) -{ - char video_path[ PATH_MAX + 1 ]; - const char *nodirfile; - int ret; - - /* Strip off the directory for our search */ - if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) { - nodirfile = &(file[ 10 ]); - } else { - nodirfile = file; - } - - ret = findDirFile( dvd->path_root, nodirfile, filename ); - if( ret < 0 ) { - /* Try also with adding the path, just in case. */ - sprintf( video_path, "%s/VIDEO_TS/", dvd->path_root ); - ret = findDirFile( video_path, nodirfile, filename ); - if( ret < 0 ) { - /* Try with the path, but in lower case. */ - sprintf( video_path, "%s/video_ts/", dvd->path_root ); - ret = findDirFile( video_path, nodirfile, filename ); - if( ret < 0 ) { - return 0; - } - } - } - - return 1; -} - -/** - * Open an unencrypted file from a DVD directory tree. - */ -static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename ) -{ - char full_path[ PATH_MAX + 1 ]; - dvd_file_t *dvd_file; - struct stat fileinfo; - dvd_input_t dev; - - /* Get the full path of the file. */ - if( !findDVDFile( dvd, filename, full_path ) ) return 0; - - dev = dvdinput_open( full_path ); - if( !dev ) return 0; - - dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); - if( !dvd_file ) return 0; - dvd_file->dvd = dvd; - dvd_file->lb_start = 0; - dvd_file->seek_pos = 0; - memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); - memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); - 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; - } - dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; - dvd_file->title_devs[ 0 ] = dev; - dvd_file->filesize = dvd_file->title_sizes[ 0 ]; - - return dvd_file; -} - -static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu ) -{ - char filename[ MAX_UDF_FILE_NAME_LEN ]; - uint32_t start, len; - dvd_file_t *dvd_file; - - if( title == 0 ) { - sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); - } else { - sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); - } - start = UDFFindFile( dvd, filename, &len ); - if( start == 0 ) return 0; - - dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); - if( !dvd_file ) return 0; - dvd_file->dvd = dvd; - /*Hack*/ dvd_file->css_title = title << 1 | menu; - dvd_file->lb_start = start; - dvd_file->seek_pos = 0; - memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); - memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); - dvd_file->filesize = len / DVD_VIDEO_LB_LEN; - - /* Calculate the complete file size for every file in the VOBS */ - if( !menu ) { - int cur; - - for( cur = 2; cur < 10; cur++ ) { - sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur ); - if( !UDFFindFile( dvd, filename, &len ) ) break; - dvd_file->filesize += len / DVD_VIDEO_LB_LEN; - } - } - - if( dvd->css_state == 1 /* Need key init */ ) { - initAllCSSKeys( dvd ); - dvd->css_state = 2; - } - /* - if( dvdinput_title( dvd_file->dvd->dev, (int)start ) < 0 ) { - fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n", - filename ); - } - */ - - return dvd_file; -} - -static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu ) -{ - char filename[ MAX_UDF_FILE_NAME_LEN ]; - char full_path[ PATH_MAX + 1 ]; - struct stat fileinfo; - dvd_file_t *dvd_file; - int i; - - dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); - if( !dvd_file ) return 0; - dvd_file->dvd = dvd; - /*Hack*/ dvd_file->css_title = title << 1 | menu; - dvd_file->lb_start = 0; - dvd_file->seek_pos = 0; - memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); - memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); - dvd_file->filesize = 0; - - if( menu ) { - dvd_input_t dev; - - if( title == 0 ) { - sprintf( filename, "VIDEO_TS.VOB" ); - } else { - sprintf( filename, "VTS_%02i_0.VOB", title ); - } - if( !findDVDFile( dvd, filename, full_path ) ) { - free( dvd_file ); - return 0; - } - - dev = dvdinput_open( full_path ); - if( dev == NULL ) { - free( dvd_file ); - return 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; - } - dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; - dvd_file->title_devs[ 0 ] = dev; - dvdinput_title( dvd_file->title_devs[0], 0); - dvd_file->filesize = dvd_file->title_sizes[ 0 ]; - - } else { - for( i = 0; i < 9; ++i ) { - - sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 ); - if( !findDVDFile( dvd, filename, full_path ) ) { - break; - } - - if( stat( full_path, &fileinfo ) < 0 ) { - if(dvd->verbose >= 1) { - fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); - } - break; - } - - dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; - dvd_file->title_devs[ i ] = dvdinput_open( full_path ); - dvdinput_title( dvd_file->title_devs[ i ], 0 ); - dvd_file->filesize += dvd_file->title_sizes[ i ]; - } - if( !dvd_file->title_devs[ 0 ] ) { - free( dvd_file ); - return 0; - } - } - - return dvd_file; -} - -dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum, - dvd_read_domain_t domain ) -{ - char filename[ MAX_UDF_FILE_NAME_LEN ]; - - /* Check arguments. */ - if( dvd == NULL || titlenum < 0 ) { - errno = EINVAL; - return NULL; - } - - switch( domain ) { - case DVD_READ_INFO_FILE: - if( titlenum == 0 ) { - sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" ); - } else { - sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum ); - } - break; - case DVD_READ_INFO_BACKUP_FILE: - if( titlenum == 0 ) { - sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" ); - } else { - sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum ); - } - break; - case DVD_READ_MENU_VOBS: - if( dvd->isImageFile ) { - return DVDOpenVOBUDF( dvd, titlenum, 1 ); - } else { - return DVDOpenVOBPath( dvd, titlenum, 1 ); - } - break; - case DVD_READ_TITLE_VOBS: - if( titlenum == 0 ) return 0; - if( dvd->isImageFile ) { - return DVDOpenVOBUDF( dvd, titlenum, 0 ); - } else { - return DVDOpenVOBPath( dvd, titlenum, 0 ); - } - break; - default: - if(dvd->verbose >= 1) { - fprintf( stderr, "libdvdread: Invalid domain for file open.\n" ); - } - errno = EINVAL; - return NULL; - } - - if( dvd->isImageFile ) { - return DVDOpenFileUDF( dvd, filename ); - } else { - return DVDOpenFilePath( dvd, filename ); - } -} - -void DVDCloseFile( dvd_file_t *dvd_file ) -{ - int i; - - if( dvd_file ) { - if( dvd_file->dvd->isImageFile ) { - ; - } else { - for( i = 0; i < 9; ++i ) { - if( dvd_file->title_devs[ i ] ) { - dvdinput_close( dvd_file->title_devs[i] ); - } - } - } - - free( dvd_file ); - dvd_file = 0; - } -} - -static int DVDFileStatVOBUDF(dvd_reader_t *dvd, int title, - int menu, dvd_stat_t *statbuf) -{ - char filename[ MAX_UDF_FILE_NAME_LEN ]; - uint32_t size; - off_t tot_size; - off_t parts_size[9]; - int nr_parts = 0; - int n; - - if( title == 0 ) { - sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); - } else { - sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); - } - if(!UDFFindFile( dvd, filename, &size )) { - return -1; - } - tot_size = size; - nr_parts = 1; - parts_size[0] = size; - - if( !menu ) { - int cur; - - for( cur = 2; cur < 10; cur++ ) { - sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur ); - if( !UDFFindFile( dvd, filename, &size ) ) { - break; - } - parts_size[nr_parts] = size; - tot_size += size; - nr_parts++; - } - } - - statbuf->size = tot_size; - statbuf->nr_parts = nr_parts; - for(n = 0; n < nr_parts; n++) { - statbuf->parts_size[n] = parts_size[n]; - } - return 0; -} - - -static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title, - int menu, dvd_stat_t *statbuf ) -{ - char filename[ MAX_UDF_FILE_NAME_LEN ]; - char full_path[ PATH_MAX + 1 ]; - struct stat fileinfo; - off_t tot_size; - off_t parts_size[9]; - int nr_parts = 0; - int n; - - - - if( title == 0 ) { - sprintf( filename, "VIDEO_TS.VOB" ); - } else { - sprintf( filename, "VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); - } - if( !findDVDFile( dvd, filename, full_path ) ) { - return -1; - } - - if( stat( full_path, &fileinfo ) < 0 ) { - if(dvd->verbose >= 1) { - fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); - } - return -1; - } - - - tot_size = fileinfo.st_size; - nr_parts = 1; - parts_size[0] = fileinfo.st_size; - - if( !menu ) { - int cur; - - for( cur = 2; cur < 10; cur++ ) { - - sprintf( filename, "VTS_%02d_%d.VOB", title, cur ); - if( !findDVDFile( dvd, filename, full_path ) ) { - break; - } - - if( stat( full_path, &fileinfo ) < 0 ) { - if(dvd->verbose >= 1) { - fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); - } - break; - } - - parts_size[nr_parts] = fileinfo.st_size; - tot_size += parts_size[nr_parts]; - nr_parts++; - } - } - - statbuf->size = tot_size; - statbuf->nr_parts = nr_parts; - for(n = 0; n < nr_parts; n++) { - statbuf->parts_size[n] = parts_size[n]; - } - return 0; -} - - -int DVDFileStat(dvd_reader_t *dvd, int titlenum, - dvd_read_domain_t domain, dvd_stat_t *statbuf) -{ - char filename[ MAX_UDF_FILE_NAME_LEN ]; - char full_path[ PATH_MAX + 1 ]; - struct stat fileinfo; - uint32_t size; - - /* Check arguments. */ - if( dvd == NULL || titlenum < 0 ) { - errno = EINVAL; - return -1; - } - - switch( domain ) { - case DVD_READ_INFO_FILE: - if( titlenum == 0 ) { - sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" ); - } else { - sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum ); - } - break; - case DVD_READ_INFO_BACKUP_FILE: - if( titlenum == 0 ) { - sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" ); - } else { - sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum ); - } - break; - case DVD_READ_MENU_VOBS: - if( dvd->isImageFile ) { - return DVDFileStatVOBUDF( dvd, titlenum, 1, statbuf ); - } else { - return DVDFileStatVOBPath( dvd, titlenum, 1, statbuf ); - } - break; - case DVD_READ_TITLE_VOBS: - if( titlenum == 0 ) { - return -1; - } - if( dvd->isImageFile ) { - return DVDFileStatVOBUDF( dvd, titlenum, 0, statbuf ); - } else { - return DVDFileStatVOBPath( dvd, titlenum, 0, statbuf ); - } - break; - default: - if(dvd->verbose >= 1) { - fprintf( stderr, "libdvdread: Invalid domain for file stat.\n" ); - } - errno = EINVAL; - return -1; - } - - if( dvd->isImageFile ) { - if( UDFFindFile( dvd, filename, &size ) ) { - statbuf->size = size; - statbuf->nr_parts = 1; - statbuf->parts_size[0] = size; - return 0; - } - } else { - if( findDVDFile( dvd, filename, full_path ) ) { - if( stat( full_path, &fileinfo ) < 0 ) { - if(dvd->verbose >= 1) { - fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); - } - } else { - statbuf->size = fileinfo.st_size; - statbuf->nr_parts = 1; - statbuf->parts_size[0] = statbuf->size; - return 0; - } - } - } - return -1; -} - -/** - * 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 ) -{ - 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 ) { - if(device->verbose >= 1) { - fprintf( stderr, - "libdvdread: UDFReadBlocksRaw: Can't seek to block %u\n", - lb_number ); - } - return 0; - } - - return dvdinput_read( device->dev, (char *) data, - (int) block_count, encrypted ); -} - -/** - * 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. - * - * @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 ) -{ - return UDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset, - block_count, data, encrypted ); -} - -/** - * This is using possibly several inputs and starting from an offset of '0'. - * 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. - * - * @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 ) -{ - int i; - int ret, ret2, off; - - ret = 0; - ret2 = 0; - for( i = 0; i < 9; ++i ) { - if( !dvd_file->title_sizes[ i ] ) return 0; /* Past end of file */ - - if( offset < dvd_file->title_sizes[ i ] ) { - 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 ) { - 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, - (int)block_count, encrypted ); - break; - } else { - size_t part1_size = dvd_file->title_sizes[ i ] - offset; - /* FIXME: Really needs to be a while loop. - * (This is only true if you try and read >1GB at a time) */ - - /* Read part 1 */ - off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); - if( off < 0 || off != (int)offset ) { - 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, - (int)part1_size, encrypted ); - if( ret < 0 ) return ret; - /* FIXME: This is wrong if i is the last file in the set. - * also error from this read will not show in ret. */ - - /* Does the next part exist? If not then return now. */ - if( !dvd_file->title_devs[ i + 1 ] ) return ret; - - /* Read part 2 */ - off = dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 ); - if( off < 0 || off != 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 ], - data + ( part1_size - * (int64_t)DVD_VIDEO_LB_LEN ), - (int)(block_count - part1_size), - encrypted ); - if( ret2 < 0 ) return ret2; - break; - } - } else { - offset -= dvd_file->title_sizes[ i ]; - } - } - - return ret + ret2; -} - -/** - * 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 ) -{ - int ret; - - /* Check arguments. */ - if( dvd_file == NULL || offset < 0 || data == NULL ) - return -1; - - /* Hack, and it will still fail for multiple opens in a threaded app ! */ - if( dvd_file->dvd->css_title != dvd_file->css_title ) { - dvd_file->dvd->css_title = dvd_file->css_title; - if( dvd_file->dvd->isImageFile ) { - dvdinput_title( dvd_file->dvd->dev, (int)dvd_file->lb_start ); - } - /* Here each vobu has it's own dvdcss handle, so no need to update - else { - dvdinput_title( dvd_file->title_devs[ 0 ], (int)dvd_file->lb_start ); - }*/ - } - - if( dvd_file->dvd->isImageFile ) { - ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset, - block_count, data, DVDINPUT_READ_DECRYPT ); - } else { - ret = DVDReadBlocksPath( dvd_file, (unsigned int)offset, - block_count, data, DVDINPUT_READ_DECRYPT ); - } - - return (ssize_t)ret; -} - -int DVDFileSeek( dvd_file_t *dvd_file, int offset ) -{ - /* Check arguments. */ - if( dvd_file == NULL || offset < 0 ) - return -1; - - if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) { - return -1; - } - dvd_file->seek_pos = (uint32_t) 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_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 ) { - 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 ); - - /* 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 ); - } else { - ret = DVDReadBlocksPath( dvd_file, seek_sector, - (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); - } - - if( ret != (int) numsec ) { - free( secbuf_start ); - return ret < 0 ? ret : 0; - } - - memcpy( data, &(secbuf[ seek_byte ]), byte_size ); - free( secbuf_start ); - - dvd_file->seek_pos += byte_size; - return byte_size; -} - -ssize_t DVDFileSize( dvd_file_t *dvd_file ) -{ - /* Check arguments. */ - if( dvd_file == NULL ) - return -1; - - return dvd_file->filesize; -} - -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 ) { - 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 ); - for( title = 0; title < 10; title++ ) { - dvd_file_t *dvd_file = DVDOpenFile( dvd, title, DVD_READ_INFO_FILE ); - if( dvd_file != NULL ) { - ssize_t bytes_read; - size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN; - char *buffer = malloc( file_size ); - - nr_of_files++; - - if( buffer == NULL ) { - /* 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", (int)bytes_read, (int)file_size ); - } - free(buffer); - DVDCloseFile( dvd_file ); - errno = tmp_errno; - return -1; - } - - md5_process_bytes( buffer, file_size, &ctx ); - - 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; -} - - -int DVDISOVolumeInfo( dvd_reader_t *dvd, - char *volid, unsigned int volid_size, - unsigned char *volsetid, unsigned int volsetid_size ) -{ - unsigned char *buffer; /* must be aligned to 2048 for raw/O_DIRECT */ - unsigned char *buffer_start; - int ret; - - /* Check arguments. */ - if( dvd == NULL ) { - errno = EINVAL; - return -1; - } - - 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; - } - - if( (volid != NULL) && (volid_size > 0) ) { - unsigned int n; - for(n = 0; n < 32; n++) { - if(buffer[40+n] == 0x20) { - break; - } - } - - if(volid_size > n+1) { - volid_size = n+1; - } - - memcpy(volid, &buffer[40], volid_size-1); - volid[volid_size-1] = '\0'; - } - - if( (volsetid != NULL) && (volsetid_size > 0) ) { - if(volsetid_size > 128) { - volsetid_size = 128; - } - memcpy(volsetid, &buffer[190], volsetid_size); - } - free(buffer_start); - - return 0; -} - - -int DVDUDFVolumeInfo( dvd_reader_t *dvd, - char *volid, unsigned int volid_size, - unsigned char *volsetid, unsigned int volsetid_size ) -{ - int ret; - /* Check arguments. */ - if( dvd == NULL ) - return -1; - - if( dvd->dev == NULL ) { - /* No block access, so no UDF VolumeSet Identifier */ - return -1; - } - - if( (volid != NULL) && (volid_size > 0) ) { - ret = UDFGetVolumeIdentifier(dvd, volid, volid_size); - if(!ret) { - return -1; - } - } - if( (volsetid != NULL) && (volsetid_size > 0) ) { - ret = UDFGetVolumeSetIdentifier(dvd, volsetid, volsetid_size); - if(!ret) { - return -1; - } - } - - return 0; -} diff --git a/dvdread/dvd_reader.h b/dvdread/dvd_reader.h deleted file mode 100644 index d666e8a..0000000 --- a/dvdread/dvd_reader.h +++ /dev/null @@ -1,344 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -#ifndef DVD_READER_H_INCLUDED -#define DVD_READER_H_INCLUDED - -/* - * Copyright (C) 2001, 2002 Billy Biggs , - * Håkan Hjort , - * Björn Englund - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -/** - * The DVD access interface. - * - * This file contains the functions that form the interface to to - * reading files located on a DVD. - */ - -/** - * The current version. (0.9.4 => 904, 1.2.3 => 10203) - */ -#define DVDREAD_VERSION 907 - - -/** - * The length of one Logical Block of a DVD. - */ -#define DVD_VIDEO_LB_LEN 2048 - -/** - * Maximum length of filenames allowed in UDF. - */ -#define MAX_UDF_FILE_NAME_LEN 2048 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Opaque type that is used as a handle for one instance of an opened DVD. - */ -typedef struct dvd_reader_s dvd_reader_t; - -/** - * Opaque type for a file read handle, much like a normal fd or FILE *. - */ -typedef struct dvd_file_s dvd_file_t; - -/** - * Returns the compiled version. (DVDREAD_VERSION as an int) - */ -int DVDVersion(void); - - -/** - * Opens a block device of a DVD-ROM file, or an image file, or a directory - * name for a mounted DVD or HD copy of a DVD. - * - * If the given file is a block device, or is the mountpoint for a block - * device, then that device is used for CSS authentication using libdvdcss. - * If no device is available, then no CSS authentication is performed, - * and we hope that the image is decrypted. - * - * If the path given is a directory, then the files in that directory may be - * in any one of these formats: - * - * path/VIDEO_TS/VTS_01_1.VOB - * path/video_ts/vts_01_1.vob - * path/VTS_01_1.VOB - * path/vts_01_1.vob - * - * @param path Specifies the the device, file or directory to be used. - * @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 * ); - -/** - * Closes and cleans up the DVD reader object. - * - * You must close all open files before calling this function. - * - * @param dvd A read handle that should be closed. - * - * DVDClose(dvd); - */ -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 { - DVD_READ_INFO_FILE, /**< VIDEO_TS.IFO or VTS_XX_0.IFO (title) */ - DVD_READ_INFO_BACKUP_FILE, /**< VIDEO_TS.BUP or VTS_XX_0.BUP (title) */ - DVD_READ_MENU_VOBS, /**< VIDEO_TS.VOB or VTS_XX_0.VOB (title) */ - DVD_READ_TITLE_VOBS /**< VTS_XX_[1-9].VOB (title). All files in - the title set are opened and read as a - single file. */ -} dvd_read_domain_t; - -/** - * - */ -typedef struct { - off_t size; /**< Total size of file in bytes */ - int nr_parts; /**< Number of file parts */ - off_t parts_size[9]; /**< Size of each part in bytes */ -} dvd_stat_t; - -/** - * Stats a file on the DVD given the title number and domain. - * The information about the file is stored in a dvd_stat_t - * which contains information about the size of the file and - * the number of parts in case of a multipart file and the respective - * sizes of the parts. - * A multipart file is for instance VTS_02_1.VOB, VTS_02_2.VOB, VTS_02_3.VOB - * The size of VTS_02_1.VOB will be stored in stat->parts_size[0], - * VTS_02_2.VOB in stat->parts_size[1], ... - * The total size (sum of all parts) is stored in stat->size and - * stat->nr_parts will hold the number of parts. - * Only DVD_READ_TITLE_VOBS (VTS_??_[1-9].VOB) can be multipart files. - * - * This function is only of use if you want to get the size of each file - * in the filesystem. These sizes are not needed to use any other - * functions in libdvdread. - * - * @param dvd A dvd read handle. - * @param titlenum Which Video Title Set should be used, VIDEO_TS is 0. - * @param domain Which domain. - * @param stat Pointer to where the result is stored. - * @return If successful 0, otherwise -1. - * - * int DVDFileStat(dvd, titlenum, domain, stat); - */ -int DVDFileStat(dvd_reader_t *, int, dvd_read_domain_t, dvd_stat_t *); - -/** - * Opens a file on the DVD given the title number and domain. - * - * If the title number is 0, the video manager information is opened - * (VIDEO_TS.[IFO,BUP,VOB]). Returns a file structure which may be - * used for reads, or 0 if the file was not found. - * - * @param dvd A dvd read handle. - * @param titlenum Which Video Title Set should be used, VIDEO_TS is 0. - * @param domain Which domain. - * @return If successful a a file read handle is returned, otherwise 0. - * - * dvd_file = DVDOpenFile(dvd, titlenum, domain); */ -dvd_file_t *DVDOpenFile( dvd_reader_t *, int, dvd_read_domain_t ); - -/** - * Closes a file and frees the associated structure. - * - * @param dvd_file The file read handle to be closed. - * - * DVDCloseFile(dvd_file); - */ -void DVDCloseFile( dvd_file_t * ); - -/** - * Reads block_count number of blocks from the file at the given block offset. - * Returns number of blocks read on success, -1 on error. This call is only - * for reading VOB data, and should not be used when reading the IFO files. - * When reading from an encrypted drive, blocks are decrypted using libdvdcss - * where required. - * - * @param dvd_file A file read handle. - * @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); - */ -ssize_t DVDReadBlocks( dvd_file_t *, int, size_t, unsigned char * ); - -/** - * Seek to the given position in the file. Returns the resulting position in - * bytes from the beginning of the file. The seek position is only used for - * byte reads from the file, the block read call always reads from the given - * offset. - * - * @param dvd_file A file read handle. - * @param seek_offset Byte offset from the start of the file to seek to. - * @return The resulting position in bytes from the beginning of the file. - * - * offset_set = DVDFileSeek(dvd_file, seek_offset); - */ -int DVDFileSeek( dvd_file_t *, int ); - -/** - * Reads the given number of bytes from the file. This call can only be used - * on the information files, and may not be used for reading from a VOB. This - * reads from and increments the currrent seek position for the file. - * - * @param dvd_file A file read handle. - * @param data Pointer to a buffer to write the data into. - * @param bytes Number of bytes to read. - * @return Returns number of bytes read on success, -1 on error. - * - * bytes_read = DVDReadBytes(dvd_file, data, bytes); - */ -ssize_t DVDReadBytes( dvd_file_t *, void *, size_t ); - -/** - * Returns the file size in blocks. - * - * @param dvd_file A file read handle. - * @return The size of the file in blocks, -1 on error. - * - * blocks = DVDFileSize(dvd_file); - */ -ssize_t DVDFileSize( dvd_file_t * ); - -/** - * Get a unique 128 bit disc ID. - * This is the MD5 sum of VIDEO_TS.IFO and the VTS_0?_0.IFO files - * in title order (those that exist). - * If you need a 'text' representation of the id, print it as a - * hexadecimal number, using lowercase letters, discid[0] first. - * I.e. the same format as the command-line 'md5sum' program uses. - * - * @param dvd A read handle to get the disc ID from - * @param discid The buffer to put the disc ID into. The buffer must - * have room for 128 bits (16 chars). - * @return 0 on success, -1 on error. - */ -int DVDDiscID( dvd_reader_t *, unsigned char * ); - -/** - * Get the UDF VolumeIdentifier and VolumeSetIdentifier - * from the PrimaryVolumeDescriptor. - * - * @param dvd A read handle to get the disc ID from - * @param volid The buffer to put the VolumeIdentifier into. - * The VolumeIdentifier is latin-1 encoded (8bit unicode) - * null terminated and max 32 bytes (including '\0') - * @param volid_size No more than volid_size bytes will be copied to volid. - * If the VolumeIdentifier is truncated because of this - * it will still be null terminated. - * @param volsetid The buffer to put the VolumeSetIdentifier into. - * The VolumeIdentifier is 128 bytes as - * stored in the UDF PrimaryVolumeDescriptor. - * Note that this is not a null terminated string. - * @param volsetid_size At most volsetid_size bytes will be copied to volsetid. - * @return 0 on success, -1 on error. - */ -int DVDUDFVolumeInfo( dvd_reader_t *, char *, unsigned int, - unsigned char *, unsigned int ); - -/** - * Get the ISO9660 VolumeIdentifier and VolumeSetIdentifier - * - * * Only use this function as fallback if DVDUDFVolumeInfo returns 0 * - * * this will happen on a disc mastered only with a iso9660 filesystem * - * * All video DVD discs have UDF filesystem * - * - * @param dvd A read handle to get the disc ID from - * @param volid The buffer to put the VolumeIdentifier into. - * The VolumeIdentifier is coded with '0-9','A-Z','_' - * null terminated and max 33 bytes (including '\0') - * @param volid_size No more than volid_size bytes will be copied to volid. - * If the VolumeIdentifier is truncated because of this - * it will still be null terminated. - * @param volsetid The buffer to put the VolumeSetIdentifier into. - * The VolumeIdentifier is 128 bytes as - * stored in the ISO9660 PrimaryVolumeDescriptor. - * Note that this is not a null terminated string. - * @param volsetid_size At most volsetid_size bytes will be copied to volsetid. - * @return 0 on success, -1 on error. - */ -int DVDISOVolumeInfo( dvd_reader_t *, char *, unsigned int, - unsigned char *, unsigned int ); - -/** - * Sets the level of caching that is done when reading from a device - * - * @param dvd A read handle to get the disc ID from - * @param level The level of caching wanted. - * -1 - returns the current setting. - * 0 - UDF Cache turned off. - * 1 - (default level) Pointers to IFO files and some data from - * PrimaryVolumeDescriptor are cached. - * - * @return The level of caching. - */ -int DVDUDFCacheLevel( dvd_reader_t *, int ); - -#ifdef __cplusplus -}; -#endif -#endif /* DVD_READER_H_INCLUDED */ diff --git a/dvdread/dvd_udf.c b/dvdread/dvd_udf.c deleted file mode 100644 index cfd4f10..0000000 --- a/dvdread/dvd_udf.c +++ /dev/null @@ -1,1216 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -/* - * This code is based on dvdudf by: - * Christian Wolff . - * - * Modifications by: - * Billy Biggs . - * Björn Englund . - * - * dvdudf: parse and read the UDF volume information of a DVD Video - * Copyright (C) 1999 Christian Wolff for convergence integrated media - * GmbH The author can be reached at scarabaeus@convergence.de, the - * project's page is at http://linuxtv.org/dvd/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. Or, point your browser to - * http://www.gnu.org/copyleft/gpl.html - */ - -#include "config.h" - -#include -#include -#include - -#include -#include -#include -#include - -#if defined(HAVE_INTTYPES_H) -#include -#elif defined(HAVE_STDINT_H) -#include -#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 ); - -/** @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 ) -{ - int ret; - size_t count = block_count; - - while(count > 0) { - - ret = UDFReadBlocksRaw(device, lb_number, count, data, encrypted); - - if(ret <= 0) { - /* One of the reads failed or nothing more to read, too bad. - * We won't even bother returning the reads that went ok. */ - return ret; - } - - count -= (size_t)ret; - lb_number += (uint32_t)ret; - } - - return block_count; -} - - -#ifndef NULL -#define NULL ((void *)0) -#endif - -struct Partition { - int valid; - char VolumeDesc[128]; - uint16_t Flags; - uint16_t Number; - char Contents[32]; - uint32_t AccessType; - uint32_t Start; - uint32_t Length; -}; - -struct AD { - uint32_t Location; - uint32_t Length; - uint8_t Flags; - uint16_t Partition; -}; - -struct extent_ad { - uint32_t location; - uint32_t length; -}; - -struct avdp_t { - struct extent_ad mvds; - struct extent_ad rvds; -}; - -struct pvd_t { - uint8_t VolumeIdentifier[32]; - uint8_t VolumeSetIdentifier[128]; -}; - -struct lbudf { - uint32_t lb; - uint8_t *data; -}; - -struct icbmap { - uint32_t lbn; - struct AD file; - uint8_t filetype; -}; - -struct udf_cache { - int avdp_valid; - struct avdp_t avdp; - int pvd_valid; - struct pvd_t pvd; - int partition_valid; - struct Partition partition; - int rooticb_valid; - struct AD rooticb; - int lb_num; - struct lbudf *lbs; - int map_num; - struct icbmap *maps; -}; - -typedef enum { - PartitionCache, RootICBCache, LBUDFCache, MapCache, AVDPCache, PVDCache -} UDFCacheType; - -extern void *GetUDFCacheHandle(dvd_reader_t *device); -extern void SetUDFCacheHandle(dvd_reader_t *device, 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); - } - if(c->maps) { - free(c->maps); - } - free(c); -} - - -static int GetUDFCache(dvd_reader_t *device, UDFCacheType type, - uint32_t nr, void *data) -{ - int n; - struct udf_cache *c; - - if(DVDUDFCacheLevel(device, -1) <= 0) { - return 0; - } - - c = (struct udf_cache *)GetUDFCacheHandle(device); - - if(c == NULL) { - return 0; - } - - switch(type) { - case AVDPCache: - if(c->avdp_valid) { - *(struct avdp_t *)data = c->avdp; - return 1; - } - break; - case PVDCache: - if(c->pvd_valid) { - *(struct pvd_t *)data = c->pvd; - return 1; - } - break; - case PartitionCache: - if(c->partition_valid) { - *(struct Partition *)data = c->partition; - return 1; - } - break; - case RootICBCache: - if(c->rooticb_valid) { - *(struct AD *)data = c->rooticb; - return 1; - } - break; - case LBUDFCache: - for(n = 0; n < c->lb_num; n++) { - if(c->lbs[n].lb == nr) { - *(uint8_t **)data = c->lbs[n].data; - return 1; - } - } - break; - case MapCache: - for(n = 0; n < c->map_num; n++) { - if(c->maps[n].lbn == nr) { - *(struct icbmap *)data = c->maps[n]; - return 1; - } - } - break; - default: - break; - } - - return 0; -} - -static int SetUDFCache(dvd_reader_t *device, UDFCacheType type, - uint32_t nr, void *data) -{ - int n; - struct udf_cache *c; - - if(DVDUDFCacheLevel(device, -1) <= 0) { - return 0; - } - - c = (struct udf_cache *)GetUDFCacheHandle(device); - - if(c == NULL) { - c = calloc(1, sizeof(struct udf_cache)); - /* fprintf(stderr, "calloc: %d\n", sizeof(struct udf_cache)); */ - if(c == NULL) { - return 0; - } - SetUDFCacheHandle(device, c); - } - - - switch(type) { - case AVDPCache: - c->avdp = *(struct avdp_t *)data; - c->avdp_valid = 1; - break; - case PVDCache: - c->pvd = *(struct pvd_t *)data; - c->pvd_valid = 1; - break; - case PartitionCache: - c->partition = *(struct Partition *)data; - c->partition_valid = 1; - break; - case RootICBCache: - c->rooticb = *(struct AD *)data; - c->rooticb_valid = 1; - break; - case LBUDFCache: - for(n = 0; n < c->lb_num; n++) { - if(c->lbs[n].lb == nr) { - /* replace with new data */ - c->lbs[n].data = *(uint8_t **)data; - c->lbs[n].lb = nr; - return 1; - } - } - c->lb_num++; - c->lbs = realloc(c->lbs, c->lb_num * sizeof(struct lbudf)); - /* - fprintf(stderr, "realloc lb: %d * %d = %d\n", - c->lb_num, sizeof(struct lbudf), - c->lb_num * sizeof(struct lbudf)); - */ - if(c->lbs == NULL) { - c->lb_num = 0; - return 0; - } - c->lbs[n].data = *(uint8_t **)data; - c->lbs[n].lb = nr; - break; - case MapCache: - for(n = 0; n < c->map_num; n++) { - if(c->maps[n].lbn == nr) { - /* replace with new data */ - c->maps[n] = *(struct icbmap *)data; - c->maps[n].lbn = nr; - return 1; - } - } - c->map_num++; - c->maps = realloc(c->maps, c->map_num * sizeof(struct icbmap)); - /* - fprintf(stderr, "realloc maps: %d * %d = %d\n", - c->map_num, sizeof(struct icbmap), - c->map_num * sizeof(struct icbmap)); - */ - if(c->maps == NULL) { - c->map_num = 0; - return 0; - } - c->maps[n] = *(struct icbmap *)data; - c->maps[n].lbn = nr; - break; - default: - return 0; - } - - return 1; -} - - -/* For direct data access, LSB first */ -#define GETN1(p) ((uint8_t)data[p]) -#define GETN2(p) ((uint16_t)data[p] | ((uint16_t)data[(p) + 1] << 8)) -#define GETN3(p) ((uint32_t)data[p] | ((uint32_t)data[(p) + 1] << 8) \ - | ((uint32_t)data[(p) + 2] << 16)) -#define GETN4(p) ((uint32_t)data[p] \ - | ((uint32_t)data[(p) + 1] << 8) \ - | ((uint32_t)data[(p) + 2] << 16) \ - | ((uint32_t)data[(p) + 3] << 24)) -/* This is wrong with regard to endianess */ -#define GETN(p, n, target) memcpy(target, &data[p], n) - -static int Unicodedecode( uint8_t *data, int len, char *target ) -{ - int p = 1, i = 0; - - if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do { - if( data[ 0 ] == 16 ) p++; /* Ignore MSB of unicode16 */ - if( p < len ) { - target[ i++ ] = data[ p++ ]; - } - } while( p < len ); - - target[ i ] = '\0'; - return 0; -} - -static int UDFDescriptor( uint8_t *data, uint16_t *TagID ) -{ - *TagID = GETN2(0); - return 0; -} - -static int UDFExtentAD( uint8_t *data, uint32_t *Length, uint32_t *Location ) -{ - *Length = GETN4(0); - *Location = GETN4(4); - return 0; -} - -static int UDFShortAD( uint8_t *data, struct AD *ad, - struct Partition *partition ) -{ - ad->Length = GETN4(0); - ad->Flags = ad->Length >> 30; - ad->Length &= 0x3FFFFFFF; - ad->Location = GETN4(4); - ad->Partition = partition->Number; /* use number of current partition*/ - return 0; -} - -static int UDFLongAD( uint8_t *data, struct AD *ad ) -{ - ad->Length = GETN4(0); - ad->Flags = ad->Length >> 30; - ad->Length &= 0x3FFFFFFF; - ad->Location = GETN4(4); - ad->Partition = GETN2(8); - /*GETN(10, 6, Use);*/ - return 0; -} - -static int UDFExtAD( uint8_t *data, struct AD *ad ) -{ - ad->Length = GETN4(0); - ad->Flags = ad->Length >> 30; - ad->Length &= 0x3FFFFFFF; - ad->Location = GETN4(12); - ad->Partition = GETN2(16); - /*GETN(10, 6, Use);*/ - return 0; -} - -static int UDFICB( uint8_t *data, uint8_t *FileType, uint16_t *Flags ) -{ - *FileType = GETN1(11); - *Flags = GETN2(18); - return 0; -} - - -static int UDFPartition( uint8_t *data, uint16_t *Flags, uint16_t *Number, - char *Contents, uint32_t *Start, uint32_t *Length ) -{ - *Flags = GETN2(20); - *Number = GETN2(22); - GETN(24, 32, Contents); - *Start = GETN4(188); - *Length = GETN4(192); - return 0; -} - -/** - * Reads the volume descriptor and checks the parameters. Returns 0 on OK, 1 - * on error. - */ -static int UDFLogVolume( uint8_t *data, char *VolumeDescriptor ) -{ - uint32_t lbsize, MT_L, N_PM; - Unicodedecode(&data[84], 128, VolumeDescriptor); - lbsize = GETN4(212); /* should be 2048*/ - MT_L = GETN4(264); /* should be 6 */ - N_PM = GETN4(268); /* should be 1 */ - if (lbsize != DVD_VIDEO_LB_LEN) return 1; - return 0; -} - -static int UDFFileEntry( uint8_t *data, uint8_t *FileType, - struct Partition *partition, struct AD *ad ) -{ - uint16_t flags; - uint32_t L_EA, L_AD; - unsigned int p; - - UDFICB( &data[ 16 ], FileType, &flags ); - - /* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */ - ad->Length = GETN4( 60 ); /* Really 8 bytes a 56*/ - ad->Flags = 0; - ad->Location = 0; /* what should we put here? */ - ad->Partition = partition->Number; /* use number of current partition*/ - - L_EA = GETN4( 168 ); - L_AD = GETN4( 172 ); - p = 176 + L_EA; - while( p < 176 + L_EA + L_AD ) { - switch( flags & 0x0007 ) { - case 0: UDFShortAD( &data[ p ], ad, partition ); p += 8; break; - case 1: UDFLongAD( &data[ p ], ad ); p += 16; break; - case 2: UDFExtAD( &data[ p ], ad ); p += 20; break; - case 3: - switch( L_AD ) { - case 8: UDFShortAD( &data[ p ], ad, partition ); break; - case 16: UDFLongAD( &data[ p ], ad ); break; - case 20: UDFExtAD( &data[ p ], ad ); break; - } - p += L_AD; - break; - default: - p += L_AD; break; - } - } - return 0; -} - -static int UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristics, - char *FileName, struct AD *FileICB ) -{ - uint8_t L_FI; - uint16_t L_IU; - - *FileCharacteristics = GETN1(18); - L_FI = GETN1(19); - UDFLongAD(&data[20], FileICB); - L_IU = GETN2(36); - if (L_FI) Unicodedecode(&data[38 + L_IU], L_FI, FileName); - else FileName[0] = '\0'; - return 4 * ((38 + L_FI + L_IU + 3) / 4); -} - -/** - * Maps ICB to FileAD - * ICB: Location of ICB of directory to scan - * FileType: Type of the file - * File: Location of file the ICB is pointing to - * return 1 on success, 0 on error; - */ -static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType, - struct Partition *partition, struct AD *File ) -{ - uint8_t *LogBlock; - uint32_t lbnum; - uint16_t TagID; - struct icbmap tmpmap; - - lbnum = partition->Start + ICB.Location; - tmpmap.lbn = lbnum; - if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) { - *FileType = tmpmap.filetype; - *File = tmpmap.file; - return 1; - } - - LogBlock = dvdalign_lbmalloc(device, 1); - if(!LogBlock) { - return 0; - } - - do { - if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { - TagID = 0; - } else { - UDFDescriptor( LogBlock, &TagID ); - } - - if( TagID == 261 ) { - UDFFileEntry( LogBlock, FileType, partition, File ); - 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; -} - -/** - * Dir: Location of directory to scan - * FileName: Name of file to look for - * FileICB: Location of ICB of the found file - * return 1 on success, 0 on error; - */ -static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName, - struct Partition *partition, struct AD *FileICB, - int cache_file_info) -{ - char filename[ MAX_UDF_FILE_NAME_LEN ]; - uint8_t *directory; - uint32_t lbnum; - uint16_t TagID; - uint8_t filechar; - unsigned int p; - uint8_t *cached_dir = NULL; - uint32_t dir_lba; - struct AD tmpICB; - int found = 0; - int in_cache = 0; - - /* Scan dir for ICB of file */ - lbnum = partition->Start + Dir.Location; - - if(DVDUDFCacheLevel(device, -1) > 0) { - /* caching */ - - if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) { - dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN; - if((cached_dir = dvdalign_lbmalloc(device, dir_lba)) == NULL) { - return 0; - } - if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) { - dvdalign_lbfree(device, cached_dir); - cached_dir = NULL; - } - SetUDFCache(device, LBUDFCache, lbnum, &cached_dir); - } else { - in_cache = 1; - } - - if(cached_dir == NULL) { - return 0; - } - - p = 0; - - while( p < Dir.Length ) { - UDFDescriptor( &cached_dir[ p ], &TagID ); - if( TagID == 257 ) { - p += UDFFileIdentifier( &cached_dir[ p ], &filechar, - filename, &tmpICB ); - if(cache_file_info && !in_cache) { - uint8_t tmpFiletype; - struct AD tmpFile; - - if( !strcasecmp( FileName, filename ) ) { - *FileICB = tmpICB; - found = 1; - - } - UDFMapICB(device, tmpICB, &tmpFiletype, - partition, &tmpFile); - } else { - if( !strcasecmp( FileName, filename ) ) { - *FileICB = tmpICB; - return 1; - } - } - } else { - if(cache_file_info && (!in_cache) && found) { - return 1; - } - return 0; - } - } - if(cache_file_info && (!in_cache) && found) { - return 1; - } - 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; - } - - p = 0; - while( p < Dir.Length ) { - if( p > DVD_VIDEO_LB_LEN ) { - ++lbnum; - 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; - } - } - UDFDescriptor( &directory[ p ], &TagID ); - if( TagID == 257 ) { - 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; -} - - -static int UDFGetAVDP( dvd_reader_t *device, - struct avdp_t *avdp) -{ - uint8_t *Anchor; - uint32_t lbnum, MVDS_location, MVDS_length; - uint16_t TagID; - uint32_t lastsector; - int terminate; - struct avdp_t; - - if(GetUDFCache(device, AVDPCache, 0, avdp)) { - return 1; - } - - /* Find Anchor */ - lastsector = 0; - 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 ); - } else { - TagID = 0; - } - if (TagID != 2) { - /* Not an anchor */ - 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. - */ - lbnum = lastsector; - terminate = 1; - } else { - /* TODO: Find last sector of the disc (this is optional). */ - if( lastsector ) { - /* Try #2, backup anchor */ - lbnum = lastsector - 256; - } else { - /* Unable to find last sector */ - dvdalign_lbfree(device, Anchor); - errno = EMEDIUMTYPE; - return 0; - } - } - } else { - /* It's an anchor! We can leave */ - break; - } - } - /* Main volume descriptor */ - UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location ); - avdp->mvds.location = MVDS_location; - avdp->mvds.length = MVDS_length; - - /* Backup volume descriptor */ - UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location ); - avdp->rvds.location = MVDS_location; - avdp->rvds.length = MVDS_length; - - SetUDFCache(device, AVDPCache, 0, avdp); - - dvdalign_lbfree(device, Anchor); - return 1; -} - -/** - * Looks for partition on the disc. Returns 1 if partition found, 0 on error. - * partnum: Number of the partition, starting at 0. - * part: structure to fill with the partition information - */ -static int UDFFindPartition( dvd_reader_t *device, int partnum, - struct Partition *part ) -{ - uint8_t *LogBlock; - uint32_t lbnum, MVDS_location, MVDS_length; - uint16_t TagID; - int i, volvalid; - struct avdp_t avdp; - - - if(!UDFGetAVDP(device, &avdp)) { - return 0; - } - - LogBlock = dvdalign_lbmalloc(device, 1); - if(!LogBlock) { - return 0; - } - /* Main volume descriptor */ - MVDS_location = avdp.mvds.location; - MVDS_length = avdp.mvds.length; - - part->valid = 0; - volvalid = 0; - part->VolumeDesc[ 0 ] = '\0'; - i = 1; - do { - /* Find Volume Descriptor */ - lbnum = MVDS_location; - do { - - if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { - TagID = 0; - } else { - UDFDescriptor( LogBlock, &TagID ); - } - - if( ( TagID == 5 ) && ( !part->valid ) ) { - /* Partition Descriptor */ - UDFPartition( LogBlock, &part->Flags, &part->Number, - part->Contents, &part->Start, &part->Length ); - part->valid = ( partnum == part->Number ); - } else if( ( TagID == 6 ) && ( !volvalid ) ) { - /* Logical Volume Descriptor */ - if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) { - /* TODO: sector size wrong! */ - } else { - volvalid = 1; - } - } - - } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) - / DVD_VIDEO_LB_LEN ) && ( TagID != 8 ) - && ( ( !part->valid ) || ( !volvalid ) ) ); - - if( ( !part->valid) || ( !volvalid ) ) { - /* Backup volume descriptor */ - MVDS_location = avdp.mvds.location; - MVDS_length = avdp.mvds.length; - } - } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) ); - - dvdalign_lbfree(device, LogBlock); - /* We only care for the partition, not the volume */ - return part->valid; -} - -uint32_t UDFFindFile( dvd_reader_t *device, char *filename, - uint32_t *filesize ) -{ - uint8_t *LogBlock; - uint32_t lbnum; - uint16_t TagID; - struct Partition partition; - struct AD RootICB, File, ICB; - char tokenline[ MAX_UDF_FILE_NAME_LEN ]; - char *token; - uint8_t filetype; - - if(filesize) { - *filesize = 0; - } - tokenline[0] = '\0'; - strcat( tokenline, 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; - } - SetUDFCache(device, PartitionCache, 0, &partition); - - LogBlock = dvdalign_lbmalloc(device, 1); - if(!LogBlock) { - return 0; - } - /* Find root dir ICB */ - lbnum = partition.Start; - do { - if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { - TagID = 0; - } else { - UDFDescriptor( LogBlock, &TagID ); - } - - /* File Set Descriptor */ - if( TagID == 256 ) { /* File Set Descriptor*/ - UDFLongAD( &LogBlock[ 400 ], &RootICB ); - } - } 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; - } - 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 */ - } - { - int cache_file_info = 0; - /* Tokenize filepath */ - token = strtok(tokenline, "/"); - - while( token != NULL ) { - - if( !UDFScanDir( device, File, token, &partition, &ICB, - cache_file_info)) { - return 0; - } - if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) { - return 0; - } - if(!strcmp(token, "VIDEO_TS")) { - cache_file_info = 1; - } - token = strtok( NULL, "/" ); - } - } - - /* Sanity check. */ - if( File.Partition != 0 ) { - return 0; - } - - if(filesize) { - *filesize = File.Length; - } - /* Hack to not return partition.Start for empty files. */ - if( !File.Location ) { - return 0; - } else { - return partition.Start + File.Location; - } -} - - - -/** - * 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) - * and aligned for raw/O_DIRECT read. - */ -static int UDFGetDescriptor( dvd_reader_t *device, int id, - uint8_t *descriptor, int bufsize) -{ - uint32_t lbnum, MVDS_location, MVDS_length; - struct avdp_t avdp; - uint16_t TagID; - uint32_t lastsector; - int i, terminate; - int desc_found = 0; - /* Find Anchor */ - lastsector = 0; - lbnum = 256; /* Try #1, prime anchor */ - terminate = 0; - if(bufsize < DVD_VIDEO_LB_LEN) { - return 0; - } - - if(!UDFGetAVDP(device, &avdp)) { - return 0; - } - - /* Main volume descriptor */ - MVDS_location = avdp.mvds.location; - MVDS_length = avdp.mvds.length; - - i = 1; - do { - /* Find Descriptor */ - lbnum = MVDS_location; - do { - - if( DVDReadLBUDF( device, lbnum++, 1, descriptor, 0 ) <= 0 ) { - TagID = 0; - } else { - UDFDescriptor( descriptor, &TagID ); - } - - if( (TagID == id) && ( !desc_found ) ) { - /* Descriptor */ - desc_found = 1; - } - } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) - / DVD_VIDEO_LB_LEN ) && ( TagID != 8 ) - && ( !desc_found) ); - - if( !desc_found ) { - /* Backup volume descriptor */ - MVDS_location = avdp.rvds.location; - MVDS_length = avdp.rvds.length; - } - } while( i-- && ( !desc_found ) ); - - - return desc_found; -} - - -static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd) -{ - uint8_t *pvd_buf; - - if(GetUDFCache(device, PVDCache, 0, pvd)) { - return 1; - } - - 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; - } - - memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32); - memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128); - SetUDFCache(device, PVDCache, 0, pvd); - - dvdalign_lbfree(device, pvd_buf); - - return 1; -} - -/** - * Gets the Volume Identifier string, in 8bit unicode (latin-1) - * volid, place to put the string - * volid_size, size of the buffer volid points to - * returns the size of buffer needed for all data - */ -int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid, - unsigned int volid_size) -{ - struct pvd_t pvd; - unsigned int volid_len; - - /* get primary volume descriptor */ - if(!UDFGetPVD(device, &pvd)) { - return 0; - } - - volid_len = pvd.VolumeIdentifier[31]; - if(volid_len > 31) { - /* this field is only 32 bytes something is wrong */ - volid_len = 31; - } - if(volid_size > volid_len) { - volid_size = volid_len; - } - Unicodedecode(pvd.VolumeIdentifier, volid_size, volid); - - return volid_len; -} - -/** - * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded) - * WARNING This is not a null terminated string - * volsetid, place to put the data - * volsetid_size, size of the buffer volsetid points to - * the buffer should be >=128 bytes to store the whole volumesetidentifier - * returns the size of the available volsetid information (128) - * or 0 on error - */ -int UDFGetVolumeSetIdentifier(dvd_reader_t *device, uint8_t *volsetid, - unsigned int volsetid_size) -{ - struct pvd_t pvd; - - /* get primary volume descriptor */ - if(!UDFGetPVD(device, &pvd)) { - return 0; - } - - - if(volsetid_size > 128) { - volsetid_size = 128; - } - - memcpy(volsetid, pvd.VolumeSetIdentifier, volsetid_size); - - return 128; -} diff --git a/dvdread/dvd_udf.h b/dvdread/dvd_udf.h deleted file mode 100644 index cf66ce4..0000000 --- a/dvdread/dvd_udf.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -#ifndef DVD_UDF_H_INCLUDED -#define DVD_UDF_H_INCLUDED - -/* - * This code is based on dvdudf by: - * Christian Wolff . - * - * Modifications by: - * Billy Biggs . - * Björn Englund . - * - * dvdudf: parse and read the UDF volume information of a DVD Video - * Copyright (C) 1999 Christian Wolff for convergence integrated media - * GmbH The author can be reached at scarabaeus@convergence.de, the - * project's page is at http://linuxtv.org/dvd/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. Or, point your browser to - * http://www.gnu.org/copyleft/gpl.html - */ - -#if defined(HAVE_INTTYPES_H) -#include -#elif defined(HAVE_STDINT_H) -#include -#endif - -#include "dvd_reader.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Looks for a file on the UDF disc/imagefile and returns the block number - * where it begins, or 0 if it is not found. The filename should be an - * absolute pathname on the UDF filesystem, starting with '/'. For example, - * '/VIDEO_TS/VTS_01_1.IFO'. On success, filesize will be set to the size of - * the file in bytes. - * This implementation relies on that the file size is less than 2^32 - * A DVD file can at most be 2^30 (-2048 ?). - */ -uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *size ); - -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, - uint8_t *volsetid, unsigned int volsetid_size); -#ifdef __cplusplus -}; -#endif -#endif /* DVD_UDF_H_INCLUDED */ diff --git a/dvdread/dvdread_internal.h b/dvdread/dvdread_internal.h deleted file mode 100644 index 995d491..0000000 --- a/dvdread/dvdread_internal.h +++ /dev/null @@ -1,18 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -#ifndef DVDREAD_INTERNAL_H -#define DVDREAD_INTERNAL_H - - -#define CHECK_VALUE(arg) \ - if(!(arg)) { \ - fprintf(stderr, "\n*** libdvdread: CHECK_VALUE failed in %s:%i ***" \ - "\n*** for %s ***\n\n", \ - __FILE__, __LINE__, # 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_read.c b/dvdread/ifo_read.c deleted file mode 100644 index ff2d78c..0000000 --- a/dvdread/ifo_read.c +++ /dev/null @@ -1,2181 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -/* - * Copyright (C) 2000, 2001, 2002, 2003 - * Björn Englund , - * Håkan Hjort - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include -#include - -#if defined(HAVE_INTTYPES_H) -#include -#elif defined(HAVE_STDINT_H) -#include -#endif - -#include -#include - -#include "bswap.h" -#include "ifo_types.h" -#include "ifo_read.h" -#include "dvd_reader.h" -#include "dvdread_internal.h" - -#ifndef DVD_BLOCK_LEN -#define DVD_BLOCK_LEN 2048 -#endif - -#ifndef NDEBUG -#define CHECK_ZERO0(arg) \ - if(arg != 0) { \ - fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x%x\n", \ - __FILE__, __LINE__, # arg, arg); \ - } -#define CHECK_ZERO(arg) \ - if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) { \ - unsigned int i_CZ; \ - fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x", \ - __FILE__, __LINE__, # arg ); \ - for(i_CZ = 0; i_CZ < sizeof(arg); i_CZ++) \ - fprintf(stderr, "%02x", *((uint8_t *)&arg + i_CZ)); \ - fprintf(stderr, "\n"); \ - } -static const uint8_t my_friendly_zeros[2048]; -#else -#define CHECK_ZERO0(arg) (void)(arg) -#define CHECK_ZERO(arg) (void)(arg) -#endif - - -/* Prototypes for internal functions */ -static int ifoRead_VMG(ifo_handle_t *ifofile); -static int ifoRead_VTS(ifo_handle_t *ifofile); -static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset); -static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile, - pgc_command_tbl_t *cmd_tbl, - unsigned int offset); -static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile, - pgc_program_map_t *program_map, - unsigned int nr, unsigned int offset); -static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile, - cell_playback_t *cell_playback, - unsigned int nr, unsigned int offset); -static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile, - cell_position_t *cell_position, - unsigned int nr, unsigned int offset); -static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, - vts_attributes_t *vts_attributes, - unsigned int offset); -static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, c_adt_t *c_adt, - unsigned int sector); -static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, - vobu_admap_t *vobu_admap, - unsigned int sector); -static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, - unsigned int offset); - -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 int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) { - return (DVDFileSeek(dvd_file, (int)offset) == (int)offset); -} - - -ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) { - ifo_handle_t *ifofile; - - 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_FILE); - 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(!ifoOpen_File(ifofile, title, "BUP")) { - if(title) { - if(dvdread_verbose(dvd) >= 1) { - fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.%s.\n", - title, "BUP"); - } - } else { - 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 NULL; - } - - /* First check if this is a VMGI file. */ - if(ifoRead_VMG(ifofile)) { - - /* These are both mandatory. */ - if(!ifoRead_FP_PGC(ifofile) || !ifoRead_TT_SRPT(ifofile)) { - if(dvdread_verbose(device_of_file(ifofile->file)) >= 0) { - fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.%s).\n", - suffix); - } - ifoClose(ifofile); - return NULL; - } - - ifoRead_PGCI_UT(ifofile); - ifoRead_PTL_MAIT(ifofile); - - /* This is also mandatory. */ - if(!ifoRead_VTS_ATRT(ifofile)) { - if(dvdread_verbose(device_of_file(ifofile->file)) >= 0) { - fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.%s).\n", - suffix); - } - ifoClose(ifofile); - return NULL; - } - - ifoRead_TXTDT_MGI(ifofile); - ifoRead_C_ADT(ifofile); - ifoRead_VOBU_ADMAP(ifofile); - - return ifofile; - } - - if(ifoRead_VTS(ifofile)) { - - if(!ifoRead_VTS_PTT_SRPT(ifofile) || !ifoRead_PGCIT(ifofile)) { - 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 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)) { - 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 NULL; - } - - return ifofile; - } - - if(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 { - if(dvdread_verbose(device_of_file(ifofile->file)) >= 0) { - fprintf(stderr, "libdvdread: Invalid IFO for VMGM (VIDEO_TS.%s).\n", - suffix); - } - } - ifoClose(ifofile); - return NULL; -} - - -ifo_handle_t *ifoOpenVMGI(dvd_reader_t *dvd) { - ifo_handle_t *ifofile; - - 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_FILE); - 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) { - free(ifofile); - return NULL; - } - - if(ifoRead_VMG(ifofile)) - return ifofile; - - if(dvdread_verbose(device_of_file(ifofile->file)) >= 0) { - fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.%s).\n", - suffix); - } - ifoClose(ifofile); - return NULL; -} - - -ifo_handle_t *ifoOpenVTSI(dvd_reader_t *dvd, int title) { - ifo_handle_t *ifofile; - - ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t)); - if(!ifofile) - 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); - errno = EINVAL; - return NULL; - } - - ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE); - 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) { - free(ifofile); - return NULL; - } - - ifoRead_VTS(ifofile); - if(ifofile->vtsi_mat) - return ifofile; - - 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 NULL; -} - - -void ifoClose(ifo_handle_t *ifofile) { - if(!ifofile) - return; - - ifoFree_VOBU_ADMAP(ifofile); - ifoFree_TITLE_VOBU_ADMAP(ifofile); - ifoFree_C_ADT(ifofile); - ifoFree_TITLE_C_ADT(ifofile); - ifoFree_TXTDT_MGI(ifofile); - ifoFree_VTS_ATRT(ifofile); - ifoFree_PTL_MAIT(ifofile); - ifoFree_PGCI_UT(ifofile); - ifoFree_TT_SRPT(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); - - if(ifofile->vtsi_mat) - free(ifofile->vtsi_mat); - - DVDCloseFile(ifofile->file); - ifofile->file = 0; - free(ifofile); - ifofile = 0; -} - - -static int ifoRead_VMG(ifo_handle_t *ifofile) { - vmgi_mat_t *vmgi_mat; - - vmgi_mat = (vmgi_mat_t *)malloc(sizeof(vmgi_mat_t)); - if(!vmgi_mat) - return 0; - - ifofile->vmgi_mat = vmgi_mat; - - if(!DVDFileSeek_(ifofile->file, 0)) { - free(ifofile->vmgi_mat); - ifofile->vmgi_mat = 0; - return 0; - } - - if(!DVDReadBytes(ifofile->file, vmgi_mat, sizeof(vmgi_mat_t))) { - free(ifofile->vmgi_mat); - ifofile->vmgi_mat = 0; - return 0; - } - - if(strncmp("DVDVIDEO-VMG", vmgi_mat->vmg_identifier, 12) != 0) { - free(ifofile->vmgi_mat); - ifofile->vmgi_mat = 0; - return 0; - } - - B2N_32(vmgi_mat->vmg_last_sector); - B2N_32(vmgi_mat->vmgi_last_sector); - B2N_32(vmgi_mat->vmg_category); - B2N_16(vmgi_mat->vmg_nr_of_volumes); - B2N_16(vmgi_mat->vmg_this_volume_nr); - B2N_16(vmgi_mat->vmg_nr_of_title_sets); - B2N_64(vmgi_mat->vmg_pos_code); - B2N_32(vmgi_mat->vmgi_last_byte); - B2N_32(vmgi_mat->first_play_pgc); - B2N_32(vmgi_mat->vmgm_vobs); - B2N_32(vmgi_mat->tt_srpt); - B2N_32(vmgi_mat->vmgm_pgci_ut); - B2N_32(vmgi_mat->ptl_mait); - B2N_32(vmgi_mat->vts_atrt); - B2N_32(vmgi_mat->txtdt_mgi); - B2N_32(vmgi_mat->vmgm_c_adt); - B2N_32(vmgi_mat->vmgm_vobu_admap); - B2N_16(vmgi_mat->vmgm_audio_attr.lang_code); - B2N_16(vmgi_mat->vmgm_subp_attr.lang_code); - - - CHECK_ZERO(vmgi_mat->zero_1); - CHECK_ZERO(vmgi_mat->zero_2); - CHECK_ZERO(vmgi_mat->zero_3); - CHECK_ZERO(vmgi_mat->zero_4); - CHECK_ZERO(vmgi_mat->zero_5); - CHECK_ZERO(vmgi_mat->zero_6); - CHECK_ZERO(vmgi_mat->zero_7); - CHECK_ZERO(vmgi_mat->zero_8); - CHECK_ZERO(vmgi_mat->zero_9); - CHECK_ZERO(vmgi_mat->zero_10); - CHECK_VALUE(vmgi_mat->vmg_last_sector != 0); - CHECK_VALUE(vmgi_mat->vmgi_last_sector != 0); - CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); - CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); - CHECK_VALUE(vmgi_mat->vmg_nr_of_volumes != 0); - CHECK_VALUE(vmgi_mat->vmg_this_volume_nr != 0); - CHECK_VALUE(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes); - CHECK_VALUE(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2); - CHECK_VALUE(vmgi_mat->vmg_nr_of_title_sets != 0); - CHECK_VALUE(vmgi_mat->vmgi_last_byte >= 341); - CHECK_VALUE(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <= - vmgi_mat->vmgi_last_sector); - /* It seems that first_play_pgc is optional. */ - CHECK_VALUE(vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte); - CHECK_VALUE(vmgi_mat->vmgm_vobs == 0 || - (vmgi_mat->vmgm_vobs > vmgi_mat->vmgi_last_sector && - vmgi_mat->vmgm_vobs < vmgi_mat->vmg_last_sector)); - CHECK_VALUE(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector); - CHECK_VALUE(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector); - CHECK_VALUE(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector); - CHECK_VALUE(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector); - CHECK_VALUE(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector); - CHECK_VALUE(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector); - CHECK_VALUE(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector); - - CHECK_VALUE(vmgi_mat->nr_of_vmgm_audio_streams <= 1); - CHECK_VALUE(vmgi_mat->nr_of_vmgm_subp_streams <= 1); - - return 1; -} - - -static int ifoRead_VTS(ifo_handle_t *ifofile) { - vtsi_mat_t *vtsi_mat; - int i; - - vtsi_mat = (vtsi_mat_t *)malloc(sizeof(vtsi_mat_t)); - if(!vtsi_mat) - return 0; - - ifofile->vtsi_mat = vtsi_mat; - - if(!DVDFileSeek_(ifofile->file, 0)) { - free(ifofile->vtsi_mat); - ifofile->vtsi_mat = 0; - return 0; - } - - if(!(DVDReadBytes(ifofile->file, vtsi_mat, sizeof(vtsi_mat_t)))) { - free(ifofile->vtsi_mat); - ifofile->vtsi_mat = 0; - return 0; - } - - if(strncmp("DVDVIDEO-VTS", vtsi_mat->vts_identifier, 12) != 0) { - free(ifofile->vtsi_mat); - ifofile->vtsi_mat = 0; - return 0; - } - - B2N_32(vtsi_mat->vts_last_sector); - B2N_32(vtsi_mat->vtsi_last_sector); - B2N_32(vtsi_mat->vts_category); - B2N_32(vtsi_mat->vtsi_last_byte); - B2N_32(vtsi_mat->vtsm_vobs); - B2N_32(vtsi_mat->vtstt_vobs); - B2N_32(vtsi_mat->vts_ptt_srpt); - B2N_32(vtsi_mat->vts_pgcit); - B2N_32(vtsi_mat->vtsm_pgci_ut); - B2N_32(vtsi_mat->vts_tmapt); - B2N_32(vtsi_mat->vtsm_c_adt); - B2N_32(vtsi_mat->vtsm_vobu_admap); - B2N_32(vtsi_mat->vts_c_adt); - B2N_32(vtsi_mat->vts_vobu_admap); - B2N_16(vtsi_mat->vtsm_audio_attr.lang_code); - B2N_16(vtsi_mat->vtsm_subp_attr.lang_code); - for(i = 0; i < 8; i++) - B2N_16(vtsi_mat->vts_audio_attr[i].lang_code); - for(i = 0; i < 32; i++) - B2N_16(vtsi_mat->vts_subp_attr[i].lang_code); - - - CHECK_ZERO(vtsi_mat->zero_1); - CHECK_ZERO(vtsi_mat->zero_2); - CHECK_ZERO(vtsi_mat->zero_3); - CHECK_ZERO(vtsi_mat->zero_4); - CHECK_ZERO(vtsi_mat->zero_5); - CHECK_ZERO(vtsi_mat->zero_6); - CHECK_ZERO(vtsi_mat->zero_7); - CHECK_ZERO(vtsi_mat->zero_8); - CHECK_ZERO(vtsi_mat->zero_9); - CHECK_ZERO(vtsi_mat->zero_10); - CHECK_ZERO(vtsi_mat->zero_11); - CHECK_ZERO(vtsi_mat->zero_12); - CHECK_ZERO(vtsi_mat->zero_13); - CHECK_ZERO(vtsi_mat->zero_14); - CHECK_ZERO(vtsi_mat->zero_15); - CHECK_ZERO(vtsi_mat->zero_16); - CHECK_ZERO(vtsi_mat->zero_17); - CHECK_ZERO(vtsi_mat->zero_18); - CHECK_ZERO(vtsi_mat->zero_19); - CHECK_ZERO(vtsi_mat->zero_20); - CHECK_ZERO(vtsi_mat->zero_21); - CHECK_VALUE(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector); - CHECK_VALUE(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector); - CHECK_VALUE(vtsi_mat->vtsm_vobs == 0 || - (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector && - vtsi_mat->vtsm_vobs < vtsi_mat->vts_last_sector)); - CHECK_VALUE(vtsi_mat->vtstt_vobs == 0 || - (vtsi_mat->vtstt_vobs > vtsi_mat->vtsi_last_sector && - vtsi_mat->vtstt_vobs < vtsi_mat->vts_last_sector)); - CHECK_VALUE(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector); - CHECK_VALUE(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector); - CHECK_VALUE(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector); - CHECK_VALUE(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector); - CHECK_VALUE(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector); - CHECK_VALUE(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector); - CHECK_VALUE(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector); - CHECK_VALUE(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector); - - CHECK_VALUE(vtsi_mat->nr_of_vtsm_audio_streams <= 1); - CHECK_VALUE(vtsi_mat->nr_of_vtsm_subp_streams <= 1); - - CHECK_VALUE(vtsi_mat->nr_of_vts_audio_streams <= 8); - for(i = vtsi_mat->nr_of_vts_audio_streams; i < 8; i++) - CHECK_ZERO(vtsi_mat->vts_audio_attr[i]); - - CHECK_VALUE(vtsi_mat->nr_of_vts_subp_streams <= 32); - for(i = vtsi_mat->nr_of_vts_subp_streams; i < 32; i++) - CHECK_ZERO(vtsi_mat->vts_subp_attr[i]); - - for(i = 0; i < 8; i++) { - CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero1); - CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero2); - CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero3); - CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero4); - CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero5); - CHECK_ZERO(vtsi_mat->vts_mu_audio_attr[i].zero6); - } - - return 1; -} - - -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)); - - if(!DVDFileSeek_(ifofile->file, offset)) - return 0; - - if(!(DVDReadBytes(ifofile->file, cmd_tbl, PGC_COMMAND_TBL_SIZE))) - return 0; - - 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); - - 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; - cmd_tbl->pre_cmds = (vm_cmd_t *)malloc(pre_cmds_size); - if(!cmd_tbl->pre_cmds) - return 0; - - if(!(DVDReadBytes(ifofile->file, cmd_tbl->pre_cmds, pre_cmds_size))) { - free(cmd_tbl->pre_cmds); - return 0; - } - } - - if(cmd_tbl->nr_of_post != 0) { - unsigned int post_cmds_size = cmd_tbl->nr_of_post * COMMAND_DATA_SIZE; - cmd_tbl->post_cmds = (vm_cmd_t *)malloc(post_cmds_size); - if(!cmd_tbl->post_cmds) { - if(cmd_tbl->pre_cmds) - free(cmd_tbl->pre_cmds); - return 0; - } - if(!(DVDReadBytes(ifofile->file, cmd_tbl->post_cmds, post_cmds_size))) { - if(cmd_tbl->pre_cmds) - free(cmd_tbl->pre_cmds); - free(cmd_tbl->post_cmds); - return 0; - } - } - - if(cmd_tbl->nr_of_cell != 0) { - unsigned int cell_cmds_size = cmd_tbl->nr_of_cell * COMMAND_DATA_SIZE; - cmd_tbl->cell_cmds = (vm_cmd_t *)malloc(cell_cmds_size); - if(!cmd_tbl->cell_cmds) { - if(cmd_tbl->pre_cmds) - free(cmd_tbl->pre_cmds); - if(cmd_tbl->post_cmds) - free(cmd_tbl->post_cmds); - return 0; - } - if(!(DVDReadBytes(ifofile->file, cmd_tbl->cell_cmds, cell_cmds_size))) { - if(cmd_tbl->pre_cmds) - free(cmd_tbl->pre_cmds); - if(cmd_tbl->post_cmds) - free(cmd_tbl->post_cmds); - free(cmd_tbl->cell_cmds); - return 0; - } - } - - /* - * Make a run over all the commands and see that we can interpret them all? - */ - return 1; -} - - -static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) { - if(cmd_tbl) { - if(cmd_tbl->nr_of_pre && cmd_tbl->pre_cmds) - free(cmd_tbl->pre_cmds); - if(cmd_tbl->nr_of_post && cmd_tbl->post_cmds) - free(cmd_tbl->post_cmds); - if(cmd_tbl->nr_of_cell && cmd_tbl->cell_cmds) - free(cmd_tbl->cell_cmds); - free(cmd_tbl); - } -} - -static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile, - pgc_program_map_t *program_map, - unsigned int nr, unsigned int offset) { - unsigned int size = nr * sizeof(pgc_program_map_t); - - if(!DVDFileSeek_(ifofile->file, offset)) - return 0; - - if(!(DVDReadBytes(ifofile->file, program_map, size))) - return 0; - - return 1; -} - -static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile, - cell_playback_t *cell_playback, - unsigned int nr, unsigned int offset) { - unsigned int i; - unsigned int size = nr * sizeof(cell_playback_t); - - if(!DVDFileSeek_(ifofile->file, offset)) - return 0; - - if(!(DVDReadBytes(ifofile->file, cell_playback, size))) - return 0; - - for(i = 0; i < nr; i++) { - B2N_32(cell_playback[i].first_sector); - B2N_32(cell_playback[i].first_ilvu_end_sector); - B2N_32(cell_playback[i].last_vobu_start_sector); - B2N_32(cell_playback[i].last_sector); - - /* Changed < to <= because this was false in the movie 'Pi'. */ - CHECK_VALUE(cell_playback[i].last_vobu_start_sector <= - cell_playback[i].last_sector); - CHECK_VALUE(cell_playback[i].first_sector <= - cell_playback[i].last_vobu_start_sector); - } - - return 1; -} - - -static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile, - cell_position_t *cell_position, - unsigned int nr, unsigned int offset) { - unsigned int i; - unsigned int size = nr * sizeof(cell_position_t); - - if(!DVDFileSeek_(ifofile->file, offset)) - return 0; - - if(!(DVDReadBytes(ifofile->file, cell_position, size))) - return 0; - - for(i = 0; i < nr; i++) { - B2N_16(cell_position[i].vob_id_nr); - CHECK_ZERO(cell_position[i].zero_1); - } - - return 1; -} - -static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { - unsigned int i; - - if(!DVDFileSeek_(ifofile->file, offset)) - return 0; - - if(!(DVDReadBytes(ifofile->file, pgc, PGC_SIZE))) - return 0; - - B2N_16(pgc->next_pgc_nr); - B2N_16(pgc->prev_pgc_nr); - B2N_16(pgc->goup_pgc_nr); - B2N_16(pgc->command_tbl_offset); - B2N_16(pgc->program_map_offset); - B2N_16(pgc->cell_playback_offset); - B2N_16(pgc->cell_position_offset); - - for(i = 0; i < 8; i++) - B2N_16(pgc->audio_control[i]); - for(i = 0; i < 32; i++) - B2N_32(pgc->subp_control[i]); - for(i = 0; i < 16; i++) - B2N_32(pgc->palette[i]); - - CHECK_ZERO(pgc->zero_1); - CHECK_VALUE(pgc->nr_of_programs <= pgc->nr_of_cells); - - /* verify time (look at print_time) */ - for(i = 0; i < 8; i++) - if(!pgc->audio_control[i] & 0x8000) /* The 'is present' bit */ - CHECK_ZERO(pgc->audio_control[i]); - for(i = 0; i < 32; i++) - if(!pgc->subp_control[i] & 0x80000000) /* The 'is present' bit */ - CHECK_ZERO(pgc->subp_control[i]); - - /* Check that time is 0:0:0:0 also if nr_of_programs == 0 */ - if(pgc->nr_of_programs == 0) { - CHECK_ZERO(pgc->still_time); - CHECK_ZERO(pgc->pg_playback_mode); /* ??*/ - CHECK_VALUE(pgc->program_map_offset == 0); - CHECK_VALUE(pgc->cell_playback_offset == 0); - CHECK_VALUE(pgc->cell_position_offset == 0); - } else { - CHECK_VALUE(pgc->program_map_offset != 0); - CHECK_VALUE(pgc->cell_playback_offset != 0); - CHECK_VALUE(pgc->cell_position_offset != 0); - } - - if(pgc->command_tbl_offset != 0) { - pgc->command_tbl = malloc(sizeof(pgc_command_tbl_t)); - if(!pgc->command_tbl) - return 0; - - if(!ifoRead_PGC_COMMAND_TBL(ifofile, pgc->command_tbl, - offset + pgc->command_tbl_offset)) { - free(pgc->command_tbl); - return 0; - } - } else { - pgc->command_tbl = NULL; - } - - 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); - return 0; - } - if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs, - offset + pgc->program_map_offset)) { - ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); - free(pgc->program_map); - return 0; - } - } 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); - if(pgc->program_map) - free(pgc->program_map); - return 0; - } - if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback, - pgc->nr_of_cells, - offset + pgc->cell_playback_offset)) { - ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); - if(pgc->program_map) - free(pgc->program_map); - free(pgc->cell_playback); - return 0; - } - } 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); - return 0; - } - if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position, - pgc->nr_of_cells, - offset + pgc->cell_position_offset)) { - ifoFree_PGC(pgc); - return 0; - } - } else { - pgc->cell_position = NULL; - } - } else { - pgc->cell_position = NULL; - } - - return 1; -} - -int ifoRead_FP_PGC(ifo_handle_t *ifofile) { - - if(!ifofile) - return 0; - - if(!ifofile->vmgi_mat) - return 0; - - /* It seems that first_play_pgc is optional after all. */ - ifofile->first_play_pgc = 0; - if(ifofile->vmgi_mat->first_play_pgc == 0) - return 1; - - ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t)); - if(!ifofile->first_play_pgc) - return 0; - - if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc, - ifofile->vmgi_mat->first_play_pgc)) { - free(ifofile->first_play_pgc); - ifofile->first_play_pgc = 0; - return 0; - } - - return 1; -} - -static void ifoFree_PGC(pgc_t *pgc) { - if(pgc) { - ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); - if(pgc->program_map) - free(pgc->program_map); - if(pgc->cell_playback) - free(pgc->cell_playback); - if(pgc->cell_position) - free(pgc->cell_position); - } -} - -void ifoFree_FP_PGC(ifo_handle_t *ifofile) { - if(!ifofile) - return; - - if(ifofile->first_play_pgc) { - ifoFree_PGC(ifofile->first_play_pgc); - free(ifofile->first_play_pgc); - ifofile->first_play_pgc = 0; - } -} - - -int ifoRead_TT_SRPT(ifo_handle_t *ifofile) { - tt_srpt_t *tt_srpt; - int i, info_length; - - if(!ifofile) - return 0; - - if(!ifofile->vmgi_mat) - return 0; - - if(ifofile->vmgi_mat->tt_srpt == 0) /* mandatory */ - return 0; - - if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN)) - return 0; - - tt_srpt = (tt_srpt_t *)malloc(sizeof(tt_srpt_t)); - if(!tt_srpt) - return 0; - - 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; - } - - B2N_16(tt_srpt->nr_of_srpts); - B2N_32(tt_srpt->last_byte); - - info_length = tt_srpt->last_byte + 1 - TT_SRPT_SIZE; - - tt_srpt->title = (title_info_t *)malloc(info_length); - if(!tt_srpt->title) { - free(tt_srpt); - ifofile->tt_srpt = 0; - 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; - } - - for(i = 0; i < tt_srpt->nr_of_srpts; i++) { - B2N_16(tt_srpt->title[i].nr_of_ptts); - B2N_16(tt_srpt->title[i].parental_id); - B2N_32(tt_srpt->title[i].title_set_sector); - } - - - CHECK_ZERO(tt_srpt->zero_1); - CHECK_VALUE(tt_srpt->nr_of_srpts != 0); - CHECK_VALUE(tt_srpt->nr_of_srpts < 100); /*??*/ - 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); - CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0); - CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10); - /*CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); - / XXX: this assertion breaks Ghostbusters:*/ - CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); /*??*/ - CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0); - CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); /* ?? */ - CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0); - CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); /* ?? */ - /*CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0);*/ - } - - /* Make this a function*/ -#if 0 - if(memcmp((uint8_t *)tt_srpt->title + - tt_srpt->nr_of_srpts * sizeof(title_info_t), - my_friendly_zeros, - info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t))) { - fprintf(stderr, "VMG_PTT_SRPT slack is != 0, "); - hexdump((uint8_t *)tt_srpt->title + - tt_srpt->nr_of_srpts * sizeof(title_info_t), - info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t)); - } -#endif - - return 1; -} - - -void ifoFree_TT_SRPT(ifo_handle_t *ifofile) { - if(!ifofile) - return; - - if(ifofile->tt_srpt) { - free(ifofile->tt_srpt->title); - free(ifofile->tt_srpt); - ifofile->tt_srpt = 0; - } -} - - -int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { - vts_ptt_srpt_t *vts_ptt_srpt; - int info_length, i, j; - uint32_t *data; - - if(!ifofile) - return 0; - - if(!ifofile->vtsi_mat) - return 0; - - if(ifofile->vtsi_mat->vts_ptt_srpt == 0) /* mandatory */ - return 0; - - if(!DVDFileSeek_(ifofile->file, - ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN)) - return 0; - - vts_ptt_srpt = (vts_ptt_srpt_t *)malloc(sizeof(vts_ptt_srpt_t)); - if(!vts_ptt_srpt) - return 0; - - 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; - } - - B2N_16(vts_ptt_srpt->nr_of_srpts); - B2N_32(vts_ptt_srpt->last_byte); - - CHECK_ZERO(vts_ptt_srpt->zero_1); - CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0); - CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); /* ??*/ - - info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE; - - data = (uint32_t *)malloc(info_length); - if(!data) { - free(vts_ptt_srpt); - ifofile->vts_ptt_srpt = 0; - 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; - return 0; - } - - for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { - B2N_32(data[i]); - /* assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); - Magic Knight Rayearth Daybreak is mastered very strange and has - Titles with 0 PTTs. They all have a data[i] offsets beyond the end of - of the vts_ptt_srpt structure. */ - CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4); - } - - vts_ptt_srpt->ttu_offset = data; - - vts_ptt_srpt->title = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t)); - if(!vts_ptt_srpt->title) { - free(vts_ptt_srpt); - free(data); - ifofile->vts_ptt_srpt = 0; - return 0; - } - for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { - int n; - if(i < vts_ptt_srpt->nr_of_srpts - 1) - n = (data[i+1] - data[i]); - else - n = (vts_ptt_srpt->last_byte + 1 - data[i]); - /* assert(n > 0 && (n % 4) == 0); - Magic Knight Rayearth Daybreak is mastered very strange and has - Titles with 0 PTTs. */ - if(n < 0) n = 0; - CHECK_VALUE(n % 4 == 0); - - vts_ptt_srpt->title[i].nr_of_ptts = n / 4; - vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t)); - if(!vts_ptt_srpt->title[i].ptt) { - for(n = 0; n < i; n++) - free(vts_ptt_srpt->title[n].ptt); - free(vts_ptt_srpt); - free(data); - ifofile->vts_ptt_srpt = 0; - return 0; - } - for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { - /* The assert placed here because of Magic Knight Rayearth Daybreak */ - CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); - vts_ptt_srpt->title[i].ptt[j].pgcn - = *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE); - vts_ptt_srpt->title[i].ptt[j].pgn - = *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE); - } - } - - for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { - for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { - B2N_16(vts_ptt_srpt->title[i].ptt[j].pgcn); - B2N_16(vts_ptt_srpt->title[i].ptt[j].pgn); - } - } - - for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { - CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ??*/ - for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { - CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 ); - CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ??*/ - CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0); - CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */ - } - } - - return 1; -} - - -void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) { - if(!ifofile) - return; - - if(ifofile->vts_ptt_srpt) { - int i; - for(i = 0; i < ifofile->vts_ptt_srpt->nr_of_srpts; i++) - free(ifofile->vts_ptt_srpt->title[i].ptt); - free(ifofile->vts_ptt_srpt->ttu_offset); - free(ifofile->vts_ptt_srpt->title); - free(ifofile->vts_ptt_srpt); - ifofile->vts_ptt_srpt = 0; - } -} - - -int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { - ptl_mait_t *ptl_mait; - int info_length; - unsigned int i, j; - - if(!ifofile) - return 0; - - if(!ifofile->vmgi_mat) - return 0; - - if(ifofile->vmgi_mat->ptl_mait == 0) - return 1; - - if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN)) - return 0; - - ptl_mait = (ptl_mait_t *)malloc(sizeof(ptl_mait_t)); - if(!ptl_mait) - return 0; - - ifofile->ptl_mait = ptl_mait; - - if(!(DVDReadBytes(ifofile->file, ptl_mait, PTL_MAIT_SIZE))) { - free(ptl_mait); - ifofile->ptl_mait = 0; - return 0; - } - - B2N_16(ptl_mait->nr_of_countries); - B2N_16(ptl_mait->nr_of_vtss); - B2N_32(ptl_mait->last_byte); - - CHECK_VALUE(ptl_mait->nr_of_countries != 0); - CHECK_VALUE(ptl_mait->nr_of_countries < 100); /* ?? */ - CHECK_VALUE(ptl_mait->nr_of_vtss != 0); - CHECK_VALUE(ptl_mait->nr_of_vtss < 100); /* ?? */ - CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE - <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE); - - info_length = ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t); - ptl_mait->countries = (ptl_mait_country_t *)malloc(info_length); - if(!ptl_mait->countries) { - free(ptl_mait); - ifofile->ptl_mait = 0; - return 0; - } - - 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; - return 0; - } - } - - for(i = 0; i < ptl_mait->nr_of_countries; i++) { - B2N_16(ptl_mait->countries[i].country_code); - B2N_16(ptl_mait->countries[i].pf_ptl_mai_start_byte); - } - - 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 + - 16U * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1U); - } - - for(i = 0; i < ptl_mait->nr_of_countries; i++) { - uint16_t *pf_temp; - - 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; - } - info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t); - pf_temp = (uint16_t *)malloc(info_length); - if(!pf_temp) { - for(j = 0; j < i ; j++) { - free(ptl_mait->countries[j].pf_ptl_mai); - } - free(ptl_mait->countries); - free(ptl_mait); - 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); - } - free(ptl_mait->countries); - free(ptl_mait); - return 0; - } - for (j = 0; j < ((ptl_mait->nr_of_vtss + 1) * 8); j++) { - B2N_16(pf_temp[j]); - } - ptl_mait->countries[i].pf_ptl_mai = (pf_level_t *)malloc(info_length); - if(!ptl_mait->countries[i].pf_ptl_mai) { - free(pf_temp); - for(j = 0; j < i ; j++) { - free(ptl_mait->countries[j].pf_ptl_mai); - } - free(ptl_mait->countries); - free(ptl_mait); - return 0; - } - { /* Transpose the array so we can use C indexing. */ - int level, vts; - for(level = 0; level < 8; level++) { - for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) { - ptl_mait->countries[i].pf_ptl_mai[vts][level] = - pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts]; - } - } - free(pf_temp); - } - } - return 1; -} - -void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) { - unsigned int i; - - if(!ifofile) - return; - - if(ifofile->ptl_mait) { - for(i = 0; i < ifofile->ptl_mait->nr_of_countries; i++) { - free(ifofile->ptl_mait->countries[i].pf_ptl_mai); - } - free(ifofile->ptl_mait->countries); - free(ifofile->ptl_mait); - ifofile->ptl_mait = 0; - } -} - -int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { - vts_tmapt_t *vts_tmapt; - uint32_t *vts_tmap_srp; - unsigned int offset; - int info_length; - unsigned int i, j; - - if(!ifofile) - return 0; - - if(!ifofile->vtsi_mat) - return 0; - - /* Seems to be optional, at least when there are no OneSequencial Titles */ - if(ifofile->vtsi_mat->vts_tmapt == 0) { - ifofile->vts_tmapt = NULL; - return 1; - } - - offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN; - - if(!DVDFileSeek_(ifofile->file, offset)) - return 0; - - vts_tmapt = (vts_tmapt_t *)malloc(sizeof(vts_tmapt_t)); - if(!vts_tmapt) - return 0; - - 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; - } - - B2N_16(vts_tmapt->nr_of_tmaps); - B2N_32(vts_tmapt->last_byte); - - CHECK_ZERO(vts_tmapt->zero_1); - - info_length = vts_tmapt->nr_of_tmaps * 4; - - vts_tmap_srp = (uint32_t *)malloc(info_length); - if(!vts_tmap_srp) { - free(vts_tmapt); - ifofile->vts_tmapt = NULL; - return 0; - } - - 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; - return 0; - } - - for (i = 0; i < vts_tmapt->nr_of_tmaps; i++) { - B2N_32(vts_tmap_srp[i]); - } - - - info_length = vts_tmapt->nr_of_tmaps * sizeof(vts_tmap_t); - - vts_tmapt->tmap = (vts_tmap_t *)malloc(info_length); - if(!vts_tmapt->tmap) { - free(vts_tmap_srp); - free(vts_tmapt); - ifofile->vts_tmapt = NULL; - return 0; - } - - memset(vts_tmapt->tmap, 0, info_length); /* So ifoFree_VTS_TMAPT works. */ - - for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) { - if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) { - ifoFree_VTS_TMAPT(ifofile); - return 0; - } - - 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; - } - - B2N_16(vts_tmapt->tmap[i].nr_of_entries); - CHECK_ZERO(vts_tmapt->tmap[i].zero_1); - - if(vts_tmapt->tmap[i].nr_of_entries == 0) { /* Early out if zero entries */ - vts_tmapt->tmap[i].map_ent = NULL; - continue; - } - - info_length = vts_tmapt->tmap[i].nr_of_entries * sizeof(map_ent_t); - - vts_tmapt->tmap[i].map_ent = (map_ent_t *)malloc(info_length); - if(!vts_tmapt->tmap[i].map_ent) { - ifoFree_VTS_TMAPT(ifofile); - return 0; - } - - 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; - } - - for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) - B2N_32(vts_tmapt->tmap[i].map_ent[j]); - } - - return 1; -} - -void ifoFree_VTS_TMAPT(ifo_handle_t *ifofile) { - unsigned int i; - - if(!ifofile) - return; - - if(ifofile->vts_tmapt) { - for(i = 0; i < ifofile->vts_tmapt->nr_of_tmaps; i++) - if(ifofile->vts_tmapt->tmap[i].map_ent) - free(ifofile->vts_tmapt->tmap[i].map_ent); - free(ifofile->vts_tmapt->tmap); - free(ifofile->vts_tmapt->tmap_offset); - free(ifofile->vts_tmapt); - ifofile->vts_tmapt = NULL; - } -} - - -int ifoRead_TITLE_C_ADT(ifo_handle_t *ifofile) { - - if(!ifofile) - return 0; - - if(!ifofile->vtsi_mat) - return 0; - - if(ifofile->vtsi_mat->vts_c_adt == 0) /* mandatory */ - return 0; - - ifofile->vts_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t)); - if(!ifofile->vts_c_adt) - return 0; - - if(!ifoRead_C_ADT_internal(ifofile, ifofile->vts_c_adt, - ifofile->vtsi_mat->vts_c_adt)) { - free(ifofile->vts_c_adt); - ifofile->vts_c_adt = 0; - return 0; - } - - return 1; -} - -int ifoRead_C_ADT(ifo_handle_t *ifofile) { - unsigned int sector; - - if(!ifofile) - return 0; - - if(ifofile->vmgi_mat) { - if(ifofile->vmgi_mat->vmgm_c_adt == 0) - return 1; - sector = ifofile->vmgi_mat->vmgm_c_adt; - } else if(ifofile->vtsi_mat) { - if(ifofile->vtsi_mat->vtsm_c_adt == 0) - return 1; - sector = ifofile->vtsi_mat->vtsm_c_adt; - } else { - return 0; - } - - ifofile->menu_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t)); - if(!ifofile->menu_c_adt) - return 0; - - if(!ifoRead_C_ADT_internal(ifofile, ifofile->menu_c_adt, sector)) { - free(ifofile->menu_c_adt); - ifofile->menu_c_adt = 0; - return 0; - } - - return 1; -} - -static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, - c_adt_t *c_adt, unsigned int sector) { - int i, info_length; - - if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) - return 0; - - if(!(DVDReadBytes(ifofile->file, c_adt, C_ADT_SIZE))) - return 0; - - B2N_16(c_adt->nr_of_vobs); - B2N_32(c_adt->last_byte); - - info_length = c_adt->last_byte + 1 - C_ADT_SIZE; - - CHECK_ZERO(c_adt->zero_1); - /* assert(c_adt->nr_of_vobs > 0); - Magic Knight Rayearth Daybreak is mastered very strange and has - Titles with a VOBS that has no cells. */ - CHECK_VALUE(info_length % sizeof(cell_adr_t) == 0); - - /* assert(info_length / sizeof(cell_adr_t) >= c_adt->nr_of_vobs); - 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); - } - - c_adt->cell_adr_table = (cell_adr_t *)malloc(info_length); - if(!c_adt->cell_adr_table) - return 0; - - if(info_length && - !(DVDReadBytes(ifofile->file, c_adt->cell_adr_table, info_length))) { - free(c_adt->cell_adr_table); - return 0; - } - - for(i = 0; i < info_length/sizeof(cell_adr_t); i++) { - B2N_16(c_adt->cell_adr_table[i].vob_id); - B2N_32(c_adt->cell_adr_table[i].start_sector); - B2N_32(c_adt->cell_adr_table[i].last_sector); - - CHECK_ZERO(c_adt->cell_adr_table[i].zero_1); - CHECK_VALUE(c_adt->cell_adr_table[i].vob_id > 0); - CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs); - CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0); - CHECK_VALUE(c_adt->cell_adr_table[i].start_sector < - c_adt->cell_adr_table[i].last_sector); - } - - return 1; -} - - -static void ifoFree_C_ADT_internal(c_adt_t *c_adt) { - if(c_adt) { - free(c_adt->cell_adr_table); - free(c_adt); - } -} - -void ifoFree_C_ADT(ifo_handle_t *ifofile) { - if(!ifofile) - return; - - ifoFree_C_ADT_internal(ifofile->menu_c_adt); - ifofile->menu_c_adt = 0; -} - -void ifoFree_TITLE_C_ADT(ifo_handle_t *ifofile) { - if(!ifofile) - return; - - ifoFree_C_ADT_internal(ifofile->vts_c_adt); - ifofile->vts_c_adt = 0; -} - -int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { - if(!ifofile) - return 0; - - if(!ifofile->vtsi_mat) - return 0; - - if(ifofile->vtsi_mat->vts_vobu_admap == 0) /* mandatory */ - return 0; - - ifofile->vts_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t)); - if(!ifofile->vts_vobu_admap) - return 0; - - if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->vts_vobu_admap, - ifofile->vtsi_mat->vts_vobu_admap)) { - free(ifofile->vts_vobu_admap); - ifofile->vts_vobu_admap = 0; - return 0; - } - - return 1; -} - -int ifoRead_VOBU_ADMAP(ifo_handle_t *ifofile) { - unsigned int sector; - - if(!ifofile) - return 0; - - if(ifofile->vmgi_mat) { - if(ifofile->vmgi_mat->vmgm_vobu_admap == 0) - return 1; - sector = ifofile->vmgi_mat->vmgm_vobu_admap; - } else if(ifofile->vtsi_mat) { - if(ifofile->vtsi_mat->vtsm_vobu_admap == 0) - return 1; - sector = ifofile->vtsi_mat->vtsm_vobu_admap; - } else { - return 0; - } - - ifofile->menu_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t)); - if(!ifofile->menu_vobu_admap) - return 0; - - if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->menu_vobu_admap, sector)) { - free(ifofile->menu_vobu_admap); - ifofile->menu_vobu_admap = 0; - return 0; - } - - return 1; -} - -static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, - vobu_admap_t *vobu_admap, - unsigned int sector) { - unsigned int i; - int info_length; - - if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) - return 0; - - if(!(DVDReadBytes(ifofile->file, vobu_admap, VOBU_ADMAP_SIZE))) - return 0; - - B2N_32(vobu_admap->last_byte); - - info_length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; - /* assert(info_length > 0); - Magic Knight Rayearth Daybreak is mastered very strange and has - Titles with a VOBS that has no VOBUs. */ - CHECK_VALUE(info_length % sizeof(uint32_t) == 0); - - vobu_admap->vobu_start_sectors = (uint32_t *)malloc(info_length); - if(!vobu_admap->vobu_start_sectors) { - return 0; - } - if(info_length && - !(DVDReadBytes(ifofile->file, - vobu_admap->vobu_start_sectors, info_length))) { - free(vobu_admap->vobu_start_sectors); - return 0; - } - - for(i = 0; i < info_length/sizeof(uint32_t); i++) - B2N_32(vobu_admap->vobu_start_sectors[i]); - - return 1; -} - - -static void ifoFree_VOBU_ADMAP_internal(vobu_admap_t *vobu_admap) { - if(vobu_admap) { - free(vobu_admap->vobu_start_sectors); - free(vobu_admap); - } -} - -void ifoFree_VOBU_ADMAP(ifo_handle_t *ifofile) { - if(!ifofile) - return; - - ifoFree_VOBU_ADMAP_internal(ifofile->menu_vobu_admap); - ifofile->menu_vobu_admap = 0; -} - -void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { - if(!ifofile) - return; - - ifoFree_VOBU_ADMAP_internal(ifofile->vts_vobu_admap); - ifofile->vts_vobu_admap = 0; -} - -int ifoRead_PGCIT(ifo_handle_t *ifofile) { - - if(!ifofile) - return 0; - - if(!ifofile->vtsi_mat) - return 0; - - if(ifofile->vtsi_mat->vts_pgcit == 0) /* mandatory */ - return 0; - - ifofile->vts_pgcit = (pgcit_t *)malloc(sizeof(pgcit_t)); - if(!ifofile->vts_pgcit) - return 0; - - if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit, - ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) { - free(ifofile->vts_pgcit); - ifofile->vts_pgcit = 0; - return 0; - } - - return 1; -} - -static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, - unsigned int offset) { - int i, info_length; - uint8_t *data, *ptr; - - if(!DVDFileSeek_(ifofile->file, offset)) - return 0; - - if(!(DVDReadBytes(ifofile->file, pgcit, PGCIT_SIZE))) - return 0; - - B2N_16(pgcit->nr_of_pgci_srp); - B2N_32(pgcit->last_byte); - - CHECK_ZERO(pgcit->zero_1); - /* assert(pgcit->nr_of_pgci_srp != 0); - Magic Knight Rayearth Daybreak is mastered very strange and has - Titles with 0 PTTs. */ - CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338*/ - - info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE; - data = malloc(info_length); - if(!data) - return 0; - - if(info_length && !(DVDReadBytes(ifofile->file, data, info_length))) { - free(data); - return 0; - } - - pgcit->pgci_srp = malloc(pgcit->nr_of_pgci_srp * sizeof(pgci_srp_t)); - if(!pgcit->pgci_srp) { - free(data); - return 0; - } - ptr = data; - for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { - 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); - } - free(data); - - for(i = 0; i < pgcit->nr_of_pgci_srp; i++) - CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1); - - for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { - pgcit->pgci_srp[i].pgc = malloc(sizeof(pgc_t)); - if(!pgcit->pgci_srp[i].pgc) { - int j; - for(j = 0; j < i; j++) { - 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, - offset + pgcit->pgci_srp[i].pgc_start_byte)) { - int j; - for(j = 0; j < i; j++) { - ifoFree_PGC(pgcit->pgci_srp[j].pgc); - free(pgcit->pgci_srp[j].pgc); - } - free(pgcit->pgci_srp); - pgcit->pgci_srp = NULL; - return 0; - } - } - - return 1; -} - -static void ifoFree_PGCIT_internal(pgcit_t *pgcit) { - if(pgcit) { - int 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); - } -} - -void ifoFree_PGCIT(ifo_handle_t *ifofile) { - if(!ifofile) - return; - - if(ifofile->vts_pgcit) { - ifoFree_PGCIT_internal(ifofile->vts_pgcit); - free(ifofile->vts_pgcit); - ifofile->vts_pgcit = 0; - } -} - - -int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { - pgci_ut_t *pgci_ut; - unsigned int sector; - unsigned int i; - int info_length; - uint8_t *data, *ptr; - - if(!ifofile) - return 0; - - if(ifofile->vmgi_mat) { - if(ifofile->vmgi_mat->vmgm_pgci_ut == 0) - return 1; - sector = ifofile->vmgi_mat->vmgm_pgci_ut; - } else if(ifofile->vtsi_mat) { - if(ifofile->vtsi_mat->vtsm_pgci_ut == 0) - return 1; - sector = ifofile->vtsi_mat->vtsm_pgci_ut; - } else { - return 0; - } - - ifofile->pgci_ut = (pgci_ut_t *)malloc(sizeof(pgci_ut_t)); - if(!ifofile->pgci_ut) - return 0; - - if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) { - free(ifofile->pgci_ut); - ifofile->pgci_ut = 0; - return 0; - } - - if(!(DVDReadBytes(ifofile->file, ifofile->pgci_ut, PGCI_UT_SIZE))) { - free(ifofile->pgci_ut); - ifofile->pgci_ut = 0; - return 0; - } - - pgci_ut = ifofile->pgci_ut; - - B2N_16(pgci_ut->nr_of_lus); - B2N_32(pgci_ut->last_byte); - - CHECK_ZERO(pgci_ut->zero_1); - CHECK_VALUE(pgci_ut->nr_of_lus != 0); - CHECK_VALUE(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ?*/ - CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte); - - info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE; - data = malloc(info_length); - if(!data) { - free(pgci_ut); - ifofile->pgci_ut = 0; - return 0; - } - if(!(DVDReadBytes(ifofile->file, data, info_length))) { - free(data); - free(pgci_ut); - ifofile->pgci_ut = 0; - return 0; - } - - pgci_ut->lu = malloc(pgci_ut->nr_of_lus * sizeof(pgci_lu_t)); - if(!pgci_ut->lu) { - free(data); - free(pgci_ut); - ifofile->pgci_ut = 0; - return 0; - } - ptr = data; - for(i = 0; i < pgci_ut->nr_of_lus; i++) { - memcpy(&pgci_ut->lu[i], ptr, PGCI_LU_SIZE); - ptr += PGCI_LU_SIZE; - B2N_16(pgci_ut->lu[i].lang_code); - B2N_32(pgci_ut->lu[i].lang_start_byte); - } - free(data); - - for(i = 0; i < pgci_ut->nr_of_lus; i++) { - /* Maybe this is only defined for v1.1 and later titles? - If the bits in 'lu[i].exists' are enumerated abcd efgh then: - VTS_x_yy.IFO VIDEO_TS.IFO - a == 0x83 "Root" 0x82 "Title" - b == 0x84 "Subpicture" - c == 0x85 "Audio" - d == 0x86 "Angle" - e == 0x87 "PTT" - */ - CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0); - } - - for(i = 0; i < pgci_ut->nr_of_lus; i++) { - pgci_ut->lu[i].pgcit = malloc(sizeof(pgcit_t)); - if(!pgci_ut->lu[i].pgcit) { - unsigned int j; - for(j = 0; j < i; j++) { - ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit); - free(pgci_ut->lu[j].pgcit); - } - free(pgci_ut->lu); - free(pgci_ut); - ifofile->pgci_ut = 0; - return 0; - } - if(!ifoRead_PGCIT_internal(ifofile, pgci_ut->lu[i].pgcit, - sector * DVD_BLOCK_LEN - + pgci_ut->lu[i].lang_start_byte)) { - unsigned int j; - for(j = 0; j < i; j++) { - ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit); - free(pgci_ut->lu[j].pgcit); - } - free(pgci_ut->lu[i].pgcit); - free(pgci_ut->lu); - free(pgci_ut); - ifofile->pgci_ut = 0; - return 0; - } - /* FIXME: Iterate and verify that all menus that should exists accordingly - / to pgci_ut->lu[i].exists really do? */ - } - - return 1; -} - - -void ifoFree_PGCI_UT(ifo_handle_t *ifofile) { - unsigned int i; - - if(!ifofile) - return; - - if(ifofile->pgci_ut) { - for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) { - ifoFree_PGCIT_internal(ifofile->pgci_ut->lu[i].pgcit); - free(ifofile->pgci_ut->lu[i].pgcit); - } - free(ifofile->pgci_ut->lu); - free(ifofile->pgci_ut); - ifofile->pgci_ut = 0; - } -} - -static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, - vts_attributes_t *vts_attributes, - unsigned int offset) { - unsigned int i; - - if(!DVDFileSeek_(ifofile->file, offset)) - return 0; - - if(!(DVDReadBytes(ifofile->file, vts_attributes, sizeof(vts_attributes_t)))) - return 0; - - B2N_32(vts_attributes->last_byte); - B2N_32(vts_attributes->vts_cat); - B2N_16(vts_attributes->vtsm_audio_attr.lang_code); - B2N_16(vts_attributes->vtsm_subp_attr.lang_code); - for(i = 0; i < 8; i++) - B2N_16(vts_attributes->vtstt_audio_attr[i].lang_code); - for(i = 0; i < 32; i++) - B2N_16(vts_attributes->vtstt_subp_attr[i].lang_code); - - CHECK_ZERO(vts_attributes->zero_1); - CHECK_ZERO(vts_attributes->zero_2); - CHECK_ZERO(vts_attributes->zero_3); - CHECK_ZERO(vts_attributes->zero_4); - CHECK_ZERO(vts_attributes->zero_5); - CHECK_ZERO(vts_attributes->zero_6); - CHECK_ZERO(vts_attributes->zero_7); - CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1); - CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1); - CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8); - for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++) - CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]); - CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32); - { - unsigned int nr_coded; - CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE); - nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6; - /* This is often nr_coded = 70, how do you know how many there really are?*/ - if(nr_coded > 32) { /* We haven't read more from disk/file anyway*/ - nr_coded = 32; - } - CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded); - for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++) - CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]); - } - - return 1; -} - - - -int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { - vts_atrt_t *vts_atrt; - unsigned int i, info_length, sector; - uint32_t *data; - - if(!ifofile) - return 0; - - if(!ifofile->vmgi_mat) - return 0; - - if(ifofile->vmgi_mat->vts_atrt == 0) /* mandatory */ - return 0; - - sector = ifofile->vmgi_mat->vts_atrt; - if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) - return 0; - - vts_atrt = (vts_atrt_t *)malloc(sizeof(vts_atrt_t)); - if(!vts_atrt) - return 0; - - ifofile->vts_atrt = vts_atrt; - - if(!(DVDReadBytes(ifofile->file, vts_atrt, VTS_ATRT_SIZE))) { - free(vts_atrt); - ifofile->vts_atrt = 0; - return 0; - } - - B2N_16(vts_atrt->nr_of_vtss); - B2N_32(vts_atrt->last_byte); - - CHECK_ZERO(vts_atrt->zero_1); - CHECK_VALUE(vts_atrt->nr_of_vtss != 0); - CHECK_VALUE(vts_atrt->nr_of_vtss < 100); /*??*/ - CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) + - VTS_ATRT_SIZE < vts_atrt->last_byte + 1); - - info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t); - data = (uint32_t *)malloc(info_length); - if(!data) { - free(vts_atrt); - ifofile->vts_atrt = 0; - return 0; - } - - vts_atrt->vts_atrt_offsets = data; - - if(!(DVDReadBytes(ifofile->file, data, info_length))) { - free(data); - free(vts_atrt); - ifofile->vts_atrt = 0; - return 0; - } - - for(i = 0; i < vts_atrt->nr_of_vtss; i++) { - B2N_32(data[i]); - CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1); - } - - info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t); - vts_atrt->vts = (vts_attributes_t *)malloc(info_length); - if(!vts_atrt->vts) { - free(data); - free(vts_atrt); - ifofile->vts_atrt = 0; - return 0; - } - for(i = 0; i < vts_atrt->nr_of_vtss; i++) { - unsigned int offset = data[i]; - if(!ifoRead_VTS_ATTRIBUTES(ifofile, &(vts_atrt->vts[i]), - (sector * DVD_BLOCK_LEN) + offset)) { - free(data); - free(vts_atrt); - ifofile->vts_atrt = 0; - return 0; - } - - /* This assert cant be in ifoRead_VTS_ATTRIBUTES*/ - CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1); - /* Is this check correct?*/ - } - - return 1; -} - - -void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) { - if(!ifofile) - return; - - if(ifofile->vts_atrt) { - free(ifofile->vts_atrt->vts); - free(ifofile->vts_atrt->vts_atrt_offsets); - free(ifofile->vts_atrt); - ifofile->vts_atrt = 0; - } -} - - -int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) { - txtdt_mgi_t *txtdt_mgi; - - if(!ifofile) - return 0; - - if(!ifofile->vmgi_mat) - return 0; - - /* Return successfully if there is nothing to read. */ - if(ifofile->vmgi_mat->txtdt_mgi == 0) - return 1; - - if(!DVDFileSeek_(ifofile->file, - ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN)) - return 0; - - txtdt_mgi = (txtdt_mgi_t *)malloc(sizeof(txtdt_mgi_t)); - if(!txtdt_mgi) { - return 0; - } - 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; - } - - /* fprintf(stderr, "-- Not done yet --\n");*/ - return 1; -} - -void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) { - if(!ifofile) - return; - - if(ifofile->txtdt_mgi) { - free(ifofile->txtdt_mgi); - ifofile->txtdt_mgi = 0; - } -} - diff --git a/dvdread/ifo_read.h b/dvdread/ifo_read.h deleted file mode 100644 index fb01983..0000000 --- a/dvdread/ifo_read.h +++ /dev/null @@ -1,228 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -#ifndef IFO_READ_H_INCLUDED -#define IFO_READ_H_INCLUDED - -/* - * Copyright (C) 2000, 2001, 2002 Björn Englund , - * Håkan Hjort - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "ifo_types.h" -#include "dvd_reader.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * handle = ifoOpen(dvd, title); - * - * Opens an IFO and reads in all the data for the IFO file corresponding to the - * given title. If title 0 is given, the video manager IFO file is read. - * Returns a handle to a completely parsed structure. - */ -ifo_handle_t *ifoOpen(dvd_reader_t *, int ); - -/** - * handle = ifoOpenVMGI(dvd); - * - * Opens an IFO and reads in _only_ the vmgi_mat data. This call can be used - * together with the calls below to read in each segment of the IFO file on - * demand. - */ -ifo_handle_t *ifoOpenVMGI(dvd_reader_t *); - -/** - * handle = ifoOpenVTSI(dvd, title); - * - * Opens an IFO and reads in _only_ the vtsi_mat data. This call can be used - * together with the calls below to read in each segment of the IFO file on - * demand. - */ -ifo_handle_t *ifoOpenVTSI(dvd_reader_t *, int); - -/** - * ifoClose(ifofile); - * Cleans up the IFO information. This will free all data allocated for the - * substructures. - */ -void ifoClose(ifo_handle_t *); - -/** - * The following functions are for reading only part of the VMGI/VTSI files. - * Returns 1 if the data was successfully read and 0 on error. - */ - -/** - * okay = ifoRead_PLT_MAIT(ifofile); - * - * Read in the Parental Management Information table, filling the - * ifofile->ptl_mait structure and its substructures. This data is only - * located in the video manager information file. This fills the - * ifofile->ptl_mait structure and all its substructures. - */ -int ifoRead_PTL_MAIT(ifo_handle_t *); - -/** - * okay = ifoRead_VTS_ATRT(ifofile); - * - * Read in the attribute table for the main menu vob, filling the - * ifofile->vts_atrt structure and its substructures. Only located in the - * video manager information file. This fills in the ifofile->vts_atrt - * structure and all its substructures. - */ -int ifoRead_VTS_ATRT(ifo_handle_t *); - -/** - * okay = ifoRead_TT_SRPT(ifofile); - * - * Reads the title info for the main menu, filling the ifofile->tt_srpt - * structure and its substructures. This data is only located in the video - * manager information file. This structure is mandatory in the IFO file. - */ -int ifoRead_TT_SRPT(ifo_handle_t *); - -/** - * okay = ifoRead_VTS_PTT_SRPT(ifofile); - * - * Reads in the part of title search pointer table, filling the - * ifofile->vts_ptt_srpt structure and its substructures. This data is only - * located in the video title set information file. This structure is - * mandatory, and must be included in the VTSI file. - */ -int ifoRead_VTS_PTT_SRPT(ifo_handle_t *); - -/** - * okay = ifoRead_FP_PGC(ifofile); - * - * Reads in the first play program chain data, filling the - * ifofile->first_play_pgc structure. This data is only located in the video - * manager information file (VMGI). This structure is optional. - */ -int ifoRead_FP_PGC(ifo_handle_t *); - -/** - * okay = ifoRead_PGCIT(ifofile); - * - * Reads in the program chain information table for the video title set. Fills - * in the ifofile->vts_pgcit structure and its substructures, which includes - * the data for each program chain in the set. This data is only located in - * the video title set information file. This structure is mandatory, and must - * be included in the VTSI file. - */ -int ifoRead_PGCIT(ifo_handle_t *); - -/** - * okay = ifoRead_PGCI_UT(ifofile); - * - * Reads in the menu PGCI unit table for the menu VOB. For the video manager, - * this corresponds to the VIDEO_TS.VOB file, and for each title set, this - * corresponds to the VTS_XX_0.VOB file. This data is located in both the - * video manager and video title set information files. For VMGI files, this - * fills the ifofile->vmgi_pgci_ut structure and all its substructures. For - * VTSI files, this fills the ifofile->vtsm_pgci_ut structure. - */ -int ifoRead_PGCI_UT(ifo_handle_t *); - -/** - * okay = ifoRead_VTS_TMAPT(ifofile); - * - * Reads in the VTS Time Map Table, this data is only located in the video - * title set information file. This fills the ifofile->vts_tmapt structure - * and all its substructures. When pressent enables VOBU level time-based - * seeking for One_Sequential_PGC_Titles. - */ -int ifoRead_VTS_TMAPT(ifo_handle_t *); - -/** - * okay = ifoRead_C_ADT(ifofile); - * - * Reads in the cell address table for the menu VOB. For the video manager, - * this corresponds to the VIDEO_TS.VOB file, and for each title set, this - * corresponds to the VTS_XX_0.VOB file. This data is located in both the - * video manager and video title set information files. For VMGI files, this - * fills the ifofile->vmgm_c_adt structure and all its substructures. For VTSI - * files, this fills the ifofile->vtsm_c_adt structure. - */ -int ifoRead_C_ADT(ifo_handle_t *); - -/** - * okay = ifoRead_TITLE_C_ADT(ifofile); - * - * Reads in the cell address table for the video title set corresponding to - * this IFO file. This data is only located in the video title set information - * file. This structure is mandatory, and must be included in the VTSI file. - * This call fills the ifofile->vts_c_adt structure and its substructures. - */ -int ifoRead_TITLE_C_ADT(ifo_handle_t *); - -/** - * okay = ifoRead_VOBU_ADMAP(ifofile); - * - * Reads in the VOBU address map for the menu VOB. For the video manager, this - * corresponds to the VIDEO_TS.VOB file, and for each title set, this - * corresponds to the VTS_XX_0.VOB file. This data is located in both the - * video manager and video title set information files. For VMGI files, this - * fills the ifofile->vmgm_vobu_admap structure and all its substructures. For - * VTSI files, this fills the ifofile->vtsm_vobu_admap structure. - */ -int ifoRead_VOBU_ADMAP(ifo_handle_t *); - -/** - * okay = ifoRead_TITLE_VOBU_ADMAP(ifofile); - * - * Reads in the VOBU address map for the associated video title set. This data - * is only located in the video title set information file. This structure is - * mandatory, and must be included in the VTSI file. Fills the - * ifofile->vts_vobu_admap structure and its substructures. - */ -int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *); - -/** - * okay = ifoRead_TXTDT_MGI(ifofile); - * - * Reads in the text data strings for the DVD. Fills the ifofile->txtdt_mgi - * structure and all its substructures. This data is only located in the video - * manager information file. This structure is mandatory, and must be included - * in the VMGI file. - */ -int ifoRead_TXTDT_MGI(ifo_handle_t *); - -/** - * The following functions are used for freeing parsed sections of the - * ifo_handle_t structure and the allocated substructures. The free calls - * below are safe: they will not mind if you attempt to free part of an IFO - * file which was not read in or which does not exist. - */ -void ifoFree_PTL_MAIT(ifo_handle_t *); -void ifoFree_VTS_ATRT(ifo_handle_t *); -void ifoFree_TT_SRPT(ifo_handle_t *); -void ifoFree_VTS_PTT_SRPT(ifo_handle_t *); -void ifoFree_FP_PGC(ifo_handle_t *); -void ifoFree_PGCIT(ifo_handle_t *); -void ifoFree_PGCI_UT(ifo_handle_t *); -void ifoFree_VTS_TMAPT(ifo_handle_t *); -void ifoFree_C_ADT(ifo_handle_t *); -void ifoFree_TITLE_C_ADT(ifo_handle_t *); -void ifoFree_VOBU_ADMAP(ifo_handle_t *); -void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *); -void ifoFree_TXTDT_MGI(ifo_handle_t *); - -#ifdef __cplusplus -}; -#endif -#endif /* IFO_READ_H_INCLUDED */ diff --git a/dvdread/ifo_types.h b/dvdread/ifo_types.h deleted file mode 100644 index 0bf601c..0000000 --- a/dvdread/ifo_types.h +++ /dev/null @@ -1,893 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -#ifndef IFO_TYPES_H_INCLUDED -#define IFO_TYPES_H_INCLUDED - -/* - * Copyright (C) 2000, 2001 Björn Englund , - * Håkan Hjort - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "dvd_reader.h" - -#if defined(__BEOS__) -#if !defined(_INTTYPES_H_) && !defined(_INTTYPES_H) && !defined(_STDINT_H_) && !defined(_STDINT_H) -#error "Must include or before any libdvdread header." -#endif -#else -#if !defined(UINT8_MAX) || !defined(UINT16_MAX) || !defined(INT32_MAX) -#error "Must include or before any libdvdread header." -#endif -#endif - -#undef ATTRIBUTE_PACKED -#undef PRAGMA_PACK_BEGIN -#undef PRAGMA_PACK_END - -#if defined(__GNUC__) -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) -#define ATTRIBUTE_PACKED __attribute__ ((packed)) -#define PRAGMA_PACK 0 -#endif -#endif - -#if !defined(ATTRIBUTE_PACKED) -#define ATTRIBUTE_PACKED -#define PRAGMA_PACK 1 -#endif - -#if PRAGMA_PACK -#pragma pack(1) -#endif - - -/** - * Common - * - * The following structures are used in both the VMGI and VTSI. - */ - - -/** - * DVD Time Information. - */ -typedef struct { - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t frame_u; /* The two high bits are the frame rate. */ -} ATTRIBUTE_PACKED dvd_time_t; - -/** - * Type to store per-command data. - */ -typedef struct { - uint8_t bytes[8]; -} ATTRIBUTE_PACKED vm_cmd_t; -#define COMMAND_DATA_SIZE 8U - - -/** - * Video Attributes. - */ -typedef struct { -#ifdef WORDS_BIGENDIAN - unsigned int mpeg_version : 2; - unsigned int video_format : 2; - unsigned int display_aspect_ratio : 2; - unsigned int permitted_df : 2; - - unsigned int line21_cc_1 : 1; - unsigned int line21_cc_2 : 1; - unsigned int unknown1 : 1; - unsigned int bit_rate : 1; - - unsigned int picture_size : 2; - unsigned int letterboxed : 1; - unsigned int film_mode : 1; -#else - unsigned int permitted_df : 2; - unsigned int display_aspect_ratio : 2; - unsigned int video_format : 2; - unsigned int mpeg_version : 2; - - unsigned int film_mode : 1; - unsigned int letterboxed : 1; - unsigned int picture_size : 2; - - unsigned int bit_rate : 1; - unsigned int unknown1 : 1; - unsigned int line21_cc_2 : 1; - unsigned int line21_cc_1 : 1; -#endif -} ATTRIBUTE_PACKED video_attr_t; - -/** - * Audio Attributes. - */ -typedef struct { -#ifdef WORDS_BIGENDIAN - unsigned int audio_format : 3; - unsigned int multichannel_extension : 1; - unsigned int lang_type : 2; - unsigned int application_mode : 2; - - unsigned int quantization : 2; - unsigned int sample_frequency : 2; - unsigned int unknown1 : 1; - unsigned int channels : 3; -#else - unsigned int application_mode : 2; - unsigned int lang_type : 2; - unsigned int multichannel_extension : 1; - unsigned int audio_format : 3; - - unsigned int channels : 3; - unsigned int unknown1 : 1; - unsigned int sample_frequency : 2; - unsigned int quantization : 2; -#endif - uint16_t lang_code; - uint8_t lang_extension; - uint8_t code_extension; - uint8_t unknown3; - union { - struct { -#ifdef WORDS_BIGENDIAN - unsigned int unknown4 : 1; - unsigned int channel_assignment : 3; - unsigned int version : 2; - unsigned int mc_intro : 1; /* probably 0: true, 1:false */ - unsigned int mode : 1; /* Karaoke mode 0: solo 1: duet */ -#else - unsigned int mode : 1; - unsigned int mc_intro : 1; - unsigned int version : 2; - unsigned int channel_assignment : 3; - unsigned int unknown4 : 1; -#endif - } ATTRIBUTE_PACKED karaoke; - struct { -#ifdef WORDS_BIGENDIAN - unsigned int unknown5 : 4; - unsigned int dolby_encoded : 1; /* suitable for surround decoding */ - unsigned int unknown6 : 3; -#else - unsigned int unknown6 : 3; - unsigned int dolby_encoded : 1; - unsigned int unknown5 : 4; -#endif - } ATTRIBUTE_PACKED surround; - } ATTRIBUTE_PACKED app_info; -} ATTRIBUTE_PACKED audio_attr_t; - - -/** - * MultiChannel Extension - */ -typedef struct { -#ifdef WORDS_BIGENDIAN - unsigned int zero1 : 7; - unsigned int ach0_gme : 1; - - unsigned int zero2 : 7; - unsigned int ach1_gme : 1; - - unsigned int zero3 : 4; - unsigned int ach2_gv1e : 1; - unsigned int ach2_gv2e : 1; - unsigned int ach2_gm1e : 1; - unsigned int ach2_gm2e : 1; - - unsigned int zero4 : 4; - unsigned int ach3_gv1e : 1; - unsigned int ach3_gv2e : 1; - unsigned int ach3_gmAe : 1; - unsigned int ach3_se2e : 1; - - unsigned int zero5 : 4; - unsigned int ach4_gv1e : 1; - unsigned int ach4_gv2e : 1; - unsigned int ach4_gmBe : 1; - unsigned int ach4_seBe : 1; -#else - unsigned int ach0_gme : 1; - unsigned int zero1 : 7; - - unsigned int ach1_gme : 1; - unsigned int zero2 : 7; - - unsigned int ach2_gm2e : 1; - unsigned int ach2_gm1e : 1; - unsigned int ach2_gv2e : 1; - unsigned int ach2_gv1e : 1; - unsigned int zero3 : 4; - - unsigned int ach3_se2e : 1; - unsigned int ach3_gmAe : 1; - unsigned int ach3_gv2e : 1; - unsigned int ach3_gv1e : 1; - unsigned int zero4 : 4; - - unsigned int ach4_seBe : 1; - unsigned int ach4_gmBe : 1; - unsigned int ach4_gv2e : 1; - unsigned int ach4_gv1e : 1; - unsigned int zero5 : 4; -#endif - uint8_t zero6[19]; -} ATTRIBUTE_PACKED multichannel_ext_t; - - -/** - * Subpicture Attributes. - */ -typedef struct { - /* - * type: 0 not specified - * 1 language - * 2 other - * coding mode: 0 run length - * 1 extended - * 2 other - * language: indicates language if type == 1 - * lang extension: if type == 1 contains the lang extension - */ -#ifdef WORDS_BIGENDIAN - unsigned int code_mode : 3; - unsigned int zero1 : 3; - unsigned int type : 2; -#else - unsigned int type : 2; - unsigned int zero1 : 3; - unsigned int code_mode : 3; -#endif - uint8_t zero2; - uint16_t lang_code; - uint8_t lang_extension; - uint8_t code_extension; -} ATTRIBUTE_PACKED subp_attr_t; - - - -/** - * PGC Command Table. - */ -typedef struct { - uint16_t nr_of_pre; - uint16_t nr_of_post; - uint16_t nr_of_cell; - 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 8U - -/** - * PGC Program Map - */ -typedef uint8_t pgc_program_map_t; - -/** - * Cell Playback Information. - */ -typedef struct { -#ifdef WORDS_BIGENDIAN - unsigned int block_mode : 2; - unsigned int block_type : 2; - unsigned int seamless_play : 1; - unsigned int interleaved : 1; - unsigned int stc_discontinuity: 1; - unsigned int seamless_angle : 1; - - unsigned int playback_mode : 1; /**< When set, enter StillMode after each VOBU */ - unsigned int restricted : 1; /**< ?? drop out of fastforward? */ - unsigned int unknown2 : 6; -#else - unsigned int seamless_angle : 1; - unsigned int stc_discontinuity: 1; - unsigned int interleaved : 1; - unsigned int seamless_play : 1; - unsigned int block_type : 2; - unsigned int block_mode : 2; - - unsigned int unknown2 : 6; - unsigned int restricted : 1; - unsigned int playback_mode : 1; -#endif - uint8_t still_time; - uint8_t cell_cmd_nr; - dvd_time_t playback_time; - uint32_t first_sector; - uint32_t first_ilvu_end_sector; - uint32_t last_vobu_start_sector; - uint32_t last_sector; -} ATTRIBUTE_PACKED cell_playback_t; - -#define BLOCK_TYPE_NONE 0x0 -#define BLOCK_TYPE_ANGLE_BLOCK 0x1 - -#define BLOCK_MODE_NOT_IN_BLOCK 0x0 -#define BLOCK_MODE_FIRST_CELL 0x1 -#define BLOCK_MODE_IN_BLOCK 0x2 -#define BLOCK_MODE_LAST_CELL 0x3 - -/** - * Cell Position Information. - */ -typedef struct { - uint16_t vob_id_nr; - uint8_t zero_1; - uint8_t cell_nr; -} ATTRIBUTE_PACKED cell_position_t; - -/** - * User Operations. - */ -typedef struct { -#ifdef WORDS_BIGENDIAN - unsigned int zero : 7; /* 25-31 */ - unsigned int video_pres_mode_change : 1; /* 24 */ - - unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */ - unsigned int angle_change : 1; - unsigned int subpic_stream_change : 1; - unsigned int audio_stream_change : 1; - unsigned int pause_on : 1; - unsigned int still_off : 1; - unsigned int button_select_or_activate : 1; - unsigned int resume : 1; /* 16 */ - - unsigned int chapter_menu_call : 1; /* 15 */ - unsigned int angle_menu_call : 1; - unsigned int audio_menu_call : 1; - unsigned int subpic_menu_call : 1; - unsigned int root_menu_call : 1; - unsigned int title_menu_call : 1; - unsigned int backward_scan : 1; - unsigned int forward_scan : 1; /* 8 */ - - unsigned int next_pg_search : 1; /* 7 */ - unsigned int prev_or_top_pg_search : 1; - unsigned int time_or_chapter_search : 1; - unsigned int go_up : 1; - unsigned int stop : 1; - unsigned int title_play : 1; - unsigned int chapter_search_or_play : 1; - unsigned int title_or_time_play : 1; /* 0 */ -#else - unsigned int video_pres_mode_change : 1; /* 24 */ - unsigned int zero : 7; /* 25-31 */ - - unsigned int resume : 1; /* 16 */ - unsigned int button_select_or_activate : 1; - unsigned int still_off : 1; - unsigned int pause_on : 1; - unsigned int audio_stream_change : 1; - unsigned int subpic_stream_change : 1; - unsigned int angle_change : 1; - unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */ - - unsigned int forward_scan : 1; /* 8 */ - unsigned int backward_scan : 1; - unsigned int title_menu_call : 1; - unsigned int root_menu_call : 1; - unsigned int subpic_menu_call : 1; - unsigned int audio_menu_call : 1; - unsigned int angle_menu_call : 1; - unsigned int chapter_menu_call : 1; /* 15 */ - - unsigned int title_or_time_play : 1; /* 0 */ - unsigned int chapter_search_or_play : 1; - unsigned int title_play : 1; - unsigned int stop : 1; - unsigned int go_up : 1; - unsigned int time_or_chapter_search : 1; - unsigned int prev_or_top_pg_search : 1; - unsigned int next_pg_search : 1; /* 7 */ -#endif -} ATTRIBUTE_PACKED user_ops_t; - -/** - * Program Chain Information. - */ -typedef struct { - uint16_t zero_1; - uint8_t nr_of_programs; - uint8_t nr_of_cells; - dvd_time_t playback_time; - user_ops_t prohibited_ops; - uint16_t audio_control[8]; /* New type? */ - uint32_t subp_control[32]; /* New type? */ - uint16_t next_pgc_nr; - uint16_t prev_pgc_nr; - uint16_t goup_pgc_nr; - 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; - uint16_t cell_playback_offset; - uint16_t cell_position_offset; - pgc_command_tbl_t *command_tbl; - pgc_program_map_t *program_map; - cell_playback_t *cell_playback; - cell_position_t *cell_position; -} ATTRIBUTE_PACKED pgc_t; -#define PGC_SIZE 236U - -/** - * Program Chain Information Search Pointer. - */ -typedef struct { - uint8_t entry_id; -#ifdef WORDS_BIGENDIAN - unsigned int block_mode : 2; - unsigned int block_type : 2; - unsigned int unknown1 : 4; -#else - unsigned int unknown1 : 4; - unsigned int block_type : 2; - unsigned int block_mode : 2; -#endif - uint16_t ptl_id_mask; - uint32_t pgc_start_byte; - pgc_t *pgc; -} ATTRIBUTE_PACKED pgci_srp_t; -#define PGCI_SRP_SIZE 8U - -/** - * Program Chain Information Table. - */ -typedef struct { - uint16_t nr_of_pgci_srp; - uint16_t zero_1; - uint32_t last_byte; - pgci_srp_t *pgci_srp; -} ATTRIBUTE_PACKED pgcit_t; -#define PGCIT_SIZE 8U - -/** - * Menu PGCI Language Unit. - */ -typedef struct { - uint16_t lang_code; - uint8_t lang_extension; - uint8_t exists; - uint32_t lang_start_byte; - pgcit_t *pgcit; -} ATTRIBUTE_PACKED pgci_lu_t; -#define PGCI_LU_SIZE 8U - -/** - * Menu PGCI Unit Table. - */ -typedef struct { - uint16_t nr_of_lus; - uint16_t zero_1; - uint32_t last_byte; - pgci_lu_t *lu; -} ATTRIBUTE_PACKED pgci_ut_t; -#define PGCI_UT_SIZE 8U - -/** - * Cell Address Information. - */ -typedef struct { - uint16_t vob_id; - uint8_t cell_id; - uint8_t zero_1; - uint32_t start_sector; - uint32_t last_sector; -} ATTRIBUTE_PACKED cell_adr_t; - -/** - * Cell Address Table. - */ -typedef struct { - uint16_t nr_of_vobs; /* VOBs */ - uint16_t zero_1; - uint32_t last_byte; - cell_adr_t *cell_adr_table; /* No explicit size given. */ -} ATTRIBUTE_PACKED c_adt_t; -#define C_ADT_SIZE 8U - -/** - * VOBU Address Map. - */ -typedef struct { - uint32_t last_byte; - uint32_t *vobu_start_sectors; -} ATTRIBUTE_PACKED vobu_admap_t; -#define VOBU_ADMAP_SIZE 4U - - - - -/** - * VMGI - * - * The following structures relate to the Video Manager. - */ - -/** - * Video Manager Information Management Table. - */ -typedef struct { - char vmg_identifier[12]; - uint32_t vmg_last_sector; - uint8_t zero_1[12]; - uint32_t vmgi_last_sector; - uint8_t zero_2; - uint8_t specification_version; - uint32_t vmg_category; - uint16_t vmg_nr_of_volumes; - uint16_t vmg_this_volume_nr; - uint8_t disc_side; - uint8_t zero_3[19]; - uint16_t vmg_nr_of_title_sets; /* Number of VTSs. */ - char provider_identifier[32]; - uint64_t vmg_pos_code; - uint8_t zero_4[24]; - uint32_t vmgi_last_byte; - uint32_t first_play_pgc; - uint8_t zero_5[56]; - uint32_t vmgm_vobs; /* sector */ - uint32_t tt_srpt; /* sector */ - uint32_t vmgm_pgci_ut; /* sector */ - uint32_t ptl_mait; /* sector */ - uint32_t vts_atrt; /* sector */ - uint32_t txtdt_mgi; /* sector */ - uint32_t vmgm_c_adt; /* sector */ - uint32_t vmgm_vobu_admap; /* sector */ - uint8_t zero_6[32]; - - video_attr_t vmgm_video_attr; - uint8_t zero_7; - uint8_t nr_of_vmgm_audio_streams; /* should be 0 or 1 */ - audio_attr_t vmgm_audio_attr; - audio_attr_t zero_8[7]; - uint8_t zero_9[17]; - uint8_t nr_of_vmgm_subp_streams; /* should be 0 or 1 */ - subp_attr_t vmgm_subp_attr; - subp_attr_t zero_10[27]; /* XXX: how much 'padding' here? */ -} ATTRIBUTE_PACKED vmgi_mat_t; - -typedef struct { -#ifdef WORDS_BIGENDIAN - unsigned int zero_1 : 1; - unsigned int multi_or_random_pgc_title : 1; /* 0: one sequential pgc title */ - unsigned int jlc_exists_in_cell_cmd : 1; - unsigned int jlc_exists_in_prepost_cmd : 1; - unsigned int jlc_exists_in_button_cmd : 1; - unsigned int jlc_exists_in_tt_dom : 1; - unsigned int chapter_search_or_play : 1; /* UOP 1 */ - unsigned int title_or_time_play : 1; /* UOP 0 */ -#else - unsigned int title_or_time_play : 1; - unsigned int chapter_search_or_play : 1; - unsigned int jlc_exists_in_tt_dom : 1; - unsigned int jlc_exists_in_button_cmd : 1; - unsigned int jlc_exists_in_prepost_cmd : 1; - unsigned int jlc_exists_in_cell_cmd : 1; - unsigned int multi_or_random_pgc_title : 1; - unsigned int zero_1 : 1; -#endif -} ATTRIBUTE_PACKED playback_type_t; - -/** - * Title Information. - */ -typedef struct { - playback_type_t pb_ty; - uint8_t nr_of_angles; - uint16_t nr_of_ptts; - uint16_t parental_id; - uint8_t title_set_nr; - uint8_t vts_ttn; - uint32_t title_set_sector; -} ATTRIBUTE_PACKED title_info_t; - -/** - * PartOfTitle Search Pointer Table. - */ -typedef struct { - uint16_t nr_of_srpts; - uint16_t zero_1; - uint32_t last_byte; - title_info_t *title; -} ATTRIBUTE_PACKED tt_srpt_t; -#define TT_SRPT_SIZE 8U - - -/** - * Parental Management Information Unit Table. - * Level 1 (US: G), ..., 7 (US: NC-17), 8 - */ -typedef uint16_t pf_level_t[8]; - -/** - * Parental Management Information Unit Table. - */ -typedef struct { - uint16_t country_code; - uint16_t zero_1; - uint16_t pf_ptl_mai_start_byte; - 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 8U - -/** - * Parental Management Information Table. - */ -typedef struct { - uint16_t nr_of_countries; - uint16_t nr_of_vtss; - uint32_t last_byte; - ptl_mait_country_t *countries; -} ATTRIBUTE_PACKED ptl_mait_t; -#define PTL_MAIT_SIZE 8U - -/** - * Video Title Set Attributes. - */ -typedef struct { - uint32_t last_byte; - uint32_t vts_cat; - - video_attr_t vtsm_vobs_attr; - uint8_t zero_1; - uint8_t nr_of_vtsm_audio_streams; /* should be 0 or 1 */ - audio_attr_t vtsm_audio_attr; - audio_attr_t zero_2[7]; - uint8_t zero_3[16]; - uint8_t zero_4; - uint8_t nr_of_vtsm_subp_streams; /* should be 0 or 1 */ - subp_attr_t vtsm_subp_attr; - subp_attr_t zero_5[27]; - - uint8_t zero_6[2]; - - video_attr_t vtstt_vobs_video_attr; - uint8_t zero_7; - uint8_t nr_of_vtstt_audio_streams; - audio_attr_t vtstt_audio_attr[8]; - uint8_t zero_8[16]; - uint8_t zero_9; - uint8_t nr_of_vtstt_subp_streams; - subp_attr_t vtstt_subp_attr[32]; -} ATTRIBUTE_PACKED vts_attributes_t; -#define VTS_ATTRIBUTES_SIZE 542U -#define VTS_ATTRIBUTES_MIN_SIZE 356U - -/** - * Video Title Set Attribute Table. - */ -typedef struct { - uint16_t nr_of_vtss; - uint16_t zero_1; - uint32_t last_byte; - vts_attributes_t *vts; - uint32_t *vts_atrt_offsets; /* offsets table for each vts_attributes */ -} ATTRIBUTE_PACKED vts_atrt_t; -#define VTS_ATRT_SIZE 8U - -/** - * Text Data. (Incomplete) - */ -typedef struct { - uint32_t last_byte; /* offsets are relative here */ - uint16_t offsets[100]; /* == nr_of_srpts + 1 (first is disc title) */ -#if 0 - uint16_t unknown; /* 0x48 ?? 0x48 words (16bit) info following */ - uint16_t zero_1; - - uint8_t type_of_info; /* ?? 01 == disc, 02 == Title, 04 == Title part */ - uint8_t unknown1; - uint8_t unknown2; - uint8_t unknown3; - uint8_t unknown4; /* ?? allways 0x30 language?, text format? */ - uint8_t unknown5; - uint16_t offset; /* from first */ - - char text[12]; /* ended by 0x09 */ -#endif -} ATTRIBUTE_PACKED txtdt_t; - -/** - * Text Data Language Unit. (Incomplete) - */ -typedef struct { - uint16_t lang_code; - uint16_t unknown; /* 0x0001, title 1? disc 1? side 1? */ - uint32_t txtdt_start_byte; /* prt, rel start of vmg_txtdt_mgi */ - txtdt_t *txtdt; -} ATTRIBUTE_PACKED txtdt_lu_t; -#define TXTDT_LU_SIZE 8U - -/** - * Text Data Manager Information. (Incomplete) - */ -typedef struct { - char disc_name[14]; /* how many bytes?? */ - uint16_t nr_of_language_units; /* 32bit?? */ - uint32_t last_byte; - txtdt_lu_t *lu; -} ATTRIBUTE_PACKED txtdt_mgi_t; -#define TXTDT_MGI_SIZE 20U - - -/** - * VTS - * - * Structures relating to the Video Title Set (VTS). - */ - -/** - * Video Title Set Information Management Table. - */ -typedef struct { - char vts_identifier[12]; - uint32_t vts_last_sector; - uint8_t zero_1[12]; - uint32_t vtsi_last_sector; - uint8_t zero_2; - uint8_t specification_version; - uint32_t vts_category; - uint16_t zero_3; - uint16_t zero_4; - uint8_t zero_5; - uint8_t zero_6[19]; - uint16_t zero_7; - uint8_t zero_8[32]; - uint64_t zero_9; - uint8_t zero_10[24]; - uint32_t vtsi_last_byte; - uint32_t zero_11; - uint8_t zero_12[56]; - uint32_t vtsm_vobs; /* sector */ - uint32_t vtstt_vobs; /* sector */ - uint32_t vts_ptt_srpt; /* sector */ - uint32_t vts_pgcit; /* sector */ - uint32_t vtsm_pgci_ut; /* sector */ - uint32_t vts_tmapt; /* sector */ - uint32_t vtsm_c_adt; /* sector */ - uint32_t vtsm_vobu_admap; /* sector */ - uint32_t vts_c_adt; /* sector */ - uint32_t vts_vobu_admap; /* sector */ - uint8_t zero_13[24]; - - video_attr_t vtsm_video_attr; - uint8_t zero_14; - uint8_t nr_of_vtsm_audio_streams; /* should be 0 or 1 */ - audio_attr_t vtsm_audio_attr; - audio_attr_t zero_15[7]; - uint8_t zero_16[17]; - uint8_t nr_of_vtsm_subp_streams; /* should be 0 or 1 */ - subp_attr_t vtsm_subp_attr; - subp_attr_t zero_17[27]; - uint8_t zero_18[2]; - - video_attr_t vts_video_attr; - uint8_t zero_19; - uint8_t nr_of_vts_audio_streams; - audio_attr_t vts_audio_attr[8]; - uint8_t zero_20[17]; - uint8_t nr_of_vts_subp_streams; - subp_attr_t vts_subp_attr[32]; - uint16_t zero_21; - multichannel_ext_t vts_mu_audio_attr[8]; - /* XXX: how much 'padding' here, if any? */ -} ATTRIBUTE_PACKED vtsi_mat_t; - -/** - * PartOfTitle Unit Information. - */ -typedef struct { - uint16_t pgcn; - uint16_t pgn; -} ATTRIBUTE_PACKED ptt_info_t; - -/** - * PartOfTitle Information. - */ -typedef struct { - uint16_t nr_of_ptts; - ptt_info_t *ptt; -} ATTRIBUTE_PACKED ttu_t; - -/** - * PartOfTitle Search Pointer Table. - */ -typedef struct { - uint16_t nr_of_srpts; - uint16_t zero_1; - uint32_t last_byte; - ttu_t *title; - uint32_t *ttu_offset; /* offset table for each ttu */ -} ATTRIBUTE_PACKED vts_ptt_srpt_t; -#define VTS_PTT_SRPT_SIZE 8U - - -/** - * Time Map Entry. - */ -/* Should this be bit field at all or just the uint32_t? */ -typedef uint32_t map_ent_t; - -/** - * Time Map. - */ -typedef struct { - uint8_t tmu; /* Time unit, in seconds */ - uint8_t zero_1; - uint16_t nr_of_entries; - map_ent_t *map_ent; -} ATTRIBUTE_PACKED vts_tmap_t; -#define VTS_TMAP_SIZE 4U - -/** - * Time Map Table. - */ -typedef struct { - uint16_t nr_of_tmaps; - uint16_t zero_1; - uint32_t last_byte; - vts_tmap_t *tmap; - uint32_t *tmap_offset; /* offset table for each tmap */ -} ATTRIBUTE_PACKED vts_tmapt_t; -#define VTS_TMAPT_SIZE 8U - - -#if PRAGMA_PACK -#pragma pack() -#endif - - -/** - * The following structure defines an IFO file. The structure is divided into - * two parts, the VMGI, or Video Manager Information, which is read from the - * VIDEO_TS.[IFO,BUP] file, and the VTSI, or Video Title Set Information, which - * is read in from the VTS_XX_0.[IFO,BUP] files. - */ -typedef struct { - dvd_file_t *file; - - /* VMGI */ - vmgi_mat_t *vmgi_mat; - tt_srpt_t *tt_srpt; - pgc_t *first_play_pgc; - ptl_mait_t *ptl_mait; - vts_atrt_t *vts_atrt; - txtdt_mgi_t *txtdt_mgi; - - /* Common */ - pgci_ut_t *pgci_ut; - c_adt_t *menu_c_adt; - vobu_admap_t *menu_vobu_admap; - - /* VTSI */ - vtsi_mat_t *vtsi_mat; - vts_ptt_srpt_t *vts_ptt_srpt; - pgcit_t *vts_pgcit; - vts_tmapt_t *vts_tmapt; - c_adt_t *vts_c_adt; - vobu_admap_t *vts_vobu_admap; -} ifo_handle_t; - -#endif /* IFO_TYPES_H_INCLUDED */ diff --git a/dvdread/md5.c b/dvdread/md5.c deleted file mode 100644 index 3e02b6b..0000000 --- a/dvdread/md5.c +++ /dev/null @@ -1,407 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -/* md5.c - Functions to compute MD5 message digest of files or memory blocks - according to the definition of MD5 in RFC 1321 from April 1992. - Copyright (C) 1995, 1996, 2001 Free Software Foundation, Inc. - NOTE: The canonical source of this file is maintained with the GNU C - Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Ulrich Drepper , 1995. */ - -#include "config.h" - -#include -#include -#include -#include "md5.h" - -#ifdef _LIBC -# include -# if __BYTE_ORDER == __BIG_ENDIAN -# define WORDS_BIGENDIAN 1 -# endif -#endif - -#ifdef WORDS_BIGENDIAN -# define SWAP(n) \ - (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) -#else -# define SWAP(n) (n) -#endif - - -/* This array contains the bytes used to pad the buffer to the next - 64-byte boundary. (RFC 1321, 3.1: Step 1) */ -static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; - - -/* Initialize structure containing state of computation. - (RFC 1321, 3.3: Step 3) */ -void -md5_init_ctx (ctx) - struct md5_ctx *ctx; -{ - ctx->A = 0x67452301; - ctx->B = 0xefcdab89; - ctx->C = 0x98badcfe; - ctx->D = 0x10325476; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -/* Put result from CTX in first 16 bytes following RESBUF. The result - must be in little endian byte order. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -void * -md5_read_ctx (ctx, resbuf) - const struct md5_ctx *ctx; - void *resbuf; -{ - ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); - ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); - ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); - ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -void * -md5_finish_ctx (ctx, resbuf) - struct md5_ctx *ctx; - void *resbuf; -{ - /* Take yet unprocessed bytes into account. */ - md5_uint32 bytes = ctx->buflen; - size_t pad; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if (ctx->total[0] < bytes) - ++ctx->total[1]; - - pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; - memcpy (&ctx->buffer[bytes], fillbuf, pad); - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); - *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | - (ctx->total[0] >> 29)); - - /* Process last bytes. */ - md5_process_block (ctx->buffer, bytes + pad + 8, ctx); - - return md5_read_ctx (ctx, resbuf); -} - -/* Compute MD5 message digest for bytes read from STREAM. The - resulting message digest number will be written into the 16 bytes - beginning at RESBLOCK. */ -int -md5_stream (stream, resblock) - FILE *stream; - void *resblock; -{ - /* Important: BLOCKSIZE must be a multiple of 64. */ -#define BLOCKSIZE 4096 - struct md5_ctx ctx; - char buffer[BLOCKSIZE + 72]; - size_t sum; - - /* Initialize the computation context. */ - md5_init_ctx (&ctx); - - /* Iterate over full file contents. */ - while (1) - { - /* We read the file in blocks of BLOCKSIZE bytes. One call of the - computation function processes the whole buffer so that with the - next round of the loop another block can be read. */ - size_t n; - sum = 0; - - /* Read block. Take care for partial reads. */ - do - { - n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); - - sum += n; - } - while (sum < BLOCKSIZE && n != 0); - if (n == 0 && ferror (stream)) - return 1; - - /* If end of file is reached, end the loop. */ - if (n == 0) - break; - - /* Process buffer with BLOCKSIZE bytes. Note that - BLOCKSIZE % 64 == 0 - */ - md5_process_block (buffer, BLOCKSIZE, &ctx); - } - - /* Add the last bytes if necessary. */ - if (sum > 0) - md5_process_bytes (buffer, sum, &ctx); - - /* Construct result in desired memory. */ - md5_finish_ctx (&ctx, resblock); - return 0; -} - -/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void * -md5_buffer (buffer, len, resblock) - const char *buffer; - size_t len; - void *resblock; -{ - struct md5_ctx ctx; - - /* Initialize the computation context. */ - md5_init_ctx (&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - md5_process_bytes (buffer, len, &ctx); - - /* Put result in desired memory area. */ - return md5_finish_ctx (&ctx, resblock); -} - - -void -md5_process_bytes (buffer, len, ctx) - const void *buffer; - size_t len; - struct md5_ctx *ctx; -{ - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if (ctx->buflen != 0) - { - size_t left_over = ctx->buflen; - size_t add = 128 - left_over > len ? len : 128 - left_over; - - memcpy (&ctx->buffer[left_over], buffer, add); - ctx->buflen += add; - - if (left_over + add > 64) - { - md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx); - /* The regions in the following copy operation cannot overlap. */ - memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], - (left_over + add) & 63); - ctx->buflen = (left_over + add) & 63; - } - - buffer = (const char *) buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if (len > 64) - { - md5_process_block (buffer, len & ~63, ctx); - buffer = (const char *) buffer + (len & ~63); - len &= 63; - } - - /* Move remaining bytes in internal buffer. */ - if (len > 0) - { - memcpy (ctx->buffer, buffer, len); - ctx->buflen = len; - } -} - - -/* These are the four functions used in the four steps of the MD5 algorithm - and defined in the RFC 1321. The first function is a little bit optimized - (as found in Colin Plumbs public domain implementation). */ -/* #define FF(b, c, d) ((b & c) | (~b & d)) */ -#define FF(b, c, d) (d ^ (b & (c ^ d))) -#define FG(b, c, d) FF (d, b, c) -#define FH(b, c, d) (b ^ c ^ d) -#define FI(b, c, d) (c ^ (b | ~d)) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. */ - -void -md5_process_block (buffer, len, ctx) - const void *buffer; - size_t len; - struct md5_ctx *ctx; -{ - md5_uint32 correct_words[16]; - const md5_uint32 *words = buffer; - size_t nwords = len / sizeof (md5_uint32); - const md5_uint32 *endp = words + nwords; - md5_uint32 A = ctx->A; - md5_uint32 B = ctx->B; - md5_uint32 C = ctx->C; - md5_uint32 D = ctx->D; - - /* First increment the byte count. RFC 1321 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += len; - if (ctx->total[0] < len) - ++ctx->total[1]; - - /* Process all bytes in the buffer with 64 bytes in each round of - the loop. */ - while (words < endp) - { - md5_uint32 *cwp = correct_words; - md5_uint32 A_save = A; - md5_uint32 B_save = B; - md5_uint32 C_save = C; - md5_uint32 D_save = D; - - /* First round: using the given function, the context and a constant - the next context is computed. Because the algorithms processing - unit is a 32-bit word and it is determined to work on words in - little endian byte order we perhaps have to change the byte order - before the computation. To reduce the work for the next steps - we store the swapped words in the array CORRECT_WORDS. */ - -#define OP(a, b, c, d, s, T) \ - do \ - { \ - a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ - ++words; \ - a = rol (a, s); \ - a += b; \ - } \ - while (0) - - /* Before we start, one word to the strange constants. - They are defined in RFC 1321 as - - T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or - perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' - */ - - /* Round 1. */ - OP (A, B, C, D, 7, 0xd76aa478); - OP (D, A, B, C, 12, 0xe8c7b756); - OP (C, D, A, B, 17, 0x242070db); - OP (B, C, D, A, 22, 0xc1bdceee); - OP (A, B, C, D, 7, 0xf57c0faf); - OP (D, A, B, C, 12, 0x4787c62a); - OP (C, D, A, B, 17, 0xa8304613); - OP (B, C, D, A, 22, 0xfd469501); - OP (A, B, C, D, 7, 0x698098d8); - OP (D, A, B, C, 12, 0x8b44f7af); - OP (C, D, A, B, 17, 0xffff5bb1); - OP (B, C, D, A, 22, 0x895cd7be); - OP (A, B, C, D, 7, 0x6b901122); - OP (D, A, B, C, 12, 0xfd987193); - OP (C, D, A, B, 17, 0xa679438e); - OP (B, C, D, A, 22, 0x49b40821); - - /* For the second to fourth round we have the possibly swapped words - in CORRECT_WORDS. Redefine the macro to take an additional first - argument specifying the function to use. */ -#undef OP -#define OP(f, a, b, c, d, k, s, T) \ - do \ - { \ - a += f (b, c, d) + correct_words[k] + T; \ - a = rol (a, s); \ - a += b; \ - } \ - while (0) - - /* Round 2. */ - OP (FG, A, B, C, D, 1, 5, 0xf61e2562); - OP (FG, D, A, B, C, 6, 9, 0xc040b340); - OP (FG, C, D, A, B, 11, 14, 0x265e5a51); - OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); - OP (FG, A, B, C, D, 5, 5, 0xd62f105d); - OP (FG, D, A, B, C, 10, 9, 0x02441453); - OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); - OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); - OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); - OP (FG, D, A, B, C, 14, 9, 0xc33707d6); - OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); - OP (FG, B, C, D, A, 8, 20, 0x455a14ed); - OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); - OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); - OP (FG, C, D, A, B, 7, 14, 0x676f02d9); - OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); - - /* Round 3. */ - OP (FH, A, B, C, D, 5, 4, 0xfffa3942); - OP (FH, D, A, B, C, 8, 11, 0x8771f681); - OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); - OP (FH, B, C, D, A, 14, 23, 0xfde5380c); - OP (FH, A, B, C, D, 1, 4, 0xa4beea44); - OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); - OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); - OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); - OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); - OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); - OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); - OP (FH, B, C, D, A, 6, 23, 0x04881d05); - OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); - OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); - OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); - OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); - - /* Round 4. */ - OP (FI, A, B, C, D, 0, 6, 0xf4292244); - OP (FI, D, A, B, C, 7, 10, 0x432aff97); - OP (FI, C, D, A, B, 14, 15, 0xab9423a7); - OP (FI, B, C, D, A, 5, 21, 0xfc93a039); - OP (FI, A, B, C, D, 12, 6, 0x655b59c3); - OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); - OP (FI, C, D, A, B, 10, 15, 0xffeff47d); - OP (FI, B, C, D, A, 1, 21, 0x85845dd1); - OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); - OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); - OP (FI, C, D, A, B, 6, 15, 0xa3014314); - OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); - OP (FI, A, B, C, D, 4, 6, 0xf7537e82); - OP (FI, D, A, B, C, 11, 10, 0xbd3af235); - OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); - OP (FI, B, C, D, A, 9, 21, 0xeb86d391); - - /* Add the starting values of the context. */ - A += A_save; - B += B_save; - C += C_save; - D += D_save; - } - - /* Put checksum in context given as argument. */ - ctx->A = A; - ctx->B = B; - ctx->C = C; - ctx->D = D; -} diff --git a/dvdread/md5.h b/dvdread/md5.h deleted file mode 100644 index 2d9a8b4..0000000 --- a/dvdread/md5.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -/* md5.h - Declaration of functions and data types used for MD5 sum - computing library functions. - Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc. - NOTE: The canonical source of this file is maintained with the GNU C - Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _MD5_H -#define _MD5_H - -#include - -#if defined HAVE_LIMITS_H || _LIBC -# include -#endif - -/* The following contortions are an attempt to use the C preprocessor - to determine an unsigned integral type that is 32 bits wide. An - alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but - doing that would require that the configure script compile and *run* - the resulting executable. Locally running cross-compiled executables - is usually not possible. */ - -#ifdef _LIBC -# include -typedef u_int32_t md5_uint32; -#else -# if defined __STDC__ && __STDC__ -# define UINT_MAX_32_BITS 4294967295U -# else -# define UINT_MAX_32_BITS 0xFFFFFFFF -# endif - -/* If UINT_MAX isn't defined, assume it's a 32-bit type. - This should be valid for all systems GNU cares about because - that doesn't include 16-bit systems, and only modern systems - (that certainly have ) have 64+-bit integral types. */ - -# ifndef UINT_MAX -# define UINT_MAX UINT_MAX_32_BITS -# endif - -# if UINT_MAX == UINT_MAX_32_BITS -typedef unsigned int md5_uint32; -# else -# if USHRT_MAX == UINT_MAX_32_BITS -typedef unsigned short md5_uint32; -# else -# if ULONG_MAX == UINT_MAX_32_BITS -typedef unsigned long md5_uint32; -# else -/* The following line is intended to evoke an error. - Using #error is not portable enough. */ -"Cannot determine unsigned 32-bit data type." -# endif -# endif -# endif -#endif - -#undef __P -#if defined (__STDC__) && __STDC__ -#define __P(x) x -#else -#define __P(x) () -#endif - -/* Structure to save state of computation between the single steps. */ -struct md5_ctx -{ - md5_uint32 A; - md5_uint32 B; - md5_uint32 C; - md5_uint32 D; - - md5_uint32 total[2]; - md5_uint32 buflen; - char buffer[128]; -}; - -/* - * The following three functions are build up the low level used in - * the functions `md5_stream' and `md5_buffer'. - */ - -/* Initialize structure containing state of computation. - (RFC 1321, 3.3: Step 3) */ -extern void md5_init_ctx __P ((struct md5_ctx *ctx)); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 64!!! */ -extern void md5_process_block __P ((const void *buffer, size_t len, - struct md5_ctx *ctx)); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 64. */ -extern void md5_process_bytes __P ((const void *buffer, size_t len, - struct md5_ctx *ctx)); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 16 bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF be correctly - aligned for a 32 bits value. */ -extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf)); - - -/* Put result from CTX in first 16 bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf)); - - -/* Compute MD5 message digest for bytes read from STREAM. The - resulting message digest number will be written into the 16 bytes - beginning at RESBLOCK. */ -extern int md5_stream __P ((FILE *stream, void *resblock)); - -/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock)); - -/* The following is from gnupg-1.0.2's cipher/bithelp.h. */ -/* Rotate a 32 bit integer by n bytes */ -#if defined __GNUC__ && defined __i386__ -static md5_uint32 -rol(md5_uint32 x, int n) -{ - __asm__("roll %%cl,%0" - :"=r" (x) - :"0" (x),"c" (n)); - return x; -} -#else -# define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) -#endif - -#endif diff --git a/dvdread/nav_read.c b/dvdread/nav_read.c deleted file mode 100644 index a96cd75..0000000 --- a/dvdread/nav_read.c +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -/* - * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include -#include -#if defined(HAVE_INTTYPES_H) -#include -#elif defined(HAVE_STDINT_H) -#include -#endif - -#include "bswap.h" -#include "nav_types.h" -#include "nav_read.h" -#include "dvdread_internal.h" - -void navRead_PCI(pci_t *pci, unsigned char *buffer) { - int i, j; - - CHECK_VALUE(sizeof(pci_t) == PCI_BYTES - 1); /* -1 for substream id*/ - - memcpy(pci, buffer, sizeof(pci_t)); - - /* Endian conversions */ - - /* pci pci_gi */ - B2N_32(pci->pci_gi.nv_pck_lbn); - B2N_16(pci->pci_gi.vobu_cat); - B2N_32(pci->pci_gi.vobu_s_ptm); - B2N_32(pci->pci_gi.vobu_e_ptm); - B2N_32(pci->pci_gi.vobu_se_e_ptm); - - /* pci nsml_agli */ - for(i = 0; i < 9; i++) - B2N_32(pci->nsml_agli.nsml_agl_dsta[i]); - - /* pci hli hli_gi */ - B2N_16(pci->hli.hl_gi.hli_ss); - B2N_32(pci->hli.hl_gi.hli_s_ptm); - B2N_32(pci->hli.hl_gi.hli_e_ptm); - B2N_32(pci->hli.hl_gi.btn_se_e_ptm); - - /* pci hli btn_colit */ - for(i = 0; i < 3; i++) - for(j = 0; j < 2; j++) - B2N_32(pci->hli.btn_colit.btn_coli[i][j]); - - /* NOTE: I've had to change the structure from the disk layout to get - * the packing to work with Sun's Forte C compiler. */ - - /* pci hli btni */ - for(i = 0; i < 36; i++) { - char tmp[sizeof(pci->hli.btnit[i])], swap; - memcpy(tmp, &(pci->hli.btnit[i]), sizeof(pci->hli.btnit[i])); - /* Byte 4 to 7 are 'rotated' was: ABCD EFGH IJ is: ABCG DEFH IJ */ - swap = tmp[6]; - tmp[6] = tmp[5]; - tmp[5] = tmp[4]; - tmp[4] = tmp[3]; - tmp[3] = swap; - - /* Then there are the two B2N_24(..) calls */ -#ifndef WORDS_BIGENDIAN - swap = tmp[0]; - tmp[0] = tmp[2]; - tmp[2] = swap; - - swap = tmp[4]; - tmp[4] = tmp[6]; - tmp[6] = swap; -#endif - memcpy(&(pci->hli.btnit[i]), tmp, sizeof(pci->hli.btnit[i])); - } - - -#ifndef NDEBUG - /* Asserts */ - - /* pci pci gi */ - CHECK_VALUE(pci->pci_gi.zero1 == 0); - - /* pci hli hli_gi */ - CHECK_VALUE(pci->hli.hl_gi.zero1 == 0); - CHECK_VALUE(pci->hli.hl_gi.zero2 == 0); - CHECK_VALUE(pci->hli.hl_gi.zero3 == 0); - CHECK_VALUE(pci->hli.hl_gi.zero4 == 0); - CHECK_VALUE(pci->hli.hl_gi.zero5 == 0); - - /* Are there buttons defined here? */ - if((pci->hli.hl_gi.hli_ss & 0x03) != 0) { - CHECK_VALUE(pci->hli.hl_gi.btn_ns != 0); - CHECK_VALUE(pci->hli.hl_gi.btngr_ns != 0); - } else { - CHECK_VALUE((pci->hli.hl_gi.btn_ns != 0 && pci->hli.hl_gi.btngr_ns != 0) - || (pci->hli.hl_gi.btn_ns == 0 && pci->hli.hl_gi.btngr_ns == 0)); - } - - /* pci hli btnit */ - for(i = 0; i < pci->hli.hl_gi.btngr_ns; i++) { - for(j = 0; j < (36 / pci->hli.hl_gi.btngr_ns); j++) { - int n = (36 / pci->hli.hl_gi.btngr_ns) * i + j; - CHECK_VALUE(pci->hli.btnit[n].zero1 == 0); - CHECK_VALUE(pci->hli.btnit[n].zero2 == 0); - CHECK_VALUE(pci->hli.btnit[n].zero3 == 0); - CHECK_VALUE(pci->hli.btnit[n].zero4 == 0); - CHECK_VALUE(pci->hli.btnit[n].zero5 == 0); - CHECK_VALUE(pci->hli.btnit[n].zero6 == 0); - - if (j < pci->hli.hl_gi.btn_ns) { - CHECK_VALUE(pci->hli.btnit[n].x_start <= pci->hli.btnit[n].x_end); - CHECK_VALUE(pci->hli.btnit[n].y_start <= pci->hli.btnit[n].y_end); - CHECK_VALUE(pci->hli.btnit[n].up <= pci->hli.hl_gi.btn_ns); - CHECK_VALUE(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns); - CHECK_VALUE(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns); - CHECK_VALUE(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns); - /*vmcmd_verify(pci->hli.btnit[n].cmd);*/ - } else { - int k; - CHECK_VALUE(pci->hli.btnit[n].btn_coln == 0); - CHECK_VALUE(pci->hli.btnit[n].auto_action_mode == 0); - CHECK_VALUE(pci->hli.btnit[n].x_start == 0); - CHECK_VALUE(pci->hli.btnit[n].y_start == 0); - CHECK_VALUE(pci->hli.btnit[n].x_end == 0); - CHECK_VALUE(pci->hli.btnit[n].y_end == 0); - CHECK_VALUE(pci->hli.btnit[n].up == 0); - CHECK_VALUE(pci->hli.btnit[n].down == 0); - CHECK_VALUE(pci->hli.btnit[n].left == 0); - CHECK_VALUE(pci->hli.btnit[n].right == 0); - for (k = 0; k < 8; k++) - CHECK_VALUE(pci->hli.btnit[n].cmd.bytes[k] == 0); /*CHECK_ZERO?*/ - } - } - } -#endif /* !NDEBUG */ -} - -void navRead_DSI(dsi_t *dsi, unsigned char *buffer) { - int i; - - CHECK_VALUE(sizeof(dsi_t) == DSI_BYTES - 1); /* -1 for substream id*/ - - memcpy(dsi, buffer, sizeof(dsi_t)); - - /* Endian conversions */ - - /* dsi dsi gi */ - B2N_32(dsi->dsi_gi.nv_pck_scr); - B2N_32(dsi->dsi_gi.nv_pck_lbn); - B2N_32(dsi->dsi_gi.vobu_ea); - B2N_32(dsi->dsi_gi.vobu_1stref_ea); - B2N_32(dsi->dsi_gi.vobu_2ndref_ea); - B2N_32(dsi->dsi_gi.vobu_3rdref_ea); - B2N_16(dsi->dsi_gi.vobu_vob_idn); - - /* dsi sml pbi */ - B2N_16(dsi->sml_pbi.category); - B2N_32(dsi->sml_pbi.ilvu_ea); - B2N_32(dsi->sml_pbi.ilvu_sa); - B2N_16(dsi->sml_pbi.size); - B2N_32(dsi->sml_pbi.vob_v_s_s_ptm); - B2N_32(dsi->sml_pbi.vob_v_e_e_ptm); - - /* dsi sml agli */ - for(i = 0; i < 9; i++) { - B2N_32(dsi->sml_agli.data[ i ].address); - B2N_16(dsi->sml_agli.data[ i ].size); - } - - /* dsi vobu sri */ - B2N_32(dsi->vobu_sri.next_video); - for(i = 0; i < 19; i++) - B2N_32(dsi->vobu_sri.fwda[i]); - B2N_32(dsi->vobu_sri.next_vobu); - B2N_32(dsi->vobu_sri.prev_vobu); - for(i = 0; i < 19; i++) - B2N_32(dsi->vobu_sri.bwda[i]); - B2N_32(dsi->vobu_sri.prev_video); - - /* dsi synci */ - for(i = 0; i < 8; i++) - B2N_16(dsi->synci.a_synca[i]); - for(i = 0; i < 32; i++) - B2N_32(dsi->synci.sp_synca[i]); - - - /* Asserts */ - - /* dsi dsi gi */ - CHECK_VALUE(dsi->dsi_gi.zero1 == 0); -} - diff --git a/dvdread/nav_read.h b/dvdread/nav_read.h deleted file mode 100644 index d6c1a18..0000000 --- a/dvdread/nav_read.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -#ifndef NAV_READ_H_INCLUDED -#define NAV_READ_H_INCLUDED - -/* - * Copyright (C) 2000, 2001, 2002 Håkan Hjort . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "nav_types.h" - -/** - * Parsing of NAV data, PCI and DSI parts. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Reads the PCI packet data pointed to into th pci struct. - * - * @param pci Pointer to the PCI data structure to be filled in. - * @param bufffer Pointer to the buffer of the on disc PCI data. - */ -void navRead_PCI(pci_t *, unsigned char *); - -/** - * Reads the DSI packet data pointed to into dsi struct. - * - * @param dsi Pointer to the DSI data structure to be filled in. - * @param bufffer Pointer to the buffer of the on disc DSI data. - */ -void navRead_DSI(dsi_t *, unsigned char *); - -#ifdef __cplusplus -}; -#endif -#endif /* NAV_READ_H_INCLUDED */ diff --git a/dvdread/nav_types.h b/dvdread/nav_types.h deleted file mode 100644 index 0678398..0000000 --- a/dvdread/nav_types.h +++ /dev/null @@ -1,307 +0,0 @@ -/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ -#ifndef NAV_TYPES_H_INCLUDED -#define NAV_TYPES_H_INCLUDED - -/* - * Copyright (C) 2000, 2001, 2002 Håkan Hjort - * - * The data structures in this file should represent the layout of the - * pci and dsi packets as they are stored in the stream. Information - * found by reading the source to VOBDUMP is the base for the structure - * and names of these data types. - * - * VOBDUMP: a program for examining DVD .VOB files. - * Copyright 1998, 1999 Eric Smith - * - * VOBDUMP is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. Note that I am not - * granting permission to redistribute or modify VOBDUMP under the terms - * of any later version of the General Public License. - * - * This program is distributed in the hope that it will be useful (or at - * least amusing), but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -#include "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 -#undef PRAGMA_PACK_END - -#if defined(__GNUC__) -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) -#define ATTRIBUTE_PACKED __attribute__ ((packed)) -#define PRAGMA_PACK 0 -#endif -#endif - -#if !defined(ATTRIBUTE_PACKED) -#define ATTRIBUTE_PACKED -#define PRAGMA_PACK 1 -#endif - - -/* The length including the substream id byte. */ -#define PCI_BYTES 0x3d4 -#define DSI_BYTES 0x3fa - -#define PS2_PCI_SUBSTREAM_ID 0x00 -#define PS2_DSI_SUBSTREAM_ID 0x01 - -/* Remove this */ -#define DSI_START_BYTE 1031 - - -#if PRAGMA_PACK -#pragma pack(1) -#endif - - -/** - * PCI General Information - */ -typedef struct { - uint32_t nv_pck_lbn; /**< sector address of this nav pack */ - uint16_t vobu_cat; /**< 'category' of vobu */ - uint16_t zero1; /**< reserved */ - user_ops_t vobu_uop_ctl; /**< UOP of vobu */ - uint32_t vobu_s_ptm; /**< start presentation time of vobu */ - uint32_t vobu_e_ptm; /**< end presentation time of vobu */ - uint32_t vobu_se_e_ptm; /**< end ptm of sequence end in vobu */ - dvd_time_t e_eltm; /**< Cell elapsed time */ - char vobu_isrc[32]; -} ATTRIBUTE_PACKED pci_gi_t; - -/** - * Non Seamless Angle Information - */ -typedef struct { - uint32_t nsml_agl_dsta[9]; /**< address of destination vobu in AGL_C#n */ -} ATTRIBUTE_PACKED nsml_agli_t; - -/** - * Highlight General Information - * - * For btngrX_dsp_ty the bits have the following meaning: - * 000b: normal 4/3 only buttons - * XX1b: wide (16/9) buttons - * X1Xb: letterbox buttons - * 1XXb: pan&scan buttons - */ -typedef struct { - uint16_t hli_ss; /**< status, only low 2 bits 0: no buttons, 1: different 2: equal 3: eual except for button cmds */ - uint32_t hli_s_ptm; /**< start ptm of hli */ - uint32_t hli_e_ptm; /**< end ptm of hli */ - uint32_t btn_se_e_ptm; /**< end ptm of button select */ -#ifdef WORDS_BIGENDIAN - unsigned int zero1 : 2; /**< reserved */ - unsigned int btngr_ns : 2; /**< number of button groups 1, 2 or 3 with 36/18/12 buttons */ - unsigned int zero2 : 1; /**< reserved */ - unsigned int btngr1_dsp_ty : 3; /**< display type of subpic stream for button group 1 */ - unsigned int zero3 : 1; /**< reserved */ - unsigned int btngr2_dsp_ty : 3; /**< display type of subpic stream for button group 2 */ - unsigned int zero4 : 1; /**< reserved */ - unsigned int btngr3_dsp_ty : 3; /**< display type of subpic stream for button group 3 */ -#else - unsigned int btngr1_dsp_ty : 3; - unsigned int zero2 : 1; - unsigned int btngr_ns : 2; - unsigned int zero1 : 2; - unsigned int btngr3_dsp_ty : 3; - unsigned int zero4 : 1; - unsigned int btngr2_dsp_ty : 3; - unsigned int zero3 : 1; -#endif - uint8_t btn_ofn; /**< button offset number range 0-255 */ - uint8_t btn_ns; /**< number of valid buttons <= 36/18/12 (low 6 bits) */ - uint8_t nsl_btn_ns; /**< number of buttons selectable by U_BTNNi (low 6 bits) nsl_btn_ns <= btn_ns */ - uint8_t zero5; /**< reserved */ - uint8_t fosl_btnn; /**< forcedly selected button (low 6 bits) */ - uint8_t foac_btnn; /**< forcedly activated button (low 6 bits) */ -} ATTRIBUTE_PACKED hl_gi_t; - - -/** - * Button Color Information Table - * Each entry beeing a 32bit word that contains the color indexs and alpha - * values to use. They are all represented by 4 bit number and stored - * like this [Ci3, Ci2, Ci1, Ci0, A3, A2, A1, A0]. The actual palette - * that the indexes reference is in the PGC. - * @TODO split the uint32_t into a struct - */ -typedef struct { - uint32_t btn_coli[3][2]; /**< [button color number-1][select:0/action:1] */ -} ATTRIBUTE_PACKED btn_colit_t; - -/** - * Button Information - * - * NOTE: I've had to change the structure from the disk layout to get - * the packing to work with Sun's Forte C compiler. - * The 4 and 7 bytes are 'rotated' was: ABC DEF GHIJ is: ABCG DEFH IJ - */ -typedef struct { -#ifdef WORDS_BIGENDIAN - unsigned int btn_coln : 2; /**< button color number */ - unsigned int x_start : 10; /**< x start offset within the overlay */ - unsigned int zero1 : 2; /**< reserved */ - unsigned int x_end : 10; /**< x end offset within the overlay */ - - unsigned int zero3 : 2; /**< reserved */ - unsigned int up : 6; /**< button index when pressing up */ - - unsigned int auto_action_mode : 2; /**< 0: no, 1: activated if selected */ - unsigned int y_start : 10; /**< y start offset within the overlay */ - unsigned int zero2 : 2; /**< reserved */ - unsigned int y_end : 10; /**< y end offset within the overlay */ - - unsigned int zero4 : 2; /**< reserved */ - unsigned int down : 6; /**< button index when pressing down */ - unsigned int zero5 : 2; /**< reserved */ - unsigned int left : 6; /**< button index when pressing left */ - unsigned int zero6 : 2; /**< reserved */ - unsigned int right : 6; /**< button index when pressing right */ -#else - unsigned int x_end : 10; - unsigned int zero1 : 2; - unsigned int x_start : 10; - unsigned int btn_coln : 2; - - unsigned int up : 6; - unsigned int zero3 : 2; - - unsigned int y_end : 10; - unsigned int zero2 : 2; - unsigned int y_start : 10; - unsigned int auto_action_mode : 2; - - unsigned int down : 6; - unsigned int zero4 : 2; - unsigned int left : 6; - unsigned int zero5 : 2; - unsigned int right : 6; - unsigned int zero6 : 2; -#endif - vm_cmd_t cmd; -} ATTRIBUTE_PACKED btni_t; - -/** - * Highlight Information - */ -typedef struct { - hl_gi_t hl_gi; - btn_colit_t btn_colit; - btni_t btnit[36]; -} ATTRIBUTE_PACKED hli_t; - -/** - * PCI packet - */ -typedef struct { - pci_gi_t pci_gi; - nsml_agli_t nsml_agli; - hli_t hli; - uint8_t zero1[189]; -} ATTRIBUTE_PACKED pci_t; - - - - -/** - * DSI General Information - */ -typedef struct { - uint32_t nv_pck_scr; - uint32_t nv_pck_lbn; /**< sector address of this nav pack */ - uint32_t vobu_ea; /**< end address of this VOBU */ - uint32_t vobu_1stref_ea; /**< end address of the 1st reference image */ - uint32_t vobu_2ndref_ea; /**< end address of the 2nd reference image */ - uint32_t vobu_3rdref_ea; /**< end address of the 3rd reference image */ - uint16_t vobu_vob_idn; /**< VOB Id number that this VOBU is part of */ - uint8_t zero1; /**< reserved */ - uint8_t vobu_c_idn; /**< Cell Id number that this VOBU is part of */ - dvd_time_t c_eltm; /**< Cell elapsed time */ -} ATTRIBUTE_PACKED dsi_gi_t; - -/** - * Seamless Playback Information - */ -typedef struct { - uint16_t category; /**< 'category' of seamless VOBU */ - uint32_t ilvu_ea; /**< end address of interleaved Unit */ - uint32_t ilvu_sa; /**< start address of next interleaved unit */ - uint16_t size; /**< size of next interleaved unit */ - uint32_t vob_v_s_s_ptm; /**< video start ptm in vob */ - uint32_t vob_v_e_e_ptm; /**< video end ptm in vob */ - struct { - uint32_t stp_ptm1; - uint32_t stp_ptm2; - uint32_t gap_len1; - uint32_t gap_len2; - } vob_a[8]; -} ATTRIBUTE_PACKED sml_pbi_t; - -/** - * Seamless Angle Infromation for one angle - */ -typedef struct { - uint32_t address; /**< offset to next ILVU, high bit is before/after */ - uint16_t size; /**< byte size of the ILVU pointed to by address */ -} ATTRIBUTE_PACKED sml_agl_data_t; - -/** - * Seamless Angle Infromation - */ -typedef struct { - sml_agl_data_t data[9]; -} ATTRIBUTE_PACKED sml_agli_t; - -/** - * VOBU Search Information - */ -typedef struct { - uint32_t next_video; /**< Next vobu that contains video */ - uint32_t fwda[19]; /**< Forwards, time */ - uint32_t next_vobu; - uint32_t prev_vobu; - uint32_t bwda[19]; /**< Backwards, time */ - uint32_t prev_video; -} ATTRIBUTE_PACKED vobu_sri_t; - -#define SRI_END_OF_CELL 0x3fffffff - -/** - * Synchronous Information - */ -typedef struct { - uint16_t a_synca[8]; /**< offset to first audio packet for this VOBU */ - uint32_t sp_synca[32]; /**< offset to first subpicture packet */ -} ATTRIBUTE_PACKED synci_t; - -/** - * DSI packet - */ -typedef struct { - dsi_gi_t dsi_gi; - sml_pbi_t sml_pbi; - sml_agli_t sml_agli; - vobu_sri_t vobu_sri; - synci_t synci; - uint8_t zero1[471]; -} ATTRIBUTE_PACKED dsi_t; - - -#if PRAGMA_PACK -#pragma pack() -#endif - -#endif /* NAV_TYPES_H_INCLUDED */