diff options
author | Pär Björklund <per.bjorklund@gmail.com> | 2013-02-08 14:03:19 +0100 |
---|---|---|
committer | Pär Björklund <per.bjorklund@gmail.com> | 2013-02-08 14:03:19 +0100 |
commit | 57e27aff0a152ef53d29c80ff07136cd065e77ff (patch) | |
tree | 44ebfbc26b4ed544155846f49253947b4e911cc1 /lib/libdvd | |
parent | 421d9fdb0658abb01306a62e5d57da044263b216 (diff) |
Added diffs for XBMC changes to libdvd libs
cores.diff is the differences between include files in lib/libdvd
and xbmc/cores/dvdplayer/dvdinputstreams/dvdnav
Diffstat (limited to 'lib/libdvd')
-rw-r--r-- | lib/libdvd/patches/cores.diff | 545 | ||||
-rw-r--r-- | lib/libdvd/patches/libdvdcss.diff | 365 | ||||
-rw-r--r-- | lib/libdvd/patches/libdvdnav.diff | 766 | ||||
-rw-r--r-- | lib/libdvd/patches/libdvdread.diff | 296 |
4 files changed, 1972 insertions, 0 deletions
diff --git a/lib/libdvd/patches/cores.diff b/lib/libdvd/patches/cores.diff new file mode 100644 index 0000000000..bc2a4b651f --- /dev/null +++ b/lib/libdvd/patches/cores.diff @@ -0,0 +1,545 @@ +diff -uw dvdnav_diff/config.h xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/config.h +--- dvdnav_diff/config.h 2013-02-07 14:42:34 +0100 ++++ xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/config.h 2013-01-26 23:33:20 +0100 +@@ -1,56 +1,95 @@ +-/* config.h. Generated by hand. */ ++#pragma once + +-#ifndef LIBDVDREAD_CONFIG_H +-#define LIBDVDREAD_CONFIG_H ++/* ++ * Copyright (C) 2005-2012 Team XBMC ++ * http://www.xbmc.org ++ * ++ * 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 XBMC; see the file COPYING. If not, see ++ * <http://www.gnu.org/licenses/>. ++ * ++ */ + +-#define HAVE_DLFCN_H 1 ++/* config.h. Generated by hand. */ ++#if defined(_LINUX) ++#include "PlatformInclude.h" ++#else ++#include <windows.h> ++#endif ++#include <stdio.h> ++ ++//#define HAVE_DLFCN_H 1 ++#define HAVE_DVDCSS_DVDCSS_H 1 + /* #undef HAVE_DVDCSS_DVDCSS_H*/ + /* #undef HAVE_INTTYPES_H */ + #define HAVE_MEMORY_H 1 +-/* #undef HAVE_STDINT_H */ ++#define HAVE_STDINT_H 1 + #define HAVE_STDLIB_H 1 + #define HAVE_STRINGS_H 1 + #define HAVE_STRING_H 1 + #define HAVE_SYS_STAT_H 1 + #define HAVE_SYS_TYPES_H 1 + /* #undef HAVE_UNISTD_H */ ++#ifndef PACKAGE + #define PACKAGE "libdvdread" ++#endif ++#ifndef PACKAGE_BUGREPORT + #define PACKAGE_BUGREPORT "" ++#endif ++#ifndef PACKAGE_NAME + #define PACKAGE_NAME "" ++#endif ++#ifndef PACKAGE_STRING + #define PACKAGE_STRING "" ++#endif ++#ifndef PACKAGE_TARNAME + #define PACKAGE_TARNAME "" ++#endif ++#ifndef PACKAGE_VERSION + #define PACKAGE_VERSION "" ++#endif + #define STDC_HEADERS 1 ++#ifndef VERSION + #define VERSION "1.2.6" ++#endif + /* #undef WORDS_BIGENDIAN */ + /* #undef __DARWIN__ */ + /* #undef const */ + #define inline __inline + /* #undef size_t */ + +-#define ssize_t __int64 ++#define ssize_t int + + #ifndef PATH_MAX + #define PATH_MAX MAX_PATH + #endif + ++#ifndef strcasecmp + #define strcasecmp stricmp ++#endif ++#ifndef strncasecmp + #define strncasecmp strnicmp ++#endif + ++#ifndef S_ISDIR + #define S_ISDIR(m) ((m) & _S_IFDIR) ++#endif ++#ifndef S_ISREG + #define S_ISREG(m) ((m) & _S_IFREG) ++#endif ++#ifndef S_ISBLK + #define S_ISBLK(m) 0 ++#endif ++#ifndef S_ISCHR + #define S_ISCHR(m) 0 +- +-/* Fallback types (very x86-centric, sorry) */ +-typedef unsigned char uint8_t; +-typedef signed char int8_t; +-typedef unsigned short uint16_t; +-typedef signed short int16_t; +-typedef unsigned int uint32_t; +-typedef signed int int32_t; +-typedef unsigned __int64 uint64_t; +-typedef signed __int64 int64_t; +-typedef unsigned int uintptr_t; +- +-#endif /* LIBDVDREAD_CONFIG_H */ ++#endif +diff -uw dvdnav_diff/decoder.h xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/decoder.h +--- dvdnav_diff/decoder.h 2013-02-07 14:42:34 +0100 ++++ xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/decoder.h 2013-02-04 14:58:00 +0100 +@@ -22,6 +22,12 @@ + #ifndef LIBDVDNAV_DECODER_H + #define LIBDVDNAV_DECODER_H + ++//#include <inttypes.h> ++//#include <sys/time.h> ++ ++#include "ifo_types.h" /* vm_cmd_t */ ++#include "dvdnav_internal.h" ++ + /* link command types */ + typedef enum { + LinkNoLink = 0, +diff -uw dvdnav_diff/dvd_reader.h xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/dvd_reader.h +--- dvdnav_diff/dvd_reader.h 2013-02-07 14:42:34 +0100 ++++ xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/dvd_reader.h 2013-02-04 14:58:00 +0100 +@@ -24,14 +24,14 @@ + #define LIBDVDREAD_DVD_READER_H + + #ifdef _MSC_VER +-#include <config.h> ++#include "config.h" + + #include <stdio.h> + #include <stdlib.h> + #endif + + #include <sys/types.h> +-#include <inttypes.h> ++//#include <inttypes.h> + + /** + * The DVD access interface. +diff -uw dvdnav_diff/dvd_types.h xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/dvd_types.h +--- dvdnav_diff/dvd_types.h 2013-02-07 14:42:34 +0100 ++++ xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/dvd_types.h 2013-02-04 14:58:00 +0100 +@@ -26,6 +26,8 @@ + #ifndef LIBDVDNAV_DVD_TYPES_H + #define LIBDVDNAV_DVD_TYPES_H + ++//#include <inttypes.h> ++ + /* + * DVD Menu ID + * (see dvdnav_menu_call()) +@@ -60,7 +62,8 @@ + + /* the following types are currently unused */ + +-#if 0 ++//XBMC Needs some of these ++#if 1 + + /* Domain */ + typedef enum { +@@ -222,6 +225,10 @@ + DVD_DISPLAY_MODE_4x3Letterboxed = 3 + } DVDDisplayMode_t; + ++typedef int DVDAudioSampleFreq_t; ++typedef int DVDAudioSampleQuant_t; ++typedef int DVDChannelNumber_t; ++ + /* Audio attributes */ + typedef struct { + DVDAudioAppMode_t AppMode; +@@ -233,9 +240,6 @@ + DVDAudioSampleQuant_t SampleQuantization; + DVDChannelNumber_t NumberOfChannels; + } DVDAudioAttributes_t; +-typedef int DVDAudioSampleFreq_t; +-typedef int DVDAudioSampleQuant_t; +-typedef int DVDChannelNumber_t; + + /* Subpicture attributes */ + typedef enum { +@@ -255,6 +259,8 @@ + DVDSubpictureLangExt_t LanguageExtension; + } DVDSubpictureAttributes_t; + ++typedef int DVDVideoCompression_t; ++ + /* Video attributes */ + typedef struct { + DVDBool_t PanscanPermitted; +@@ -268,7 +274,6 @@ + DVDBool_t Line21Field2InGop; + int more_to_come; + } DVDVideoAttributes_t; +-typedef int DVDVideoCompression_t; + + #endif + +diff -uw dvdnav_diff/dvdnav.h xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/dvdnav.h +--- dvdnav_diff/dvdnav.h 2013-02-07 14:42:34 +0100 ++++ xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/dvdnav.h 2013-02-04 14:58:00 +0100 +@@ -32,11 +32,14 @@ + extern "C" { + #endif + +-# include <dvdnav/dvd_types.h> +-# include <dvdread/dvd_reader.h> +-# include <dvdread/nav_types.h> +-# include <dvdread/ifo_types.h> /* For vm_cmd_t */ +-# include <dvdnav/dvdnav_events.h> ++# include "dvd_types.h" ++# include "dvd_reader.h" ++# include "nav_types.h" ++# include "ifo_types.h" /* For vm_cmd_t */ ++# include "dvdnav_events.h" ++# include "dvd_types.h" ++# include "dvd_reader.h" ++# include "ifo_types.h" /* For vm_cmd_t */ + + + +@@ -63,11 +66,6 @@ + #define DVDNAV_STATUS_ERR 0 + #define DVDNAV_STATUS_OK 1 + +-#define DVDNAV_FORMAT_AC3 0 +-#define DVDNAV_FORMAT_MPEGAUDIO 3 +-#define DVDNAV_FORMAT_LPCM 4 +-#define DVDNAV_FORMAT_DTS 5 +-#define DVDNAV_FORMAT_SDDS 6 + + /********************************************************************* + * initialisation & housekeeping functions * +@@ -281,7 +279,7 @@ + /* + * 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 +@@ -695,6 +693,15 @@ + */ + int8_t dvdnav_is_domain_vts(dvdnav_t *self); + ++/* XBMC added functions */ ++int dvdnav_get_nr_of_subtitle_streams(dvdnav_t *self); ++ ++int dvdnav_get_nr_of_audio_streams(dvdnav_t *self); ++ ++int dvdnav_get_button_info(dvdnav_t* self, int alpha[2][4], int color[2][4]); ++ ++int64_t dvdnav_convert_time(dvd_time_t *time); ++ + ////////// RATDVD stuff /////////////// + + /* +diff -uw dvdnav_diff/dvdnav_events.h xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/dvdnav_events.h +--- dvdnav_diff/dvdnav_events.h 2013-02-07 14:42:34 +0100 ++++ xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/dvdnav_events.h 2013-02-04 14:58:00 +0100 +@@ -25,6 +25,10 @@ + #ifndef LIBDVDNAV_DVDNAV_EVENTS_H + #define LIBDVDNAV_DVDNAV_EVENTS_H + ++#include "ifo_types.h" ++#include "dvd_reader.h" ++#include "nav_types.h" ++ + /* + * DVDNAV_BLOCK_OK + * +diff -uw dvdnav_diff/dvdnav_internal.h xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/dvdnav_internal.h +--- dvdnav_diff/dvdnav_internal.h 2013-02-07 14:42:34 +0100 ++++ xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/dvdnav_internal.h 2013-02-07 14:33:08 +0100 +@@ -1,6 +1,5 @@ +-/* !! DO NO EDIT THIS FILE, it is automatically generated */ + /* +- * Copyright (C) 2001 Rich Wareham <richwareham@users.sourceforge.net> ++ * Copyright (C) 2001-2004 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. + * +@@ -19,8 +18,8 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +-#ifndef LIBDVDREAD_DVDNAV_INTERNAL_H +-#define LIBDVDREAD_DVDNAV_INTERNAL_H ++#ifndef LIBDVDNAV_DVDNAV_INTERNAL_H ++#define LIBDVDNAV_DVDNAV_INTERNAL_H + + #ifdef HAVE_CONFIG_H + #include "config.h" +@@ -28,16 +27,47 @@ + + #include <stdlib.h> + #include <stdio.h> +-#include <unistd.h> ++//#include <unistd.h> + #include <limits.h> + #include <string.h> +-#include <pthread.h> + +-#undef WORDS_BIGENDIAN ++#ifdef WIN32 ++ ++/* pthread_mutex_* wrapper for win32 */ ++#ifndef _LINUX ++#include <windows.h> ++#include <process.h> ++typedef CRITICAL_SECTION pthread_mutex_t; ++#define pthread_mutex_init(a, b) InitializeCriticalSection(a) ++#define pthread_mutex_lock(a) EnterCriticalSection(a) ++#define pthread_mutex_unlock(a) LeaveCriticalSection(a) ++#define pthread_mutex_destroy(a) DeleteCriticalSection(a) ++#endif // !_LINUX ++ ++#ifndef HAVE_GETTIMEOFDAY ++/* replacement gettimeofday implementation */ ++#include <sys/timeb.h> ++static inline int _private_gettimeofday( struct timeval *tv, void *tz ) ++{ ++ struct timeb t; ++ ftime( &t ); ++ tv->tv_sec = t.time; ++ tv->tv_usec = t.millitm * 1000; ++ return 0; ++} ++#define gettimeofday(TV, TZ) _private_gettimeofday((TV), (TZ)) ++#endif ++ ++#ifndef _LINUX ++#include <io.h> /* read() */ ++#define lseek64 _lseeki64 ++#endif // !_LINUX + +-#include "dvd_reader.h" +-#include "ifo_read.h" +-#include "ifo_types.h" ++#else ++ ++#include <pthread.h> ++ ++#endif /* WIN32 */ + + /* Uncomment for VM command tracing */ + /* #define TRACE */ +@@ -48,7 +78,7 @@ + #include "vmcmd.h" + + /* where should libdvdnav write its messages (stdout/stderr) */ +-#define MSG_OUT stdout ++#define MSG_OUT stderr + + /* Maximum length of an error string */ + #define MAX_ERR_LEN 255 +@@ -126,8 +156,6 @@ + /* General data */ + char path[MAX_PATH_LEN]; /* Path to DVD device/dir */ + dvd_file_t *file; /* Currently opened file */ +- int open_vtsN; /* The domain and number of the... */ +- int open_domain; /* ..currently opened VOB */ + + /* Position data */ + vm_position_t position_next; +@@ -147,6 +175,7 @@ + int started; /* vm_start has been called? */ + int use_read_ahead; /* 1 - use read-ahead cache, 0 - don't */ + int pgc_based; /* positioning works PGC based instead of PG based */ ++ int cur_cell_time; /* time expired since the beginning of the current cell, read from the dsi */ + + /* VM */ + vm_t *vm; +@@ -159,24 +188,38 @@ + char err_str[MAX_ERR_LEN]; + }; + ++/** HELPER FUNCTIONS **/ ++ ++/* converts a dvd_time_t to PTS ticks */ ++int64_t dvdnav_convert_time(dvd_time_t *time); ++ ++/* XBMC added functions */ ++/* ++ * Get current playback state ++ */ ++dvdnav_status_t dvdnav_get_state(dvdnav_t *self, dvd_state_t *save_state); ++ ++/* ++ * Resume playback state ++ */ ++dvdnav_status_t dvdnav_set_state(dvdnav_t *self, dvd_state_t *save_state); ++/* end XBMC */ ++ + /** USEFUL MACROS **/ + + #ifdef __GNUC__ +-#define printerrf(format, args...) snprintf(this->err_str, MAX_ERR_LEN, format, ## args); ++#define printerrf(format, args...) \ ++ do { if (this) snprintf(this->err_str, MAX_ERR_LEN, format, ## args); } while (0) + #else + #ifdef _MSC_VER +-#define printerrf(str) snprintf(this->err_str, MAX_ERR_LEN, str); ++#define printerrf(str) \ ++ do { if (this) snprintf(this->err_str, MAX_ERR_LEN, str); } while (0) + #else +-#define printerrf(...) snprintf(this->err_str, MAX_ERR_LEN, __VA_ARGS__); ++#define printerrf(...) \ ++ do { if (this) snprintf(this->err_str, MAX_ERR_LEN, __VA_ARGS__); } while (0) + #endif /* WIN32 */ + #endif +-#define printerr(str) strncpy(this->err_str, str, MAX_ERR_LEN); +- +-/* Save my typing */ +-#define S_ERR DVDNAV_STATUS_ERR +- +-#ifndef _MSC_VER +-#define S_OK DVDNAV_STATUS_OK +-#endif /* MSC_VER */ ++#define printerr(str) \ ++ do { if (this) strncpy(this->err_str, str, MAX_ERR_LEN - 1); } while (0) + +-#endif /* LIBDVDREAD_DVDNAV_INTERNAL_H */ ++#endif /* LIBDVDNAV_DVDNAV_INTERNAL_H */ +diff -uw dvdnav_diff/ifo_types.h xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/ifo_types.h +--- dvdnav_diff/ifo_types.h 2013-02-07 14:42:34 +0100 ++++ xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/ifo_types.h 2013-02-04 14:58:00 +0100 +@@ -22,8 +22,8 @@ + #ifndef LIBDVDREAD_IFO_TYPES_H + #define LIBDVDREAD_IFO_TYPES_H + +-#include <inttypes.h> +-#include "dvdread/dvd_reader.h" ++//#include <inttypes.h> ++#include "dvd_reader.h" + + + #undef ATTRIBUTE_PACKED +diff -uw dvdnav_diff/nav_types.h xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/nav_types.h +--- dvdnav_diff/nav_types.h 2013-02-07 14:42:34 +0100 ++++ xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/nav_types.h 2013-02-04 14:58:00 +0100 +@@ -28,9 +28,27 @@ + #ifndef LIBDVDREAD_NAV_TYPES_H + #define LIBDVDREAD_NAV_TYPES_H + +-#include <inttypes.h> ++//#include <inttypes.h> + #include "ifo_types.h" /* only dvd_time_t, vm_cmd_t and user_ops_t */ + ++ ++#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 +@@ -41,6 +59,12 @@ + /* Remove this */ + #define DSI_START_BYTE 1031 + ++ ++#if PRAGMA_PACK ++#pragma pack(1) ++#endif ++ ++ + /** + * PCI General Information + */ +diff -uw dvdnav_diff/vm.h xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/vm.h +--- dvdnav_diff/vm.h 2013-02-07 14:42:34 +0100 ++++ xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/vm.h 2013-02-07 14:33:08 +0100 +@@ -23,6 +23,9 @@ + #ifndef LIBDVDNAV_VM_H + #define LIBDVDNAV_VM_H + ++#include "remap.h" ++#include "dvdnav_internal.h" ++ + /* DOMAIN enum */ + + typedef enum { +@@ -156,11 +159,8 @@ + int vm_get_audio_active_stream(vm_t *vm); + int vm_get_subp_active_stream(vm_t *vm, int mode); + void vm_get_angle_info(vm_t *vm, int *current, int *num_avail); +-// _XBMC #if 0 +-/* currently unused */ + void vm_get_audio_info(vm_t *vm, int *current, int *num_avail); + void vm_get_subp_info(vm_t *vm, int *current, int *num_avail); +-// _XBMC #endif + void vm_get_video_res(vm_t *vm, int *width, int *height); + int vm_get_video_aspect(vm_t *vm); + int vm_get_video_scale_permission(vm_t *vm); +@@ -180,5 +180,7 @@ + void vm_position_print(vm_t *vm, vm_position_t *position); + #endif + ++/* XBMC added functions */ ++vm_t* dvdnav_get_vm(dvdnav_t *self); + + #endif /* LIBDVDNAV_VM_H */ +diff -uw dvdnav_diff/vmcmd.h xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/vmcmd.h +--- dvdnav_diff/vmcmd.h 2013-02-07 14:42:34 +0100 ++++ xbmc/xbmc/cores/dvdplayer/DVDInputStreams/dvdnav/vmcmd.h 2013-02-04 14:58:00 +0100 +@@ -22,6 +22,8 @@ + #ifndef LIBDVDNAV_VMCMD_H + #define LIBDVDNAV_VMCMD_H + ++//#include <inttypes.h> ++ + void vm_print_mnemonic(vm_cmd_t *command); + void vm_print_cmd(int row, vm_cmd_t *command); + diff --git a/lib/libdvd/patches/libdvdcss.diff b/lib/libdvd/patches/libdvdcss.diff new file mode 100644 index 0000000000..2f0caf5389 --- /dev/null +++ b/lib/libdvd/patches/libdvdcss.diff @@ -0,0 +1,365 @@ +diff -uwr libdvdcss-1.2.12/src/device.c xbmc/lib/libdvd/libdvdcss/src/device.c +--- libdvdcss-1.2.12/src/device.c 2012-03-12 00:07:48 +0100 ++++ xbmc/lib/libdvd/libdvdcss/src/device.c 2013-02-07 14:42:34 +0100 +@@ -23,6 +23,10 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *****************************************************************************/ + ++/* ++ Modifications for XBMC are all contained within _XBOX (real xbox hardware) or WITH_CACHE ++*/ ++ + /***************************************************************************** + * Preamble + *****************************************************************************/ +@@ -368,11 +372,20 @@ + + #if defined( WIN32 ) + dvdcss->b_file = 1; ++#if defined( _XBOX ) ++ // If we've passed over the device string make sure we don't try ++ // to use file based handling (libc) - we want Win2k routines ... ++ if (!stricmp(psz_device, "\\Device\\Cdrom0")) ++ dvdcss->b_file = 0; ++ else ++ dvdcss->b_file = stricmp(psz_device, "D:"); ++#else + /* If device is "X:" or "X:\", we are not actually opening a file. */ + if (psz_device[0] && psz_device[1] == ':' && + (!psz_device[2] || (psz_device[2] == '\\' && !psz_device[3]))) + dvdcss->b_file = 0; + ++#endif // _XBOX + /* Initialize readv temporary buffer */ + dvdcss->p_readv_buffer = NULL; + dvdcss->i_readv_buf_size = 0; +@@ -450,11 +463,13 @@ + } + else /* ASPI */ + { ++#if !defined(_XBOX) + struct w32_aspidev *fd = (struct w32_aspidev *) dvdcss->i_fd; + + /* Unload aspi and free w32_aspidev structure */ + FreeLibrary( (HMODULE) fd->hASPI ); + free( (void*) dvdcss->i_fd ); ++#endif // !_XBOX + } + + /* Free readv temporary buffer */ +@@ -510,9 +525,14 @@ + #if defined( WIN32 ) + static int win2k_open ( dvdcss_t dvdcss, char const *psz_device ) + { ++#ifdef _XBOX ++ char psz_dvd[70]; ++ strcpy(psz_dvd, "cdrom0:"); ++#else + char psz_dvd[7]; + snprintf( psz_dvd, 7, "\\\\.\\%c:", psz_device[0] ); + ++#endif + /* To work around an M$ bug in IOCTL_DVD_READ_STRUCTURE, we need read + * _and_ write access to the device (so we can make SCSI Pass Through + * Requests). Unfortunately this is only allowed if you have +@@ -521,17 +541,24 @@ + * won't send back the right result). + * (See Microsoft Q241374: Read and Write Access Required for SCSI + * Pass Through Requests) */ ++ ++#ifdef WITH_CACHE ++ DWORD flags = FILE_FLAG_NO_BUFFERING; /* we handle buffering ourself */ ++#else ++ DWORD flags = FILE_FLAG_RANDOM_ACCESS; ++#endif //!_XBOX ++ + dvdcss->i_fd = (int) + CreateFile( psz_dvd, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, +- FILE_FLAG_RANDOM_ACCESS, NULL ); ++ flags, NULL ); + + if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE ) + dvdcss->i_fd = (int) + CreateFile( psz_dvd, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, +- FILE_FLAG_RANDOM_ACCESS, NULL ); ++ flags, NULL ); + + if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE ) + { +@@ -727,6 +754,9 @@ + static int win2k_seek( dvdcss_t dvdcss, int i_blocks ) + { + LARGE_INTEGER li_seek; ++#ifdef WITH_CACHE ++ int iBytesToSkip; ++#endif + + #ifndef INVALID_SET_FILE_POINTER + # define INVALID_SET_FILE_POINTER ((DWORD)-1) +@@ -738,6 +768,28 @@ + return i_blocks; + } + ++#ifdef WITH_CACHE ++ ++ // if our buffer contains the position which we want to seek too, we can ++ // just decrease dwCacheBufferSize ++ iBytesToSkip = (i_blocks - dvdcss->i_pos) * DVDCSS_BLOCK_SIZE; ++ if (iBytesToSkip > 0 && iBytesToSkip < dvdcss->buffer_size) ++ { ++ dvdcss->buffer_size -= iBytesToSkip; ++ dvdcss->i_pos = i_blocks; ++ return dvdcss->i_pos; ++ } ++ else if (iBytesToSkip < 0 && (DISC_CACHE_SIZE - dvdcss->buffer_size) >= -iBytesToSkip) ++ { ++ // we want to seek backwards, and we have enough old data in our buffer ++ dvdcss->buffer_size -= iBytesToSkip; // since iBytesToSkip is negative, dwCacheBufferSize will get bigger ++ dvdcss->i_pos = i_blocks; ++ return dvdcss->i_pos; ++ } ++ else dvdcss->buffer_size = 0; ++ ++#endif ++ + li_seek.QuadPart = (LONGLONG)i_blocks * DVDCSS_BLOCK_SIZE; + + li_seek.LowPart = SetFilePointer( (HANDLE) dvdcss->i_fd, +@@ -827,6 +879,66 @@ + { + int i_bytes; + ++#ifdef WITH_CACHE ++ ++ if (dvdcss->buffer_size < i_blocks * DVDCSS_BLOCK_SIZE) ++ { ++ // we don't have enough data in our buffer ++ int iRemaining = i_blocks * DVDCSS_BLOCK_SIZE; ++ int iCopied = 0; ++ // copy data we already have and read again into the cache ++ if (dvdcss->buffer_size > 0) memcpy(p_buffer, dvdcss->buffer + (DISC_CACHE_SIZE - dvdcss->buffer_size), dvdcss->buffer_size); ++ iCopied = dvdcss->buffer_size; ++ iRemaining -= dvdcss->buffer_size; ++ (BYTE*)p_buffer += iCopied; ++ dvdcss->buffer_size = 0; ++ ++ // if remaining size is bigger >= DISC_CACHE_SIZE, don't cache it. Just read ++ if (iRemaining >= DISC_CACHE_SIZE) ++ { ++ if (!ReadFile((HANDLE)dvdcss->i_fd, p_buffer, iRemaining, (LPDWORD)&i_bytes, NULL)) ++ { ++ dvdcss->i_pos = -1; ++ return -1; ++ } ++ dvdcss->i_pos += (i_bytes + iCopied) / DVDCSS_BLOCK_SIZE; ++ return (i_bytes + iCopied) / DVDCSS_BLOCK_SIZE; ++ } ++ else ++ { ++ // read a chunk into the cache and copy the needed bytes into p_buffer ++ if (!ReadFile((HANDLE)dvdcss->i_fd, dvdcss->buffer, DISC_CACHE_SIZE, &dvdcss->buffer_size, NULL)) ++ { ++ // read error, maybe we tried to read to much. Try again but now without cache ++ if (!ReadFile((HANDLE)dvdcss->i_fd, p_buffer, iRemaining, (LPDWORD)&i_bytes, NULL)) ++ { ++ dvdcss->i_pos = -1; ++ return -1; ++ } ++ dvdcss->i_pos += (i_bytes + iCopied) / DVDCSS_BLOCK_SIZE; ++ return (i_bytes + iCopied) / DVDCSS_BLOCK_SIZE; ++ } ++ // copy bytes into the buffer ++ memcpy(p_buffer, dvdcss->buffer, iRemaining); ++ dvdcss->buffer_size -= iRemaining; ++ dvdcss->i_pos += (iRemaining + iCopied) / DVDCSS_BLOCK_SIZE; ++ return (iRemaining + iCopied) / DVDCSS_BLOCK_SIZE; ++ } ++ } ++ else ++ { ++ // we have enough data in our cache, just copy it ++ memcpy(p_buffer, dvdcss->buffer + (DISC_CACHE_SIZE - dvdcss->buffer_size), i_blocks * DVDCSS_BLOCK_SIZE); ++ dvdcss->buffer_size -= i_blocks * DVDCSS_BLOCK_SIZE; ++ dvdcss->i_pos += i_blocks; ++ return i_blocks; ++ } ++ ++ dvdcss->i_pos = -1; ++ return -1; ++ ++#else // WITH_CACHE ++ + if( !ReadFile( (HANDLE) dvdcss->i_fd, p_buffer, + i_blocks * DVDCSS_BLOCK_SIZE, + (LPDWORD)&i_bytes, NULL ) ) +@@ -837,6 +949,7 @@ + + dvdcss->i_pos += i_bytes / DVDCSS_BLOCK_SIZE; + return i_bytes / DVDCSS_BLOCK_SIZE; ++#endif // WITH_CACHE + } + + static int aspi_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks ) +diff -uwr libdvdcss-1.2.12/src/ioctl.c xbmc/lib/libdvd/libdvdcss/src/ioctl.c +--- libdvdcss-1.2.12/src/ioctl.c 2012-03-12 00:07:48 +0100 ++++ xbmc/lib/libdvd/libdvdcss/src/ioctl.c 2013-02-07 14:42:34 +0100 +@@ -373,6 +373,37 @@ + + memcpy( p_key, dvdbs.discKeyStructures, DVD_DISCKEY_SIZE ); + ++#elif defined( _XBOX ) ++ // the next piece of code will read the disc key on the xbox for all drives (samsung included) ++ // but for some reason it takes 15 - 20 seconds longer to load a dvd if mplayer has the dvd key ++ // so we let this part fail and will only use the modified ioctl_ReadTitleKey code. ++ // don't get this delay, and i'm surprised it worked as the ReadTitleKey function didn't work. ++ ++ DWORD dwBytesRead; ++ DVD_READ_STRUCTURE st; ++ char buffer[DVD_DISCKEY_SIZE]; ++ ++ memset( &buffer, 0, sizeof( buffer ) ); ++ memset( &st, 0, sizeof( st ) ); ++ ++ st.BlockByteOffset.QuadPart = 0; ++ st.SessionId = *pi_agid; ++ st.Format = DvdDiskKeyDescriptor; ++ ++ i_ret = DeviceIoControl((HANDLE) i_fd, IOCTL_DVD_READ_STRUCTURE, &st, ++ sizeof(st), buffer, DVD_DISCKEY_SIZE, &dwBytesRead, NULL ) ? 0 : -1; ++ ++ if (i_ret < 0) // didn't work ++ { ++ printf("Failed to read disc key\n"); ++ return i_ret; ++ } ++ ++ // copy the returned key into our key buffer ++ int i; ++ for (i = 0; i < DVD_DISCKEY_SIZE; i++) ++ p_key[i] = buffer[i+4]; ++ + #elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { +@@ -541,6 +572,25 @@ + + memcpy( p_key, dvdbs.titleKeyValue, DVD_KEY_SIZE ); + ++#elif defined( _XBOX ) && 0 //Faulty wrong key returned, original for WIN32 works thou so use it instead ++ DWORD dwBytesRead; ++ DVD_READ_STRUCTURE st; ++ char buffer[2048+4]; ++ ++ memset( &buffer, 0, sizeof( buffer ) ); ++ ++ st.BlockByteOffset.QuadPart = (LONGLONG) i_pos * 2048 /*DVDCSS_BLOCK_SIZE*/; ++ st.SessionId = *pi_agid; ++ st.Format = DvdDiskKeyDescriptor; ++ ++ i_ret = DeviceIoControl((HANDLE) i_fd, IOCTL_DVD_READ_STRUCTURE, &st, sizeof(st), buffer, 2048+4, &dwBytesRead, NULL ) ? 0 : -1; ++ if( i_ret < 0 ) ++ { ++ return i_ret; ++ } ++ ++ memcpy( p_key, &(buffer[4]), 2048); ++ + #elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { +@@ -693,8 +743,13 @@ + ULONG id; + DWORD tmp; + ++#if defined( _XBOX) ++ i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_START_SESSION, ++ NULL, 0, &id, sizeof(id), &tmp, NULL ) ? 0 : -1; ++#else + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_START_SESSION, + &tmp, 4, &id, sizeof( id ), &tmp, NULL ) ? 0 : -1; ++#endif + + *pi_agid = id; + } +@@ -1336,8 +1391,13 @@ + + memcpy( key->KeyData, p_challenge, DVD_CHALLENGE_SIZE ); + ++#if defined(_XBOX) ++ i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key, ++ key->KeyLength, NULL, 0, &tmp, NULL ) ? 0 : -1; ++#else + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key, + key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; ++#endif + } + else + { +diff -uwr libdvdcss-1.2.12/src/ioctl.h xbmc/lib/libdvd/libdvdcss/src/ioctl.h +--- libdvdcss-1.2.12/src/ioctl.h 2012-03-12 00:07:48 +0100 ++++ xbmc/lib/libdvd/libdvdcss/src/ioctl.h 2013-02-07 14:42:34 +0100 +@@ -324,7 +324,11 @@ + typedef DWORD (CALLBACK *GETASPI32SUPPORTINFO)(VOID); + typedef DWORD (CALLBACK *SENDASPI32COMMAND)(LPVOID); + ++#if defined(_XBOX) ++#define WIN2K 1 ++#else + #define WIN2K ( GetVersion() < 0x80000000 ) ++#endif // _XBOX + #define ASPI_HAID 0 + #define ASPI_TARGET 0 + #define DTYPE_CDROM 0x05 +diff -uwr libdvdcss-1.2.12/src/libdvdcss.c xbmc/lib/libdvd/libdvdcss/src/libdvdcss.c +--- libdvdcss-1.2.12/src/libdvdcss.c 2012-03-12 00:07:48 +0100 ++++ xbmc/lib/libdvd/libdvdcss/src/libdvdcss.c 2013-02-07 14:42:34 +0100 +@@ -195,6 +195,10 @@ + dvdcss->b_debug = 0; + dvdcss->b_errors = 0; + ++#ifdef WITH_CACHE ++ dvdcss->buffer_size = 0; ++#endif ++ + /* + * Find verbosity from DVDCSS_VERBOSE environment variable + */ +@@ -388,7 +392,7 @@ + dvdcss->b_scrambled = i_ret; + } + } +- ++ /* if wo don't have b_ioctls, we don't have a disk key, make sure area is nulled */ + memset( dvdcss->css.p_disc_key, 0, KEY_SIZE ); + /* If disc is CSS protected and the ioctls work, authenticate the drive */ + if( dvdcss->b_scrambled && dvdcss->b_ioctls ) +@@ -533,8 +537,26 @@ + goto nocache; + } + ++#ifdef _XBOX ++ //due to xbox file system having a limited length on folders/files, ++ //make separate folder for disk name first ++ if(psz_title[0] == '\0') ++ strcat(psz_title, "NONAME"); ++ ++ i += sprintf( dvdcss->psz_cachefile + i, "/%s", psz_title); ++ ++ i_ret = mkdir( dvdcss->psz_cachefile ); ++ if( i_ret < 0 && errno != EEXIST ) ++ { ++ print_error( dvdcss, "failed creating cache titledirectory" ); ++ dvdcss->psz_cachefile[0] = '\0'; ++ goto nocache; ++ } ++ i += sprintf( dvdcss->psz_cachefile + i, "/%s%s", psz_serial, psz_key ); ++#else + i += sprintf( dvdcss->psz_cachefile + i, "/%s-%s%s", psz_title, + psz_serial, psz_key ); ++#endif + #if !defined( WIN32 ) || defined( SYS_CYGWIN ) + i_ret = mkdir( dvdcss->psz_cachefile, 0755 ); + #else diff --git a/lib/libdvd/patches/libdvdnav.diff b/lib/libdvd/patches/libdvdnav.diff new file mode 100644 index 0000000000..32f7f0837a --- /dev/null +++ b/lib/libdvd/patches/libdvdnav.diff @@ -0,0 +1,766 @@ +diff -uwr libdvdnav-4.2.0/Makefile xbmc/lib/libdvd/libdvdnav/Makefile +--- libdvdnav-4.2.0/Makefile 2008-12-30 15:48:46 +0100 ++++ xbmc/lib/libdvd/libdvdnav/Makefile 2013-02-07 14:42:34 +0100 +@@ -112,7 +112,7 @@ + # Clean targets + + clean: +- rm -rf *~ $(.OBJDIR)/* version.h ++ rm -rf *~ $(.OBJDIR)/* + + pcedit = sed \ + -e 's,@prefix@,$(PREFIX),' \ +diff -uwr libdvdnav-4.2.0/src/dvdnav/dvdnav.h xbmc/lib/libdvd/libdvdnav/src/dvdnav/dvdnav.h +--- libdvdnav-4.2.0/src/dvdnav/dvdnav.h 2011-02-26 21:32:32 +0100 ++++ xbmc/lib/libdvd/libdvdnav/src/dvdnav/dvdnav.h 2013-02-07 14:42:34 +0100 +@@ -695,6 +695,42 @@ + */ + int8_t dvdnav_is_domain_vts(dvdnav_t *self); + ++////////// RATDVD stuff /////////////// ++ ++/* ++ * Get the number of audio streams. ++ */ ++int32_t dvdnav_get_audio_stream_count(dvdnav_t * self); ++ ++/* ++ * Get the number of subpicture streams. ++ */ ++int32_t dvdnav_get_subpicture_stream_count(dvdnav_t * self); ++ ++/* ++ * Get attributes of the current audio stream. ++ */ ++dvdnav_status_t dvdnav_get_audio_info(dvdnav_t * self, int32_t streamid, audio_attr_t* audio_attributes); ++ ++/* ++ * Get attributes of the current subpicture stream. ++ */ ++dvdnav_status_t dvdnav_get_stitle_info(dvdnav_t * self, int32_t streamid, subp_attr_t* stitle_attributes); ++ ++/* ++ * Get information about the current video stream ++ */ ++dvdnav_status_t dvdnav_get_video_info(dvdnav_t * self, video_attr_t* video_attributes); ++ ++/* ++ * Select the audio stream to be played ++ */ ++dvdnav_status_t dvdnav_audio_change(dvdnav_t *self, int32_t audio); ++ ++/* ++ * Select the spu stream to be displayed ++ */ ++dvdnav_status_t dvdnav_subpicture_change(dvdnav_t *self, int32_t subpicture); + + #ifdef __cplusplus + } +diff -uwr libdvdnav-4.2.0/src/dvdnav.c xbmc/lib/libdvd/libdvdnav/src/dvdnav.c +--- libdvdnav-4.2.0/src/dvdnav.c 2010-07-31 01:34:12 +0200 ++++ xbmc/lib/libdvd/libdvdnav/src/dvdnav.c 2013-02-07 14:42:34 +0100 +@@ -337,7 +337,9 @@ + } + #endif + +- if(num_angle != 0) { ++ /* 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((next = nav_pci->nsml_agli.nsml_agl_dsta[angle-1]) != 0) { + if((next & 0x3fffffff) != 0) { +@@ -466,6 +468,10 @@ + /* Decode nav into pci and dsi. Then get next VOBU info. */ + if(!dvdnav_decode_packet(this, *buf, &this->dsi, &this->pci)) { + printerr("Expected NAV packet but none found."); ++#ifdef _XBMC ++ /* skip this cell as we won't recover from this*/ ++ vm_get_next_cell(this->vm); ++#endif + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } +@@ -618,9 +624,17 @@ + cell_event->pgc_length = dvdnav_convert_time(&state->pgc->playback_time); + + cell_event->cell_start = 0; +- for (i = 1; i < state->cellN; i++) ++ for (i = 0; i < state->cellN; i++) ++ { ++ /* only count the first angle cell */ ++ if( state->pgc->cell_playback[i].block_type == BLOCK_TYPE_ANGLE_BLOCK ++ && state->pgc->cell_playback[i].block_mode != BLOCK_MODE_FIRST_CELL ) ++ continue; ++ + cell_event->cell_start += +- dvdnav_convert_time(&state->pgc->cell_playback[i - 1].playback_time); ++ dvdnav_convert_time(&state->pgc->cell_playback[i].playback_time); ++ } ++ cell_event->cell_start-= dvdnav_convert_time(&state->pgc->cell_playback[state->cellN-1].playback_time); + + cell_event->pg_start = 0; + for (i = 1; i < state->pgc->program_map[state->pgN-1]; i++) +@@ -769,6 +783,10 @@ + /* Decode nav into pci and dsi. Then get next VOBU info. */ + if(!dvdnav_decode_packet(this, *buf, &this->dsi, &this->pci)) { + printerr("Expected NAV packet but none found."); ++#ifdef _XBMC ++ /* skip this cell as we won't recover from this */ ++ vm_get_next_cell(this->vm); ++#endif + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } +@@ -1166,6 +1184,10 @@ + + ops.ops_int = 0; + ++ if(!this) { ++ printerr("Passed a NULL pointer."); ++ return ops.ops_struct; ++ } + if(!this->started) { + printerr("Virtual DVD machine not started."); + return ops.ops_struct; +@@ -1180,3 +1202,263 @@ + + return ops.ops_struct; + } ++ ++#ifdef _XBMC ++ ++vm_t* dvdnav_get_vm(dvdnav_t *this) { ++ if(!this) return 0; ++ return this->vm; ++} ++ ++int dvdnav_get_nr_of_subtitle_streams(dvdnav_t *this) ++{ ++ int i; ++ int count = 0; ++ ++ if (this && this->vm && this->vm->state.pgc) ++ { ++ for (i = 0; i < 32; i++) ++ { ++ if (this->vm->state.pgc->subp_control[i] & (1<<31)) count++; ++ } ++ } ++ return count; ++ ++ /* old code ++ if(!this || !this->vm || !this->vm->vtsi || !this->vm->vtsi->vtsi_mat) return 0; ++ ++ switch ((this->vm->state).domain) { ++ case VTS_DOMAIN: ++ return this->vm->vtsi->vtsi_mat->nr_of_vts_subp_streams; ++ case VTSM_DOMAIN: ++ return this->vm->vtsi->vtsi_mat->nr_of_vtsm_subp_streams; // 1 ++ case VMGM_DOMAIN: ++ case FP_DOMAIN: ++ return this->vm->vmgi->vmgi_mat->nr_of_vmgm_subp_streams; // 1 ++ } ++ ++ return 0; ++ */ ++} ++ ++int dvdnav_get_nr_of_audio_streams(dvdnav_t *this) ++{ ++ int i; ++ int count = 0; ++ ++ if (this && this->vm && this->vm->state.pgc) ++ { ++ for (i = 0; i < 8; i++) ++ { ++ if (this->vm->state.pgc->audio_control[i] & (1<<15)) count++; ++ } ++ } ++ return count; ++ ++ /* old code ++ if(!this || !this->vm || !this->vm->vtsi || !this->vm->vtsi->vtsi_mat) return 0; ++ ++ switch ((this->vm->state).domain) { ++ case VTS_DOMAIN: ++ return this->vm->vtsi->vtsi_mat->nr_of_vts_audio_streams; ++ case VTSM_DOMAIN: ++ return this->vm->vtsi->vtsi_mat->nr_of_vtsm_audio_streams; // 1 ++ case VMGM_DOMAIN: ++ case FP_DOMAIN: ++ return this->vm->vmgi->vmgi_mat->nr_of_vmgm_audio_streams; // 1 ++ } ++ ++ return 0; ++ */ ++} ++ ++/* return the alpha and color for the current active button ++ * color, alpha [0][] = selection ++ * color, alpha = color ++ * ++ * argsize = [2][4] ++ */ ++int dvdnav_get_button_info(dvdnav_t* this, int alpha[2][4], int color[2][4]) ++{ ++ int current_button, current_button_color, i; ++ pci_t* pci; ++ ++ if (!this) return -1; ++ ++ pci = dvdnav_get_current_nav_pci(this); ++ if (!pci) return -1; ++ ++ dvdnav_get_current_highlight(this, ¤t_button); ++ current_button_color = pci->hli.btnit[current_button - 1].btn_coln; ++ ++ for (i = 0; i < 2; i++) ++ { ++ alpha[i][0] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 0 & 0xf; ++ alpha[i][1] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 4 & 0xf; ++ alpha[i][2] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 8 & 0xf; ++ alpha[i][3] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 12 & 0xf; ++ ++ color[i][0] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 16 & 0xf; ++ color[i][1] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 20 & 0xf; ++ color[i][2] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 24 & 0xf; ++ color[i][3] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 28 & 0xf; ++ } ++ ++ return 0; ++} ++ ++/* ++ * the next stuff is taken from ratdvd ++ */ ++ ++#undef printerr ++#define printerr(str) strncpy(self->err_str, str, MAX_ERR_LEN); ++ ++dvdnav_status_t dvdnav_get_audio_info(dvdnav_t * self, int32_t streamid, audio_attr_t* audio_attributes) ++{ ++ if(!self) { ++ printerr("Passed a NULL pointer."); ++ return -1; ++ } ++ if(!self->started) { ++ printerr("Virtual DVD machine not started."); ++ return -1; ++ } ++ ++ pthread_mutex_lock(&self->vm_lock); ++ audio_attr_t attributes = vm_get_audio_attr(self->vm,streamid); ++ pthread_mutex_unlock(&self->vm_lock); ++ audio_attributes->audio_format = attributes.audio_format; ++ audio_attributes->multichannel_extension = attributes.multichannel_extension; ++ audio_attributes->lang_type = attributes.lang_type; ++ audio_attributes->application_mode = attributes.application_mode; ++ audio_attributes->quantization = attributes.quantization; ++ audio_attributes->sample_frequency = attributes.sample_frequency; ++ audio_attributes->channels = attributes.channels; ++ audio_attributes->lang_code = attributes.lang_code; ++ audio_attributes->lang_extension = attributes.lang_extension; ++ audio_attributes->code_extension = attributes.code_extension; ++ audio_attributes->unknown3 = attributes.unknown3; ++ audio_attributes->app_info = attributes.app_info; ++ return DVDNAV_STATUS_OK; ++} ++ ++dvdnav_status_t dvdnav_get_stitle_info(dvdnav_t * self ++ , int32_t streamid, subp_attr_t* stitle_attributes) ++{ ++ if(!self) { ++ printerr("Passed a NULL pointer."); ++ return -1; ++ } ++ if(!self->started) { ++ printerr("Virtual DVD machine not started."); ++ return -1; ++ } ++ ++ pthread_mutex_lock(&self->vm_lock); ++ subp_attr_t attributes = vm_get_subp_attr(self->vm,streamid); ++ pthread_mutex_unlock(&self->vm_lock); ++ stitle_attributes->code_mode = attributes.code_mode; ++ stitle_attributes->zero1 = attributes.zero1; ++ stitle_attributes->type = attributes.type; ++ stitle_attributes->zero2 = attributes.zero2; ++ stitle_attributes->lang_code = attributes.lang_code; ++ stitle_attributes->lang_extension = attributes.lang_extension; ++ stitle_attributes->code_extension = attributes.code_extension; ++ return DVDNAV_STATUS_OK; ++} ++ ++dvdnav_status_t dvdnav_get_video_info(dvdnav_t * self, video_attr_t* video_attributes) ++{ ++ if(!self) { ++ printerr("Passed a NULL pointer."); ++ return -1; ++ } ++ if(!self->started) { ++ printerr("Virtual DVD machine not started."); ++ return -1; ++ } ++ ++ pthread_mutex_lock(&self->vm_lock); ++ video_attr_t attributes = vm_get_video_attr(self->vm); ++ pthread_mutex_unlock(&self->vm_lock); ++ ++ video_attributes->video_format = attributes.video_format; ++ video_attributes->permitted_df = attributes.permitted_df; ++ video_attributes->display_aspect_ratio = attributes.display_aspect_ratio; ++ video_attributes->mpeg_version = attributes.mpeg_version; ++ video_attributes->film_mode = attributes.film_mode; ++ video_attributes->letterboxed = attributes.letterboxed; ++ video_attributes->picture_size = attributes.picture_size; ++ video_attributes->bit_rate = attributes.bit_rate; ++ video_attributes->unknown1 = attributes.unknown1; ++ video_attributes->line21_cc_2 = attributes.line21_cc_2; ++ video_attributes->line21_cc_1 = attributes.line21_cc_1; ++ return DVDNAV_STATUS_OK; ++} ++ ++dvdnav_status_t dvdnav_audio_change(dvdnav_t *self, int32_t audio) ++{ ++ int32_t num; ++ ++ if(!self) { ++ printerr("Passed a NULL pointer."); ++ return DVDNAV_STATUS_ERR; ++ } ++ ++ num = dvdnav_get_nr_of_audio_streams(self); ++ pthread_mutex_lock(&self->vm_lock); ++ /* Set subp AUDIO if valid */ ++ if((audio >= 0) && (audio <= num)) { ++ self->vm->state.AST_REG = audio; ++ } else { ++ //printerr("Passed an invalid audio number."); ++ pthread_mutex_unlock(&self->vm_lock); ++ return DVDNAV_STATUS_ERR; ++ } ++ pthread_mutex_unlock(&self->vm_lock); ++ ++ return DVDNAV_STATUS_OK; ++} ++ ++dvdnav_status_t dvdnav_subpicture_change(dvdnav_t *self, int32_t subpicture) ++{ ++ int32_t num; ++ ++ if(!self) { ++ printerr("Passed a NULL pointer."); ++ return DVDNAV_STATUS_ERR; ++ } ++ ++ num = dvdnav_get_nr_of_subtitle_streams(self); ++ pthread_mutex_lock(&self->vm_lock); ++ /* Set subp SPRM if valid */ ++ if((subpicture >= 0) && (subpicture <= num)) { ++ self->vm->state.SPST_REG = subpicture | 0x40; ++ } else if (subpicture & 0x80) { ++ self->vm->state.SPST_REG = subpicture & ~0x80; ++ } else { ++ self->vm->state.SPST_REG = subpicture; ++ //printerr("Passed an invalid subpicture number."); ++ //pthread_mutex_unlock(&self->vm_lock); ++ //return DVDNAV_STATUS_ERR; ++ } ++ pthread_mutex_unlock(&self->vm_lock); ++ ++ return DVDNAV_STATUS_OK; ++} ++ ++void dvdnav_lock(dvdnav_t *self) ++{ ++ // we do not check for null pointer problems ++ pthread_mutex_lock(&self->vm_lock); ++} ++ ++void dvdnav_unlock(dvdnav_t *self) ++{ ++ // we do not check for null pointer problems ++ pthread_mutex_unlock(&self->vm_lock); ++} ++ ++#endif // _XBMC ++ +diff -uwr libdvdnav-4.2.0/src/dvdnav_internal.h xbmc/lib/libdvd/libdvdnav/src/dvdnav_internal.h +--- libdvdnav-4.2.0/src/dvdnav_internal.h 2010-06-01 12:02:38 +0200 ++++ xbmc/lib/libdvd/libdvdnav/src/dvdnav_internal.h 2013-02-07 14:42:34 +0100 +@@ -175,6 +175,18 @@ + /* converts a dvd_time_t to PTS ticks */ + int64_t dvdnav_convert_time(dvd_time_t *time); + ++/* XBMC added functions */ ++/* ++ * Get current playback state ++ */ ++dvdnav_status_t dvdnav_get_state(dvdnav_t *this, dvd_state_t *save_state); ++ ++/* ++ * Resume playback state ++ */ ++dvdnav_status_t dvdnav_set_state(dvdnav_t *this, dvd_state_t *save_state); ++/* end XBMC */ ++ + /** USEFUL MACROS **/ + + #ifdef __GNUC__ +diff -uwr libdvdnav-4.2.0/src/read_cache.c xbmc/lib/libdvd/libdvdnav/src/read_cache.c +--- libdvdnav-4.2.0/src/read_cache.c 2008-12-30 15:48:46 +0100 ++++ xbmc/lib/libdvd/libdvdnav/src/read_cache.c 2013-02-07 14:42:34 +0100 +@@ -338,7 +338,7 @@ + pthread_mutex_lock(&cache->lock); + for (i = 0; i < READ_CACHE_CHUNKS; i++) { + if (cache->chunk[i].cache_buffer && buf >= cache->chunk[i].cache_buffer && +- buf < cache->chunk[i].cache_buffer + cache->chunk[i].cache_malloc_size * DVD_VIDEO_LB_LEN) { ++ buf < cache->chunk[i].cache_buffer + cache->chunk[i].cache_malloc_size * DVD_VIDEO_LB_LEN && cache->chunk[i].usage_count > 0) { + cache->chunk[i].usage_count--; + } + } +diff -uwr libdvdnav-4.2.0/src/searching.c xbmc/lib/libdvd/libdvdnav/src/searching.c +--- libdvdnav-4.2.0/src/searching.c 2011-10-07 19:06:24 +0200 ++++ xbmc/lib/libdvd/libdvdnav/src/searching.c 2013-02-07 14:42:34 +0100 +@@ -121,6 +121,12 @@ + return DVDNAV_STATUS_ERR; + } + ++ if((state->pgc->prohibited_ops.title_or_time_play == 1) || ++ (this->pci.pci_gi.vobu_uop_ctl.title_or_time_play == 1 )){ ++ printerr("operation forbidden."); ++ pthread_mutex_unlock(&this->vm_lock); ++ return DVDNAV_STATUS_ERR; ++ } + + this->cur_cell_time = 0; + if (this->pgc_based) { +@@ -136,24 +142,109 @@ + last_cell_nr = state->pgc->nr_of_cells; + } + ++ /* FIXME: using time map is not going to work unless we are pgc_based */ ++ /* we'd need to recalculate the time to be relative to full pgc first*/ ++ if(!this->pgc_based) ++ { ++#ifdef LOG_DEBUG ++ fprintf(MSG_OUT, "libdvdnav: time_search - not pgc based\n"); ++#endif ++ goto timemapdone; ++ } ++ ++ if(!this->vm->vtsi->vts_tmapt){ ++ /* no time map for this program chain */ ++#ifdef LOG_DEBUG ++ fprintf(MSG_OUT, "libdvdnav: time_search - no time map for this program chain\n"); ++#endif ++ goto timemapdone; ++ } ++ ++ if(this->vm->vtsi->vts_tmapt->nr_of_tmaps < state->pgcN){ ++ /* to few time maps for this program chain */ ++#ifdef LOG_DEBUG ++ fprintf(MSG_OUT, "libdvdnav: time_search - to few time maps for this program chain\n"); ++#endif ++ goto timemapdone; ++ } ++ ++ /* get the tmpat corresponding to the pgc */ ++ vts_tmap_t *tmap = &(this->vm->vtsi->vts_tmapt->tmap[state->pgcN-1]); ++ ++ if(tmap->tmu == 0){ ++ /* no time unit for this time map */ ++#ifdef LOG_DEBUG ++ fprintf(MSG_OUT, "libdvdnav: time_search - no time unit for this time map\n"); ++#endif ++ goto timemapdone; ++ } ++ ++ /* time is in pts (90khz clock), get the number of tmu's that represent */ ++ /* first entry defines at time tmu not time zero */ ++ int entry = time / tmap->tmu / 90000 - 1; ++ if(entry > tmap->nr_of_entries) ++ entry = tmap->nr_of_entries -1; ++ ++ if(entry > 0) ++ { ++ /* get the table entry, disregarding marking of discontinuity */ ++ target = tmap->map_ent[entry] & 0x7fffffff; ++ } ++ else ++ { ++ /* start from first vobunit */ ++ target = state->pgc->cell_playback[first_cell_nr-1].first_sector;; ++ } ++ ++ /* if we have an additional entry we can interpolate next position */ ++ /* allowed only if next entry isn't discontinious */ ++ ++ if( entry < tmap->nr_of_entries - 1) ++ { ++ const uint32_t target2 = tmap->map_ent[entry+1]; ++ const uint64_t timeunit = tmap->tmu*90000; ++ if( !( target2 & 0x80000000) ) ++ { ++ length = target2 - target; ++ target += (uint32_t) (length * ( time - (entry+1)*timeunit ) / timeunit); ++ } ++ } ++ found = 1; ++ ++timemapdone: ++ + found = 0; +- for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { ++ for(cell_nr = first_cell_nr; cell_nr <= last_cell_nr; cell_nr ++) { + cell = &(state->pgc->cell_playback[cell_nr-1]); + if(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL) + continue; ++ ++ if(found) { ++ ++ if (target >= cell->first_sector ++ && target <= cell->last_sector) ++ break; ++ ++ } else { ++ + length = dvdnav_convert_time(&cell->playback_time); +- if (target >= length) { +- target -= length; ++ if (time >= length) { ++ time -= length; + } else { + /* FIXME: there must be a better way than interpolation */ +- target = target * (cell->last_sector - cell->first_sector + 1) / length; ++ target = time * (cell->last_sector - cell->first_sector + 1) / length; + target += cell->first_sector; + ++ #ifdef LOG_DEBUG ++ if( cell->first_sector > target || target > cell->last_sector ) ++ fprintf(MSG_OUT, "libdvdnav: time_search - sector is not within cell min:%u, max:%u, cur:%u\n", cell->first_sector, cell->last_sector, target); ++ #endif ++ + found = 1; + break; + } + } +- ++ } + if(found) { + uint32_t vobu; + #ifdef LOG_DEBUG +@@ -202,6 +293,7 @@ + + result = dvdnav_get_position(this, &target, &length); + if(!result) { ++ printerr("Cannot get current position"); + return DVDNAV_STATUS_ERR; + } + +@@ -213,7 +305,7 @@ + return DVDNAV_STATUS_ERR; + } + #ifdef LOG_DEBUG +- fprintf(MSG_OUT, "libdvdnav: seeking to offset=%lu pos=%u length=%u\n", offset, target, length); ++ fprintf(MSG_OUT, "libdvdnav: seeking to offset=%llu pos=%u length=%u\n", offset, target, length); + fprintf(MSG_OUT, "libdvdnav: Before cellN=%u blockN=%u\n", state->cellN, state->blockN); + #endif + +@@ -654,3 +746,62 @@ + free(tmp); + return retval; + } ++ ++dvdnav_status_t dvdnav_get_state(dvdnav_t *this, dvd_state_t *save_state) ++{ ++ if(!this || !this->vm) return DVDNAV_STATUS_ERR; ++ ++ pthread_mutex_lock(&this->vm_lock); ++ ++ if( !vm_get_state(this->vm, save_state) ) ++ { ++ printerr("Failed to get vm state."); ++ pthread_mutex_unlock(&this->vm_lock); ++ return DVDNAV_STATUS_ERR; ++ } ++ ++ pthread_mutex_unlock(&this->vm_lock); ++ return DVDNAV_STATUS_OK; ++} ++ ++dvdnav_status_t dvdnav_set_state(dvdnav_t *this, dvd_state_t *save_state) ++{ ++ if(!this || !this->vm) ++ { ++ printerr("Passed a NULL pointer."); ++ return DVDNAV_STATUS_ERR; ++ } ++ ++ if(!this->started) { ++ printerr("Virtual DVD machine not started."); ++ return DVDNAV_STATUS_ERR; ++ } ++ ++ pthread_mutex_lock(&this->vm_lock); ++ ++ /* reset the dvdnav state */ ++ memset(&this->pci,0,sizeof(this->pci)); ++ memset(&this->dsi,0,sizeof(this->dsi)); ++ this->last_cmd_nav_lbn = SRI_END_OF_CELL; ++ ++ /* Set initial values of flags */ ++ this->position_current.still = 0; ++ this->skip_still = 0; ++ this->sync_wait = 0; ++ this->sync_wait_skip = 0; ++ this->spu_clut_changed = 0; ++ ++ ++ /* set the state. this will also start the vm on that state */ ++ /* means the next read block should be comming from that new */ ++ /* state */ ++ if( !vm_set_state(this->vm, save_state) ) ++ { ++ printerr("Failed to set vm state."); ++ pthread_mutex_unlock(&this->vm_lock); ++ return DVDNAV_STATUS_ERR; ++ } ++ ++ pthread_mutex_unlock(&this->vm_lock); ++ return DVDNAV_STATUS_OK; ++} +diff -uwr libdvdnav-4.2.0/src/vm/vm.c xbmc/lib/libdvd/libdvdnav/src/vm/vm.c +--- libdvdnav-4.2.0/src/vm/vm.c 2010-11-22 00:59:44 +0100 ++++ xbmc/lib/libdvd/libdvdnav/src/vm/vm.c 2013-02-07 14:42:34 +0100 +@@ -255,6 +255,15 @@ + fprintf(MSG_OUT, "libdvdnav: ifoRead_TITLE_VOBU_ADMAP vtsi failed\n"); + return 0; + } ++ if(!ifoRead_VTS_TMAPT(vm->vtsi)) { ++ fprintf(MSG_OUT, "libdvdnav: ifoRead_VTS_TMAPT vtsi failed\n"); ++ return 0; ++ } ++ if(!ifoRead_TITLE_C_ADT(vm->vtsi)) { ++ fprintf(MSG_OUT, "libdvdnav: ifoRead_TITLE_C_ADT vtsi failed\n"); ++ return 0; ++ } ++ + (vm->state).vtsN = vtsN; + + return 1; +@@ -390,7 +399,15 @@ + /* return 0; Not really used for now.. */ + } + /* ifoRead_TXTDT_MGI(vmgi); Not implemented yet */ ++#ifdef _XBMC ++ if(DVDUDFVolumeInfo(vm->dvd, vm->dvd_name, sizeof(vm->dvd_name), NULL, 0)) ++ if(DVDISOVolumeInfo(vm->dvd, vm->dvd_name, sizeof(vm->dvd_name), NULL, 0)) ++ strcpy(vm->dvd_name, ""); ++ ++ fprintf(MSG_OUT, "libdvdnav: vm: DVD Title: %s\n", vm->dvd_name); ++#else + dvd_read_name(vm->dvd_name, vm->dvd_serial, dvdroot); ++#endif + vm->map = remap_loadmap(vm->dvd_name); + } + if (vm->vmgi) { +@@ -846,7 +863,7 @@ + } + } + +-#if 0 ++// XBMC #if 0 + /* currently unused */ + void vm_get_audio_info(vm_t *vm, int *current, int *num_avail) { + switch ((vm->state).domain) { +@@ -884,7 +901,7 @@ + break; + } + } +-#endif ++// XBMC #endif + + void vm_get_video_res(vm_t *vm, int *width, int *height) { + video_attr_t attr = vm_get_video_attr(vm); +@@ -1981,6 +1998,50 @@ + ifoClose(ifo); + } + ++int vm_get_state(vm_t *vm, dvd_state_t *save_state) { ++ *save_state = vm->state; ++ ++ /* remove the pgc pointer as it might not be valid later*/ ++ save_state->pgc = NULL; ++ ++ return 1; ++} ++ ++int vm_set_state(vm_t *vm, dvd_state_t *save_state) { ++ ++ /* restore state from save_state as taken from ogle */ ++ ++ /* open the needed vts */ ++ if( !ifoOpenNewVTSI(vm, vm->dvd, save_state->vtsN) ) return 0; ++ // sets state.vtsN ++ ++ vm->state = *save_state; ++ /* set state.domain before calling */ ++ //calls get_pgcit() ++ // needs state.domain and sprm[0] set ++ // sets pgcit depending on state.domain ++ //writes: state.pgc ++ // state.pgN ++ // state.TT_PGCN_REG ++ ++ if( !set_PGCN(vm, save_state->pgcN) ) return 0; ++ save_state->pgc = vm->state.pgc; ++ ++ /* set the rest of state after the call */ ++ vm->state = *save_state; ++ ++ /* if we are not in standard playback, we must get all data */ ++ /* otherwise we risk loosing stillframes, and overlays */ ++ if(vm->state.domain != VTS_DOMAIN) ++ vm->state.blockN = 0; ++ ++ /* force a flush of data here */ ++ /* we don't need a hop seek here as it's a complete state*/ ++ vm->hop_channel++; ++ ++ return 1; ++} ++ + /* Debug functions */ + + #ifdef TRACE +diff -uwr libdvdnav-4.2.0/src/vm/vm.h xbmc/lib/libdvd/libdvdnav/src/vm/vm.h +--- libdvdnav-4.2.0/src/vm/vm.h 2010-07-31 01:34:16 +0200 ++++ xbmc/lib/libdvd/libdvdnav/src/vm/vm.h 2013-02-07 14:42:34 +0100 +@@ -156,11 +156,11 @@ + int vm_get_audio_active_stream(vm_t *vm); + int vm_get_subp_active_stream(vm_t *vm, int mode); + void vm_get_angle_info(vm_t *vm, int *current, int *num_avail); +-#if 0 ++// _XBMC #if 0 + /* currently unused */ + void vm_get_audio_info(vm_t *vm, int *current, int *num_avail); + void vm_get_subp_info(vm_t *vm, int *current, int *num_avail); +-#endif ++// _XBMC #endif + void vm_get_video_res(vm_t *vm, int *width, int *height); + int vm_get_video_aspect(vm_t *vm); + int vm_get_video_scale_permission(vm_t *vm); +@@ -170,6 +170,9 @@ + ifo_handle_t *vm_get_title_ifo(vm_t *vm, uint32_t title); + void vm_ifo_close(ifo_handle_t *ifo); + ++int vm_get_state(vm_t *vm, dvd_state_t *save_state); ++int vm_set_state(vm_t *vm, dvd_state_t *save_state); ++ + /* Uncomment for VM command tracing */ + /* #define TRACE */ + #ifdef TRACE +Only in xbmc/lib/libdvd/libdvdnav: version.h diff --git a/lib/libdvd/patches/libdvdread.diff b/lib/libdvd/patches/libdvdread.diff new file mode 100644 index 0000000000..fbf185f0dd --- /dev/null +++ b/lib/libdvd/patches/libdvdread.diff @@ -0,0 +1,296 @@ +diff -uwr libdvdread-4.2.0/Makefile xbmc/lib/libdvd/libdvdread/Makefile +--- libdvdread-4.2.0/Makefile 2008-12-31 09:43:04 +0100 ++++ xbmc/lib/libdvd/libdvdread/Makefile 2013-02-07 14:42:34 +0100 +@@ -121,7 +121,7 @@ + # Clean targets + + clean: +- rm -rf *~ $(.OBJDIR)/* version.h ++ rm -rf *~ $(.OBJDIR)/* + + + distclean: clean +diff -uwr libdvdread-4.2.0/src/dvd_input.h xbmc/lib/libdvd/libdvdread/src/dvd_input.h +--- libdvdread-4.2.0/src/dvd_input.h 2010-06-01 19:07:14 +0200 ++++ xbmc/lib/libdvd/libdvdread/src/dvd_input.h 2013-02-07 14:42:34 +0100 +@@ -34,6 +34,13 @@ + #if defined( __MINGW32__ ) + # undef lseek + # define lseek _lseeki64 ++# undef fseeko ++# define fseeko fseeko64 ++# undef ftello ++# define ftello ftello64 ++# define flockfile(...) ++# define funlockfile(...) ++# define getc_unlocked getc + # undef off_t + # define off_t off64_t + # undef stat +diff -uwr libdvdread-4.2.0/src/dvd_reader.c xbmc/lib/libdvd/libdvdread/src/dvd_reader.c +--- libdvdread-4.2.0/src/dvd_reader.c 2011-06-15 20:09:16 +0200 ++++ xbmc/lib/libdvd/libdvdread/src/dvd_reader.c 2013-02-07 14:42:34 +0100 +@@ -32,6 +32,11 @@ + #include <unistd.h> + #include <limits.h> + #include <dirent.h> ++#ifndef WIN32 ++#include <paths.h> ++#endif ++ ++#define WITH_CACHE + + /* misc win32 helpers */ + #ifdef WIN32 +@@ -105,6 +110,10 @@ + uint32_t lb_start; + uint32_t seek_pos; + ++#ifdef WITH_CACHE ++ char cache[DVD_VIDEO_LB_LEN]; ++ uint32_t lb_cache; ++#endif + /* Information required for a directory path drive. */ + size_t title_sizes[ TITLES_MAX ]; + dvd_input_t title_devs[ TITLES_MAX ]; +@@ -617,6 +626,10 @@ + memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); + dvd_file->filesize = len / DVD_VIDEO_LB_LEN; + ++#ifdef WITH_CACHE ++ dvd_file->lb_cache = -1; ++#endif ++ + return dvd_file; + } + +@@ -628,6 +641,18 @@ + */ + static int findDirFile( const char *path, const char *file, char *filename ) + { ++#if defined(_XBMC) ++ struct stat fileinfo; ++ ++ // no emulated opendir function in xbmc, so we'll ++ // check if the file exists by stat'ing it ... ++ sprintf(filename, "%s%s%s", path, ++ ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ), ++ file ); ++ ++ if (stat(filename, &fileinfo) == 0) return 0; ++ ++#else + DIR *dir; + struct dirent *ent; + +@@ -644,6 +669,7 @@ + } + } + closedir(dir); ++#endif // _XBMC + return -1; + } + +@@ -722,6 +748,9 @@ + dvd_file->title_devs[ 0 ] = dev; + dvd_file->filesize = dvd_file->title_sizes[ 0 ]; + ++#ifdef WITH_CACHE ++ dvd_file->lb_cache = -1; ++#endif + return dvd_file; + } + +@@ -749,6 +778,9 @@ + memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); + dvd_file->filesize = len / DVD_VIDEO_LB_LEN; + ++#ifdef WITH_CACHE ++ dvd_file->lb_cache = -1; ++#endif + /* Calculate the complete file size for every file in the VOBS */ + if( !menu ) { + int cur; +@@ -792,6 +824,10 @@ + memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); + dvd_file->filesize = 0; + ++#ifdef WITH_CACHE ++ dvd_file->lb_cache = -1; ++#endif ++ + if( menu ) { + dvd_input_t dev; + +@@ -1203,6 +1239,100 @@ + return ret + ret2; + } + ++#ifdef WITH_CACHE ++ ++/* returns true aslong as the sector isn't all zeros */ ++int DVDCheckSector(unsigned char *data, int offset) ++{ ++ int i = 0; ++ int32_t *p = (int32_t*)data + (DVD_VIDEO_LB_LEN>>2)*offset; ++ for(;i<(DVD_VIDEO_LB_LEN<<2);i++) { ++ if(*(p+i) != 0) ++ break; ++ } ++ return (i!=(DVD_VIDEO_LB_LEN>>2)); ++} ++ ++int DVDReadBlocksCached( dvd_file_t *dvd_file, int offset, ++ size_t block_count, unsigned char *data, int encrypted ) ++{ ++ int ret=0; ++ /* Check arguments. */ ++ if( dvd_file == NULL || offset < 0 || data == NULL ) ++ return -1; ++ ++ if(encrypted & DVDINPUT_READ_DECRYPT) { ++ /* 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 ); ++ }*/ ++ } ++ } ++ ++ /* check if first sector is in cache */ ++ int cachehit = 0; ++ if( offset == dvd_file->lb_cache ) { ++ memcpy( data, dvd_file->cache, DVD_VIDEO_LB_LEN ); ++ block_count--; ++ offset++; ++ data+=DVD_VIDEO_LB_LEN; ++ cachehit = 1; ++ } ++ ++ ++ if( block_count > 0 ) ++ { ++ if( dvd_file->dvd->isImageFile ) ++ ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset, ++ block_count, data, encrypted ); ++ else ++ ret = DVDReadBlocksPath( dvd_file, (unsigned int)offset, ++ block_count, data, encrypted ); ++ ++ if(ret<0) ++ return ret; ++ ++ /* here is a hack for drive wich don't handle layerchange properly */ ++ /* they start returning zero data while laser is shifting position */ ++ /* normally just doing a reread will get the correct data */ ++ if( dvd_file->dvd->isImageFile ) ++ { ++ /* check sectors from the back */ ++ int count = ret; /* previous call could have returned fewer than requested */ ++ int i = count-1; ++ for(;i>=0;i--) ++ if(!DVDCheckSector(data, i)) break; ++ ++ if(i>=0) { ++ fprintf( stderr, "libdvdread: potential layer change. %d zero sectors detected starting at %d!\n", i+1, offset); ++ ++ /* reread the invalid sectors */ ++ count = DVDReadBlocksUDF( dvd_file, (uint32_t)offset+i, ++ count-i, data+DVD_VIDEO_LB_LEN*i, encrypted ); ++ ++ if(count<0) ++ return count; ++ } ++ } ++ ++ } ++ ++ if(ret>0) ++ { /* store last sector read into cache */ ++ dvd_file->lb_cache = offset+ret-1; ++ memcpy( dvd_file->cache, data+(DVD_VIDEO_LB_LEN*(ret-1)), DVD_VIDEO_LB_LEN ); ++ } ++ ++ return (ssize_t)(ret+cachehit); ++} ++#endif ++ + /* This is broken reading more than 2Gb at a time is ssize_t is 32-bit. */ + ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset, + size_t block_count, unsigned char *data ) +@@ -1213,6 +1343,10 @@ + if( dvd_file == NULL || offset < 0 || data == NULL ) + return -1; + ++#ifdef WITH_CACHE ++ return (ssize_t)DVDReadBlocksCached( dvd_file, offset, block_count, data, DVDINPUT_READ_DECRYPT ); ++#endif ++ + /* 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; +@@ -1295,6 +1429,10 @@ + return 0; + } + ++#ifdef WITH_CACHE ++ ret = DVDReadBlocksCached( dvd_file, (uint32_t) seek_sector, ++ (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); ++#else + if( dvd_file->dvd->isImageFile ) { + ret = DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector, + (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); +@@ -1302,6 +1440,7 @@ + ret = DVDReadBlocksPath( dvd_file, seek_sector, + (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); + } ++#endif + + if( ret != (int) numsec ) { + free( secbuf_base ); +Only in xbmc/lib/libdvd/libdvdread: version.h +diff -uwr libdvdread-4.2.0/version.sh xbmc/lib/libdvd/libdvdread/version.sh +--- libdvdread-4.2.0/version.sh 2008-05-01 11:27:16 +0200 ++++ xbmc/lib/libdvd/libdvdread/version.sh 2013-02-07 14:42:34 +0100 +@@ -1,18 +1,18 @@ +-#!/bin/sh +- +-svn_revision=`cd "$1" && LC_ALL=C svn info 2> /dev/null | grep Revision | cut -d' ' -f2` +-test $svn_revision || svn_revision=`cd "$1" && grep revision .svn/entries 2>/dev/null | \ +- cut -d '"' -f2 2> /dev/null` +-test $svn_revision || svn_revision=UNKNOWN +- +-if test "$svn_revision" = UNKNOWN && test -n "$2"; then +- NEW_REVISION="#define VERSION \"$2\"" +-else +- NEW_REVISION="#define VERSION \"SVN-r$svn_revision\"" +-fi +-OLD_REVISION=`cat version.h 2> /dev/null` +- +-# Update version.h only on revision changes to avoid spurious rebuilds +-if test "$NEW_REVISION" != "$OLD_REVISION"; then +- echo "$NEW_REVISION" > version.h +-fi ++##!/bin/sh ++# ++#svn_revision=`cd "$1" && LC_ALL=C svn info 2> /dev/null | grep Revision | cut -d' ' -f2` ++#test $svn_revision || svn_revision=`cd "$1" && grep revision .svn/entries 2>/dev/null | \ ++# cut -d '"' -f2 2> /dev/null` ++#test $svn_revision || svn_revision=UNKNOWN ++# ++#if test "$svn_revision" = UNKNOWN && test -n "$2"; then ++# NEW_REVISION="#define VERSION \"$2\"" ++#else ++# NEW_REVISION="#define VERSION \"SVN-r$svn_revision\"" ++#fi ++#OLD_REVISION=`cat version.h 2> /dev/null` ++# ++## Update version.h only on revision changes to avoid spurious rebuilds ++#if test "$NEW_REVISION" != "$OLD_REVISION"; then ++# echo "$NEW_REVISION" > version.h ++#fi |