diff options
author | Voyager1 <voyager@xbmc.org> | 2014-01-29 21:41:41 +0100 |
---|---|---|
committer | Voyager1 <voyager@xbmc.org> | 2014-02-11 19:23:28 +0100 |
commit | 19ac2c411c2166201ac24998e2b1c3e930ee5c0e (patch) | |
tree | 60170364c7e1838a13a823dc12041864bea6f530 /lib/libdvd | |
parent | d69747f8a266759691ae51f52b9fd81378f90336 (diff) |
libdvdread-libdvdnav update to 4.2.1
Diffstat (limited to 'lib/libdvd')
23 files changed, 306 insertions, 113 deletions
diff --git a/lib/libdvd/libdvdnav/ChangeLog b/lib/libdvd/libdvdnav/ChangeLog index c038ef11be..470b3941c1 100644 --- a/lib/libdvd/libdvdnav/ChangeLog +++ b/lib/libdvd/libdvdnav/ChangeLog @@ -1,3 +1,11 @@ +libdvdnav (4.2.1) + * fixed failed assertion on menu-less DVDs + * fixed playback issues on multi-angle DVDs + * fixed crash when playing a DVD from different region than currently set + in the DVD drive + * fixed segfaults when reading certain DVDs (including "Jack Reacher", + "Ghost Protocol", "Inside Man", "Tangled" and "The Dictator") + libdvdnav (4.2.0) * OS/2 support * added dvdnav_get_serial_string() function diff --git a/lib/libdvd/libdvdnav/configure.ac b/lib/libdvd/libdvdnav/configure.ac index 20acae17e8..8c5bafdaf2 100644 --- a/lib/libdvd/libdvdnav/configure.ac +++ b/lib/libdvd/libdvdnav/configure.ac @@ -14,7 +14,7 @@ dnl These are defined in m4 so they can be passed to AC_INIT dnl -------------------------------------------------------------- m4_define([dvdnav_major], [4]) m4_define([dvdnav_minor], [2]) -m4_define([dvdnav_sub], [0]) +m4_define([dvdnav_sub], [1]) m4_define([dvdnav_pre], []) AC_INIT([libdvdnav], [dvdnav_major.dvdnav_minor.dvdnav_sub[]dvdnav_pre]) diff --git a/lib/libdvd/libdvdnav/configure2 b/lib/libdvd/libdvdnav/configure2 index 8c3b917c2b..298b0f8093 100755 --- a/lib/libdvd/libdvdnav/configure2 +++ b/lib/libdvd/libdvdnav/configure2 @@ -1,6 +1,6 @@ #!/bin/sh -dvdnav_sh_version=4.2.0 +dvdnav_sh_version=4.2.1 dvdnav_sh_major=`echo $dvdnav_sh_version | awk -F. '{print $1}'` cc=gcc diff --git a/lib/libdvd/libdvdnav/src/dvdnav.c b/lib/libdvd/libdvdnav/src/dvdnav.c index 6009b37f6c..fd2a187022 100644 --- a/lib/libdvd/libdvdnav/src/dvdnav.c +++ b/lib/libdvd/libdvdnav/src/dvdnav.c @@ -203,7 +203,7 @@ int64_t dvdnav_convert_time(dvd_time_t *time) { int64_t result; int64_t frames; - result = (time->hour >> 4 ) * 10 * 60 * 60 * 90000; + result = (time->hour >> 4 ) * 10 * 60 * 60 * 90000ull; result += (time->hour & 0x0f) * 60 * 60 * 90000; result += (time->minute >> 4 ) * 10 * 60 * 90000; result += (time->minute & 0x0f) * 60 * 90000; @@ -336,10 +336,9 @@ static int32_t dvdnav_get_vobu(dvdnav_t *this, dsi_t *nav_dsi, pci_t *nav_pci, d dvdnav_angle_change(this, 1); } #endif - /* only use ILVU information if we are at the last vobunit in ILVU */ /* otherwise we will miss nav packets from vobunits inbetween */ - if(num_angle != 0 && (nav_dsi->sml_pbi.category & 0x5000) == 0x5000 ) { + if(num_angle != 0 && (nav_dsi->sml_pbi.category & DSI_ILVU_MASK) == (DSI_ILVU_BLOCK | DSI_ILVU_LAST)) { if((next = nav_pci->nsml_agli.nsml_agl_dsta[angle-1]) != 0) { if((next & 0x3fffffff) != 0) { @@ -1163,7 +1162,7 @@ user_ops_t dvdnav_get_restrictions(dvdnav_t* this) { union { user_ops_t ops_struct; uint32_t ops_int; - } ops; + } ops, tmp; ops.ops_int = 0; @@ -1171,16 +1170,19 @@ user_ops_t dvdnav_get_restrictions(dvdnav_t* this) { printerr("Passed a NULL pointer."); return ops.ops_struct; } + if(!this->started) { printerr("Virtual DVD machine not started."); return ops.ops_struct; } pthread_mutex_lock(&this->vm_lock); - ops.ops_int |= *(uint32_t*)&this->pci.pci_gi.vobu_uop_ctl; + ops.ops_struct = this->pci.pci_gi.vobu_uop_ctl; - if(this->vm && this->vm->state.pgc) - ops.ops_int |= *(uint32_t*)&this->vm->state.pgc->prohibited_ops; + if(this->vm && this->vm->state.pgc) { + tmp.ops_struct = this->vm->state.pgc->prohibited_ops; + ops.ops_int |= tmp.ops_int; + } pthread_mutex_unlock(&this->vm_lock); return ops.ops_struct; @@ -1444,4 +1446,3 @@ void dvdnav_unlock(dvdnav_t *self) } #endif // _XBMC - diff --git a/lib/libdvd/libdvdnav/src/dvdnav/dvdnav.h b/lib/libdvd/libdvdnav/src/dvdnav/dvdnav.h index 506a2867d3..d24e0a602a 100644 --- a/lib/libdvd/libdvdnav/src/dvdnav/dvdnav.h +++ b/lib/libdvd/libdvdnav/src/dvdnav/dvdnav.h @@ -275,7 +275,7 @@ dvdnav_status_t dvdnav_part_play(dvdnav_t *self, int32_t title, int32_t part); /* * Plays the specified title, starting from the specified program */ -dvdnav_status_t dvdnav_program_play(dvdnav_t *this, int32_t title, int32_t pgcn, int32_t pgn); +dvdnav_status_t dvdnav_program_play(dvdnav_t *self, int32_t title, int32_t pgcn, int32_t pgn); /* * Stores in *times an array (that the application *must* free) of @@ -384,7 +384,7 @@ dvdnav_status_t dvdnav_jump_to_sector_by_time(dvdnav_t *this, * Stop playing the current position and start playback of the title * from the specified timecode. * - * Currently unimplemented! + * Currently implemented using interpolation, which is slightly inaccurate. */ dvdnav_status_t dvdnav_time_search(dvdnav_t *self, uint64_t time); diff --git a/lib/libdvd/libdvdnav/src/dvdnav_internal.h b/lib/libdvd/libdvdnav/src/dvdnav_internal.h index df26014d8d..8fdd1f0904 100644 --- a/lib/libdvd/libdvdnav/src/dvdnav_internal.h +++ b/lib/libdvd/libdvdnav/src/dvdnav_internal.h @@ -76,6 +76,14 @@ static inline int _private_gettimeofday( struct timeval *tv, void *tz ) #define DVD_VIDEO_LB_LEN 2048 #endif +typedef enum { + DSI_ILVU_PRE = 1 << 15, /* set during the last 3 VOBU preceeding an interleaved block. */ + DSI_ILVU_BLOCK = 1 << 14, /* set for all VOBU in an interleaved block */ + DSI_ILVU_FIRST = 1 << 13, /* set for the first VOBU for a given angle or scene within a ILVU, or the first VOBU in the preparation (PREU) sequence */ + DSI_ILVU_LAST = 1 << 12, /* set for the last VOBU for a given angle or scene within a ILVU, or the last VOBU in the preparation (PREU) sequence */ + DSI_ILVU_MASK = 0xf000 +} DSI_ILVU; + typedef struct read_cache_s read_cache_t; /* diff --git a/lib/libdvd/libdvdnav/src/navigation.c b/lib/libdvd/libdvdnav/src/navigation.c index efce45e102..6f8a080b06 100644 --- a/lib/libdvd/libdvdnav/src/navigation.c +++ b/lib/libdvd/libdvdnav/src/navigation.c @@ -268,9 +268,11 @@ dvdnav_status_t dvdnav_stop(dvdnav_t *this) { dvdnav_status_t dvdnav_go_up(dvdnav_t *this) { /* A nice easy function... delegate to the VM */ + int32_t retval; + pthread_mutex_lock(&this->vm_lock); - vm_jump_up(this->vm); + retval = vm_jump_up(this->vm); pthread_mutex_unlock(&this->vm_lock); - return DVDNAV_STATUS_OK; + return retval ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR; } diff --git a/lib/libdvd/libdvdnav/src/remap.c b/lib/libdvd/libdvdnav/src/remap.c index f1dea937c4..4632a49dab 100644 --- a/lib/libdvd/libdvdnav/src/remap.c +++ b/lib/libdvd/libdvdnav/src/remap.c @@ -22,6 +22,7 @@ #include <stdlib.h> #include <string.h> +#include <strings.h> #include <stdio.h> #ifndef _MSC_VER diff --git a/lib/libdvd/libdvdnav/src/searching.c b/lib/libdvd/libdvdnav/src/searching.c index 0115e2fa21..3f4a6df1e4 100644 --- a/lib/libdvd/libdvdnav/src/searching.c +++ b/lib/libdvd/libdvdnav/src/searching.c @@ -709,13 +709,41 @@ uint32_t dvdnav_describe_title_chapters(dvdnav_t *this, int32_t title, uint64_t length = 0; for(i=0; i<parts; i++) { uint32_t cellnr, endcellnr; + if (ptt[i].pgcn == 0 || ptt[i].pgcn > ifo->vts_pgcit->nr_of_pgci_srp) { + printerr("PGCN out of bounds."); + continue; + } + if (ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc_start_byte >= ifo->vts_pgcit->last_byte) { + printerr("PGC start out of bounds"); + continue; + } pgc = ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc; - if(ptt[i].pgn > pgc->nr_of_programs) { + if (pgc == NULL) { + printerr("PGC missing."); + continue; + } + if (pgc->program_map == NULL) { + printerr("Program map missing."); + continue; + } + if(ptt[i].pgn == 0 || ptt[i].pgn > pgc->nr_of_programs) { printerr("WRONG part number."); goto fail; } - cellnr = pgc->program_map[ptt[i].pgn-1]; + if (pgc->nr_of_cells == 0) { + printerr("Number of cells cannot be 0"); + continue; + } + if ((cellnr = pgc->program_map[ptt[i].pgn-1]) == 0) { + printerr("Cell new row cannot be 0"); + continue; + } + if (pgc->cell_playback == NULL) { + printerr("Cell missing"); + continue; + } + if(ptt[i].pgn < pgc->nr_of_programs) endcellnr = pgc->program_map[ptt[i].pgn]; else diff --git a/lib/libdvd/libdvdnav/src/vm/vm.c b/lib/libdvd/libdvdnav/src/vm/vm.c index a14e6750af..ed3342febd 100644 --- a/lib/libdvd/libdvdnav/src/vm/vm.c +++ b/lib/libdvd/libdvdnav/src/vm/vm.c @@ -59,7 +59,7 @@ #endif /* -#define STRICT +#define DVDNAV_STRICT */ /* Local prototypes */ @@ -272,7 +272,7 @@ static int ifoOpenNewVTSI(vm_t *vm, dvd_reader_t *dvd, int vtsN) { /* Initialisation & Destruction */ vm_t* vm_new_vm() { - return (vm_t*)calloc(sizeof(vm_t), sizeof(char)); + return (vm_t*)calloc(1, sizeof(vm_t)); } void vm_free_vm(vm_t *vm) { @@ -358,6 +358,8 @@ int vm_reset(vm_t *vm, const char *dvdroot) { (vm->state).vtsN = -1; + vm->hop_channel = 0; + if (vm->dvd && dvdroot) { /* a new dvd device has been requested */ vm_stop(vm); @@ -1144,7 +1146,7 @@ static link_t play_Cell(vm_t *vm) { case 1: /* Angle block */ /* Loop and check each cell instead? So we don't get outside the block? */ (vm->state).cellN += (vm->state).AGL_REG - 1; -#ifdef STRICT +#ifdef DVDNAV_STRICT assert((vm->state).cellN <= (vm->state).pgc->nr_of_cells); assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode != 0); assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 1); @@ -1777,7 +1779,8 @@ static int set_PGCN(vm_t *vm, int pgcN) { pgcit_t *pgcit; pgcit = get_PGCIT(vm); - assert(pgcit != NULL); /* ?? Make this return -1 instead */ + if (pgcit == NULL) + return 0; if(pgcN < 1 || pgcN > pgcit->nr_of_pgci_srp) { #ifdef TRACE diff --git a/lib/libdvd/libdvdnav/version.h b/lib/libdvd/libdvdnav/version.h index 8a8730651b..ddbe066ef1 100644 --- a/lib/libdvd/libdvdnav/version.h +++ b/lib/libdvd/libdvdnav/version.h @@ -1 +1 @@ -#define VERSION "4.2.0" +#define VERSION "4.2.1" diff --git a/lib/libdvd/libdvdread/ChangeLog b/lib/libdvd/libdvdread/ChangeLog index ab8eaaeceb..5d074bfe20 100644 --- a/lib/libdvd/libdvdread/ChangeLog +++ b/lib/libdvd/libdvdread/ChangeLog @@ -1,3 +1,9 @@ +libdvdread (4.2.1) + * fix huge memory consumption when reading DVDs: "Up" and "Dark Knight" + * fix segfault when reading DVDs: "The Express", "Transformers 3" + and "Cars 2" + * fix packed structures with mingw gcc >= 4.7 + libdvdread (4.2.0) * added OS/2 support * fixed ARM memory alignment issue diff --git a/lib/libdvd/libdvdread/configure.ac b/lib/libdvd/libdvdread/configure.ac index 596a752c7c..79da93f855 100644 --- a/lib/libdvd/libdvdread/configure.ac +++ b/lib/libdvd/libdvdread/configure.ac @@ -14,11 +14,12 @@ dnl These are defined in m4 so they can be passed to AC_INIT dnl -------------------------------------------------------------- m4_define([dvdread_major], [4]) m4_define([dvdread_minor], [2]) -m4_define([dvdread_sub], [0]) +m4_define([dvdread_sub], [1]) m4_define([dvdread_pre], []) AC_INIT([libdvdread], [dvdread_major.dvdread_minor.dvdread_sub[]dvdread_pre]) AC_CONFIG_SRCDIR([src/dvdread/dvd_reader.h]) +m4_include([m4/ax_check_compile_flag.m4]) AM_INIT_AUTOMAKE([1.6]) dnl create a config.h file (Automake will add -DHAVE_CONFIG_H) @@ -168,6 +169,11 @@ DEBUG_CFLAGS="-g -DDEBUG $CFLAGS" AC_SUBST(DEBUG_CFLAGS) dnl --------------------------------------------- +dnl Check for bitfield compiler flag +dnl --------------------------------------------- +AX_CHECK_COMPILE_FLAG([-mno-ms-bitfields], [CFLAGS="-mno-ms-bitfields $CFLAGS"]) + +dnl --------------------------------------------- dnl Check for doxygen (dynamic documentation generator) dnl --------------------------------------------- AC_CHECK_PROG(DOXYGEN, doxygen, doxygen, no) diff --git a/lib/libdvd/libdvdread/configure2 b/lib/libdvd/libdvdread/configure2 index f9facbee7d..e2cdb9e0c1 100755 --- a/lib/libdvd/libdvdread/configure2 +++ b/lib/libdvd/libdvdread/configure2 @@ -1,6 +1,6 @@ #!/bin/sh -dvdread_sh_version=4.2.0 +dvdread_sh_version=4.2.1 dvdread_sh_major=`echo $dvdread_sh_version | awk -F. '{print $1}'` cc=gcc @@ -121,6 +121,18 @@ od -A n -t x1 $TMPO | grep -q '42 *49 *47 *45' && bigendian=yes rm -rf $TMPD echo "$bigendian" +echo -n "Checking for -mno-ms-bitfields flag support... " +no_ms_bitfields=no +TMPD=`mktemp -d` +TMPC=$TMPD/no_ms_bitfields.c +TMPO=$TMPD/no_ms_bitfields.o +cat > $TMPC <<EOF +int main(void) { return 0; } +EOF +$cc $optimizations $cflags -mno-ms-bitfields -c -o $TMPO $TMPC && no_ms_bitfields=yes && cflags="$cflags -mno-ms-bitfields" +rm -rf $TMPD +echo "$no_ms_bitfields" + cat > config.mak << EOF # Automatically generated by configure, do not edit PREFIX=$PREFIX @@ -149,7 +161,7 @@ cat > config.h << EOF /* Automatically generated by configure, do not edit */ #include "version.h" EOF -test "$bigendian" = "yes" && echo "#define WORDS_BIGENDIAN" || echo "#undef WORDS_BIGENDIAN" >> config.h +test "$bigendian" = "yes" && echo "#define WORDS_BIGENDIAN" >> config.h || echo "#undef WORDS_BIGENDIAN" >> config.h # build tree in object directory if source path is different from current one if test "$source_path_used" != "no"; then diff --git a/lib/libdvd/libdvdread/m4/ax_check_compile_flag.m4 b/lib/libdvd/libdvdread/m4/ax_check_compile_flag.m4 new file mode 100644 index 0000000000..c3a8d695a1 --- /dev/null +++ b/lib/libdvd/libdvdread/m4/ax_check_compile_flag.m4 @@ -0,0 +1,72 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> +# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> +# +# 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 3 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, see <http://www.gnu.org/licenses/>. +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/lib/libdvd/libdvdread/src/dvd_input.c b/lib/libdvd/libdvdread/src/dvd_input.c index 43b8292afa..4a0252431a 100644 --- a/lib/libdvd/libdvdread/src/dvd_input.c +++ b/lib/libdvd/libdvdread/src/dvd_input.c @@ -43,7 +43,6 @@ char * (*dvdinput_error) (dvd_input_t); #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 @@ -56,19 +55,19 @@ char * (*dvdinput_error) (dvd_input_t); #include "../../msvc/contrib/dlfcn.c" #endif -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); +typedef struct dvdcss_s *dvdcss_t; +static dvdcss_t (*DVDcss_open) (const char *); +static int (*DVDcss_close) (dvdcss_t); +static int (*DVDcss_seek) (dvdcss_t, int, int); +static int (*DVDcss_read) (dvdcss_t, void *, int, int); +static char * (*DVDcss_error) (dvdcss_t); +#define DVDCSS_SEEK_KEY (1 << 1) #endif /* The DVDinput handle, add stuff here for new input methods. */ struct dvd_input_s { /* libdvdcss handle */ - dvdcss_handle dvdcss; + dvdcss_t dvdcss; /* dummy file input */ int fd; @@ -122,7 +121,7 @@ static int css_seek(dvd_input_t dev, int blocks) */ static int css_title(dvd_input_t dev, int block) { - return DVDcss_title(dev->dvdcss, block); + return DVDcss_seek(dev->dvdcss, block, DVDCSS_SEEK_KEY); } /** @@ -272,13 +271,10 @@ static int file_close(dvd_input_t dev) int dvdinput_setup(void) { void *dvdcss_library = NULL; - char **dvdcss_version = NULL; #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 /* dlopening libdvdcss */ @@ -286,7 +282,7 @@ int dvdinput_setup(void) #ifdef __APPLE__ #define CSS_LIB "libdvdcss.2.dylib" #elif defined(WIN32) - #define CSS_LIB "libdvdcss.dll" + #define CSS_LIB "libdvdcss-2.dll" #elif defined(__OS2__) #define CSS_LIB "dvdcss.dll" #else @@ -300,21 +296,17 @@ int dvdinput_setup(void) #else #define U_S #endif - DVDcss_open = (dvdcss_handle (*)(const char*)) + DVDcss_open = (dvdcss_t (*)(const char*)) dlsym(dvdcss_library, U_S "dvdcss_open"); - DVDcss_close = (int (*)(dvdcss_handle)) + DVDcss_close = (int (*)(dvdcss_t)) 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)) + DVDcss_seek = (int (*)(dvdcss_t, int, int)) dlsym(dvdcss_library, U_S "dvdcss_seek"); - DVDcss_read = (int (*)(dvdcss_handle, void*, int, int)) + DVDcss_read = (int (*)(dvdcss_t, void*, int, int)) dlsym(dvdcss_library, U_S "dvdcss_read"); - DVDcss_error = (char* (*)(dvdcss_handle)) + DVDcss_error = (char* (*)(dvdcss_t)) 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")) { fprintf(stderr, "libdvdread: Old (pre-0.0.2) version of libdvdcss found.\n" @@ -322,8 +314,8 @@ int dvdinput_setup(void) "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) { + } else if(!DVDcss_open || !DVDcss_close || !DVDcss_seek + || !DVDcss_read || !DVDcss_error) { fprintf(stderr, "libdvdread: Missing symbols in %s, " "this shouldn't happen !\n", CSS_LIB); dlclose(dvdcss_library); @@ -338,8 +330,6 @@ int dvdinput_setup(void) fprintf(stderr, "DVDCSS_METHOD %s\n", psz_method); fprintf(stderr, "DVDCSS_VERBOSE %s\n", psz_verbose); */ - fprintf(stderr, "libdvdread: Using libdvdcss version %s for DVD access\n", - dvdcss_version ? *dvdcss_version : ""); /* libdvdcss wrapper functions */ dvdinput_open = css_open; diff --git a/lib/libdvd/libdvdread/src/dvd_reader.c b/lib/libdvd/libdvdread/src/dvd_reader.c index 57dd2d0fe2..f8df635797 100644 --- a/lib/libdvd/libdvdread/src/dvd_reader.c +++ b/lib/libdvd/libdvdread/src/dvd_reader.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <errno.h> #include <string.h> +#include <strings.h> #include <ctype.h> #include <unistd.h> #include <limits.h> diff --git a/lib/libdvd/libdvdread/src/dvd_udf.c b/lib/libdvd/libdvdread/src/dvd_udf.c index 81491d8b38..9d1976dbb7 100644 --- a/lib/libdvd/libdvdread/src/dvd_udf.c +++ b/lib/libdvd/libdvdread/src/dvd_udf.c @@ -31,6 +31,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <strings.h> #include <sys/types.h> #include <sys/stat.h> @@ -593,8 +594,10 @@ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName, } else in_cache = 1; - if(cached_dir == NULL) + if(cached_dir == NULL) { + free(cached_dir_base); return 0; + } p = 0; diff --git a/lib/libdvd/libdvdread/src/dvdread/ifo_types.h b/lib/libdvd/libdvdread/src/dvdread/ifo_types.h index 7db7d34dbb..aa4c9d3393 100644 --- a/lib/libdvd/libdvdread/src/dvdread/ifo_types.h +++ b/lib/libdvd/libdvdread/src/dvdread/ifo_types.h @@ -301,6 +301,7 @@ typedef struct { pgc_program_map_t *program_map; cell_playback_t *cell_playback; cell_position_t *cell_position; + int ref_count; } ATTRIBUTE_PACKED pgc_t; #define PGC_SIZE 236U @@ -326,6 +327,7 @@ typedef struct { uint16_t zero_1; uint32_t last_byte; pgci_srp_t *pgci_srp; + int ref_count; } ATTRIBUTE_PACKED pgcit_t; #define PGCIT_SIZE 8U diff --git a/lib/libdvd/libdvdread/src/ifo_print.c b/lib/libdvd/libdvdread/src/ifo_print.c index 4d4eb885b9..38b1b75c4d 100644 --- a/lib/libdvd/libdvdread/src/ifo_print.c +++ b/lib/libdvd/libdvdread/src/ifo_print.c @@ -1189,10 +1189,10 @@ void ifo_print(dvd_reader_t *dvd, int title) { if(ifohandle->menu_vobu_admap) { ifoPrint_VOBU_ADMAP(ifohandle->menu_vobu_admap); } else { - printf("No Menu VOBU address map present\n"); + printf("No Menu VOBU Address map present\n"); } - printf("\nCell Adress table\n"); + printf("\nCell Address table\n"); printf( "-----------------\n"); ifoPrint_C_ADT(ifohandle->vts_c_adt); diff --git a/lib/libdvd/libdvdread/src/ifo_read.c b/lib/libdvd/libdvdread/src/ifo_read.c index 1bf1d6702d..76c9fafcb9 100644 --- a/lib/libdvd/libdvdread/src/ifo_read.c +++ b/lib/libdvd/libdvdread/src/ifo_read.c @@ -87,9 +87,9 @@ static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, 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(pgc_t **pgc); static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl); -static void ifoFree_PGCIT_internal(pgcit_t *pgcit); +static void ifoFree_PGCIT_internal(pgcit_t **pgcit); static inline int DVDFileSeekForce_( dvd_file_t *dvd_file, uint32_t offset, int force_size ) { return (DVDFileSeekForce(dvd_file, (int)offset, force_size) == (int)offset); @@ -568,6 +568,8 @@ static int ifoRead_VMG(ifo_handle_t *ifofile) { CHECK_ZERO(vmgi_mat->zero_1); CHECK_ZERO(vmgi_mat->zero_2); + /* DVDs created by VDR-to-DVD device LG RC590M violate the following check with + * vmgi_mat->zero_3 = 0x00000000010000000000000000000000000000. */ CHECK_ZERO(vmgi_mat->zero_3); CHECK_ZERO(vmgi_mat->zero_4); CHECK_ZERO(vmgi_mat->zero_5); @@ -923,7 +925,6 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { if(!ifoRead_PGC_COMMAND_TBL(ifofile, pgc->command_tbl, offset + pgc->command_tbl_offset)) { - free(pgc->command_tbl); return 0; } } else { @@ -933,13 +934,10 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { if(pgc->program_map_offset != 0 && 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 { @@ -949,18 +947,11 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { if(pgc->cell_playback_offset != 0 && 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 { @@ -970,13 +961,11 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { if(pgc->cell_position_offset != 0 && 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 { @@ -999,29 +988,33 @@ int ifoRead_FP_PGC(ifo_handle_t *ifofile) { if(ifofile->vmgi_mat->first_play_pgc == 0) return 1; - ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t)); + ifofile->first_play_pgc = (pgc_t *)calloc(1, sizeof(pgc_t)); if(!ifofile->first_play_pgc) return 0; + ifofile->first_play_pgc->ref_count = 1; if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc, ifofile->vmgi_mat->first_play_pgc)) { - free(ifofile->first_play_pgc); - ifofile->first_play_pgc = 0; + ifoFree_PGC(&ifofile->first_play_pgc); 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); +static void ifoFree_PGC(pgc_t **pgc) { + if(pgc && *pgc && (--(*pgc)->ref_count) <= 0) { + 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); + free(*pgc); + } + if (pgc) { + *pgc = NULL; } } @@ -1030,9 +1023,7 @@ void ifoFree_FP_PGC(ifo_handle_t *ifofile) { return; if(ifofile->first_play_pgc) { - ifoFree_PGC(ifofile->first_play_pgc); - free(ifofile->first_play_pgc); - ifofile->first_play_pgc = 0; + ifoFree_PGC(&ifofile->first_play_pgc); } } @@ -1082,6 +1073,12 @@ int ifoRead_TT_SRPT(ifo_handle_t *ifofile) { return 0; } + if(tt_srpt->nr_of_srpts>info_length/sizeof(title_info_t)){ + fprintf(stderr,"libdvdread: data mismatch: info_length (%ld)!= nr_of_srpts (%d). Truncating.\n", + info_length/sizeof(title_info_t),tt_srpt->nr_of_srpts); + tt_srpt->nr_of_srpts=info_length/sizeof(title_info_t); + } + 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); @@ -1189,8 +1186,22 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { fprintf(stderr, "libdvdread: PTT search table too small.\n"); goto fail; } + + if(vts_ptt_srpt->nr_of_srpts == 0) { + fprintf(stderr, "libdvdread: Zero entries in PTT search table.\n"); + goto fail; + } + for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { - B2N_32(data[i]); + /* Transformers 3 has PTT start bytes that point outside the SRPT PTT */ + uint32_t start = data[i]; + B2N_32(start); + if(start + sizeof(ptt_info_t) > vts_ptt_srpt->last_byte + 1) { + /* don't mess with any bytes beyond the end of the allocation */ + vts_ptt_srpt->nr_of_srpts = i; + break; + } + data[i] = start; /* 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 @@ -1216,6 +1227,7 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { Titles with 0 PTTs. */ if(n < 0) n = 0; + /* DVDs created by the VDR-to-DVD device LG RC590M violate the following requirement */ CHECK_VALUE(n % 4 == 0); vts_ptt_srpt->title[i].nr_of_ptts = n / 4; @@ -1250,6 +1262,13 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { 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); /* ?? */ + if (vts_ptt_srpt->title[i].ptt[j].pgcn == 0 || + vts_ptt_srpt->title[i].ptt[j].pgcn >= 1000 || + vts_ptt_srpt->title[i].ptt[j].pgn == 0 || + vts_ptt_srpt->title[i].ptt[j].pgn >= 100) { + return 0; + } + } } @@ -1291,7 +1310,7 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { if(!ifofile->vmgi_mat) return 0; - if(ifofile->vmgi_mat->ptl_mait == NULL) + if(ifofile->vmgi_mat->ptl_mait == 0) return 1; if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN)) @@ -1372,6 +1391,7 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { ifofile->ptl_mait = NULL; return 0; } + memset(pf_temp, 0, info_length); if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) { fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table at index %d.\n",i); free(pf_temp); @@ -1434,7 +1454,7 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { if(ifofile->vtsi_mat->vts_tmapt == 0) { /* optional(?) */ ifofile->vts_tmapt = NULL; - fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n"); + fprintf(stderr,"libdvdread: No VTS_TMAPT available - skipping.\n"); return 1; } @@ -1818,10 +1838,11 @@ int ifoRead_PGCIT(ifo_handle_t *ifofile) { if(ifofile->vtsi_mat->vts_pgcit == 0) /* mandatory */ return 0; - ifofile->vts_pgcit = (pgcit_t *)malloc(sizeof(pgcit_t)); + ifofile->vts_pgcit = (pgcit_t *)calloc(1, sizeof(pgcit_t)); if(!ifofile->vts_pgcit) return 0; + ifofile->vts_pgcit->ref_count = 1; if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit, ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) { free(ifofile->vts_pgcit); @@ -1832,6 +1853,17 @@ int ifoRead_PGCIT(ifo_handle_t *ifofile) { return 1; } +static int find_dup_pgc(pgci_srp_t *pgci_srp, uint32_t start_byte, int count) { + int i; + + for(i = 0; i < count; i++) { + if(pgci_srp[i].pgc_start_byte == start_byte) { + return i; + } + } + return -1; +} + static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, unsigned int offset) { int i, info_length; @@ -1880,21 +1912,26 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, 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)); + int dup; + if((dup = find_dup_pgc(pgcit->pgci_srp, pgcit->pgci_srp[i].pgc_start_byte, i)) >= 0) { + pgcit->pgci_srp[i].pgc = pgcit->pgci_srp[dup].pgc; + pgcit->pgci_srp[i].pgc->ref_count++; + continue; + } + pgcit->pgci_srp[i].pgc = calloc(1, 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); + ifoFree_PGC(&pgcit->pgci_srp[j].pgc); } goto fail; } + pgcit->pgci_srp[i].pgc->ref_count = 1; 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); + for(j = 0; j <= i; j++) { + ifoFree_PGC(&pgcit->pgci_srp[j].pgc); } free(pgcit->pgci_srp[i].pgc); goto fail; @@ -1908,16 +1945,18 @@ fail: return 0; } -static void ifoFree_PGCIT_internal(pgcit_t *pgcit) { - if(pgcit) { +static void ifoFree_PGCIT_internal(pgcit_t **pgcit) { + if(pgcit && *pgcit && (--(*pgcit)->ref_count <= 0)) { int i; - for(i = 0; i < pgcit->nr_of_pgci_srp; i++) + for(i = 0; i < (*pgcit)->nr_of_pgci_srp; i++) { - ifoFree_PGC(pgcit->pgci_srp[i].pgc); - free(pgcit->pgci_srp[i].pgc); + ifoFree_PGC(&(*pgcit)->pgci_srp[i].pgc); } - free(pgcit->pgci_srp); + free((*pgcit)->pgci_srp); + free(*pgcit); } + if (pgcit) + *pgcit = NULL; } void ifoFree_PGCIT(ifo_handle_t *ifofile) { @@ -1925,12 +1964,20 @@ void ifoFree_PGCIT(ifo_handle_t *ifofile) { return; if(ifofile->vts_pgcit) { - ifoFree_PGCIT_internal(ifofile->vts_pgcit); - free(ifofile->vts_pgcit); - ifofile->vts_pgcit = 0; + ifoFree_PGCIT_internal(&ifofile->vts_pgcit); } } +static int find_dup_lut(pgci_lu_t *lu, uint32_t start_byte, int count) { + int i; + + for(i = 0; i < count; i++) { + if(lu[i].lang_start_byte == start_byte) { + return i; + } + } + return -1; +} int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { pgci_ut_t *pgci_ut; @@ -2024,27 +2071,31 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { } for(i = 0; i < pgci_ut->nr_of_lus; i++) { + int dup; + if((dup = find_dup_lut(pgci_ut->lu, pgci_ut->lu[i].lang_start_byte, i)) >= 0) { + pgci_ut->lu[i].pgcit = pgci_ut->lu[dup].pgcit; + pgci_ut->lu[i].pgcit->ref_count++; + continue; + } 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); + ifoFree_PGCIT_internal(&pgci_ut->lu[j].pgcit); } free(pgci_ut->lu); free(pgci_ut); ifofile->pgci_ut = 0; return 0; } + pgci_ut->lu[i].pgcit->ref_count = 1; 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); + for(j = 0; j <= i; j++) { + ifoFree_PGCIT_internal(&pgci_ut->lu[j].pgcit); } - free(pgci_ut->lu[i].pgcit); free(pgci_ut->lu); free(pgci_ut); ifofile->pgci_ut = 0; @@ -2066,8 +2117,7 @@ void ifoFree_PGCI_UT(ifo_handle_t *ifofile) { 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); + ifoFree_PGCIT_internal(&ifofile->pgci_ut->lu[i].pgcit); } free(ifofile->pgci_ut->lu); free(ifofile->pgci_ut); diff --git a/lib/libdvd/libdvdread/src/md5.h b/lib/libdvd/libdvdread/src/md5.h index 810113dd82..1e5311f922 100644 --- a/lib/libdvd/libdvdread/src/md5.h +++ b/lib/libdvd/libdvdread/src/md5.h @@ -23,7 +23,7 @@ #include <stdio.h> -#if defined HAVE_LIMITS_H || _LIBC +#if defined HAVE_LIMITS_H || defined _LIBC # include <limits.h> #endif diff --git a/lib/libdvd/libdvdread/version.h b/lib/libdvd/libdvdread/version.h index 8a8730651b..ddbe066ef1 100644 --- a/lib/libdvd/libdvdread/version.h +++ b/lib/libdvd/libdvdread/version.h @@ -1 +1 @@ -#define VERSION "4.2.0" +#define VERSION "4.2.1" |