summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/input/libdvdread/bswap.h13
-rw-r--r--src/input/libdvdread/diff_against_cvs.patch768
-rw-r--r--src/input/libdvdread/dvd_input.c86
-rw-r--r--src/input/libdvdread/dvd_input.h16
-rw-r--r--src/input/libdvdread/dvd_reader.c262
-rw-r--r--src/input/libdvdread/dvd_reader.h82
-rw-r--r--src/input/libdvdread/dvd_udf.c629
-rw-r--r--src/input/libdvdread/dvd_udf.h8
-rw-r--r--src/input/libdvdread/dvdread_internal.h12
-rw-r--r--src/input/libdvdread/ifo_print.c218
-rw-r--r--src/input/libdvdread/ifo_read.c367
-rw-r--r--src/input/libdvdread/ifo_read.h3
-rw-r--r--src/input/libdvdread/ifo_types.h228
-rw-r--r--src/input/libdvdread/md5.c417
-rw-r--r--src/input/libdvdread/md5.h161
-rw-r--r--src/input/libdvdread/nav_print.c16
-rw-r--r--src/input/libdvdread/nav_read.c123
-rw-r--r--src/input/libdvdread/nav_types.h32
18 files changed, 2464 insertions, 977 deletions
diff --git a/src/input/libdvdread/bswap.h b/src/input/libdvdread/bswap.h
index dd7417059..9c7402957 100644
--- a/src/input/libdvdread/bswap.h
+++ b/src/input/libdvdread/bswap.h
@@ -30,6 +30,11 @@
#else
+/* For __FreeBSD_version */
+#if defined(HAVE_SYS_PARAM_H)
+#include <sys/param.h>
+#endif
+
#if defined(__linux__)
#include <byteswap.h>
#define B2N_16(x) x = bswap_16(x)
@@ -48,9 +53,15 @@
#define B2N_32(x) x = swap32(x)
#define B2N_64(x) x = swap64(x)
+#elif defined(__FreeBSD__) && __FreeBSD_version >= 470000
+#include <sys/endian.h>
+#define B2N_16(x) x = be16toh(x)
+#define B2N_32(x) x = be32toh(x)
+#define B2N_64(x) x = be64toh(x)
+
/* This is a slow but portable implementation, it has multiple evaluation
* problems so beware.
- * FreeBSD and Solaris don't have <byteswap.h> or any other such
+ * Old FreeBSD's and Solaris don't have <byteswap.h> or any other such
* functionality!
*/
diff --git a/src/input/libdvdread/diff_against_cvs.patch b/src/input/libdvdread/diff_against_cvs.patch
index f5470a554..349b4c1ee 100644
--- a/src/input/libdvdread/diff_against_cvs.patch
+++ b/src/input/libdvdread/diff_against_cvs.patch
@@ -1,6 +1,6 @@
---- src/input/libdvdread/dvd_input.c 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/dvd_input.c 2002-11-27 21:50:03.000000000 +0100
-@@ -63,7 +63,7 @@
+--- src/input/libdvdread/dvd_input.c 2003-02-13 22:48:24.000000000 +0100
++++ src/input/libdvdread/dvd_input.c 2003-02-28 14:12:36.000000000 +0100
+@@ -74,7 +74,7 @@
dvd_input_t dev;
/* Allocate the handle structure */
@@ -9,7 +9,7 @@
if(dev == NULL) {
fprintf(stderr, "libdvdread: Could not allocate memory.\n");
return NULL;
-@@ -143,7 +143,7 @@
+@@ -154,7 +154,7 @@
dvd_input_t dev;
/* Allocate the library structure */
@@ -18,17 +18,9 @@
if(dev == NULL) {
fprintf(stderr, "libdvdread: Could not allocate memory.\n");
return NULL;
---- src/input/libdvdread/dvd_reader.c 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/dvd_reader.c 2002-11-27 21:51:31.000000000 +0100
-@@ -28,7 +28,6 @@
- #include <unistd.h>
- #include <limits.h>
- #include <dirent.h>
--
- #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)|| defined(__DARWIN__)
- #define SYS_BSD 1
- #endif
-@@ -41,6 +40,7 @@
+--- src/input/libdvdread/dvd_reader.c 2003-02-13 23:31:21.000000000 +0100
++++ src/input/libdvdread/dvd_reader.c 2003-02-28 14:24:48.000000000 +0100
+@@ -44,6 +44,7 @@
#include <mntent.h>
#endif
@@ -36,7 +28,7 @@
#include "dvd_udf.h"
#include "dvd_input.h"
#include "dvd_reader.h"
-@@ -289,7 +289,7 @@
+@@ -349,7 +350,7 @@
if( cdir >= 0 ) {
chdir( path_copy );
@@ -45,7 +37,7 @@
fchdir( cdir );
close( cdir );
if( new_path ) {
-@@ -452,7 +452,7 @@
+@@ -513,7 +514,7 @@
static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename )
{
@@ -54,7 +46,7 @@
const char *nodirfile;
int ret;
-@@ -486,7 +486,7 @@
+@@ -547,7 +548,7 @@
*/
static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
{
@@ -63,7 +55,7 @@
dvd_file_t *dvd_file;
struct stat fileinfo;
dvd_input_t dev;
-@@ -570,7 +570,7 @@
+@@ -631,7 +632,7 @@
static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
@@ -72,7 +64,7 @@
struct stat fileinfo;
dvd_file_t *dvd_file;
int i;
-@@ -867,7 +867,7 @@
+@@ -930,7 +931,7 @@
ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
{
@@ -81,17 +73,19 @@
unsigned int numsec, seek_sector, seek_byte;
int ret;
-@@ -881,7 +881,8 @@
+@@ -944,8 +945,9 @@
numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) +
( ( ( seek_byte + byte_size ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 );
- secbuf = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN );
+- if( !secbuf ) {
+ secbuf_base = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN + 2048 );
+ secbuf = (unsigned char *)(((int)secbuf_base & ~2047) + 2048);
- if( !secbuf ) {
++ if( !secbuf_base ) {
fprintf( stderr, "libdvdread: Can't allocate memory "
"for file read!\n" );
-@@ -897,12 +898,12 @@
+ return 0;
+@@ -960,12 +962,12 @@
}
if( ret != (int) numsec ) {
@@ -106,9 +100,85 @@
dvd_file->seek_pos += byte_size;
return byte_size;
---- src/input/libdvdread/dvd_udf.c 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/dvd_udf.c 2002-11-27 21:50:03.000000000 +0100
-@@ -123,7 +123,7 @@
+@@ -997,9 +999,10 @@
+ if( dvd_file != NULL ) {
+ ssize_t bytes_read;
+ size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN;
+- char *buffer = malloc( file_size );
++ char *buffer_base = malloc( file_size + 2048 );
++ char *buffer = (unsigned char *)(((int)buffer_base & ~2047) + 2048);
+
+- if( buffer == NULL ) {
++ if( buffer_base == NULL ) {
+ fprintf( stderr, "libdvdread: DVDDiscId, failed to "
+ "allocate memory for file read!\n" );
+ return -1;
+@@ -1009,13 +1012,14 @@
+ fprintf( stderr, "libdvdread: DVDDiscId read returned %d bytes"
+ ", wanted %d\n", bytes_read, file_size );
+ DVDCloseFile( dvd_file );
++ free( buffer_base );
+ return -1;
+ }
+
+ md5_process_bytes( buffer, file_size, &ctx );
+
+ DVDCloseFile( dvd_file );
+- free( buffer );
++ free( buffer_base );
+ }
+ }
+ md5_finish_ctx( &ctx, discid );
+@@ -1028,7 +1032,7 @@
+ char *volid, unsigned int volid_size,
+ unsigned char *volsetid, unsigned int volsetid_size )
+ {
+- unsigned char *buffer;
++ unsigned char *buffer, *buffer_base;
+ int ret;
+
+ /* Check arguments. */
+@@ -1040,8 +1044,10 @@
+ return -1;
+ }
+
+- buffer = malloc( DVD_VIDEO_LB_LEN );
+- if( buffer == NULL ) {
++ buffer_base = malloc( DVD_VIDEO_LB_LEN + 2048 );
++ buffer = (unsigned char *)(((int)buffer_base & ~2047) + 2048);
++
++ if( buffer_base == NULL ) {
+ fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
+ "allocate memory for file read!\n" );
+ return -1;
+@@ -1051,6 +1057,7 @@
+ if( ret != 1 ) {
+ fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
+ "read ISO9660 Primary Volume Descriptor!\n" );
++ free( buffer_base );
+ return -1;
+ }
+
+@@ -1076,6 +1083,7 @@
+ }
+ memcpy(volsetid, &buffer[190], volsetid_size);
+ }
++ free( buffer_base );
+ return 0;
+ }
+
+--- src/input/libdvdread/dvd_udf.c 2003-02-13 22:57:17.000000000 +0100
++++ src/input/libdvdread/dvd_udf.c 2003-02-28 14:53:36.000000000 +0100
+@@ -237,7 +237,7 @@
+
+ if(c == NULL) {
+ c = calloc(1, sizeof(struct udf_cache));
+- // fprintf(stderr, "calloc: %d\n", sizeof(struct udf_cache));
++ /* fprintf(stderr, "calloc: %d\n", sizeof(struct udf_cache)); */
+ if(c == NULL) {
+ return 0;
+ }
+@@ -346,7 +346,7 @@
static int UDFDescriptor( uint8_t *data, uint16_t *TagID )
{
*TagID = GETN2(0);
@@ -117,7 +187,7 @@
return 0;
}
-@@ -141,7 +141,7 @@
+@@ -364,7 +364,7 @@
ad->Flags = ad->Length >> 30;
ad->Length &= 0x3FFFFFFF;
ad->Location = GETN4(4);
@@ -126,7 +196,7 @@
return 0;
}
-@@ -152,7 +152,7 @@
+@@ -375,7 +375,7 @@
ad->Length &= 0x3FFFFFFF;
ad->Location = GETN4(4);
ad->Partition = GETN2(8);
@@ -135,7 +205,7 @@
return 0;
}
-@@ -163,7 +163,7 @@
+@@ -386,7 +386,7 @@
ad->Length &= 0x3FFFFFFF;
ad->Location = GETN4(12);
ad->Partition = GETN2(16);
@@ -144,7 +214,7 @@
return 0;
}
-@@ -194,9 +194,9 @@
+@@ -417,9 +417,9 @@
{
uint32_t lbsize, MT_L, N_PM;
Unicodedecode(&data[84], 128, VolumeDescriptor);
@@ -157,7 +227,7 @@
if (lbsize != DVD_VIDEO_LB_LEN) return 1;
return 0;
}
-@@ -211,10 +211,10 @@
+@@ -434,10 +434,10 @@
UDFICB( &data[ 16 ], FileType, &flags );
/* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */
@@ -171,7 +241,7 @@
L_EA = GETN4( 168 );
L_AD = GETN4( 172 );
-@@ -264,7 +264,8 @@
+@@ -487,7 +487,8 @@
static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType,
struct Partition *partition, struct AD *File )
{
@@ -180,9 +250,9 @@
+ uint8_t *LogBlock = (uint8_t *)(((int)LogBlock_base & ~2047) + 2048);
uint32_t lbnum;
uint16_t TagID;
-
-@@ -296,7 +297,8 @@
- struct Partition *partition, struct AD *FileICB )
+ struct icbmap tmpmap;
+@@ -531,12 +532,13 @@
+ int cache_file_info)
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
- uint8_t directory[ 2 * DVD_VIDEO_LB_LEN ];
@@ -191,19 +261,48 @@
uint32_t lbnum;
uint16_t TagID;
uint8_t filechar;
-@@ -342,7 +344,10 @@
+ unsigned int p;
+- uint8_t *cached_dir = NULL;
++ uint8_t *cached_dir_base = NULL, *cached_dir;
+ uint32_t dir_lba;
+ struct AD tmpICB;
+ int found = 0;
+@@ -550,11 +552,12 @@
+
+ if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) {
+ dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN;
+- if((cached_dir = malloc(dir_lba * DVD_VIDEO_LB_LEN)) == NULL) {
++ if((cached_dir_base = malloc(dir_lba * DVD_VIDEO_LB_LEN + 2048)) == NULL) {
+ return 0;
+ }
++ cached_dir = (uint8_t *)(((int)cached_dir_base & ~2047) + 2048);
+ if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) {
+- free(cached_dir);
++ free(cached_dir_base);
+ cached_dir = NULL;
+ }
+ /*
+@@ -642,7 +645,8 @@
+ static int UDFGetAVDP( dvd_reader_t *device,
+ struct avdp_t *avdp)
+ {
+- uint8_t Anchor[ DVD_VIDEO_LB_LEN ];
++ uint8_t Anchor_base[ DVD_VIDEO_LB_LEN + 2048 ];
++ uint8_t *Anchor = (uint8_t *)(((int)Anchor_base & ~2047) + 2048);
+ uint32_t lbnum, MVDS_location, MVDS_length;
+ uint16_t TagID;
+ uint32_t lastsector;
+@@ -713,7 +717,8 @@
static int UDFFindPartition( dvd_reader_t *device, int partnum,
struct Partition *part )
{
-- uint8_t LogBlock[ DVD_VIDEO_LB_LEN ], Anchor[ DVD_VIDEO_LB_LEN ];
+- uint8_t LogBlock[ DVD_VIDEO_LB_LEN ];
+ uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ];
+ uint8_t *LogBlock = (uint8_t *)(((int)LogBlock_base & ~2047) + 2048);
-+ uint8_t Anchor_base[ DVD_VIDEO_LB_LEN + 2048 ];
-+ uint8_t *Anchor = (uint8_t *)(((int)Anchor_base & ~2047) + 2048);
uint32_t lbnum, MVDS_location, MVDS_length;
uint16_t TagID;
- uint32_t lastsector;
-@@ -434,7 +439,8 @@
+ int i, volvalid;
+@@ -775,7 +780,8 @@
uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
uint32_t *filesize )
{
@@ -213,7 +312,7 @@
uint32_t lbnum;
uint16_t TagID;
struct Partition partition;
-@@ -460,7 +466,7 @@
+@@ -805,7 +811,7 @@
}
/* File Set Descriptor */
@@ -222,18 +321,19 @@
UDFLongAD( &LogBlock[ 400 ], &RootICB );
}
} while( ( lbnum < partition.Start + partition.Length )
---- src/input/libdvdread/ifo_print.c 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/ifo_print.c 2002-11-27 21:50:03.000000000 +0100
-@@ -25,7 +25,7 @@
- #include <ctype.h>
- #include <assert.h>
-
--#include "config.h" // Needed for WORDS_BIGENDIAN
-+#include "config.h" /* Needed for WORDS_BIGENDIAN */
- #include "ifo_types.h"
- #include "ifo_read.h"
- #include "ifo_print.h"
-@@ -71,7 +71,7 @@
+@@ -919,7 +925,8 @@
+
+ static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd)
+ {
+- uint8_t pvd_buf[DVD_VIDEO_LB_LEN];
++ uint8_t pvd_buf_base[DVD_VIDEO_LB_LEN + 2048];
++ uint8_t *pvd_buf = (uint8_t *)(((int)pvd_buf_base & ~2047) + 2048);
+
+ if(GetUDFCache(device, PVDCache, 0, pvd)) {
+ return 1;
+--- src/input/libdvdread/ifo_print.c 2003-02-02 03:23:53.000000000 +0100
++++ src/input/libdvdread/ifo_print.c 2003-02-28 14:40:32.000000000 +0100
+@@ -73,7 +73,7 @@
printf("%02x ", command->bytes[i]);
printf("| ");
@@ -242,7 +342,7 @@
printf("\n");
}
-@@ -126,19 +126,19 @@
+@@ -129,19 +129,19 @@
printf("(please send a bug report) ");
}
@@ -265,7 +365,7 @@
break;
default:
printf("(please send a bug report)");
-@@ -184,7 +184,7 @@
+@@ -198,7 +198,7 @@
if(attr->film_mode) {
printf("film");
} else {
@@ -274,16 +374,16 @@
}
}
-@@ -235,7 +235,7 @@
+@@ -251,7 +251,7 @@
switch(attr->lang_type) {
case 0:
- // not specified
+ /* not specified */
- assert(attr->lang_code == 0 || attr->lang_code == 0xffff);
+ CHECK_VALUE(attr->lang_code == 0 || attr->lang_code == 0xffff);
break;
case 1:
-@@ -247,7 +247,7 @@
+@@ -264,7 +264,7 @@
switch(attr->application_mode) {
case 0:
@@ -292,7 +392,7 @@
break;
case 1:
printf("karaoke mode ");
-@@ -294,19 +294,19 @@
+@@ -311,19 +311,19 @@
case 0:
printf("Not specified ");
break;
@@ -317,16 +417,7 @@
default:
printf("(please send a bug report) ");
}
-@@ -796,7 +796,7 @@
-
- printf("Number of Countries: %i\n", ptl_mait->nr_of_countries);
- printf("Number of VTSs: %i\n", ptl_mait->nr_of_vtss);
-- //printf("Last byte: %i\n", ptl_mait->last_byte);
-+ /* printf("Last byte: %i\n", ptl_mait->last_byte); */
-
- for(i = 0; i < ptl_mait->nr_of_countries; i++) {
- printf("Country code: %c%c\n",
-@@ -846,7 +846,7 @@
+@@ -913,7 +913,7 @@
int i, entries;
printf("Number of VOBs in this VOBS: %i\n", c_adt->nr_of_vobs);
@@ -335,7 +426,7 @@
entries = (c_adt->last_byte + 1 - C_ADT_SIZE)/sizeof(c_adt_t);
for(i = 0; i < entries; i++) {
-@@ -996,7 +996,7 @@
+@@ -1066,7 +1066,7 @@
printf("\nText Data Manager Information\n");
printf( "-----------------------------\n");
if(ifohandle->txtdt_mgi) {
@@ -344,8 +435,8 @@
} else {
printf("No Text Data Manager Information present\n");
}
---- src/input/libdvdread/ifo_print.h 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/ifo_print.h 2002-11-27 21:50:03.000000000 +0100
+--- src/input/libdvdread/ifo_print.h 2002-08-15 22:13:21.000000000 +0200
++++ src/input/libdvdread/ifo_print.h 2003-02-28 14:12:36.000000000 +0100
@@ -20,8 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -357,52 +448,43 @@
#ifdef __cplusplus
extern "C" {
---- src/input/libdvdread/ifo_read.c 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/ifo_read.c 2002-11-27 21:50:03.000000000 +0100
-@@ -26,7 +26,7 @@
-
- #include "dvd_reader.h"
-
--#include "config.h" // Needed for WORDS_BIGENDIAN
-+#include "config.h" /* Needed for WORDS_BIGENDIAN */
- #include "bswap.h"
- #include "ifo_types.h"
- #include "ifo_read.h"
-@@ -643,7 +643,7 @@
+--- src/input/libdvdread/ifo_read.c 2003-01-17 21:49:16.000000000 +0100
++++ src/input/libdvdread/ifo_read.c 2003-02-28 14:43:40.000000000 +0100
+@@ -659,7 +659,7 @@
/* Check that time is 0:0:0:0 also if nr_of_programs == 0 */
if(pgc->nr_of_programs == 0) {
CHECK_ZERO(pgc->still_time);
- CHECK_ZERO(pgc->pg_playback_mode); // ??
+ CHECK_ZERO(pgc->pg_playback_mode); /* ?? */
- assert(pgc->program_map_offset == 0);
- assert(pgc->cell_playback_offset == 0);
- assert(pgc->cell_position_offset == 0);
-@@ -829,24 +829,24 @@
+ CHECK_VALUE(pgc->program_map_offset == 0);
+ CHECK_VALUE(pgc->cell_playback_offset == 0);
+ CHECK_VALUE(pgc->cell_position_offset == 0);
+@@ -844,24 +844,24 @@
CHECK_ZERO(tt_srpt->zero_1);
- assert(tt_srpt->nr_of_srpts != 0);
-- assert(tt_srpt->nr_of_srpts < 100); // ??
-+ assert(tt_srpt->nr_of_srpts < 100); /* ?? */
- assert((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length);
+ CHECK_VALUE(tt_srpt->nr_of_srpts != 0);
+- CHECK_VALUE(tt_srpt->nr_of_srpts < 100); // ??
++ CHECK_VALUE(tt_srpt->nr_of_srpts < 100); /* ?? */
+ CHECK_VALUE((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length);
for(i = 0; i < tt_srpt->nr_of_srpts; i++) {
- assert(tt_srpt->title[i].pb_ty.zero_1 == 0);
- assert(tt_srpt->title[i].nr_of_angles != 0);
- assert(tt_srpt->title[i].nr_of_angles < 10);
-- //assert(tt_srpt->title[i].nr_of_ptts != 0);
+ CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0);
+ CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0);
+ CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10);
+- //CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0);
- // XXX: this assertion breaks Ghostbusters:
-- assert(tt_srpt->title[i].nr_of_ptts < 1000); // ??
-+ /* assert(tt_srpt->title[i].nr_of_ptts != 0); */
+- CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); // ??
++ /* CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); */
+ /* XXX: this assertion breaks Ghostbusters: */
-+ assert(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */
- assert(tt_srpt->title[i].title_set_nr != 0);
-- assert(tt_srpt->title[i].title_set_nr < 100); // ??
-+ assert(tt_srpt->title[i].title_set_nr < 100); /* ?? */
- assert(tt_srpt->title[i].vts_ttn != 0);
-- assert(tt_srpt->title[i].vts_ttn < 100); // ??
-- //assert(tt_srpt->title[i].title_set_sector != 0);
-+ assert(tt_srpt->title[i].vts_ttn < 100); /* ?? */
-+ /* assert(tt_srpt->title[i].title_set_sector != 0); */
++ CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */
+ CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0);
+- CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); // ??
++ CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); /* ?? */
+ CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0);
+- CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); // ??
+- //CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0);
++ CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); /* ?? */
++ /* CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); */
}
- // Make this a function
@@ -410,74 +492,71 @@
#if 0
if(memcmp((uint8_t *)tt_srpt->title +
tt_srpt->nr_of_srpts * sizeof(title_info_t),
-@@ -910,7 +910,7 @@
+@@ -925,7 +925,7 @@
CHECK_ZERO(vts_ptt_srpt->zero_1);
- assert(vts_ptt_srpt->nr_of_srpts != 0);
-- assert(vts_ptt_srpt->nr_of_srpts < 100); // ??
-+ assert(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */
+ CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0);
+- CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); // ??
++ CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */
info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE;
-@@ -985,12 +985,12 @@
+@@ -1001,12 +1001,12 @@
}
for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
-- assert(vts_ptt_srpt->title[i].nr_of_ptts < 1000); // ??
-+ assert(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */
+- CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); // ??
++ CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */
for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
- assert(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 );
-- assert(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); // ??
-+ assert(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */
- assert(vts_ptt_srpt->title[i].ptt[j].pgn != 0);
-- assert(vts_ptt_srpt->title[i].ptt[j].pgn < 100); // ??
-+ assert(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */
+ CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 );
+- CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); // ??
++ CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */
+ CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0);
+- CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); // ??
++ CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */
}
}
-@@ -1049,9 +1049,9 @@
- info_length = ptl_mait->last_byte + 1 - PTL_MAIT_SIZE;
+@@ -1064,9 +1064,9 @@
+ B2N_32(ptl_mait->last_byte);
- assert(ptl_mait->nr_of_countries != 0);
-- assert(ptl_mait->nr_of_countries < 100); // ??
-+ assert(ptl_mait->nr_of_countries < 100); /* ?? */
- assert(ptl_mait->nr_of_vtss != 0);
-- assert(ptl_mait->nr_of_vtss < 100); // ??
-+ assert(ptl_mait->nr_of_vtss < 100); /* ?? */
- assert(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE <= info_length);
+ CHECK_VALUE(ptl_mait->nr_of_countries != 0);
+- CHECK_VALUE(ptl_mait->nr_of_countries < 100); // ??
++ CHECK_VALUE(ptl_mait->nr_of_countries < 100); /* ?? */
+ CHECK_VALUE(ptl_mait->nr_of_vtss != 0);
+- CHECK_VALUE(ptl_mait->nr_of_vtss < 100); // ??
++ CHECK_VALUE(ptl_mait->nr_of_vtss < 100); /* ?? */
+ CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE
+ <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE);
- /* Change this to read and 'translate' the tables too.
-@@ -1519,7 +1519,7 @@
+@@ -1605,7 +1605,7 @@
/* assert(pgcit->nr_of_pgci_srp != 0);
Magic Knight Rayearth Daybreak is mastered very strange and has
Titles with 0 PTTs. */
-- assert(pgcit->nr_of_pgci_srp < 10000); // ?? seen max of 1338
-+ assert(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */
+- CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); // ?? seen max of 1338
++ CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */
info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE;
data = malloc(info_length);
-@@ -1640,7 +1640,7 @@
+@@ -1726,7 +1726,7 @@
CHECK_ZERO(pgci_ut->zero_1);
- assert(pgci_ut->nr_of_lus != 0);
-- assert(pgci_ut->nr_of_lus < 100); // ?? 3-4 ?
-+ assert(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */
- assert((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte);
+ CHECK_VALUE(pgci_ut->nr_of_lus != 0);
+- CHECK_VALUE(pgci_ut->nr_of_lus < 100); // ?? 3-4 ?
++ CHECK_VALUE(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */
+ CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte);
info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE;
-@@ -1675,8 +1675,9 @@
+@@ -1760,7 +1760,7 @@
+ free(data);
for(i = 0; i < pgci_ut->nr_of_lus; i++) {
- CHECK_ZERO(pgci_ut->lu[i].zero_1);
- // Maybe this is only defined for v1.1 and later titles?
-- /* If the bits in 'lu[i].exists' are enumerated abcd efgh then:
-+ /*
-+ Maybe this is only defined for v1.1 and later titles?
-+ If the bits in 'lu[i].exists' are enumerated abcd efgh then:
++ /* Maybe this is only defined for v1.1 and later titles? */
+ /* If the bits in 'lu[i].exists' are enumerated abcd efgh then:
VTS_x_yy.IFO VIDEO_TS.IFO
a == 0x83 "Root" 0x82 "Title"
- b == 0x84 "Subpicture"
-@@ -1714,8 +1715,10 @@
+@@ -1799,8 +1799,10 @@
ifofile->pgci_ut = 0;
return 0;
}
@@ -490,9 +569,9 @@
}
return 1;
-@@ -1776,8 +1779,8 @@
+@@ -1861,8 +1863,8 @@
unsigned int nr_coded;
- assert(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE);
+ CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE);
nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6;
- // This is often nr_coded = 70, how do you know how many there really are?
- if(nr_coded > 32) { // We haven't read more from disk/file anyway
@@ -500,29 +579,29 @@
+ if(nr_coded > 32) { /* We haven't read more from disk/file anyway */
nr_coded = 32;
}
- assert(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded);
-@@ -1825,7 +1828,7 @@
+ CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded);
+@@ -1910,7 +1912,7 @@
CHECK_ZERO(vts_atrt->zero_1);
- assert(vts_atrt->nr_of_vtss != 0);
-- assert(vts_atrt->nr_of_vtss < 100); //??
-+ assert(vts_atrt->nr_of_vtss < 100); /* ?? */
- assert((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) +
+ CHECK_VALUE(vts_atrt->nr_of_vtss != 0);
+- CHECK_VALUE(vts_atrt->nr_of_vtss < 100); //??
++ CHECK_VALUE(vts_atrt->nr_of_vtss < 100); /* ?? */
+ CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) +
VTS_ATRT_SIZE < vts_atrt->last_byte + 1);
-@@ -1866,9 +1869,9 @@
+@@ -1954,9 +1956,9 @@
return 0;
}
- // This assert cant be in ifoRead_VTS_ATTRIBUTES
+ /* This assert cant be in ifoRead_VTS_ATTRIBUTES */
- assert(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1);
+ CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1);
- // Is this check correct?
+ /* Is this check correct? */
}
- free(data);
-@@ -1918,7 +1921,7 @@
+ return 1;
+@@ -2006,7 +2008,7 @@
return 0;
}
@@ -531,8 +610,8 @@
return 1;
}
---- src/input/libdvdread/ifo_read.h 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/ifo_read.h 2002-11-27 21:50:03.000000000 +0100
+--- src/input/libdvdread/ifo_read.h 2002-12-15 01:09:12.000000000 +0100
++++ src/input/libdvdread/ifo_read.h 2003-02-28 14:12:36.000000000 +0100
@@ -20,8 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -544,9 +623,8 @@
#ifdef __cplusplus
extern "C" {
-diff -urN libdvdread.cvs/ifo_types.h libdvdread.new/ifo_types.h
---- src/input/libdvdread/ifo_types.h 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/ifo_types.h 2002-11-27 21:50:03.000000000 +0100
+--- src/input/libdvdread/ifo_types.h 2003-02-22 22:42:11.000000000 +0100
++++ src/input/libdvdread/ifo_types.h 2003-02-28 14:12:36.000000000 +0100
@@ -21,7 +21,7 @@
*/
@@ -556,263 +634,19 @@ diff -urN libdvdread.cvs/ifo_types.h libdvdread.new/ifo_types.h
#undef ATTRIBUTE_PACKED
-@@ -59,7 +59,7 @@
- uint8_t hour;
- uint8_t minute;
- uint8_t second;
-- uint8_t frame_u; // The two high bits are the frame rate.
-+ uint8_t frame_u; /* The two high bits are the frame rate. */
- } ATTRIBUTE_PACKED dvd_time_t;
-
- /**
-@@ -130,7 +130,7 @@
- unsigned int quantization : 2;
- #endif
- uint16_t lang_code;
-- uint8_t lang_code2; // ??
-+ uint8_t lang_code2; /* ?? */
- uint8_t lang_extension;
- uint16_t unknown2;
- } ATTRIBUTE_PACKED audio_attr_t;
-@@ -235,65 +235,65 @@
- */
- typedef struct {
- #ifdef WORDS_BIGENDIAN
-- unsigned int zero : 7; // 25-31
-- unsigned int video_pres_mode_change : 1; // 24
--
-- unsigned int karaoke_audio_pres_mode_change : 1; // 23
-- unsigned int angle_change : 1; // 22
-- unsigned int subpic_stream_change : 1; // 21
-- unsigned int audio_stream_change : 1; // 20
-- unsigned int pause_on : 1; // 19
-- unsigned int still_off : 1; // 18
-- unsigned int button_select_or_activate : 1; // 17
-- unsigned int resume : 1; // 16
--
-- unsigned int chapter_menu_call : 1; // 15
-- unsigned int angle_menu_call : 1; // 14
-- unsigned int audio_menu_call : 1; // 13
-- unsigned int subpic_menu_call : 1; // 12
-- unsigned int root_menu_call : 1; // 11
-- unsigned int title_menu_call : 1; // 10
-- unsigned int backward_scan : 1; // 9
-- unsigned int forward_scan : 1; // 8
--
-- unsigned int next_pg_search : 1; // 7
-- unsigned int prev_or_top_pg_search : 1; // 6
-- unsigned int time_or_chapter_search : 1; // 5
-- unsigned int go_up : 1; // 4
-- unsigned int stop : 1; // 3
-- unsigned int title_play : 1; // 2
-- unsigned int chapter_search_or_play : 1; // 1
-- unsigned int title_or_time_play : 1; // 0
-+ unsigned int zero : 7; /* 25-31 */
-+ unsigned int video_pres_mode_change : 1; /* 24 */
-+
-+ unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */
-+ unsigned int angle_change : 1; /* 22 */
-+ unsigned int subpic_stream_change : 1; /* 21 */
-+ unsigned int audio_stream_change : 1; /* 20 */
-+ unsigned int pause_on : 1; /* 19 */
-+ unsigned int still_off : 1; /* 18 */
-+ unsigned int button_select_or_activate : 1; /* 17 */
-+ unsigned int resume : 1; /* 16 */
-+
-+ unsigned int chapter_menu_call : 1; /* 15 */
-+ unsigned int angle_menu_call : 1; /* 14 */
-+ unsigned int audio_menu_call : 1; /* 13 */
-+ unsigned int subpic_menu_call : 1; /* 12 */
-+ unsigned int root_menu_call : 1; /* 11 */
-+ unsigned int title_menu_call : 1; /* 10 */
-+ unsigned int backward_scan : 1; /* 9 */
-+ unsigned int forward_scan : 1; /* 8 */
-+
-+ unsigned int next_pg_search : 1; /* 7 */
-+ unsigned int prev_or_top_pg_search : 1; /* 6 */
-+ unsigned int time_or_chapter_search : 1; /* 5 */
-+ unsigned int go_up : 1; /* 4 */
-+ unsigned int stop : 1; /* 3 */
-+ unsigned int title_play : 1; /* 2 */
-+ unsigned int chapter_search_or_play : 1; /* 1 */
-+ unsigned int title_or_time_play : 1; /* 0 */
- #else
-- unsigned int video_pres_mode_change : 1; // 24
-- unsigned int zero : 7; // 25-31
--
-- unsigned int resume : 1; // 16
-- unsigned int button_select_or_activate : 1; // 17
-- unsigned int still_off : 1; // 18
-- unsigned int pause_on : 1; // 19
-- unsigned int audio_stream_change : 1; // 20
-- unsigned int subpic_stream_change : 1; // 21
-- unsigned int angle_change : 1; // 22
-- unsigned int karaoke_audio_pres_mode_change : 1; // 23
--
-- unsigned int forward_scan : 1; // 8
-- unsigned int backward_scan : 1; // 9
-- unsigned int title_menu_call : 1; // 10
-- unsigned int root_menu_call : 1; // 11
-- unsigned int subpic_menu_call : 1; // 12
-- unsigned int audio_menu_call : 1; // 13
-- unsigned int angle_menu_call : 1; // 14
-- unsigned int chapter_menu_call : 1; // 15
--
-- unsigned int title_or_time_play : 1; // 0
-- unsigned int chapter_search_or_play : 1; // 1
-- unsigned int title_play : 1; // 2
-- unsigned int stop : 1; // 3
-- unsigned int go_up : 1; // 4
-- unsigned int time_or_chapter_search : 1; // 5
-- unsigned int prev_or_top_pg_search : 1; // 6
-- unsigned int next_pg_search : 1; // 7
-+ unsigned int video_pres_mode_change : 1; /* 24 */
-+ unsigned int zero : 7; /* 25-31 */
-+
-+ unsigned int resume : 1; /* 16 */
-+ unsigned int button_select_or_activate : 1; /* 17 */
-+ unsigned int still_off : 1; /* 18 */
-+ unsigned int pause_on : 1; /* 19 */
-+ unsigned int audio_stream_change : 1; /* 20 */
-+ unsigned int subpic_stream_change : 1; /* 21 */
-+ unsigned int angle_change : 1; /* 22 */
-+ unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */
-+
-+ unsigned int forward_scan : 1; /* 8 */
-+ unsigned int backward_scan : 1; /* 9 */
-+ unsigned int title_menu_call : 1; /* 10 */
-+ unsigned int root_menu_call : 1; /* 11 */
-+ unsigned int subpic_menu_call : 1; /* 12 */
-+ unsigned int audio_menu_call : 1; /* 13 */
-+ unsigned int angle_menu_call : 1; /* 14 */
-+ unsigned int chapter_menu_call : 1; /* 15 */
-+
-+ unsigned int title_or_time_play : 1; /* 0 */
-+ unsigned int chapter_search_or_play : 1; /* 1 */
-+ unsigned int title_play : 1; /* 2 */
-+ unsigned int stop : 1; /* 3 */
-+ unsigned int go_up : 1; /* 4 */
-+ unsigned int time_or_chapter_search : 1; /* 5 */
-+ unsigned int prev_or_top_pg_search : 1; /* 6 */
-+ unsigned int next_pg_search : 1; /* 7 */
- #endif
- } ATTRIBUTE_PACKED user_ops_t;
-
-@@ -453,11 +453,11 @@
-
- video_attr_t vmgm_video_attr;
- uint8_t zero_7;
-- uint8_t nr_of_vmgm_audio_streams; // should be 0 or 1
-+ uint8_t nr_of_vmgm_audio_streams; /* should be 0 or 1 */
- audio_attr_t vmgm_audio_attr;
- audio_attr_t zero_8[7];
- uint8_t zero_9[17];
-- uint8_t nr_of_vmgm_subp_streams; // should be 0 or 1
-+ uint8_t nr_of_vmgm_subp_streams; /* should be 0 or 1 */
- subp_attr_t vmgm_subp_attr;
- subp_attr_t zero_10[27]; /* XXX: how much 'padding' here? */
- } ATTRIBUTE_PACKED vmgi_mat_t;
-@@ -465,21 +465,21 @@
- typedef struct {
- #ifdef WORDS_BIGENDIAN
- unsigned int zero_1 : 1;
-- unsigned int multi_or_random_pgc_title : 1; // 0 == one sequential pgc title
-+ unsigned int multi_or_random_pgc_title : 1; /* 0 == one sequential pgc title */
- unsigned int jlc_exists_in_cell_cmd : 1;
- unsigned int jlc_exists_in_prepost_cmd : 1;
- unsigned int jlc_exists_in_button_cmd : 1;
- unsigned int jlc_exists_in_tt_dom : 1;
-- unsigned int chapter_search_or_play : 1; // UOP 1
-- unsigned int title_or_time_play : 1; // UOP 0
-+ unsigned int chapter_search_or_play : 1; /* UOP 1 */
-+ unsigned int title_or_time_play : 1; /* UOP 0 */
- #else
-- unsigned int title_or_time_play : 1; // UOP 0
-- unsigned int chapter_search_or_play : 1; // UOP 1
-+ unsigned int title_or_time_play : 1; /* UOP 0 */
-+ unsigned int chapter_search_or_play : 1; /* UOP 1 */
- unsigned int jlc_exists_in_tt_dom : 1;
- unsigned int jlc_exists_in_button_cmd : 1;
- unsigned int jlc_exists_in_prepost_cmd : 1;
- unsigned int jlc_exists_in_cell_cmd : 1;
-- unsigned int multi_or_random_pgc_title : 1; // 0 == one sequential pgc title
-+ unsigned int multi_or_random_pgc_title : 1; /* 0 == one sequential pgc title */
- unsigned int zero_1 : 1;
- #endif
- } ATTRIBUTE_PACKED playback_type_t;
-@@ -540,12 +540,12 @@
-
- video_attr_t vtsm_vobs_attr;
- uint8_t zero_1;
-- uint8_t nr_of_vtsm_audio_streams; // should be 0 or 1
-+ uint8_t nr_of_vtsm_audio_streams; /* should be 0 or 1 */
- audio_attr_t vtsm_audio_attr;
- audio_attr_t zero_2[7];
- uint8_t zero_3[16];
- uint8_t zero_4;
-- uint8_t nr_of_vtsm_subp_streams; // should be 0 or 1
-+ uint8_t nr_of_vtsm_subp_streams; /* should be 0 or 1 */
- subp_attr_t vtsm_subp_attr;
- subp_attr_t zero_5[27];
-
-@@ -581,18 +581,18 @@
- uint32_t last_byte; /* offsets are relative here */
- uint16_t offsets[100]; /* == nr_of_srpts + 1 (first is disc title) */
- #if 0
-- uint16_t unknown; // 0x48 ?? 0x48 words (16bit) info following
-+ uint16_t unknown; /* 0x48 ?? 0x48 words (16bit) info following */
- uint16_t zero_1;
-
-- uint8_t type_of_info;//?? 01 == disc, 02 == Title, 04 == Title part
-+ uint8_t type_of_info; /* ?? 01 == disc, 02 == Title, 04 == Title part */
- uint8_t unknown1;
- uint8_t unknown2;
- uint8_t unknown3;
-- uint8_t unknown4;//?? allways 0x30 language?, text format?
-+ uint8_t unknown4; /*?? allways 0x30 language?, text format? */
- uint8_t unknown5;
-- uint16_t offset; // from first
-+ uint16_t offset; /* from first */
-
-- char text[12]; // ended by 0x09
-+ char text[12]; /* ended by 0x09 */
+--- src/input/libdvdread/md5.c 2003-01-12 01:46:16.000000000 +0100
++++ src/input/libdvdread/md5.c 2003-02-28 14:53:15.000000000 +0100
+@@ -36,7 +36,7 @@
#endif
- } ATTRIBUTE_PACKED txtdt_t;
-
-@@ -652,7 +652,7 @@
- uint32_t vts_ptt_srpt; /* sector */
- uint32_t vts_pgcit; /* sector */
- uint32_t vtsm_pgci_ut; /* sector */
-- uint32_t vts_tmapt; /* sector */ // XXX: FIXME TODO Implement
-+ uint32_t vts_tmapt; /* sector */ /* XXX: FIXME TODO Implement */
- uint32_t vtsm_c_adt; /* sector */
- uint32_t vtsm_vobu_admap; /* sector */
- uint32_t vts_c_adt; /* sector */
-@@ -661,11 +661,11 @@
-
- video_attr_t vtsm_video_attr;
- uint8_t zero_14;
-- uint8_t nr_of_vtsm_audio_streams; // should be 0 or 1
-+ uint8_t nr_of_vtsm_audio_streams; /* should be 0 or 1 */
- audio_attr_t vtsm_audio_attr;
- audio_attr_t zero_15[7];
- uint8_t zero_16[17];
-- uint8_t nr_of_vtsm_subp_streams; // should be 0 or 1
-+ uint8_t nr_of_vtsm_subp_streams; /* should be 0 or 1 */
- subp_attr_t vtsm_subp_attr;
- subp_attr_t zero_17[27];
- uint8_t zero_18[2];
---- src/input/libdvdread/nav_print.c 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/nav_print.c 2002-11-27 21:50:03.000000000 +0100
-@@ -27,7 +27,7 @@
- #include <inttypes.h>
- #include <assert.h>
--#include "config.h" // Needed for WORDS_BIGENDIAN
-+#include "config.h" /* Needed for WORDS_BIGENDIAN */
- #include "nav_types.h"
- #include "nav_print.h"
+ #include "md5.h"
+-//#include "unlocked-io.h"
++/* #include "unlocked-io.h" */
+ #ifdef _LIBC
+ # include <endian.h>
+--- src/input/libdvdread/nav_print.c 2003-01-07 21:58:15.000000000 +0100
++++ src/input/libdvdread/nav_print.c 2003-02-28 14:12:36.000000000 +0100
@@ -167,7 +167,7 @@
printf("left %d, ", btni->left);
printf("right %d\n", btni->right);
@@ -822,8 +656,8 @@ diff -urN libdvdread.cvs/ifo_types.h libdvdread.new/ifo_types.h
printf("\n");
}
}
---- src/input/libdvdread/nav_print.h 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/nav_print.h 2002-11-27 21:50:03.000000000 +0100
+--- src/input/libdvdread/nav_print.h 2002-07-26 23:20:28.000000000 +0200
++++ src/input/libdvdread/nav_print.h 2003-02-28 14:12:36.000000000 +0100
@@ -20,7 +20,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -833,90 +667,46 @@ diff -urN libdvdread.cvs/ifo_types.h libdvdread.new/ifo_types.h
/**
* Pretty printing of the NAV packets, PCI and DSI structs.
---- src/input/libdvdread/nav_read.c 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/nav_read.c 2002-11-27 21:50:03.000000000 +0100
-@@ -21,15 +21,19 @@
- #include <inttypes.h>
- #include <assert.h>
-
--#include "config.h" // Needed for WORDS_BIGENDIAN
-+#include "config.h" /* Needed for WORDS_BIGENDIAN */
- #include "bswap.h"
- #include "nav_types.h"
- #include "nav_read.h"
-
-+/*
-+#define STRICT
-+*/
-+
+--- src/input/libdvdread/nav_read.c 2003-01-07 21:58:15.000000000 +0100
++++ src/input/libdvdread/nav_read.c 2003-02-28 14:49:04.000000000 +0100
+@@ -30,7 +30,7 @@
void navRead_PCI(pci_t *pci, unsigned char *buffer) {
-- int i, j, k;
-+ int i, j;
+ int i, j;
-- assert(sizeof(pci_t) == PCI_BYTES - 1); // -1 for substream id
-+ assert(sizeof(pci_t) == PCI_BYTES - 1); /* -1 for substream id */
+- CHECK_VALUE(sizeof(pci_t) == PCI_BYTES - 1); // -1 for substream id
++ CHECK_VALUE(sizeof(pci_t) == PCI_BYTES - 1); /* -1 for substream id */
memcpy(pci, buffer, sizeof(pci_t));
-@@ -71,6 +75,7 @@
- #endif
-
-
-+#ifdef STRICT
- /* Asserts */
-
- /* pci pci gi */
-@@ -95,6 +100,7 @@
- /* pci hli btnit */
- for(i = 0; i < pci->hli.hl_gi.btngr_ns; i++) {
- for(j = 0; j < (36 / pci->hli.hl_gi.btngr_ns); j++) {
-+ int k;
- int n = (36 / pci->hli.hl_gi.btngr_ns) * i + j;
- assert(pci->hli.btnit[n].zero1 == 0);
- assert(pci->hli.btnit[n].zero2 == 0);
-@@ -110,7 +116,7 @@
- assert(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns);
- assert(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns);
- assert(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns);
+@@ -126,7 +126,7 @@
+ CHECK_VALUE(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns);
+ CHECK_VALUE(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns);
+ CHECK_VALUE(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns);
- //vmcmd_verify(pci->hli.btnit[n].cmd);
-+ /* vmcmd_verify(pci->hli.btnit[n].cmd); */
++ /*vmcmd_verify(pci->hli.btnit[n].cmd);*/
} else {
- assert(pci->hli.btnit[n].btn_coln == 0);
- assert(pci->hli.btnit[n].auto_action_mode == 0);
-@@ -123,16 +129,17 @@
- assert(pci->hli.btnit[n].left == 0);
- assert(pci->hli.btnit[n].right == 0);
+ int k;
+ CHECK_VALUE(pci->hli.btnit[n].btn_coln == 0);
+@@ -140,7 +140,7 @@
+ CHECK_VALUE(pci->hli.btnit[n].left == 0);
+ CHECK_VALUE(pci->hli.btnit[n].right == 0);
for (k = 0; k < 8; k++)
-- assert(pci->hli.btnit[n].cmd.bytes[k] == 0); //CHECK_ZERO?
-+ assert(pci->hli.btnit[n].cmd.bytes[k] == 0); /* CHECK_ZERO? */
+- CHECK_VALUE(pci->hli.btnit[n].cmd.bytes[k] == 0); //CHECK_ZERO?
++ CHECK_VALUE(pci->hli.btnit[n].cmd.bytes[k] == 0); /* CHECK_ZERO? */
}
}
}
-+#endif
- }
-
+@@ -150,7 +150,7 @@
void navRead_DSI(dsi_t *dsi, unsigned char *buffer) {
int i;
-- assert(sizeof(dsi_t) == DSI_BYTES - 1); // -1 for substream id
-+ assert(sizeof(dsi_t) == DSI_BYTES - 1); /* -1 for substream id */
+- CHECK_VALUE(sizeof(dsi_t) == DSI_BYTES - 1); // -1 for substream id
++ CHECK_VALUE(sizeof(dsi_t) == DSI_BYTES - 1); /* -1 for substream id */
memcpy(dsi, buffer, sizeof(dsi_t));
-@@ -178,9 +185,11 @@
- B2N_32(dsi->synci.sp_synca[i]);
-
-
-+#ifdef STRICT
- /* Asserts */
-
- /* dsi dsi gi */
- assert(dsi->dsi_gi.zero1 == 0);
-+#endif
- }
-
---- src/input/libdvdread/nav_read.h 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/nav_read.h 2002-11-27 21:50:03.000000000 +0100
+--- src/input/libdvdread/nav_read.h 2002-07-26 23:04:05.000000000 +0200
++++ src/input/libdvdread/nav_read.h 2003-02-28 14:12:36.000000000 +0100
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -926,8 +716,8 @@ diff -urN libdvdread.cvs/ifo_types.h libdvdread.new/ifo_types.h
/**
* Parsing of NAV data, PCI and DSI parts.
---- src/input/libdvdread/nav_types.h 2002-11-27 21:56:47.000000000 +0100
-+++ src/input/libdvdread/nav_types.h 2002-11-27 21:55:06.000000000 +0100
+--- src/input/libdvdread/nav_types.h 2003-01-02 21:11:06.000000000 +0100
++++ src/input/libdvdread/nav_types.h 2003-02-28 14:12:36.000000000 +0100
@@ -30,7 +30,7 @@
*/
diff --git a/src/input/libdvdread/dvd_input.c b/src/input/libdvdread/dvd_input.c
index d1782500f..ba1cb4c02 100644
--- a/src/input/libdvdread/dvd_input.c
+++ b/src/input/libdvdread/dvd_input.c
@@ -17,33 +17,44 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
+#include "config.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
-#include <dlfcn.h>
#include "dvd_reader.h"
#include "dvd_input.h"
/* The function pointers that is the exported interface of this file. */
-dvd_input_t (*DVDinput_open) (const char *);
-int (*DVDinput_close) (dvd_input_t);
-int (*DVDinput_seek) (dvd_input_t, int);
-int (*DVDinput_title) (dvd_input_t, int);
-int (*DVDinput_read) (dvd_input_t, void *, int, int);
-char * (*DVDinput_error) (dvd_input_t);
-
-/* For libdvdcss */
+dvd_input_t (*dvdinput_open) (const char *);
+int (*dvdinput_close) (dvd_input_t);
+int (*dvdinput_seek) (dvd_input_t, int);
+int (*dvdinput_title) (dvd_input_t, int);
+int (*dvdinput_read) (dvd_input_t, void *, int, int);
+char * (*dvdinput_error) (dvd_input_t);
+
+#ifdef HAVE_DVDCSS_DVDCSS_H
+/* linking to libdvdcss */
+#include <dvdcss/dvdcss.h>
+#define DVDcss_open(a) dvdcss_open((char*)(a))
+#define DVDcss_close dvdcss_close
+#define DVDcss_seek dvdcss_seek
+#define DVDcss_title dvdcss_title
+#define DVDcss_read dvdcss_read
+#define DVDcss_error dvdcss_error
+#else
+/* dlopening libdvdcss */
+#include <dlfcn.h>
typedef struct dvdcss_s *dvdcss_handle;
-
-dvdcss_handle (*DVDcss_open) (const char *);
-int (*DVDcss_close) (dvdcss_handle);
-int (*DVDcss_seek) (dvdcss_handle, int, int);
-int (*DVDcss_title) (dvdcss_handle, int);
-int (*DVDcss_read) (dvdcss_handle, void *, int, int);
-char * (*DVDcss_error) (dvdcss_handle);
-
+static dvdcss_handle (*DVDcss_open) (const char *);
+static int (*DVDcss_close) (dvdcss_handle);
+static int (*DVDcss_seek) (dvdcss_handle, int, int);
+static int (*DVDcss_title) (dvdcss_handle, int);
+static int (*DVDcss_read) (dvdcss_handle, void *, int, int);
+static char * (*DVDcss_error) (dvdcss_handle);
+#endif
/* The DVDinput handle, add stuff here for new input methods. */
struct dvd_input_s {
@@ -72,7 +83,7 @@ static dvd_input_t css_open(const char *target)
/* Really open it with libdvdcss */
dev->dvdcss = DVDcss_open(target);
if(dev->dvdcss == 0) {
- fprintf(stderr, "libdvdread: Could not open device with libdvdcss.\n");
+ fprintf(stderr, "libdvdread: Could not open %s with libdvdcss.\n", target);
free(dev);
return NULL;
}
@@ -250,11 +261,19 @@ static int file_close(dvd_input_t dev)
/**
* Setup read functions with either libdvdcss or minimal DVD access.
*/
-int DVDInputSetup(void)
+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 */
dvdcss_library = dlopen("libdvdcss.so.2", RTLD_LAZY);
if(dvdcss_library != NULL) {
@@ -292,6 +311,7 @@ int DVDInputSetup(void)
dlclose(dvdcss_library);
}
}
+#endif /* HAVE_DVDCSS_DVDCSS_H */
if(dvdcss_library != NULL) {
/*
@@ -303,25 +323,25 @@ int DVDInputSetup(void)
fprintf(stderr, "libdvdread: Using libdvdcss version %s for DVD access\n",
*dvdcss_version);
- /* libdvdcss wraper functions */
- DVDinput_open = css_open;
- DVDinput_close = css_close;
- DVDinput_seek = css_seek;
- DVDinput_title = css_title;
- DVDinput_read = css_read;
- DVDinput_error = css_error;
+ /* libdvdcss wrapper functions */
+ dvdinput_open = css_open;
+ dvdinput_close = css_close;
+ dvdinput_seek = css_seek;
+ dvdinput_title = css_title;
+ dvdinput_read = css_read;
+ dvdinput_error = css_error;
return 1;
} else {
fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n");
/* libdvdcss replacement functions */
- DVDinput_open = file_open;
- DVDinput_close = file_close;
- DVDinput_seek = file_seek;
- DVDinput_title = file_title;
- DVDinput_read = file_read;
- DVDinput_error = file_error;
+ dvdinput_open = file_open;
+ dvdinput_close = file_close;
+ dvdinput_seek = file_seek;
+ dvdinput_title = file_title;
+ dvdinput_read = file_read;
+ dvdinput_error = file_error;
return 0;
}
}
diff --git a/src/input/libdvdread/dvd_input.h b/src/input/libdvdread/dvd_input.h
index 0f13385bf..e9e84917e 100644
--- a/src/input/libdvdread/dvd_input.h
+++ b/src/input/libdvdread/dvd_input.h
@@ -30,18 +30,18 @@
typedef struct dvd_input_s *dvd_input_t;
/**
- * Pointers which will be filled either the input meathods functions.
+ * Pointers which will be filled either the input methods functions.
*/
-extern dvd_input_t (*DVDinput_open) (const char *);
-extern int (*DVDinput_close) (dvd_input_t);
-extern int (*DVDinput_seek) (dvd_input_t, int);
-extern int (*DVDinput_title) (dvd_input_t, int);
-extern int (*DVDinput_read) (dvd_input_t, void *, int, int);
-extern char * (*DVDinput_error) (dvd_input_t);
+extern dvd_input_t (*dvdinput_open) (const char *);
+extern int (*dvdinput_close) (dvd_input_t);
+extern int (*dvdinput_seek) (dvd_input_t, int);
+extern int (*dvdinput_title) (dvd_input_t, int);
+extern int (*dvdinput_read) (dvd_input_t, void *, int, int);
+extern char * (*dvdinput_error) (dvd_input_t);
/**
* Setup function accessed by dvd_reader.c. Returns 1 if there is CSS support.
*/
-int DVDInputSetup(void);
+int dvdinput_setup(void);
#endif /* DVD_INPUT_H_INCLUDED */
diff --git a/src/input/libdvdread/dvd_reader.c b/src/input/libdvdread/dvd_reader.c
index 242bd2ba7..a46b47f02 100644
--- a/src/input/libdvdread/dvd_reader.c
+++ b/src/input/libdvdread/dvd_reader.c
@@ -1,6 +1,7 @@
/*
- * Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>,
- * Håkan Hjort <d95hjort@dtek.chalmers.se>
+ * Copyright (C) 2001, 2002, 2003 Billy Biggs <vektor@dumbterm.net>,
+ * Håkan Hjort <d95hjort@dtek.chalmers.se>,
+ * Björn Englund <d4bjorn@dtek.chalmers.se>
*
* 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
@@ -17,6 +18,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
+#include "config.h"
+
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h> /* For the timing of dvdcss_title crack. */
@@ -28,6 +31,7 @@
#include <unistd.h>
#include <limits.h>
#include <dirent.h>
+
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)|| defined(__DARWIN__)
#define SYS_BSD 1
#endif
@@ -44,6 +48,9 @@
#include "dvd_udf.h"
#include "dvd_input.h"
#include "dvd_reader.h"
+#include "md5.h"
+
+#define DEFAULT_UDF_CACHE_LEVEL 1
struct dvd_reader_s {
/* Basic information. */
@@ -52,13 +59,17 @@ struct dvd_reader_s {
/* Hack for keeping track of the css status.
* 0: no css, 1: perhaps (need init of keys), 2: have done init */
int css_state;
- int css_title; /* Last title that we have called DVDinpute_title for. */
+ int css_title; /* Last title that we have called dvdinpute_title for. */
/* Information required for an image file. */
dvd_input_t dev;
/* Information required for a directory path drive. */
char *path_root;
+
+ /* Filesystem cache */
+ int udfcache_level; /* 0 - turned off, 1 - on */
+ void *udfcache;
};
struct dvd_file_s {
@@ -80,6 +91,42 @@ struct dvd_file_s {
ssize_t filesize;
};
+/**
+ * Set the level of caching on udf
+ * level = 0 (no caching)
+ * level = 1 (caching filesystem info)
+ */
+int DVDUDFCacheLevel(dvd_reader_t *device, int level)
+{
+ struct dvd_reader_s *dev = (struct dvd_reader_s *)device;
+
+ if(level > 0) {
+ level = 1;
+ } else if(level < 0) {
+ return dev->udfcache_level;
+ }
+
+ dev->udfcache_level = level;
+
+ return level;
+}
+
+void *GetUDFCacheHandle(dvd_reader_t *device)
+{
+ struct dvd_reader_s *dev = (struct dvd_reader_s *)device;
+
+ return dev->udfcache;
+}
+
+void SetUDFCacheHandle(dvd_reader_t *device, void *cache)
+{
+ struct dvd_reader_s *dev = (struct dvd_reader_s *)device;
+
+ dev->udfcache = cache;
+}
+
+
+
/* Loop over all titles and call dvdcss_title to crack the keys. */
static int initAllCSSKeys( dvd_reader_t *dvd )
{
@@ -89,6 +136,10 @@ static int initAllCSSKeys( dvd_reader_t *dvd )
uint32_t start, len;
int title;
+ char *nokeys_str = getenv("DVDREAD_NOKEYS");
+ if(nokeys_str != NULL)
+ return 0;
+
fprintf( stderr, "\n" );
fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" );
fprintf( stderr, "libdvdread: This can take a _long_ time, "
@@ -108,7 +159,7 @@ static int initAllCSSKeys( dvd_reader_t *dvd )
/* Perform CSS key cracking for this title. */
fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
filename, start );
- if( DVDinput_title( dvd->dev, (int)start ) < 0 ) {
+ if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start);
}
gettimeofday( &t_e, NULL );
@@ -126,7 +177,7 @@ static int initAllCSSKeys( dvd_reader_t *dvd )
/* Perform CSS key cracking for this title. */
fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
filename, start );
- if( DVDinput_title( dvd->dev, (int)start ) < 0 ) {
+ if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start);
}
gettimeofday( &t_e, NULL );
@@ -153,7 +204,7 @@ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css )
dvd_reader_t *dvd;
dvd_input_t dev;
- dev = DVDinput_open( location );
+ dev = dvdinput_open( location );
if( !dev ) {
fprintf( stderr, "libdvdread: Can't open %s for reading\n", location );
return 0;
@@ -165,6 +216,9 @@ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css )
dvd->dev = dev;
dvd->path_root = 0;
+ dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL;
+ dvd->udfcache = NULL;
+
if( have_css ) {
/* Only if DVDCSS_METHOD = title, a bit if it's disc or if
* DVDCSS_METHOD = key but region missmatch. Unfortunaly we
@@ -172,6 +226,7 @@ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css )
dvd->css_state = 1; /* Need key init. */
}
+ dvd->css_title = 0;
return dvd;
}
@@ -186,6 +241,12 @@ static dvd_reader_t *DVDOpenPath( const char *path_root )
dvd->dev = 0;
dvd->path_root = strdup( path_root );
+ dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL;
+ dvd->udfcache = NULL;
+
+ dvd->css_state = 0; /* Only used in the UDF path */
+ dvd->css_title = 0; /* Only matters in the UDF path */
+
return dvd;
}
@@ -252,7 +313,7 @@ dvd_reader_t *DVDOpen( const char *path )
}
/* Try to open libdvdcss or fall back to standard functions */
- have_css = DVDInputSetup();
+ have_css = dvdinput_setup();
/* First check if this is a block/char device or a file*/
if( S_ISBLK( fileinfo.st_mode ) ||
@@ -395,8 +456,9 @@ dvd_reader_t *DVDOpen( const char *path )
void DVDClose( dvd_reader_t *dvd )
{
if( dvd ) {
- if( dvd->dev ) DVDinput_close( dvd->dev );
+ if( dvd->dev ) dvdinput_close( dvd->dev );
if( dvd->path_root ) free( dvd->path_root );
+ if( dvd->udfcache ) FreeUDFCache( dvd->udfcache );
free( dvd );
}
}
@@ -494,7 +556,7 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
/* Get the full path of the file. */
if( !findDVDFile( dvd, filename, full_path ) ) return 0;
- dev = DVDinput_open( full_path );
+ dev = dvdinput_open( full_path );
if( !dev ) return 0;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
@@ -558,7 +620,7 @@ static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu )
dvd->css_state = 2;
}
/*
- if( DVDinput_title( dvd_file->dvd->dev, (int)start ) < 0 ) {
+ if( dvdinput_title( dvd_file->dvd->dev, (int)start ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n",
filename );
}
@@ -598,7 +660,7 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu )
return 0;
}
- dev = DVDinput_open( full_path );
+ dev = dvdinput_open( full_path );
if( dev == NULL ) {
free( dvd_file );
return 0;
@@ -611,7 +673,7 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu )
}
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_devs[ 0 ] = dev;
- DVDinput_title( dvd_file->title_devs[0], 0);
+ dvdinput_title( dvd_file->title_devs[0], 0);
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
} else {
@@ -628,8 +690,8 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu )
}
dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
- dvd_file->title_devs[ i ] = DVDinput_open( full_path );
- DVDinput_title( dvd_file->title_devs[ i ], 0);
+ dvd_file->title_devs[ i ] = dvdinput_open( full_path );
+ dvdinput_title( dvd_file->title_devs[ i ], 0 );
dvd_file->filesize += dvd_file->title_sizes[ i ];
}
if( !dvd_file->title_devs[ 0 ] ) {
@@ -702,7 +764,7 @@ void DVDCloseFile( dvd_file_t *dvd_file )
} else {
for( i = 0; i < 9; ++i ) {
if( dvd_file->title_devs[ i ] ) {
- DVDinput_close( dvd_file->title_devs[i] );
+ dvdinput_close( dvd_file->title_devs[i] );
}
}
}
@@ -713,7 +775,7 @@ void DVDCloseFile( dvd_file_t *dvd_file )
}
/* Internal, but used from dvd_udf.c */
-int DVDReadBlocksUDFRaw( dvd_reader_t *device, uint32_t lb_number,
+int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, unsigned char *data,
int encrypted )
{
@@ -724,13 +786,13 @@ int DVDReadBlocksUDFRaw( dvd_reader_t *device, uint32_t lb_number,
return 0;
}
- ret = DVDinput_seek( device->dev, (int) lb_number );
+ ret = dvdinput_seek( device->dev, (int) lb_number );
if( ret != (int) lb_number ) {
fprintf( stderr, "libdvdread: Can't seek to block %u\n", lb_number );
return 0;
}
- return DVDinput_read( device->dev, (char *) data,
+ return dvdinput_read( device->dev, (char *) data,
(int) block_count, encrypted );
}
@@ -744,8 +806,8 @@ static int DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
size_t block_count, unsigned char *data,
int encrypted )
{
- return DVDReadBlocksUDFRaw( dvd_file->dvd, dvd_file->lb_start + offset,
- block_count, data, encrypted );
+ return UDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset,
+ block_count, data, encrypted );
}
/* This is using possibly several inputs and starting from an offset of '0'.
@@ -768,13 +830,13 @@ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset,
if( offset < dvd_file->title_sizes[ i ] ) {
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
- off = DVDinput_seek( dvd_file->title_devs[ i ], (int)offset );
+ off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset );
if( off < 0 || off != (int)offset ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return off < 0 ? off : 0;
}
- ret = DVDinput_read( dvd_file->title_devs[ i ], data,
+ ret = dvdinput_read( dvd_file->title_devs[ i ], data,
(int)block_count, encrypted );
break;
} else {
@@ -783,13 +845,13 @@ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset,
* (This is only true if you try and read >1GB at a time) */
/* Read part 1 */
- off = DVDinput_seek( dvd_file->title_devs[ i ], (int)offset );
+ off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset );
if( off < 0 || off != (int)offset ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return off < 0 ? off : 0;
}
- ret = DVDinput_read( dvd_file->title_devs[ i ], data,
+ ret = dvdinput_read( dvd_file->title_devs[ i ], data,
(int)part1_size, encrypted );
if( ret < 0 ) return ret;
/* FIXME: This is wrong if i is the last file in the set.
@@ -799,13 +861,13 @@ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset,
if( !dvd_file->title_devs[ i + 1 ] ) return ret;
/* Read part 2 */
- off = DVDinput_seek( dvd_file->title_devs[ i + 1 ], 0 );
+ off = dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 );
if( off < 0 || off != 0 ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
0 );
return off < 0 ? off : 0;
}
- ret2 = DVDinput_read( dvd_file->title_devs[ i + 1 ],
+ ret2 = dvdinput_read( dvd_file->title_devs[ i + 1 ],
data + ( part1_size
* (int64_t)DVD_VIDEO_LB_LEN ),
(int)(block_count - part1_size),
@@ -835,10 +897,12 @@ ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
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 );
- } else {
- DVDinput_title( dvd_file->title_devs[ 0 ], (int)dvd_file->lb_start );
- }
+ dvdinput_title( dvd_file->dvd->dev, (int)dvd_file->lb_start );
+ }
+ /* Here each vobu has it's own dvdcss handle, so no need to update
+ else {
+ dvdinput_title( dvd_file->title_devs[ 0 ], (int)dvd_file->lb_start );
+ }*/
}
if( dvd_file->dvd->isImageFile ) {
@@ -883,7 +947,7 @@ ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
secbuf_base = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN + 2048 );
secbuf = (unsigned char *)(((int)secbuf_base & ~2047) + 2048);
- if( !secbuf ) {
+ if( !secbuf_base ) {
fprintf( stderr, "libdvdread: Can't allocate memory "
"for file read!\n" );
return 0;
@@ -917,3 +981,139 @@ ssize_t DVDFileSize( dvd_file_t *dvd_file )
return dvd_file->filesize;
}
+
+int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid )
+{
+ struct md5_ctx ctx;
+ int title;
+
+ /* Check arguments. */
+ if( dvd == NULL || discid == NULL )
+ return 0;
+
+ /* Go through the first 10 IFO:s, in order,
+ * and md5sum them, i.e VIDEO_TS.IFO and VTS_0?_0.IFO */
+ md5_init_ctx( &ctx );
+ for( title = 0; title < 10; title++ ) {
+ dvd_file_t *dvd_file = DVDOpenFile( dvd, title, DVD_READ_INFO_FILE );
+ if( dvd_file != NULL ) {
+ ssize_t bytes_read;
+ size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN;
+ char *buffer_base = malloc( file_size + 2048 );
+ char *buffer = (unsigned char *)(((int)buffer_base & ~2047) + 2048);
+
+ if( buffer_base == NULL ) {
+ fprintf( stderr, "libdvdread: DVDDiscId, failed to "
+ "allocate memory for file read!\n" );
+ return -1;
+ }
+ bytes_read = DVDReadBytes( dvd_file, buffer, file_size );
+ if( bytes_read != file_size ) {
+ fprintf( stderr, "libdvdread: DVDDiscId read returned %d bytes"
+ ", wanted %d\n", bytes_read, file_size );
+ DVDCloseFile( dvd_file );
+ free( buffer_base );
+ return -1;
+ }
+
+ md5_process_bytes( buffer, file_size, &ctx );
+
+ DVDCloseFile( dvd_file );
+ free( buffer_base );
+ }
+ }
+ md5_finish_ctx( &ctx, discid );
+
+ return 0;
+}
+
+
+int DVDISOVolumeInfo( dvd_reader_t *dvd,
+ char *volid, unsigned int volid_size,
+ unsigned char *volsetid, unsigned int volsetid_size )
+{
+ unsigned char *buffer, *buffer_base;
+ int ret;
+
+ /* Check arguments. */
+ if( dvd == NULL )
+ return 0;
+
+ if( dvd->dev == NULL ) {
+ /* No block access, so no ISO... */
+ return -1;
+ }
+
+ buffer_base = malloc( DVD_VIDEO_LB_LEN + 2048 );
+ buffer = (unsigned char *)(((int)buffer_base & ~2047) + 2048);
+
+ if( buffer_base == NULL ) {
+ fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
+ "allocate memory for file read!\n" );
+ return -1;
+ }
+
+ ret = UDFReadBlocksRaw( dvd, 16, 1, buffer, 0 );
+ if( ret != 1 ) {
+ fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
+ "read ISO9660 Primary Volume Descriptor!\n" );
+ free( buffer_base );
+ return -1;
+ }
+
+ if( (volid != NULL) && (volid_size > 0) ) {
+ unsigned int n;
+ for(n = 0; n < 32; n++) {
+ if(buffer[40+n] == 0x20) {
+ break;
+ }
+ }
+
+ if(volid_size > n+1) {
+ volid_size = n+1;
+ }
+
+ memcpy(volid, &buffer[40], volid_size-1);
+ volid[volid_size-1] = '\0';
+ }
+
+ if( (volsetid != NULL) && (volsetid_size > 0) ) {
+ if(volsetid_size > 128) {
+ volsetid_size = 128;
+ }
+ memcpy(volsetid, &buffer[190], volsetid_size);
+ }
+ free( buffer_base );
+ return 0;
+}
+
+
+int DVDUDFVolumeInfo( dvd_reader_t *dvd,
+ char *volid, unsigned int volid_size,
+ unsigned char *volsetid, unsigned int volsetid_size )
+{
+ int ret;
+ /* Check arguments. */
+ if( dvd == NULL )
+ return -1;
+
+ if( dvd->dev == NULL ) {
+ /* No block access, so no UDF VolumeSet Identifier */
+ return -1;
+ }
+
+ if( (volid != NULL) && (volid_size > 0) ) {
+ ret = UDFGetVolumeIdentifier(dvd, volid, volid_size);
+ if(!ret) {
+ return -1;
+ }
+ }
+ if( (volsetid != NULL) && (volsetid_size > 0) ) {
+ ret = UDFGetVolumeSetIdentifier(dvd, volsetid, volsetid_size);
+ if(!ret) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/input/libdvdread/dvd_reader.h b/src/input/libdvdread/dvd_reader.h
index 631475976..cc4ba5489 100644
--- a/src/input/libdvdread/dvd_reader.h
+++ b/src/input/libdvdread/dvd_reader.h
@@ -3,7 +3,8 @@
/*
* Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>,
- * Håkan Hjort <d95hjort@dtek.chalmers.se>
+ * Håkan Hjort <d95hjort@dtek.chalmers.se>,
+ * Björn Englund <d4bjorn@dtek.chalmers.se>
*
* 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
@@ -30,6 +31,11 @@
*/
/**
+ * The current version.
+ */
+#define DVDREAD_VERSION 904
+
+/**
* The length of one Logical Block of a DVD.
*/
#define DVD_VIDEO_LB_LEN 2048
@@ -179,6 +185,80 @@ ssize_t DVDReadBytes( dvd_file_t *, void *, size_t );
*/
ssize_t DVDFileSize( dvd_file_t * );
+/**
+ * Get a unique 128 bit disc ID.
+ * This is the MD5 sum of VIDEO_TS.IFO and the VTS_0?_0.IFO files
+ * in title order (those that exist).
+ * If you need a 'text' representation of the id, print it as a
+ * hexadecimal number, using lowercase letters, discid[0] first.
+ * I.e. the same format as the command-line 'md5sum' program uses.
+ *
+ * @param dvd A read handle to get the disc ID from
+ * @param discid The buffer to put the disc ID into. The buffer must
+ * have room for 128 bits (16 chars).
+ * @return 0 on success, -1 on error.
+ */
+int DVDDiscID( dvd_reader_t *, unsigned char * );
+
+/**
+ * Get the UDF VolumeIdentifier and VolumeSetIdentifier
+ * from the PrimaryVolumeDescriptor.
+ *
+ * @param dvd A read handle to get the disc ID from
+ * @param volid The buffer to put the VolumeIdentifier into.
+ * The VolumeIdentifier is latin-1 encoded (8bit unicode)
+ * null terminated and max 32 bytes (including '\0')
+ * @param volid_size No more than volid_size bytes will be copied to volid.
+ * If the VolumeIdentifier is truncated because of this
+ * it will still be null terminated.
+ * @param volsetid The buffer to put the VolumeSetIdentifier into.
+ * The VolumeIdentifier is 128 bytes as
+ * stored in the UDF PrimaryVolumeDescriptor.
+ * Note that this is not a null terminated string.
+ * @param volsetid_size At most volsetid_size bytes will be copied to volsetid.
+ * @return 0 on success, -1 on error.
+ */
+int DVDUDFVolumeInfo( dvd_reader_t *, char *, unsigned int,
+ unsigned char *, unsigned int );
+
+/**
+ * Get the ISO9660 VolumeIdentifier and VolumeSetIdentifier
+ *
+ * * Only use this function as fallback if DVDUDFVolumeInfo returns 0 *
+ * * this will happen on a disc mastered only with a iso9660 filesystem *
+ * * All video DVD discs have UDF filesystem *
+ *
+ * @param dvd A read handle to get the disc ID from
+ * @param volid The buffer to put the VolumeIdentifier into.
+ * The VolumeIdentifier is coded with '0-9','A-Z','_'
+ * null terminated and max 33 bytes (including '\0')
+ * @param volid_size No more than volid_size bytes will be copied to volid.
+ * If the VolumeIdentifier is truncated because of this
+ * it will still be null terminated.
+ * @param volsetid The buffer to put the VolumeSetIdentifier into.
+ * The VolumeIdentifier is 128 bytes as
+ * stored in the ISO9660 PrimaryVolumeDescriptor.
+ * Note that this is not a null terminated string.
+ * @param volsetid_size At most volsetid_size bytes will be copied to volsetid.
+ * @return 0 on success, -1 on error.
+ */
+int DVDISOVolumeInfo( dvd_reader_t *, char *, unsigned int,
+ unsigned char *, unsigned int );
+
+/**
+ * Sets the level of caching that is done when reading from a device
+ *
+ * @param dvd A read handle to get the disc ID from
+ * @param level The level of caching wanted.
+ * -1 - returns the current setting.
+ * 0 - UDF Cache turned off.
+ * 1 - (default level) Pointers to IFO files and some data from
+ * PrimaryVolumeDescriptor are cached.
+ *
+ * @return The level of caching.
+ */
+int DVDUDFCacheLevel( dvd_reader_t *, int );
+
#ifdef __cplusplus
};
#endif
diff --git a/src/input/libdvdread/dvd_udf.c b/src/input/libdvdread/dvd_udf.c
index eb5e159f8..7183f280e 100644
--- a/src/input/libdvdread/dvd_udf.c
+++ b/src/input/libdvdread/dvd_udf.c
@@ -4,6 +4,7 @@
*
* Modifications by:
* Billy Biggs <vektor@dumbterm.net>.
+ * Björn Englund <d4bjorn@dtek.chalmers.se>.
*
* dvdudf: parse and read the UDF volume information of a DVD Video
* Copyright (C) 1999 Christian Wolff for convergence integrated media
@@ -27,10 +28,11 @@
* http://www.gnu.org/copyleft/gpl.html
*/
+#include "config.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -41,7 +43,7 @@
#include "dvd_udf.h"
/* Private but located in/shared with dvd_reader.c */
-extern int DVDReadBlocksUDFRaw( dvd_reader_t *device, uint32_t lb_number,
+extern int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, unsigned char *data,
int encrypted );
@@ -55,7 +57,7 @@ static int DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number,
while(count > 0) {
- ret = DVDReadBlocksUDFRaw(device, lb_number, count, data, encrypted);
+ ret = UDFReadBlocksRaw(device, lb_number, count, data, encrypted);
if(ret <= 0) {
/* One of the reads failed or nothing more to read, too bad.
@@ -93,6 +95,227 @@ struct AD {
uint16_t Partition;
};
+struct extent_ad {
+ uint32_t location;
+ uint32_t length;
+};
+
+struct avdp_t {
+ struct extent_ad mvds;
+ struct extent_ad rvds;
+};
+
+struct pvd_t {
+ uint8_t VolumeIdentifier[32];
+ uint8_t VolumeSetIdentifier[128];
+};
+
+struct lbudf {
+ uint32_t lb;
+ uint8_t *data;
+};
+
+struct icbmap {
+ uint32_t lbn;
+ struct AD file;
+ uint8_t filetype;
+};
+
+struct udf_cache {
+ int avdp_valid;
+ struct avdp_t avdp;
+ int pvd_valid;
+ struct pvd_t pvd;
+ int partition_valid;
+ struct Partition partition;
+ int rooticb_valid;
+ struct AD rooticb;
+ int lb_num;
+ struct lbudf *lbs;
+ int map_num;
+ struct icbmap *maps;
+};
+
+typedef enum {
+ PartitionCache, RootICBCache, LBUDFCache, MapCache, AVDPCache, PVDCache
+} UDFCacheType;
+
+extern void *GetUDFCacheHandle(dvd_reader_t *device);
+extern void SetUDFCacheHandle(dvd_reader_t *device, void *cache);
+
+void FreeUDFCache(void *cache)
+{
+ struct udf_cache *c = (struct udf_cache *)cache;
+ if(c == NULL) {
+ return;
+ }
+ if(c->lbs) {
+ free(c->lbs);
+ }
+ if(c->maps) {
+ free(c->maps);
+ }
+ free(c);
+}
+
+
+static int GetUDFCache(dvd_reader_t *device, UDFCacheType type,
+ uint32_t nr, void *data)
+{
+ int n;
+ struct udf_cache *c;
+
+ if(DVDUDFCacheLevel(device, -1) <= 0) {
+ return 0;
+ }
+
+ c = (struct udf_cache *)GetUDFCacheHandle(device);
+
+ if(c == NULL) {
+ return 0;
+ }
+
+ switch(type) {
+ case AVDPCache:
+ if(c->avdp_valid) {
+ *(struct avdp_t *)data = c->avdp;
+ return 1;
+ }
+ break;
+ case PVDCache:
+ if(c->pvd_valid) {
+ *(struct pvd_t *)data = c->pvd;
+ return 1;
+ }
+ break;
+ case PartitionCache:
+ if(c->partition_valid) {
+ *(struct Partition *)data = c->partition;
+ return 1;
+ }
+ break;
+ case RootICBCache:
+ if(c->rooticb_valid) {
+ *(struct AD *)data = c->rooticb;
+ return 1;
+ }
+ break;
+ case LBUDFCache:
+ for(n = 0; n < c->lb_num; n++) {
+ if(c->lbs[n].lb == nr) {
+ *(uint8_t **)data = c->lbs[n].data;
+ return 1;
+ }
+ }
+ break;
+ case MapCache:
+ for(n = 0; n < c->map_num; n++) {
+ if(c->maps[n].lbn == nr) {
+ *(struct icbmap *)data = c->maps[n];
+ return 1;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int SetUDFCache(dvd_reader_t *device, UDFCacheType type,
+ uint32_t nr, void *data)
+{
+ int n;
+ struct udf_cache *c;
+
+ if(DVDUDFCacheLevel(device, -1) <= 0) {
+ return 0;
+ }
+
+ c = (struct udf_cache *)GetUDFCacheHandle(device);
+
+ if(c == NULL) {
+ c = calloc(1, sizeof(struct udf_cache));
+ /* fprintf(stderr, "calloc: %d\n", sizeof(struct udf_cache)); */
+ if(c == NULL) {
+ return 0;
+ }
+ SetUDFCacheHandle(device, c);
+ }
+
+
+ switch(type) {
+ case AVDPCache:
+ c->avdp = *(struct avdp_t *)data;
+ c->avdp_valid = 1;
+ break;
+ case PVDCache:
+ c->pvd = *(struct pvd_t *)data;
+ c->pvd_valid = 1;
+ break;
+ case PartitionCache:
+ c->partition = *(struct Partition *)data;
+ c->partition_valid = 1;
+ break;
+ case RootICBCache:
+ c->rooticb = *(struct AD *)data;
+ c->rooticb_valid = 1;
+ break;
+ case LBUDFCache:
+ for(n = 0; n < c->lb_num; n++) {
+ if(c->lbs[n].lb == nr) {
+ /* replace with new data */
+ c->lbs[n].data = *(uint8_t **)data;
+ c->lbs[n].lb = nr;
+ return 1;
+ }
+ }
+ c->lb_num++;
+ c->lbs = realloc(c->lbs, c->lb_num * sizeof(struct lbudf));
+ /*
+ fprintf(stderr, "realloc lb: %d * %d = %d\n",
+ c->lb_num, sizeof(struct lbudf),
+ c->lb_num * sizeof(struct lbudf));
+ */
+ if(c->lbs == NULL) {
+ c->lb_num = 0;
+ return 0;
+ }
+ c->lbs[n].data = *(uint8_t **)data;
+ c->lbs[n].lb = nr;
+ break;
+ case MapCache:
+ for(n = 0; n < c->map_num; n++) {
+ if(c->maps[n].lbn == nr) {
+ /* replace with new data */
+ c->maps[n] = *(struct icbmap *)data;
+ c->maps[n].lbn = nr;
+ return 1;
+ }
+ }
+ c->map_num++;
+ c->maps = realloc(c->maps, c->map_num * sizeof(struct icbmap));
+ /*
+ fprintf(stderr, "realloc maps: %d * %d = %d\n",
+ c->map_num, sizeof(struct icbmap),
+ c->map_num * sizeof(struct icbmap));
+ */
+ if(c->maps == NULL) {
+ c->map_num = 0;
+ return 0;
+ }
+ c->maps[n] = *(struct icbmap *)data;
+ c->maps[n].lbn = nr;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+
/* For direct data access, LSB first */
#define GETN1(p) ((uint8_t)data[p])
#define GETN2(p) ((uint16_t)data[p] | ((uint16_t)data[(p) + 1] << 8))
@@ -268,8 +491,16 @@ static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType,
uint8_t *LogBlock = (uint8_t *)(((int)LogBlock_base & ~2047) + 2048);
uint32_t lbnum;
uint16_t TagID;
+ struct icbmap tmpmap;
lbnum = partition->Start + ICB.Location;
+ tmpmap.lbn = lbnum;
+ if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) {
+ *FileType = tmpmap.filetype;
+ *File = tmpmap.file;
+ return 1;
+ }
+
do {
if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
TagID = 0;
@@ -279,6 +510,9 @@ static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType,
if( TagID == 261 ) {
UDFFileEntry( LogBlock, FileType, partition, File );
+ tmpmap.file = *File;
+ tmpmap.filetype = *FileType;
+ SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap);
return 1;
};
} while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 )
@@ -294,7 +528,8 @@ static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType,
* return 1 on success, 0 on error;
*/
static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
- struct Partition *partition, struct AD *FileICB )
+ struct Partition *partition, struct AD *FileICB,
+ int cache_file_info)
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
uint8_t directory_base[ 2 * DVD_VIDEO_LB_LEN + 2048];
@@ -303,9 +538,79 @@ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
uint16_t TagID;
uint8_t filechar;
unsigned int p;
+ uint8_t *cached_dir_base = NULL, *cached_dir;
+ uint32_t dir_lba;
+ struct AD tmpICB;
+ int found = 0;
+ int in_cache = 0;
/* Scan dir for ICB of file */
lbnum = partition->Start + Dir.Location;
+
+ if(DVDUDFCacheLevel(device, -1) > 0) {
+ /* caching */
+
+ if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) {
+ dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN;
+ if((cached_dir_base = malloc(dir_lba * DVD_VIDEO_LB_LEN + 2048)) == NULL) {
+ return 0;
+ }
+ cached_dir = (uint8_t *)(((int)cached_dir_base & ~2047) + 2048);
+ if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) {
+ free(cached_dir_base);
+ cached_dir = NULL;
+ }
+ /*
+ if(cached_dir) {
+ fprintf(stderr, "malloc dir: %d\n",
+ dir_lba * DVD_VIDEO_LB_LEN);
+ }
+ */
+ SetUDFCache(device, LBUDFCache, lbnum, &cached_dir);
+ } else {
+ in_cache = 1;
+ }
+
+ if(cached_dir == NULL) {
+ return 0;
+ }
+
+ p = 0;
+
+ while( p < Dir.Length ) {
+ UDFDescriptor( &cached_dir[ p ], &TagID );
+ if( TagID == 257 ) {
+ p += UDFFileIdentifier( &cached_dir[ p ], &filechar,
+ filename, &tmpICB );
+ if(cache_file_info && !in_cache) {
+ uint8_t tmpFiletype;
+ struct AD tmpFile;
+
+ if( !strcasecmp( FileName, filename ) ) {
+ *FileICB = tmpICB;
+ found = 1;
+
+ }
+ UDFMapICB(device, tmpICB, &tmpFiletype,
+ partition, &tmpFile);
+ } else {
+ if( !strcasecmp( FileName, filename ) ) {
+ *FileICB = tmpICB;
+ return 1;
+ }
+ }
+ } else {
+ if(cache_file_info && (!in_cache) && found) {
+ return 1;
+ }
+ return 0;
+ }
+ }
+ if(cache_file_info && (!in_cache) && found) {
+ return 1;
+ }
+ return 0;
+ }
if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
return 0;
@@ -336,6 +641,74 @@ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
return 0;
}
+
+static int UDFGetAVDP( dvd_reader_t *device,
+ struct avdp_t *avdp)
+{
+ uint8_t Anchor_base[ DVD_VIDEO_LB_LEN + 2048 ];
+ uint8_t *Anchor = (uint8_t *)(((int)Anchor_base & ~2047) + 2048);
+ uint32_t lbnum, MVDS_location, MVDS_length;
+ uint16_t TagID;
+ uint32_t lastsector;
+ int terminate;
+ struct avdp_t;
+
+ if(GetUDFCache(device, AVDPCache, 0, avdp)) {
+ return 1;
+ }
+
+ /* Find Anchor */
+ lastsector = 0;
+ lbnum = 256; /* Try #1, prime anchor */
+ terminate = 0;
+
+ for(;;) {
+ if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) {
+ UDFDescriptor( Anchor, &TagID );
+ } else {
+ TagID = 0;
+ }
+ if (TagID != 2) {
+ /* Not an anchor */
+ if( terminate ) return 0; /* Final try failed */
+
+ if( lastsector ) {
+
+ /* We already found the last sector. Try #3, alternative
+ * backup anchor. If that fails, don't try again.
+ */
+ lbnum = lastsector;
+ terminate = 1;
+ } else {
+ /* TODO: Find last sector of the disc (this is optional). */
+ if( lastsector ) {
+ /* Try #2, backup anchor */
+ lbnum = lastsector - 256;
+ } else {
+ /* Unable to find last sector */
+ return 0;
+ }
+ }
+ } else {
+ /* It's an anchor! We can leave */
+ break;
+ }
+ }
+ /* Main volume descriptor */
+ UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location );
+ avdp->mvds.location = MVDS_location;
+ avdp->mvds.length = MVDS_length;
+
+ /* Backup volume descriptor */
+ UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location );
+ avdp->rvds.location = MVDS_location;
+ avdp->rvds.length = MVDS_length;
+
+ SetUDFCache(device, AVDPCache, 0, avdp);
+
+ return 1;
+}
+
/**
* Looks for partition on the disc. Returns 1 if partition found, 0 on error.
* partnum: Number of the partition, starting at 0.
@@ -346,53 +719,20 @@ static int UDFFindPartition( dvd_reader_t *device, int partnum,
{
uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ];
uint8_t *LogBlock = (uint8_t *)(((int)LogBlock_base & ~2047) + 2048);
- uint8_t Anchor_base[ DVD_VIDEO_LB_LEN + 2048 ];
- uint8_t *Anchor = (uint8_t *)(((int)Anchor_base & ~2047) + 2048);
uint32_t lbnum, MVDS_location, MVDS_length;
uint16_t TagID;
- uint32_t lastsector;
- int i, terminate, volvalid;
-
- /* Find Anchor */
- lastsector = 0;
- lbnum = 256; /* Try #1, prime anchor */
- terminate = 0;
-
- for(;;) {
- if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) {
- UDFDescriptor( Anchor, &TagID );
- } else {
- TagID = 0;
- }
- if (TagID != 2) {
- /* Not an anchor */
- if( terminate ) return 0; /* Final try failed */
+ int i, volvalid;
+ struct avdp_t avdp;
- if( lastsector ) {
-
- /* We already found the last sector. Try #3, alternative
- * backup anchor. If that fails, don't try again.
- */
- lbnum = lastsector;
- terminate = 1;
- } else {
- /* TODO: Find last sector of the disc (this is optional). */
- if( lastsector ) {
- /* Try #2, backup anchor */
- lbnum = lastsector - 256;
- } else {
- /* Unable to find last sector */
- return 0;
- }
- }
- } else {
- /* It's an anchor! We can leave */
- break;
- }
+
+ if(!UDFGetAVDP(device, &avdp)) {
+ return 0;
}
+
/* Main volume descriptor */
- UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location );
-
+ MVDS_location = avdp.mvds.location;
+ MVDS_length = avdp.mvds.length;
+
part->valid = 0;
volvalid = 0;
part->VolumeDesc[ 0 ] = '\0';
@@ -427,8 +767,9 @@ static int UDFFindPartition( dvd_reader_t *device, int partnum,
&& ( ( !part->valid ) || ( !volvalid ) ) );
if( ( !part->valid) || ( !volvalid ) ) {
- /* Backup volume descriptor */
- UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location );
+ /* Backup volume descriptor */
+ MVDS_location = avdp.mvds.location;
+ MVDS_length = avdp.mvds.length;
}
} while( i-- && ( ( !part->valid ) || ( !volvalid ) ) );
@@ -448,17 +789,21 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
char tokenline[ MAX_UDF_FILE_NAME_LEN ];
char *token;
uint8_t filetype;
-
+
*filesize = 0;
tokenline[0] = '\0';
strcat( tokenline, filename );
- /* Find partition, 0 is the standard location for DVD Video.*/
- if( !UDFFindPartition( device, 0, &partition ) ) return 0;
-
- /* Find root dir ICB */
- lbnum = partition.Start;
- do {
+
+ if(!(GetUDFCache(device, PartitionCache, 0, &partition) &&
+ GetUDFCache(device, RootICBCache, 0, &RootICB))) {
+ /* Find partition, 0 is the standard location for DVD Video.*/
+ if( !UDFFindPartition( device, 0, &partition ) ) return 0;
+ SetUDFCache(device, PartitionCache, 0, &partition);
+
+ /* Find root dir ICB */
+ lbnum = partition.Start;
+ do {
if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
TagID = 0;
} else {
@@ -475,19 +820,34 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
/* Sanity checks. */
if( TagID != 256 ) return 0;
if( RootICB.Partition != 0 ) return 0;
-
+ SetUDFCache(device, RootICBCache, 0, &RootICB);
+ }
+
/* Find root dir */
if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) return 0;
if( filetype != 4 ) return 0; /* Root dir should be dir */
- /* Tokenize filepath */
- token = strtok(tokenline, "/");
- while( token != NULL ) {
- if( !UDFScanDir( device, File, token, &partition, &ICB ) ) return 0;
- if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) return 0;
+ {
+ int cache_file_info = 0;
+ /* Tokenize filepath */
+ token = strtok(tokenline, "/");
+
+ while( token != NULL ) {
+
+ if( !UDFScanDir( device, File, token, &partition, &ICB,
+ cache_file_info)) {
+ return 0;
+ }
+ if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) {
+ return 0;
+ }
+ if(!strcmp(token, "VIDEO_TS")) {
+ cache_file_info = 1;
+ }
token = strtok( NULL, "/" );
- }
-
+ }
+ }
+
/* Sanity check. */
if( File.Partition != 0 ) return 0;
@@ -498,3 +858,146 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
else
return partition.Start + File.Location;
}
+
+
+
+/**
+ * Gets a Descriptor .
+ * Returns 1 if descriptor found, 0 on error.
+ * id, tagid of descriptor
+ * bufsize, size of BlockBuf (must be >= DVD_VIDEO_LB_LEN).
+ */
+static int UDFGetDescriptor( dvd_reader_t *device, int id,
+ uint8_t *descriptor, int bufsize)
+{
+ uint32_t lbnum, MVDS_location, MVDS_length;
+ struct avdp_t avdp;
+ uint16_t TagID;
+ uint32_t lastsector;
+ int i, terminate;
+ int desc_found = 0;
+ /* Find Anchor */
+ lastsector = 0;
+ lbnum = 256; /* Try #1, prime anchor */
+ terminate = 0;
+ if(bufsize < DVD_VIDEO_LB_LEN) {
+ return 0;
+ }
+
+ if(!UDFGetAVDP(device, &avdp)) {
+ return 0;
+ }
+
+ /* Main volume descriptor */
+ MVDS_location = avdp.mvds.location;
+ MVDS_length = avdp.mvds.length;
+
+ i = 1;
+ do {
+ /* Find Descriptor */
+ lbnum = MVDS_location;
+ do {
+
+ if( DVDReadLBUDF( device, lbnum++, 1, descriptor, 0 ) <= 0 ) {
+ TagID = 0;
+ } else {
+ UDFDescriptor( descriptor, &TagID );
+ }
+
+ if( (TagID == id) && ( !desc_found ) ) {
+ /* Descriptor */
+ desc_found = 1;
+ }
+ } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 )
+ / DVD_VIDEO_LB_LEN ) && ( TagID != 8 )
+ && ( !desc_found) );
+
+ if( !desc_found ) {
+ /* Backup volume descriptor */
+ MVDS_location = avdp.rvds.location;
+ MVDS_length = avdp.rvds.length;
+ }
+ } while( i-- && ( !desc_found ) );
+
+ return desc_found;
+}
+
+
+static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd)
+{
+ uint8_t pvd_buf_base[DVD_VIDEO_LB_LEN + 2048];
+ uint8_t *pvd_buf = (uint8_t *)(((int)pvd_buf_base & ~2047) + 2048);
+
+ if(GetUDFCache(device, PVDCache, 0, pvd)) {
+ return 1;
+ }
+
+ if(!UDFGetDescriptor( device, 1, pvd_buf, sizeof(pvd_buf))) {
+ return 0;
+ }
+
+ memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32);
+ memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128);
+ SetUDFCache(device, PVDCache, 0, pvd);
+
+ return 1;
+}
+
+/**
+ * Gets the Volume Identifier string, in 8bit unicode (latin-1)
+ * volid, place to put the string
+ * volid_size, size of the buffer volid points to
+ * returns the size of buffer needed for all data
+ */
+int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid,
+ unsigned int volid_size)
+{
+ struct pvd_t pvd;
+ unsigned int volid_len;
+
+ /* get primary volume descriptor */
+ if(!UDFGetPVD(device, &pvd)) {
+ return 0;
+ }
+
+ volid_len = pvd.VolumeIdentifier[31];
+ if(volid_len > 31) {
+ /* this field is only 32 bytes something is wrong */
+ volid_len = 31;
+ }
+ if(volid_size > volid_len) {
+ volid_size = volid_len;
+ }
+ Unicodedecode(pvd.VolumeIdentifier, volid_size, volid);
+
+ return volid_len;
+}
+
+/**
+ * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded)
+ * WARNING This is not a null terminated string
+ * volsetid, place to put the data
+ * volsetid_size, size of the buffer volsetid points to
+ * the buffer should be >=128 bytes to store the whole volumesetidentifier
+ * returns the size of the available volsetid information (128)
+ * or 0 on error
+ */
+int UDFGetVolumeSetIdentifier(dvd_reader_t *device, uint8_t *volsetid,
+ unsigned int volsetid_size)
+{
+ struct pvd_t pvd;
+
+ /* get primary volume descriptor */
+ if(!UDFGetPVD(device, &pvd)) {
+ return 0;
+ }
+
+
+ if(volsetid_size > 128) {
+ volsetid_size = 128;
+ }
+
+ memcpy(volsetid, pvd.VolumeSetIdentifier, volsetid_size);
+
+ return 128;
+}
diff --git a/src/input/libdvdread/dvd_udf.h b/src/input/libdvdread/dvd_udf.h
index 960ccf405..b600983d9 100644
--- a/src/input/libdvdread/dvd_udf.h
+++ b/src/input/libdvdread/dvd_udf.h
@@ -7,7 +7,8 @@
*
* Modifications by:
* Billy Biggs <vektor@dumbterm.net>.
- *
+ * Björn Englund <d4bjorn@dtek.chalmers.se>.
+ *
* dvdudf: parse and read the UDF volume information of a DVD Video
* Copyright (C) 1999 Christian Wolff for convergence integrated media
* GmbH The author can be reached at scarabaeus@convergence.de, the
@@ -47,6 +48,11 @@ extern "C" {
*/
uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *size );
+void FreeUDFCache(void *cache);
+int UDFGetVolumeIdentifier(dvd_reader_t *device,
+ char *volid, unsigned int volid_size);
+int UDFGetVolumeSetIdentifier(dvd_reader_t *device,
+ uint8_t *volsetid, unsigned int volsetid_size);
#ifdef __cplusplus
};
#endif
diff --git a/src/input/libdvdread/dvdread_internal.h b/src/input/libdvdread/dvdread_internal.h
new file mode 100644
index 000000000..a7c802d98
--- /dev/null
+++ b/src/input/libdvdread/dvdread_internal.h
@@ -0,0 +1,12 @@
+#ifndef DVDREAD_INTERNAL_H
+#define DVDREAD_INTERNAL_H
+
+
+#define CHECK_VALUE(arg) \
+ if(!(arg)) { \
+ fprintf(stderr, "\n*** libdvdread: CHECK_VALUE failed in %s:%i ***" \
+ "\n*** for %s ***\n\n", \
+ __FILE__, __LINE__, # arg ); \
+ }
+
+#endif /* DVDREAD_INTERNAL_H */
diff --git a/src/input/libdvdread/ifo_print.c b/src/input/libdvdread/ifo_print.c
index 21f28aa2b..50aeacd17 100644
--- a/src/input/libdvdread/ifo_print.c
+++ b/src/input/libdvdread/ifo_print.c
@@ -1,6 +1,7 @@
/*
- * Copyright (C) 2000, 2001, 2002 Björn Englund <d4bjorn@dtek.chalmers.se>,
- * Håkan Hjort <d95hjort@dtek.chalmers.se>
+ * Copyright (C) 2000, 2001, 2002, 2003
+ * Björn Englund <d4bjorn@dtek.chalmers.se>,
+ * Håkan Hjort <d95hjort@dtek.chalmers.se>
*
* 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
@@ -17,26 +18,27 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "config.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <string.h>
#include <ctype.h>
-#include <assert.h>
-#include "config.h" /* Needed for WORDS_BIGENDIAN */
#include "ifo_types.h"
#include "ifo_read.h"
#include "ifo_print.h"
+#include "dvdread_internal.h"
/* Put this in some other file / package? It's used in nav_print too. */
-static void ifoPrint_time(int level, dvd_time_t *dtime) {
+static void ifoPrint_time(dvd_time_t *dtime) {
const char *rate;
- assert((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa);
- assert((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa);
- assert((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa);
- assert((dtime->frame_u&0xf) < 0xa);
+ CHECK_VALUE((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa);
+ CHECK_VALUE((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa);
+ CHECK_VALUE((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa);
+ CHECK_VALUE((dtime->frame_u&0xf) < 0xa);
printf("%02x:%02x:%02x.%02x",
dtime->hour,
@@ -75,7 +77,7 @@ static void ifoPrint_CMD(int row, vm_cmd_t *command) {
printf("\n");
}
-static void ifoPrint_video_attributes(int level, video_attr_t *attr) {
+static void ifoPrint_video_attributes(video_attr_t *attr) {
/* The following test is shorter but not correct ISO C,
memcmp(attr,my_friendly_zeros, sizeof(video_attr_t)) */
@@ -86,6 +88,7 @@ static void ifoPrint_video_attributes(int level, video_attr_t *attr) {
&& attr->unknown1 == 0
&& attr->line21_cc_1 == 0
&& attr->line21_cc_2 == 0
+ && attr->bit_rate == 0
&& attr->video_format == 0
&& attr->letterboxed == 0
&& attr->film_mode == 0) {
@@ -145,7 +148,7 @@ static void ifoPrint_video_attributes(int level, video_attr_t *attr) {
}
printf("U%x ", attr->unknown1);
- assert(!attr->unknown1);
+ CHECK_VALUE(!attr->unknown1);
if(attr->line21_cc_1 || attr->line21_cc_2) {
printf("NTSC CC ");
@@ -154,6 +157,17 @@ static void ifoPrint_video_attributes(int level, video_attr_t *attr) {
if(attr->line21_cc_2)
printf("2 ");
}
+
+ switch(attr->bit_rate) {
+ case 0:
+ printf("Variable Bit Rate ");
+ break;
+ case 1:
+ printf("Constant Bit Rate ");
+ break;
+ default:
+ printf("(please send a bug report)");
+ }
{
int height = 480;
@@ -188,7 +202,7 @@ static void ifoPrint_video_attributes(int level, video_attr_t *attr) {
}
}
-static void ifoPrint_audio_attributes(int level, audio_attr_t *attr) {
+static void ifoPrint_audio_attributes(audio_attr_t *attr) {
if(attr->audio_format == 0
&& attr->multichannel_extension == 0
@@ -197,8 +211,10 @@ static void ifoPrint_audio_attributes(int level, audio_attr_t *attr) {
&& attr->quantization == 0
&& attr->sample_frequency == 0
&& attr->channels == 0
+ && attr->lang_code == 0
&& attr->lang_extension == 0
- && attr->unknown1 == 0
+ && attr->code_extension == 0
+ && attr->unknown3 == 0
&& attr->unknown1 == 0) {
printf("-- Unspecified --");
return;
@@ -236,10 +252,11 @@ static void ifoPrint_audio_attributes(int level, audio_attr_t *attr) {
switch(attr->lang_type) {
case 0:
/* not specified */
- assert(attr->lang_code == 0 || attr->lang_code == 0xffff);
+ CHECK_VALUE(attr->lang_code == 0 || attr->lang_code == 0xffff);
break;
case 1:
- printf("%c%c ", attr->lang_code>>8, attr->lang_code & 0xff);
+ printf("%c%c (%c) ", attr->lang_code>>8, attr->lang_code & 0xff,
+ attr->lang_extension ? attr->lang_extension : ' ');
break;
default:
printf("(please send a bug report) ");
@@ -290,7 +307,7 @@ static void ifoPrint_audio_attributes(int level, audio_attr_t *attr) {
printf("%dCh ", attr->channels + 1);
- switch(attr->lang_extension) {
+ switch(attr->code_extension) {
case 0:
printf("Not specified ");
break;
@@ -311,34 +328,64 @@ static void ifoPrint_audio_attributes(int level, audio_attr_t *attr) {
printf("(please send a bug report) ");
}
- printf("%d ", attr->unknown1);
- printf("%d ", attr->unknown2);
+ printf("%d ", attr->unknown3);
+ if(attr->application_mode == 1) {
+ printf("ca=%d ", attr->app_info.karaoke.channel_assignment);
+ printf("%d ", attr->app_info.karaoke.version);
+ if(attr->app_info.karaoke.mc_intro)
+ printf("mc intro ");
+ printf("%s ", attr->app_info.karaoke.mode ? "duet" : "solo");
+ printf("%d ", attr->app_info.karaoke.unknown4);
+ }
+ if(attr->application_mode == 2) {
+ if(attr->app_info.surround.dolby_encoded) {
+ printf("dolby surround ");
+ }
+ printf("%d ", attr->app_info.surround.unknown5);
+ printf("%d ", attr->app_info.surround.unknown6);
+ }
}
-static void ifoPrint_subp_attributes(int level, subp_attr_t *attr) {
+static void ifoPrint_subp_attributes(subp_attr_t *attr) {
if(attr->type == 0
+ && attr->code_mode == 0
&& attr->lang_code == 0
+ && attr->lang_extension == 0
&& attr->zero1 == 0
&& attr->zero2 == 0
- && attr->lang_extension== 0) {
+ && attr->code_extension == 0) {
printf("-- Unspecified --");
return;
}
- printf("type %02x ", attr->type);
-
- if(isalpha((int)(attr->lang_code >> 8))
- && isalpha((int)(attr->lang_code & 0xff))) {
- printf("%c%c ", attr->lang_code >> 8, attr->lang_code & 0xff);
+ switch(attr->code_mode) {
+ case 0:
+ printf("Coding Mode RLE ");
+ break;
+ case 1:
+ printf("Coding Mode Extended ");
+ break;
+ default:
+ printf("(please send a bug report) ");
+ }
+
+ if(attr->type == 1) {
+ if(isalpha((int)(attr->lang_code >> 8))
+ && isalpha((int)(attr->lang_code & 0xff))) {
+ printf("%c%c ", attr->lang_code >> 8, attr->lang_code & 0xff);
+ } else {
+ printf("%02x%02x ", attr->lang_code >> 8, attr->lang_code & 0xff);
+ }
} else {
- printf("%02x%02x ", 0xff & (unsigned)(attr->lang_code >> 8),
- 0xff & (unsigned)(attr->lang_code & 0xff));
+ printf("lang not specified ");
}
printf("%d ", attr->zero1);
printf("%d ", attr->zero2);
-
+ printf("%d ", attr->code_extension);
+
+ /* Is this correct? should it not be subp_code_ext here instead? */
switch(attr->lang_extension) {
case 0:
printf("Not specified ");
@@ -494,20 +541,20 @@ void ifoPrint_VMGI_MAT(vmgi_mat_t *vmgi_mat) {
printf("Start sector of VMGM_VOBU_ADMAP: %08x\n",
vmgi_mat->vmgm_vobu_admap);
printf("Video attributes of VMGM_VOBS: ");
- ifoPrint_video_attributes(5, &vmgi_mat->vmgm_video_attr);
+ ifoPrint_video_attributes(&vmgi_mat->vmgm_video_attr);
printf("\n");
printf("VMGM Number of Audio attributes: %i\n",
vmgi_mat->nr_of_vmgm_audio_streams);
if(vmgi_mat->nr_of_vmgm_audio_streams > 0) {
printf("\tstream %i status: ", 1);
- ifoPrint_audio_attributes(5, &vmgi_mat->vmgm_audio_attr);
+ ifoPrint_audio_attributes(&vmgi_mat->vmgm_audio_attr);
printf("\n");
}
printf("VMGM Number of Sub-picture attributes: %i\n",
vmgi_mat->nr_of_vmgm_subp_streams);
if(vmgi_mat->nr_of_vmgm_subp_streams > 0) {
printf("\tstream %2i status: ", 1);
- ifoPrint_subp_attributes(5, &vmgi_mat->vmgm_subp_attr);
+ ifoPrint_subp_attributes(&vmgi_mat->vmgm_subp_attr);
printf("\n");
}
}
@@ -536,14 +583,14 @@ void ifoPrint_VTSI_MAT(vtsi_mat_t *vtsi_mat) {
printf("Start sector of VTS_VOBU_ADMAP: %08x\n", vtsi_mat->vts_vobu_admap);
printf("Video attributes of VTSM_VOBS: ");
- ifoPrint_video_attributes(5, &vtsi_mat->vtsm_video_attr);
+ ifoPrint_video_attributes(&vtsi_mat->vtsm_video_attr);
printf("\n");
printf("VTSM Number of Audio attributes: %i\n",
vtsi_mat->nr_of_vtsm_audio_streams);
if(vtsi_mat->nr_of_vtsm_audio_streams > 0) {
printf("\tstream %i status: ", 1);
- ifoPrint_audio_attributes(5, &vtsi_mat->vtsm_audio_attr);
+ ifoPrint_audio_attributes(&vtsi_mat->vtsm_audio_attr);
printf("\n");
}
@@ -551,19 +598,19 @@ void ifoPrint_VTSI_MAT(vtsi_mat_t *vtsi_mat) {
vtsi_mat->nr_of_vtsm_subp_streams);
if(vtsi_mat->nr_of_vtsm_subp_streams > 0) {
printf("\tstream %2i status: ", 1);
- ifoPrint_subp_attributes(5, &vtsi_mat->vtsm_subp_attr);
+ ifoPrint_subp_attributes(&vtsi_mat->vtsm_subp_attr);
printf("\n");
}
printf("Video attributes of VTS_VOBS: ");
- ifoPrint_video_attributes(5, &vtsi_mat->vts_video_attr);
+ ifoPrint_video_attributes(&vtsi_mat->vts_video_attr);
printf("\n");
printf("VTS Number of Audio attributes: %i\n",
vtsi_mat->nr_of_vts_audio_streams);
for(i = 0; i < vtsi_mat->nr_of_vts_audio_streams; i++) {
printf("\tstream %i status: ", i);
- ifoPrint_audio_attributes(5, &vtsi_mat->vts_audio_attr[i]);
+ ifoPrint_audio_attributes(&vtsi_mat->vts_audio_attr[i]);
printf("\n");
}
@@ -571,9 +618,11 @@ void ifoPrint_VTSI_MAT(vtsi_mat_t *vtsi_mat) {
vtsi_mat->nr_of_vts_subp_streams);
for(i = 0; i < vtsi_mat->nr_of_vts_subp_streams; i++) {
printf("\tstream %2i status: ", i);
- ifoPrint_subp_attributes(5, &vtsi_mat->vts_subp_attr[i]);
+ ifoPrint_subp_attributes(&vtsi_mat->vts_subp_attr[i]);
printf("\n");
}
+
+ /* FIXME: Add printing of MultiChannel Extension */
}
@@ -627,7 +676,7 @@ static void ifoPrint_CELL_PLAYBACK(cell_playback_t *cell_playback, int nr) {
for(i=0;i<nr;i++) {
printf("Cell: %3i ", i + 1);
- ifoPrint_time(5, &cell_playback[i].playback_time);
+ ifoPrint_time(&cell_playback[i].playback_time);
printf("\t");
if(cell_playback[i].block_mode || cell_playback[i].block_type) {
@@ -705,7 +754,7 @@ void ifoPrint_PGC(pgc_t *pgc) {
printf("Number of Cells: %i\n", pgc->nr_of_cells);
/* Check that time is 0:0:0:0 also if nr_of_programs==0 */
printf("Playback time: ");
- ifoPrint_time(5, &pgc->playback_time); printf("\n");
+ ifoPrint_time(&pgc->playback_time); printf("\n");
/* If no programs/no time then does this mean anything? */
printf("Prohibited user operations: ");
@@ -730,7 +779,12 @@ void ifoPrint_PGC(pgc_t *pgc) {
printf("GoUp PGC number: %i\n", pgc->goup_pgc_nr);
if(pgc->nr_of_programs != 0) {
printf("Still time: %i seconds (255=inf)\n", pgc->still_time);
- printf("PG Playback mode %02x\n", pgc->pg_playback_mode);
+ if(pgc->pg_playback_mode == 0)
+ printf("PG Playback mode: Sequential\n");
+ else if(!(pgc->pg_playback_mode & 0x80))
+ printf("PG Playback mode: Random %i\n", pgc->pg_playback_mode);
+ else
+ printf("PG Playback mode: Shuffle %i\n", pgc->pg_playback_mode & 0x7f );
}
if(pgc->nr_of_programs != 0) {
@@ -760,8 +814,23 @@ void ifoPrint_TT_SRPT(tt_srpt_t *tt_srpt) {
printf("\tNumber of PTTs: %i\n", tt_srpt->title[i].nr_of_ptts);
printf("\tNumber of angles: %i\n",
tt_srpt->title[i].nr_of_angles);
- printf("\tTitle playback type: %02x\n", /* XXX: TODO FIXME */
- *(uint8_t *)&(tt_srpt->title[i].pb_ty));
+ printf("\tTitle playback type: %s%s%s%s%s%s%s\n",
+ tt_srpt->title[i].pb_ty.multi_or_random_pgc_title ?
+ " One Random PGC Title or Multi PGC Title" :
+ " One Sequential PGC Title",
+ tt_srpt->title[i].pb_ty.jlc_exists_in_cell_cmd ?
+ "" : ", No Link/Jump/Call exists in Cell command",
+ tt_srpt->title[i].pb_ty.jlc_exists_in_prepost_cmd ?
+ "" : ", No Link/Jump/Call exists in Pre- and/or Post-command",
+ tt_srpt->title[i].pb_ty.jlc_exists_in_button_cmd ?
+ "" : ", No Link/Jump/Call exists in Button command",
+ tt_srpt->title[i].pb_ty.jlc_exists_in_tt_dom ?
+ "" : ", No Link/Jump/Call exists in TT_DOM",
+ tt_srpt->title[i].pb_ty.chapter_search_or_play ?
+ ", UOP1 (TT_Play and PTT_Search) prohibited" : "",
+ tt_srpt->title[i].pb_ty.title_or_time_play ?
+ ", UOP0 (Time_Play and Time_Search) prohibited" : ""
+ );
printf("\tParental ID field: %04x\n",
tt_srpt->title[i].parental_id);
printf("\tTitle set starting sector %08x\n",
@@ -776,6 +845,8 @@ void ifoPrint_VTS_PTT_SRPT(vts_ptt_srpt_t *vts_ptt_srpt) {
vts_ptt_srpt->nr_of_srpts,
vts_ptt_srpt->last_byte);
for(i=0;i<vts_ptt_srpt->nr_of_srpts;i++) {
+ printf("\nVTS_PTT number %d has a offset %d relative to VTS_PTT_SRPT\n",
+ i + 1, vts_ptt_srpt->ttu_offset[i]);
for(j=0;j<vts_ptt_srpt->title[i].nr_of_ptts;j++) {
printf("VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n",
i + 1, j + 1,
@@ -786,35 +857,30 @@ void ifoPrint_VTS_PTT_SRPT(vts_ptt_srpt_t *vts_ptt_srpt) {
}
-static void hexdump(uint8_t *ptr, int len) {
- while(len--)
- printf("%02x ", *ptr++);
-}
-
void ifoPrint_PTL_MAIT(ptl_mait_t *ptl_mait) {
- int i, j;
+ int i, level, vts;
printf("Number of Countries: %i\n", ptl_mait->nr_of_countries);
printf("Number of VTSs: %i\n", ptl_mait->nr_of_vtss);
- /* printf("Last byte: %i\n", ptl_mait->last_byte); */
+ printf("Last byte: %i\n", ptl_mait->last_byte);
for(i = 0; i < ptl_mait->nr_of_countries; i++) {
- printf("Country code: %c%c\n",
+
+ printf("Start byte: %i\n", ptl_mait->countries[i].pf_ptl_mai_start_byte);
+ printf("Parental Masks for country: %c%c\n",
ptl_mait->countries[i].country_code >> 8,
ptl_mait->countries[i].country_code & 0xff);
- /*
- printf("Start byte: %04x %i\n",
- ptl_mait->countries[i].pf_ptl_mai_start_byte,
- ptl_mait->countries[i].pf_ptl_mai_start_byte);
- */
- /* This seems to be pointing at a array with 8 2byte fields per VTS
- ? and one extra for the menu? always an odd number of VTSs on
- all the dics I tested so it might be padding to even also.
- If it is for the menu it probably the first entry. */
- for(j=0;j<8;j++) {
- hexdump( (uint8_t *)ptl_mait->countries - PTL_MAIT_COUNTRY_SIZE
- + ptl_mait->countries[i].pf_ptl_mai_start_byte
- + j*(ptl_mait->nr_of_vtss+1)*2, (ptl_mait->nr_of_vtss+1)*2);
+
+ for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) {
+ if( vts == 0 ) {
+ printf("VMG ");
+ } else {
+ printf("VTS %2d ", vts);
+ }
+ for(level = 0; level < 8; level++) {
+ printf("%d: %04x ", level,
+ ptl_mait->countries[i].pf_ptl_mai[vts][level] );
+ }
printf("\n");
}
}
@@ -825,10 +891,11 @@ void ifoPrint_VTS_TMAPT(vts_tmapt_t *vts_tmapt) {
int i, j;
printf("Number of VTS_TMAPS: %i\n", vts_tmapt->nr_of_tmaps);
- /*printf("Last byte: %i\n", vts_tmapt->last_byte);*/
-
+ printf("Last byte: %i\n", vts_tmapt->last_byte);
+
for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) {
- printf("TMAP %i\n", i);
+ printf("TMAP %i\n", i + 1);
+ printf(" offset %d relative to VTS_TMAPTI\n", vts_tmapt->tmap_offset[i]);
printf(" Time unit (seconds): %i\n", vts_tmapt->tmap[i].tmu);
printf(" Number of entries: %i\n", vts_tmapt->tmap[i].nr_of_entries);
timeunit = vts_tmapt->tmap[i].tmu;
@@ -887,9 +954,10 @@ void ifoPrint_PGCI_UT(pgci_ut_t *pgci_ut) {
printf("Number of Menu Language Units (PGCI_LU): %3i\n", pgci_ut->nr_of_lus);
for(i = 0; i < pgci_ut->nr_of_lus; i++) {
- printf("\nMenu Language Code: %c%c\n",
+ printf("\nMenu Language Code: %c%c (%c)\n",
pgci_ut->lu[i].lang_code >> 8,
- pgci_ut->lu[i].lang_code & 0xff);
+ pgci_ut->lu[i].lang_code & 0xff,
+ pgci_ut->lu[i].lang_extension ? pgci_ut->lu[i].lang_extension :' ');
printf("Menu Existence: %02x\n", pgci_ut->lu[i].exists);
ifoPrint_PGCIT(pgci_ut->lu[i].pgcit);
}
@@ -902,31 +970,31 @@ static void ifoPrint_VTS_ATTRIBUTES(vts_attributes_t *vts_attributes) {
printf("VTS_CAT Application type: %08x\n", vts_attributes->vts_cat);
printf("Video attributes of VTSM_VOBS: ");
- ifoPrint_video_attributes(5, &vts_attributes->vtsm_vobs_attr);
+ ifoPrint_video_attributes(&vts_attributes->vtsm_vobs_attr);
printf("\n");
printf("Number of Audio streams: %i\n",
vts_attributes->nr_of_vtsm_audio_streams);
if(vts_attributes->nr_of_vtsm_audio_streams > 0) {
printf("\tstream %i attributes: ", 1);
- ifoPrint_audio_attributes(5, &vts_attributes->vtsm_audio_attr);
+ ifoPrint_audio_attributes(&vts_attributes->vtsm_audio_attr);
printf("\n");
}
printf("Number of Subpicture streams: %i\n",
vts_attributes->nr_of_vtsm_subp_streams);
if(vts_attributes->nr_of_vtsm_subp_streams > 0) {
printf("\tstream %2i attributes: ", 1);
- ifoPrint_subp_attributes(5, &vts_attributes->vtsm_subp_attr);
+ ifoPrint_subp_attributes(&vts_attributes->vtsm_subp_attr);
printf("\n");
}
printf("Video attributes of VTSTT_VOBS: ");
- ifoPrint_video_attributes(5, &vts_attributes->vtstt_vobs_video_attr);
+ ifoPrint_video_attributes(&vts_attributes->vtstt_vobs_video_attr);
printf("\n");
printf("Number of Audio streams: %i\n",
vts_attributes->nr_of_vtstt_audio_streams);
for(i = 0; i < vts_attributes->nr_of_vtstt_audio_streams; i++) {
printf("\tstream %i attributes: ", i);
- ifoPrint_audio_attributes(5, &vts_attributes->vtstt_audio_attr[i]);
+ ifoPrint_audio_attributes(&vts_attributes->vtstt_audio_attr[i]);
printf("\n");
}
@@ -934,7 +1002,7 @@ static void ifoPrint_VTS_ATTRIBUTES(vts_attributes_t *vts_attributes) {
vts_attributes->nr_of_vtstt_subp_streams);
for(i = 0; i < vts_attributes->nr_of_vtstt_subp_streams; i++) {
printf("\tstream %2i attributes: ", i);
- ifoPrint_subp_attributes(5, &vts_attributes->vtstt_subp_attr[i]);
+ ifoPrint_subp_attributes(&vts_attributes->vtstt_subp_attr[i]);
printf("\n");
}
}
@@ -946,6 +1014,8 @@ void ifoPrint_VTS_ATRT(vts_atrt_t *vts_atrt) {
printf("Number of Video Title Sets: %3i\n", vts_atrt->nr_of_vtss);
for(i = 0; i < vts_atrt->nr_of_vtss; i++) {
printf("\nVideo Title Set %i\n", i + 1);
+ printf(" offset %d relative to VMG_VTS_ATRT\n",
+ vts_atrt->vts_atrt_offsets[i]);
ifoPrint_VTS_ATTRIBUTES(&vts_atrt->vts[i]);
}
}
diff --git a/src/input/libdvdread/ifo_read.c b/src/input/libdvdread/ifo_read.c
index 6dd5d3d5d..7bc9a2769 100644
--- a/src/input/libdvdread/ifo_read.c
+++ b/src/input/libdvdread/ifo_read.c
@@ -1,6 +1,7 @@
/*
- * Copyright (C) 2000, 2001, 2002 Björn Englund <d4bjorn@dtek.chalmers.se>,
- * Håkan Hjort <d95hjort@dtek.chalmers.se>
+ * Copyright (C) 2000, 2001, 2002, 2003
+ * Björn Englund <d4bjorn@dtek.chalmers.se>,
+ * Håkan Hjort <d95hjort@dtek.chalmers.se>
*
* 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
@@ -17,25 +18,29 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "config.h"
+
#include <stdio.h>
#include <stdlib.h>
-
#include <inttypes.h>
#include <string.h>
-#include <assert.h>
-
-#include "dvd_reader.h"
-#include "config.h" /* Needed for WORDS_BIGENDIAN */
#include "bswap.h"
#include "ifo_types.h"
#include "ifo_read.h"
+#include "dvd_reader.h"
+#include "dvdread_internal.h"
#ifndef DVD_BLOCK_LEN
#define DVD_BLOCK_LEN 2048
#endif
#ifndef NDEBUG
+#define CHECK_ZERO0(arg) \
+ if(arg != 0) { \
+ fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x%x\n", \
+ __FILE__, __LINE__, # arg, arg); \
+ }
#define CHECK_ZERO(arg) \
if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) { \
unsigned int i_CZ; \
@@ -47,6 +52,7 @@
}
static const uint8_t my_friendly_zeros[2048];
#else
+#define CHECK_ZERO0(arg) (void)(arg)
#define CHECK_ZERO(arg) (void)(arg)
#endif
@@ -323,33 +329,33 @@ static int ifoRead_VMG(ifo_handle_t *ifofile) {
CHECK_ZERO(vmgi_mat->zero_8);
CHECK_ZERO(vmgi_mat->zero_9);
CHECK_ZERO(vmgi_mat->zero_10);
- assert(vmgi_mat->vmg_last_sector != 0);
- assert(vmgi_mat->vmgi_last_sector != 0);
- assert(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector);
- assert(vmgi_mat->vmg_nr_of_volumes != 0);
- assert(vmgi_mat->vmg_this_volume_nr != 0);
- assert(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes);
- assert(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2);
- assert(vmgi_mat->vmg_nr_of_title_sets != 0);
- assert(vmgi_mat->vmgi_last_byte >= 341);
- assert(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <=
+ CHECK_VALUE(vmgi_mat->vmg_last_sector != 0);
+ CHECK_VALUE(vmgi_mat->vmgi_last_sector != 0);
+ CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector);
+ CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector);
+ CHECK_VALUE(vmgi_mat->vmg_nr_of_volumes != 0);
+ CHECK_VALUE(vmgi_mat->vmg_this_volume_nr != 0);
+ CHECK_VALUE(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes);
+ CHECK_VALUE(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2);
+ CHECK_VALUE(vmgi_mat->vmg_nr_of_title_sets != 0);
+ CHECK_VALUE(vmgi_mat->vmgi_last_byte >= 341);
+ CHECK_VALUE(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <=
vmgi_mat->vmgi_last_sector);
- /* It seems that first_play_pgc might be optional. */
- assert(vmgi_mat->first_play_pgc != 0 &&
- vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte);
- assert(vmgi_mat->vmgm_vobs == 0 ||
+ /* It seems that first_play_pgc is optional. */
+ CHECK_VALUE(vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte);
+ CHECK_VALUE(vmgi_mat->vmgm_vobs == 0 ||
(vmgi_mat->vmgm_vobs > vmgi_mat->vmgi_last_sector &&
vmgi_mat->vmgm_vobs < vmgi_mat->vmg_last_sector));
- assert(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector);
- assert(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector);
- assert(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector);
- assert(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector);
- assert(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector);
- assert(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector);
- assert(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector);
+ CHECK_VALUE(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector);
+ CHECK_VALUE(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector);
+ CHECK_VALUE(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector);
+ CHECK_VALUE(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector);
+ CHECK_VALUE(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector);
+ CHECK_VALUE(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector);
+ CHECK_VALUE(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector);
- assert(vmgi_mat->nr_of_vmgm_audio_streams <= 1);
- assert(vmgi_mat->nr_of_vmgm_subp_streams <= 1);
+ CHECK_VALUE(vmgi_mat->nr_of_vmgm_audio_streams <= 1);
+ CHECK_VALUE(vmgi_mat->nr_of_vmgm_subp_streams <= 1);
return 1;
}
@@ -425,34 +431,44 @@ static int ifoRead_VTS(ifo_handle_t *ifofile) {
CHECK_ZERO(vtsi_mat->zero_18);
CHECK_ZERO(vtsi_mat->zero_19);
CHECK_ZERO(vtsi_mat->zero_20);
- assert(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector);
- assert(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector);
- assert(vtsi_mat->vtsm_vobs == 0 ||
- (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector &&
+ CHECK_ZERO(vtsi_mat->zero_21);
+ CHECK_VALUE(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector);
+ CHECK_VALUE(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector);
+ CHECK_VALUE(vtsi_mat->vtsm_vobs == 0 ||
+ (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector &&
vtsi_mat->vtsm_vobs < vtsi_mat->vts_last_sector));
- assert(vtsi_mat->vtstt_vobs == 0 ||
+ CHECK_VALUE(vtsi_mat->vtstt_vobs == 0 ||
(vtsi_mat->vtstt_vobs > vtsi_mat->vtsi_last_sector &&
vtsi_mat->vtstt_vobs < vtsi_mat->vts_last_sector));
- assert(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector);
- assert(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector);
- assert(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector);
- assert(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector);
- assert(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector);
- assert(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector);
- assert(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector);
- assert(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector);
-
- assert(vtsi_mat->nr_of_vtsm_audio_streams <= 1);
- assert(vtsi_mat->nr_of_vtsm_subp_streams <= 1);
-
- assert(vtsi_mat->nr_of_vts_audio_streams <= 8);
+ CHECK_VALUE(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector);
+ CHECK_VALUE(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector);
+ CHECK_VALUE(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector);
+ CHECK_VALUE(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector);
+ CHECK_VALUE(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector);
+ CHECK_VALUE(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector);
+ CHECK_VALUE(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector);
+ CHECK_VALUE(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector);
+
+ CHECK_VALUE(vtsi_mat->nr_of_vtsm_audio_streams <= 1);
+ CHECK_VALUE(vtsi_mat->nr_of_vtsm_subp_streams <= 1);
+
+ CHECK_VALUE(vtsi_mat->nr_of_vts_audio_streams <= 8);
for(i = vtsi_mat->nr_of_vts_audio_streams; i < 8; i++)
CHECK_ZERO(vtsi_mat->vts_audio_attr[i]);
- assert(vtsi_mat->nr_of_vts_subp_streams <= 32);
+ CHECK_VALUE(vtsi_mat->nr_of_vts_subp_streams <= 32);
for(i = vtsi_mat->nr_of_vts_subp_streams; i < 32; i++)
CHECK_ZERO(vtsi_mat->vts_subp_attr[i]);
-
+
+ for(i = 0; i < 8; i++) {
+ CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero1);
+ CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero2);
+ CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero3);
+ CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero4);
+ CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero5);
+ CHECK_ZERO(vtsi_mat->vts_mu_audio_attr[i].zero6);
+ }
+
return 1;
}
@@ -473,7 +489,7 @@ static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,
B2N_16(cmd_tbl->nr_of_post);
B2N_16(cmd_tbl->nr_of_cell);
- assert(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255);
+ CHECK_VALUE(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255);
if(cmd_tbl->nr_of_pre != 0) {
unsigned int pre_cmds_size = cmd_tbl->nr_of_pre * COMMAND_DATA_SIZE;
@@ -575,9 +591,9 @@ static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile,
B2N_32(cell_playback[i].last_sector);
/* Changed < to <= because this was false in the movie 'Pi'. */
- assert(cell_playback[i].last_vobu_start_sector <=
+ CHECK_VALUE(cell_playback[i].last_vobu_start_sector <=
cell_playback[i].last_sector);
- assert(cell_playback[i].first_sector <=
+ CHECK_VALUE(cell_playback[i].first_sector <=
cell_playback[i].last_vobu_start_sector);
}
@@ -630,7 +646,7 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) {
B2N_32(pgc->palette[i]);
CHECK_ZERO(pgc->zero_1);
- assert(pgc->nr_of_programs <= pgc->nr_of_cells);
+ CHECK_VALUE(pgc->nr_of_programs <= pgc->nr_of_cells);
/* verify time (look at print_time) */
for(i = 0; i < 8; i++)
@@ -644,13 +660,13 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) {
if(pgc->nr_of_programs == 0) {
CHECK_ZERO(pgc->still_time);
CHECK_ZERO(pgc->pg_playback_mode); /* ?? */
- assert(pgc->program_map_offset == 0);
- assert(pgc->cell_playback_offset == 0);
- assert(pgc->cell_position_offset == 0);
+ CHECK_VALUE(pgc->program_map_offset == 0);
+ CHECK_VALUE(pgc->cell_playback_offset == 0);
+ CHECK_VALUE(pgc->cell_position_offset == 0);
} else {
- assert(pgc->program_map_offset != 0);
- assert(pgc->cell_playback_offset != 0);
- assert(pgc->cell_position_offset != 0);
+ CHECK_VALUE(pgc->program_map_offset != 0);
+ CHECK_VALUE(pgc->cell_playback_offset != 0);
+ CHECK_VALUE(pgc->cell_position_offset != 0);
}
if(pgc->command_tbl_offset != 0) {
@@ -731,11 +747,10 @@ int ifoRead_FP_PGC(ifo_handle_t *ifofile) {
if(!ifofile->vmgi_mat)
return 0;
- /* It seems that first_play_pgc might be optional after all. */
- if(ifofile->vmgi_mat->first_play_pgc == 0) { /* mandatory */
- ifofile->first_play_pgc = 0;
- return 0; /* change this to a 1 if it's optional. */
- }
+ /* It seems that first_play_pgc is optional after all. */
+ ifofile->first_play_pgc = 0;
+ if(ifofile->vmgi_mat->first_play_pgc == 0)
+ return 1;
ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t));
if(!ifofile->first_play_pgc)
@@ -828,22 +843,22 @@ int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
CHECK_ZERO(tt_srpt->zero_1);
- assert(tt_srpt->nr_of_srpts != 0);
- assert(tt_srpt->nr_of_srpts < 100); /* ?? */
- assert((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length);
+ CHECK_VALUE(tt_srpt->nr_of_srpts != 0);
+ CHECK_VALUE(tt_srpt->nr_of_srpts < 100); /* ?? */
+ CHECK_VALUE((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length);
for(i = 0; i < tt_srpt->nr_of_srpts; i++) {
- assert(tt_srpt->title[i].pb_ty.zero_1 == 0);
- assert(tt_srpt->title[i].nr_of_angles != 0);
- assert(tt_srpt->title[i].nr_of_angles < 10);
- /* assert(tt_srpt->title[i].nr_of_ptts != 0); */
+ CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0);
+ CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0);
+ CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10);
+ /* CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); */
/* XXX: this assertion breaks Ghostbusters: */
- assert(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */
- assert(tt_srpt->title[i].title_set_nr != 0);
- assert(tt_srpt->title[i].title_set_nr < 100); /* ?? */
- assert(tt_srpt->title[i].vts_ttn != 0);
- assert(tt_srpt->title[i].vts_ttn < 100); /* ?? */
- /* assert(tt_srpt->title[i].title_set_sector != 0); */
+ CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */
+ CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0);
+ CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); /* ?? */
+ CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0);
+ CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); /* ?? */
+ /* CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); */
}
/* Make this a function */
@@ -909,8 +924,8 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
B2N_32(vts_ptt_srpt->last_byte);
CHECK_ZERO(vts_ptt_srpt->zero_1);
- assert(vts_ptt_srpt->nr_of_srpts != 0);
- assert(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */
+ CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0);
+ CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */
info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE;
@@ -934,8 +949,10 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
Magic Knight Rayearth Daybreak is mastered very strange and has
Titles with 0 PTTs. They all have a data[i] offsets beyond the end of
of the vts_ptt_srpt structure. */
- assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4);
+ CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4);
}
+
+ vts_ptt_srpt->ttu_offset = data;
vts_ptt_srpt->title = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t));
if(!vts_ptt_srpt->title) {
@@ -954,7 +971,7 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
Magic Knight Rayearth Daybreak is mastered very strange and has
Titles with 0 PTTs. */
if(n < 0) n = 0;
- assert(n % 4 == 0);
+ CHECK_VALUE(n % 4 == 0);
vts_ptt_srpt->title[i].nr_of_ptts = n / 4;
vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t));
@@ -968,14 +985,13 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
}
for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
/* The assert placed here because of Magic Knight Rayearth Daybreak */
- assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1);
+ CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1);
vts_ptt_srpt->title[i].ptt[j].pgcn
= *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE);
vts_ptt_srpt->title[i].ptt[j].pgn
= *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE);
}
}
- free(data);
for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
@@ -985,12 +1001,12 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
}
for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
- assert(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */
+ CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */
for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
- assert(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 );
- assert(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */
- assert(vts_ptt_srpt->title[i].ptt[j].pgn != 0);
- assert(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */
+ CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 );
+ CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */
+ CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0);
+ CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */
}
}
@@ -1006,6 +1022,7 @@ void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
int i;
for(i = 0; i < ifofile->vts_ptt_srpt->nr_of_srpts; i++)
free(ifofile->vts_ptt_srpt->title[i].ptt);
+ free(ifofile->vts_ptt_srpt->ttu_offset);
free(ifofile->vts_ptt_srpt->title);
free(ifofile->vts_ptt_srpt);
ifofile->vts_ptt_srpt = 0;
@@ -1016,7 +1033,7 @@ void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
ptl_mait_t *ptl_mait;
int info_length;
- unsigned int i;
+ unsigned int i, j;
if(!ifofile)
return 0;
@@ -1046,26 +1063,29 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
B2N_16(ptl_mait->nr_of_vtss);
B2N_32(ptl_mait->last_byte);
- info_length = ptl_mait->last_byte + 1 - PTL_MAIT_SIZE;
+ CHECK_VALUE(ptl_mait->nr_of_countries != 0);
+ CHECK_VALUE(ptl_mait->nr_of_countries < 100); /* ?? */
+ CHECK_VALUE(ptl_mait->nr_of_vtss != 0);
+ CHECK_VALUE(ptl_mait->nr_of_vtss < 100); /* ?? */
+ CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE
+ <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE);
- assert(ptl_mait->nr_of_countries != 0);
- assert(ptl_mait->nr_of_countries < 100); /* ?? */
- assert(ptl_mait->nr_of_vtss != 0);
- assert(ptl_mait->nr_of_vtss < 100); /* ?? */
- assert(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE <= info_length);
-
- /* Change this to read and 'translate' the tables too.
- I.e don't read so much here */
+ info_length = ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t);
ptl_mait->countries = (ptl_mait_country_t *)malloc(info_length);
if(!ptl_mait->countries) {
free(ptl_mait);
ifofile->ptl_mait = 0;
return 0;
}
- if(!(DVDReadBytes(ifofile->file, ptl_mait->countries, info_length))) {
- fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n");
- ifoFree_PTL_MAIT(ifofile);
- return 0;
+
+ for(i = 0; i < ptl_mait->nr_of_countries; i++) {
+ if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) {
+ fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n");
+ free(ptl_mait->countries);
+ free(ptl_mait);
+ ifofile->ptl_mait = 0;
+ return 0;
+ }
}
for(i = 0; i < ptl_mait->nr_of_countries; i++) {
@@ -1076,18 +1096,78 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
for(i = 0; i < ptl_mait->nr_of_countries; i++) {
CHECK_ZERO(ptl_mait->countries[i].zero_1);
CHECK_ZERO(ptl_mait->countries[i].zero_2);
- assert(ptl_mait->countries[i].pf_ptl_mai_start_byte +
- 8 * (ptl_mait->nr_of_vtss + 1) * 2 <= ptl_mait->last_byte + 1);
+ CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte
+ + 8*2 * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1);
}
+ for(i = 0; i < ptl_mait->nr_of_countries; i++) {
+ uint16_t *pf_temp;
+
+ if(!DVDFileSeek_(ifofile->file,
+ ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN
+ + ptl_mait->countries[i].pf_ptl_mai_start_byte)) {
+ fprintf(stderr, "libdvdread: Unable to seak PTL_MAIT table.\n");
+ free(ptl_mait->countries);
+ free(ptl_mait);
+ return 0;
+ }
+ info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t);
+ pf_temp = (uint16_t *)malloc(info_length);
+ if(!pf_temp) {
+ for(j = 0; j < i ; j++) {
+ free(ptl_mait->countries[j].pf_ptl_mai);
+ }
+ free(ptl_mait->countries);
+ free(ptl_mait);
+ return 0;
+ }
+ if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) {
+ fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table.\n");
+ free(pf_temp);
+ for(j = 0; j < i ; j++) {
+ free(ptl_mait->countries[j].pf_ptl_mai);
+ }
+ free(ptl_mait->countries);
+ free(ptl_mait);
+ return 0;
+ }
+ for (j = 0; j < ((ptl_mait->nr_of_vtss + 1) * 8); j++) {
+ B2N_16(pf_temp[j]);
+ }
+ ptl_mait->countries[i].pf_ptl_mai = (pf_level_t *)malloc(info_length);
+ if(!ptl_mait->countries[i].pf_ptl_mai) {
+ free(pf_temp);
+ for(j = 0; j < i ; j++) {
+ free(ptl_mait->countries[j].pf_ptl_mai);
+ }
+ free(ptl_mait->countries);
+ free(ptl_mait);
+ return 0;
+ }
+ { /* Transpose the array so we can use C indexing. */
+ int level, vts;
+ for(level = 0; level < 8; level++) {
+ for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) {
+ ptl_mait->countries[i].pf_ptl_mai[vts][level] =
+ pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts];
+ }
+ }
+ free(pf_temp);
+ }
+ }
return 1;
}
void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) {
+ unsigned int i;
+
if(!ifofile)
return;
if(ifofile->ptl_mait) {
+ for(i = 0; i < ifofile->ptl_mait->nr_of_countries; i++) {
+ free(ifofile->ptl_mait->countries[i].pf_ptl_mai);
+ }
free(ifofile->ptl_mait->countries);
free(ifofile->ptl_mait);
ifofile->ptl_mait = 0;
@@ -1109,12 +1189,13 @@ 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");
return 1;
}
offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN;
- if(!DVDFileSeek_(ifofile->file, offset))
+ if(!DVDFileSeek_(ifofile->file, offset))
return 0;
vts_tmapt = (vts_tmapt_t *)malloc(sizeof(vts_tmapt_t));
@@ -1143,6 +1224,8 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
ifofile->vts_tmapt = NULL;
return 0;
}
+
+ vts_tmapt->tmap_offset = vts_tmap_srp;
if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) {
fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
@@ -1151,6 +1234,11 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
ifofile->vts_tmapt = NULL;
return 0;
}
+
+ for (i = 0; i < vts_tmapt->nr_of_tmaps; i++) {
+ B2N_32(vts_tmap_srp[i]);
+ }
+
info_length = vts_tmapt->nr_of_tmaps * sizeof(vts_tmap_t);
@@ -1161,17 +1249,17 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
ifofile->vts_tmapt = NULL;
return 0;
}
+
memset(vts_tmapt->tmap, 0, info_length); /* So ifoFree_VTS_TMAPT works. */
for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) {
if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) {
- free(vts_tmap_srp);
ifoFree_VTS_TMAPT(ifofile);
return 0;
}
+
if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) {
fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n");
- free(vts_tmap_srp);
ifoFree_VTS_TMAPT(ifofile);
return 0;
}
@@ -1188,14 +1276,12 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
vts_tmapt->tmap[i].map_ent = (map_ent_t *)malloc(info_length);
if(!vts_tmapt->tmap[i].map_ent) {
- free(vts_tmap_srp);
ifoFree_VTS_TMAPT(ifofile);
return 0;
}
if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) {
fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n");
- free(vts_tmap_srp);
ifoFree_VTS_TMAPT(ifofile);
return 0;
}
@@ -1203,7 +1289,6 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++)
B2N_32(vts_tmapt->tmap[i].map_ent[j]);
}
- free(vts_tmap_srp);
return 1;
}
@@ -1219,6 +1304,7 @@ void ifoFree_VTS_TMAPT(ifo_handle_t *ifofile) {
if(ifofile->vts_tmapt->tmap[i].map_ent)
free(ifofile->vts_tmapt->tmap[i].map_ent);
free(ifofile->vts_tmapt->tmap);
+ free(ifofile->vts_tmapt->tmap_offset);
free(ifofile->vts_tmapt);
ifofile->vts_tmapt = NULL;
}
@@ -1300,7 +1386,7 @@ static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile,
/* assert(c_adt->nr_of_vobs > 0);
Magic Knight Rayearth Daybreak is mastered very strange and has
Titles with a VOBS that has no cells. */
- assert(info_length % sizeof(cell_adr_t) == 0);
+ CHECK_VALUE(info_length % sizeof(cell_adr_t) == 0);
/* assert(info_length / sizeof(cell_adr_t) >= c_adt->nr_of_vobs);
Enemy of the State region 2 (de) has Titles where nr_of_vobs field
@@ -1326,10 +1412,10 @@ static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile,
B2N_32(c_adt->cell_adr_table[i].last_sector);
CHECK_ZERO(c_adt->cell_adr_table[i].zero_1);
- assert(c_adt->cell_adr_table[i].vob_id > 0);
- assert(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs);
- assert(c_adt->cell_adr_table[i].cell_id > 0);
- assert(c_adt->cell_adr_table[i].start_sector <
+ CHECK_VALUE(c_adt->cell_adr_table[i].vob_id > 0);
+ CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs);
+ CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0);
+ CHECK_VALUE(c_adt->cell_adr_table[i].start_sector <
c_adt->cell_adr_table[i].last_sector);
}
@@ -1433,7 +1519,7 @@ static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile,
/* assert(info_length > 0);
Magic Knight Rayearth Daybreak is mastered very strange and has
Titles with a VOBS that has no VOBUs. */
- assert(info_length % sizeof(uint32_t) == 0);
+ CHECK_VALUE(info_length % sizeof(uint32_t) == 0);
vobu_admap->vobu_start_sectors = (uint32_t *)malloc(info_length);
if(!vobu_admap->vobu_start_sectors) {
@@ -1519,7 +1605,7 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
/* assert(pgcit->nr_of_pgci_srp != 0);
Magic Knight Rayearth Daybreak is mastered very strange and has
Titles with 0 PTTs. */
- assert(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */
+ CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */
info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE;
data = malloc(info_length);
@@ -1542,12 +1628,12 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
ptr += PGCI_LU_SIZE;
B2N_16(pgcit->pgci_srp[i].ptl_id_mask);
B2N_32(pgcit->pgci_srp[i].pgc_start_byte);
- assert(pgcit->pgci_srp[i].unknown1 == 0);
+ CHECK_VALUE(pgcit->pgci_srp[i].unknown1 == 0);
}
free(data);
for(i = 0; i < pgcit->nr_of_pgci_srp; i++)
- assert(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1);
+ 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));
@@ -1639,9 +1725,9 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
B2N_32(pgci_ut->last_byte);
CHECK_ZERO(pgci_ut->zero_1);
- assert(pgci_ut->nr_of_lus != 0);
- assert(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */
- assert((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte);
+ CHECK_VALUE(pgci_ut->nr_of_lus != 0);
+ CHECK_VALUE(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */
+ CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte);
info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE;
data = malloc(info_length);
@@ -1674,10 +1760,8 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
free(data);
for(i = 0; i < pgci_ut->nr_of_lus; i++) {
- CHECK_ZERO(pgci_ut->lu[i].zero_1);
- /*
- Maybe this is only defined for v1.1 and later titles?
- If the bits in 'lu[i].exists' are enumerated abcd efgh then:
+ /* Maybe this is only defined for v1.1 and later titles? */
+ /* If the bits in 'lu[i].exists' are enumerated abcd efgh then:
VTS_x_yy.IFO VIDEO_TS.IFO
a == 0x83 "Root" 0x82 "Title"
b == 0x84 "Subpicture"
@@ -1685,7 +1769,7 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
d == 0x86 "Angle"
e == 0x87 "PTT"
*/
- assert((pgci_ut->lu[i].exists & 0x07) == 0);
+ CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0);
}
for(i = 0; i < pgci_ut->nr_of_lus; i++) {
@@ -1769,21 +1853,21 @@ static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile,
CHECK_ZERO(vts_attributes->zero_5);
CHECK_ZERO(vts_attributes->zero_6);
CHECK_ZERO(vts_attributes->zero_7);
- assert(vts_attributes->nr_of_vtsm_audio_streams <= 1);
- assert(vts_attributes->nr_of_vtsm_subp_streams <= 1);
- assert(vts_attributes->nr_of_vtstt_audio_streams <= 8);
+ CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1);
+ CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1);
+ CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8);
for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++)
CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]);
- assert(vts_attributes->nr_of_vtstt_subp_streams <= 32);
+ CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32);
{
unsigned int nr_coded;
- assert(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE);
+ CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE);
nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6;
/* This is often nr_coded = 70, how do you know how many there really are? */
if(nr_coded > 32) { /* We haven't read more from disk/file anyway */
nr_coded = 32;
}
- assert(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded);
+ CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded);
for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++)
CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]);
}
@@ -1827,9 +1911,9 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) {
B2N_32(vts_atrt->last_byte);
CHECK_ZERO(vts_atrt->zero_1);
- assert(vts_atrt->nr_of_vtss != 0);
- assert(vts_atrt->nr_of_vtss < 100); /* ?? */
- assert((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) +
+ CHECK_VALUE(vts_atrt->nr_of_vtss != 0);
+ CHECK_VALUE(vts_atrt->nr_of_vtss < 100); /* ?? */
+ CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) +
VTS_ATRT_SIZE < vts_atrt->last_byte + 1);
info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t);
@@ -1839,6 +1923,9 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) {
ifofile->vts_atrt = 0;
return 0;
}
+
+ vts_atrt->vts_atrt_offsets = data;
+
if(!(DVDReadBytes(ifofile->file, data, info_length))) {
free(data);
free(vts_atrt);
@@ -1848,7 +1935,7 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) {
for(i = 0; i < vts_atrt->nr_of_vtss; i++) {
B2N_32(data[i]);
- assert(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1);
+ CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1);
}
info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t);
@@ -1870,10 +1957,9 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) {
}
/* This assert cant be in ifoRead_VTS_ATTRIBUTES */
- assert(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1);
+ CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1);
/* Is this check correct? */
}
- free(data);
return 1;
}
@@ -1885,6 +1971,7 @@ void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) {
if(ifofile->vts_atrt) {
free(ifofile->vts_atrt->vts);
+ free(ifofile->vts_atrt->vts_atrt_offsets);
free(ifofile->vts_atrt);
ifofile->vts_atrt = 0;
}
diff --git a/src/input/libdvdread/ifo_read.h b/src/input/libdvdread/ifo_read.h
index 588d075b8..3b9b27f20 100644
--- a/src/input/libdvdread/ifo_read.h
+++ b/src/input/libdvdread/ifo_read.h
@@ -110,8 +110,7 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *);
*
* Reads in the first play program chain data, filling the
* ifofile->first_play_pgc structure. This data is only located in the video
- * manager information file. This structure is mandatory, and must be included
- * in the VMGI file. **Possibly this is only optional.**
+ * manager information file (VMGI). This structure is optional.
*/
int ifoRead_FP_PGC(ifo_handle_t *);
diff --git a/src/input/libdvdread/ifo_types.h b/src/input/libdvdread/ifo_types.h
index c0b6f57ea..f707d9d83 100644
--- a/src/input/libdvdread/ifo_types.h
+++ b/src/input/libdvdread/ifo_types.h
@@ -83,7 +83,8 @@ typedef struct {
unsigned int line21_cc_1 : 1;
unsigned int line21_cc_2 : 1;
- unsigned int unknown1 : 2;
+ unsigned int unknown1 : 1;
+ unsigned int bit_rate : 1;
unsigned int picture_size : 2;
unsigned int letterboxed : 1;
@@ -98,14 +99,15 @@ typedef struct {
unsigned int letterboxed : 1;
unsigned int picture_size : 2;
- unsigned int unknown1 : 2;
+ unsigned int bit_rate : 1;
+ unsigned int unknown1 : 1;
unsigned int line21_cc_2 : 1;
unsigned int line21_cc_1 : 1;
#endif
} ATTRIBUTE_PACKED video_attr_t;
/**
- * Audio Attributes. (Incomplete/Wrong?)
+ * Audio Attributes.
*/
typedef struct {
#ifdef WORDS_BIGENDIAN
@@ -130,13 +132,99 @@ typedef struct {
unsigned int quantization : 2;
#endif
uint16_t lang_code;
- uint8_t lang_code2; /* ?? */
uint8_t lang_extension;
- uint16_t unknown2;
+ uint8_t code_extension;
+ uint8_t unknown3;
+ union {
+ struct ATTRIBUTE_PACKED {
+#ifdef WORDS_BIGENDIAN
+ unsigned int unknown4 : 1;
+ unsigned int channel_assignment : 3;
+ unsigned int version : 2;
+ unsigned int mc_intro : 1; /* probably 0: true, 1:false */
+ unsigned int mode : 1; /* Karaoke mode 0: solo 1: duet */
+#else
+ unsigned int mode : 1;
+ unsigned int mc_intro : 1;
+ unsigned int version : 2;
+ unsigned int channel_assignment : 3;
+ unsigned int unknown4 : 1;
+#endif
+ } karaoke;
+ struct ATTRIBUTE_PACKED {
+#ifdef WORDS_BIGENDIAN
+ unsigned int unknown5 : 4;
+ unsigned int dolby_encoded : 1; /* suitable for surround decoding */
+ unsigned int unknown6 : 3;
+#else
+ unsigned int unknown6 : 3;
+ unsigned int dolby_encoded : 1;
+ unsigned int unknown5 : 4;
+#endif
+ } surround;
+ } app_info;
} ATTRIBUTE_PACKED audio_attr_t;
+
/**
- * Subpicture Attributes.(Incomplete/Wrong)
+ * MultiChannel Extension
+ */
+typedef struct {
+#ifdef WORDS_BIGENDIAN
+ unsigned int zero1 : 7;
+ unsigned int ach0_gme : 1;
+
+ unsigned int zero2 : 7;
+ unsigned int ach1_gme : 1;
+
+ unsigned int zero3 : 4;
+ unsigned int ach2_gv1e : 1;
+ unsigned int ach2_gv2e : 1;
+ unsigned int ach2_gm1e : 1;
+ unsigned int ach2_gm2e : 1;
+
+ unsigned int zero4 : 4;
+ unsigned int ach3_gv1e : 1;
+ unsigned int ach3_gv2e : 1;
+ unsigned int ach3_gmAe : 1;
+ unsigned int ach3_se2e : 1;
+
+ unsigned int zero5 : 4;
+ unsigned int ach4_gv1e : 1;
+ unsigned int ach4_gv2e : 1;
+ unsigned int ach4_gmBe : 1;
+ unsigned int ach4_seBe : 1;
+#else
+ unsigned int ach0_gme : 1;
+ unsigned int zero1 : 7;
+
+ unsigned int ach1_gme : 1;
+ unsigned int zero2 : 7;
+
+ unsigned int ach2_gm2e : 1;
+ unsigned int ach2_gm1e : 1;
+ unsigned int ach2_gv2e : 1;
+ unsigned int ach2_gv1e : 1;
+ unsigned int zero3 : 4;
+
+ unsigned int ach3_se2e : 1;
+ unsigned int ach3_gmAe : 1;
+ unsigned int ach3_gv2e : 1;
+ unsigned int ach3_gv1e : 1;
+ unsigned int zero4 : 4;
+
+ unsigned int ach4_seBe : 1;
+ unsigned int ach4_gmBe : 1;
+ unsigned int ach4_gv2e : 1;
+ unsigned int ach4_gv1e : 1;
+ unsigned int zero5 : 4;
+#endif
+ uint8_t zero6[19];
+} ATTRIBUTE_PACKED multichannel_ext_t;
+
+
+/**
+ * Subpicture Attributes.
*/
typedef struct {
/*
@@ -149,11 +237,19 @@ typedef struct {
* language: indicates language if type == 1
* lang extension: if type == 1 contains the lang extension
*/
- uint8_t type;
- uint8_t zero1;
+#ifdef WORDS_BIGENDIAN
+ unsigned int code_mode : 3;
+ unsigned int zero1 : 3;
+ unsigned int type : 2;
+#else
+ unsigned int type : 2;
+ unsigned int zero1 : 3;
+ unsigned int code_mode : 3;
+#endif
+ uint8_t zero2;
uint16_t lang_code;
- uint8_t lang_extension;
- uint8_t zero2;
+ uint8_t lang_extension;
+ uint8_t code_extension;
} ATTRIBUTE_PACKED subp_attr_t;
@@ -237,62 +333,62 @@ typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int zero : 7; /* 25-31 */
unsigned int video_pres_mode_change : 1; /* 24 */
-
+
unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */
- unsigned int angle_change : 1; /* 22 */
- unsigned int subpic_stream_change : 1; /* 21 */
- unsigned int audio_stream_change : 1; /* 20 */
- unsigned int pause_on : 1; /* 19 */
- unsigned int still_off : 1; /* 18 */
- unsigned int button_select_or_activate : 1; /* 17 */
+ unsigned int angle_change : 1;
+ unsigned int subpic_stream_change : 1;
+ unsigned int audio_stream_change : 1;
+ unsigned int pause_on : 1;
+ unsigned int still_off : 1;
+ unsigned int button_select_or_activate : 1;
unsigned int resume : 1; /* 16 */
-
+
unsigned int chapter_menu_call : 1; /* 15 */
- unsigned int angle_menu_call : 1; /* 14 */
- unsigned int audio_menu_call : 1; /* 13 */
- unsigned int subpic_menu_call : 1; /* 12 */
- unsigned int root_menu_call : 1; /* 11 */
- unsigned int title_menu_call : 1; /* 10 */
- unsigned int backward_scan : 1; /* 9 */
+ unsigned int angle_menu_call : 1;
+ unsigned int audio_menu_call : 1;
+ unsigned int subpic_menu_call : 1;
+ unsigned int root_menu_call : 1;
+ unsigned int title_menu_call : 1;
+ unsigned int backward_scan : 1;
unsigned int forward_scan : 1; /* 8 */
-
+
unsigned int next_pg_search : 1; /* 7 */
- unsigned int prev_or_top_pg_search : 1; /* 6 */
- unsigned int time_or_chapter_search : 1; /* 5 */
- unsigned int go_up : 1; /* 4 */
- unsigned int stop : 1; /* 3 */
- unsigned int title_play : 1; /* 2 */
- unsigned int chapter_search_or_play : 1; /* 1 */
+ unsigned int prev_or_top_pg_search : 1;
+ unsigned int time_or_chapter_search : 1;
+ unsigned int go_up : 1;
+ unsigned int stop : 1;
+ unsigned int title_play : 1;
+ unsigned int chapter_search_or_play : 1;
unsigned int title_or_time_play : 1; /* 0 */
#else
unsigned int video_pres_mode_change : 1; /* 24 */
unsigned int zero : 7; /* 25-31 */
-
+
unsigned int resume : 1; /* 16 */
- unsigned int button_select_or_activate : 1; /* 17 */
- unsigned int still_off : 1; /* 18 */
- unsigned int pause_on : 1; /* 19 */
- unsigned int audio_stream_change : 1; /* 20 */
- unsigned int subpic_stream_change : 1; /* 21 */
- unsigned int angle_change : 1; /* 22 */
+ unsigned int button_select_or_activate : 1;
+ unsigned int still_off : 1;
+ unsigned int pause_on : 1;
+ unsigned int audio_stream_change : 1;
+ unsigned int subpic_stream_change : 1;
+ unsigned int angle_change : 1;
unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */
-
+
unsigned int forward_scan : 1; /* 8 */
- unsigned int backward_scan : 1; /* 9 */
- unsigned int title_menu_call : 1; /* 10 */
- unsigned int root_menu_call : 1; /* 11 */
- unsigned int subpic_menu_call : 1; /* 12 */
- unsigned int audio_menu_call : 1; /* 13 */
- unsigned int angle_menu_call : 1; /* 14 */
+ unsigned int backward_scan : 1;
+ unsigned int title_menu_call : 1;
+ unsigned int root_menu_call : 1;
+ unsigned int subpic_menu_call : 1;
+ unsigned int audio_menu_call : 1;
+ unsigned int angle_menu_call : 1;
unsigned int chapter_menu_call : 1; /* 15 */
-
+
unsigned int title_or_time_play : 1; /* 0 */
- unsigned int chapter_search_or_play : 1; /* 1 */
- unsigned int title_play : 1; /* 2 */
- unsigned int stop : 1; /* 3 */
- unsigned int go_up : 1; /* 4 */
- unsigned int time_or_chapter_search : 1; /* 5 */
- unsigned int prev_or_top_pg_search : 1; /* 6 */
+ unsigned int chapter_search_or_play : 1;
+ unsigned int title_play : 1;
+ unsigned int stop : 1;
+ unsigned int go_up : 1;
+ unsigned int time_or_chapter_search : 1;
+ unsigned int prev_or_top_pg_search : 1;
unsigned int next_pg_search : 1; /* 7 */
#endif
} ATTRIBUTE_PACKED user_ops_t;
@@ -361,7 +457,7 @@ typedef struct {
*/
typedef struct {
uint16_t lang_code;
- uint8_t zero_1;
+ uint8_t lang_extension;
uint8_t exists;
uint32_t lang_start_byte;
pgcit_t *pgcit;
@@ -465,7 +561,7 @@ typedef struct {
typedef struct {
#ifdef WORDS_BIGENDIAN
unsigned int zero_1 : 1;
- unsigned int multi_or_random_pgc_title : 1; /* 0 == one sequential pgc title */
+ unsigned int multi_or_random_pgc_title : 1; /* 0: one sequential pgc title */
unsigned int jlc_exists_in_cell_cmd : 1;
unsigned int jlc_exists_in_prepost_cmd : 1;
unsigned int jlc_exists_in_button_cmd : 1;
@@ -473,13 +569,13 @@ typedef struct {
unsigned int chapter_search_or_play : 1; /* UOP 1 */
unsigned int title_or_time_play : 1; /* UOP 0 */
#else
- unsigned int title_or_time_play : 1; /* UOP 0 */
- unsigned int chapter_search_or_play : 1; /* UOP 1 */
+ unsigned int title_or_time_play : 1;
+ unsigned int chapter_search_or_play : 1;
unsigned int jlc_exists_in_tt_dom : 1;
unsigned int jlc_exists_in_button_cmd : 1;
unsigned int jlc_exists_in_prepost_cmd : 1;
unsigned int jlc_exists_in_cell_cmd : 1;
- unsigned int multi_or_random_pgc_title : 1; /* 0 == one sequential pgc title */
+ unsigned int multi_or_random_pgc_title : 1;
unsigned int zero_1 : 1;
#endif
} ATTRIBUTE_PACKED playback_type_t;
@@ -508,6 +604,13 @@ typedef struct {
} ATTRIBUTE_PACKED tt_srpt_t;
#define TT_SRPT_SIZE 8
+
+/**
+ * Parental Management Information Unit Table.
+ * Level 1 (US: G), ..., 7 (US: NC-17), 8
+ */
+typedef uint16_t pf_level_t[8];
+
/**
* Parental Management Information Unit Table.
*/
@@ -516,7 +619,7 @@ typedef struct {
uint16_t zero_1;
uint16_t pf_ptl_mai_start_byte;
uint16_t zero_2;
- /* uint16_t *pf_ptl_mai // table of nr_of_vtss+1 x 8 */
+ pf_level_t *pf_ptl_mai; /* table of (nr_of_vtss + 1), video_ts is first */
} ATTRIBUTE_PACKED ptl_mait_country_t;
#define PTL_MAIT_COUNTRY_SIZE 8
@@ -571,6 +674,7 @@ typedef struct {
uint16_t zero_1;
uint32_t last_byte;
vts_attributes_t *vts;
+ uint32_t *vts_atrt_offsets; /* offsets table for each vts_attributes */
} ATTRIBUTE_PACKED vts_atrt_t;
#define VTS_ATRT_SIZE 8
@@ -588,7 +692,7 @@ typedef struct {
uint8_t unknown1;
uint8_t unknown2;
uint8_t unknown3;
- uint8_t unknown4; /*?? allways 0x30 language?, text format? */
+ uint8_t unknown4; /* ?? allways 0x30 language?, text format? */
uint8_t unknown5;
uint16_t offset; /* from first */
@@ -652,7 +756,7 @@ typedef struct {
uint32_t vts_ptt_srpt; /* sector */
uint32_t vts_pgcit; /* sector */
uint32_t vtsm_pgci_ut; /* sector */
- uint32_t vts_tmapt; /* sector */ /* XXX: FIXME TODO Implement */
+ uint32_t vts_tmapt; /* sector */
uint32_t vtsm_c_adt; /* sector */
uint32_t vtsm_vobu_admap; /* sector */
uint32_t vts_c_adt; /* sector */
@@ -677,6 +781,8 @@ typedef struct {
uint8_t zero_20[17];
uint8_t nr_of_vts_subp_streams;
subp_attr_t vts_subp_attr[32];
+ uint16_t zero_21;
+ multichannel_ext_t vts_mu_audio_attr[8];
/* XXX: how much 'padding' here, if any? */
} ATTRIBUTE_PACKED vtsi_mat_t;
@@ -704,6 +810,7 @@ typedef struct {
uint16_t zero_1;
uint32_t last_byte;
ttu_t *title;
+ uint32_t *ttu_offset; /* offset table for each ttu */
} ATTRIBUTE_PACKED vts_ptt_srpt_t;
#define VTS_PTT_SRPT_SIZE 8
@@ -733,6 +840,7 @@ typedef struct {
uint16_t zero_1;
uint32_t last_byte;
vts_tmap_t *tmap;
+ uint32_t *tmap_offset; /* offset table for each tmap */
} ATTRIBUTE_PACKED vts_tmapt_t;
#define VTS_TMAPT_SIZE 8
diff --git a/src/input/libdvdread/md5.c b/src/input/libdvdread/md5.c
new file mode 100644
index 000000000..3ee9abae5
--- /dev/null
+++ b/src/input/libdvdread/md5.c
@@ -0,0 +1,417 @@
+/* md5.c - Functions to compute MD5 message digest of files or memory blocks
+ according to the definition of MD5 in RFC 1321 from April 1992.
+ Copyright (C) 1995, 1996, 2001 Free Software Foundation, Inc.
+ NOTE: The canonical source of this file is maintained with the GNU C
+ Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+# include <string.h>
+#else
+# ifndef HAVE_MEMCPY
+# define memcpy(d, s, n) bcopy ((s), (d), (n))
+# endif
+#endif
+
+#include "md5.h"
+/* #include "unlocked-io.h" */
+
+#ifdef _LIBC
+# include <endian.h>
+# if __BYTE_ORDER == __BIG_ENDIAN
+# define WORDS_BIGENDIAN 1
+# endif
+#endif
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n) \
+ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#else
+# define SWAP(n) (n)
+#endif
+
+
+/* This array contains the bytes used to pad the buffer to the next
+ 64-byte boundary. (RFC 1321, 3.1: Step 1) */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
+
+
+/* Initialize structure containing state of computation.
+ (RFC 1321, 3.3: Step 3) */
+void
+md5_init_ctx (ctx)
+ struct md5_ctx *ctx;
+{
+ ctx->A = 0x67452301;
+ ctx->B = 0xefcdab89;
+ ctx->C = 0x98badcfe;
+ ctx->D = 0x10325476;
+
+ ctx->total[0] = ctx->total[1] = 0;
+ ctx->buflen = 0;
+}
+
+/* Put result from CTX in first 16 bytes following RESBUF. The result
+ must be in little endian byte order.
+
+ IMPORTANT: On some systems it is required that RESBUF is correctly
+ aligned for a 32 bits value. */
+void *
+md5_read_ctx (ctx, resbuf)
+ const struct md5_ctx *ctx;
+ void *resbuf;
+{
+ ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
+ ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
+ ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
+ ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
+
+ return resbuf;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+ prolog according to the standard and write the result to RESBUF.
+
+ IMPORTANT: On some systems it is required that RESBUF is correctly
+ aligned for a 32 bits value. */
+void *
+md5_finish_ctx (ctx, resbuf)
+ struct md5_ctx *ctx;
+ void *resbuf;
+{
+ /* Take yet unprocessed bytes into account. */
+ md5_uint32 bytes = ctx->buflen;
+ size_t pad;
+
+ /* Now count remaining bytes. */
+ ctx->total[0] += bytes;
+ if (ctx->total[0] < bytes)
+ ++ctx->total[1];
+
+ pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+ memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+ /* Put the 64-bit file length in *bits* at the end of the buffer. */
+ *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
+ *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
+ (ctx->total[0] >> 29));
+
+ /* Process last bytes. */
+ md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+ return md5_read_ctx (ctx, resbuf);
+}
+
+/* Compute MD5 message digest for bytes read from STREAM. The
+ resulting message digest number will be written into the 16 bytes
+ beginning at RESBLOCK. */
+int
+md5_stream (stream, resblock)
+ FILE *stream;
+ void *resblock;
+{
+ /* Important: BLOCKSIZE must be a multiple of 64. */
+#define BLOCKSIZE 4096
+ struct md5_ctx ctx;
+ char buffer[BLOCKSIZE + 72];
+ size_t sum;
+
+ /* Initialize the computation context. */
+ md5_init_ctx (&ctx);
+
+ /* Iterate over full file contents. */
+ while (1)
+ {
+ /* We read the file in blocks of BLOCKSIZE bytes. One call of the
+ computation function processes the whole buffer so that with the
+ next round of the loop another block can be read. */
+ size_t n;
+ sum = 0;
+
+ /* Read block. Take care for partial reads. */
+ do
+ {
+ n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+ sum += n;
+ }
+ while (sum < BLOCKSIZE && n != 0);
+ if (n == 0 && ferror (stream))
+ return 1;
+
+ /* If end of file is reached, end the loop. */
+ if (n == 0)
+ break;
+
+ /* Process buffer with BLOCKSIZE bytes. Note that
+ BLOCKSIZE % 64 == 0
+ */
+ md5_process_block (buffer, BLOCKSIZE, &ctx);
+ }
+
+ /* Add the last bytes if necessary. */
+ if (sum > 0)
+ md5_process_bytes (buffer, sum, &ctx);
+
+ /* Construct result in desired memory. */
+ md5_finish_ctx (&ctx, resblock);
+ return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
+ result is always in little endian byte order, so that a byte-wise
+ output yields to the wanted ASCII representation of the message
+ digest. */
+void *
+md5_buffer (buffer, len, resblock)
+ const char *buffer;
+ size_t len;
+ void *resblock;
+{
+ struct md5_ctx ctx;
+
+ /* Initialize the computation context. */
+ md5_init_ctx (&ctx);
+
+ /* Process whole buffer but last len % 64 bytes. */
+ md5_process_bytes (buffer, len, &ctx);
+
+ /* Put result in desired memory area. */
+ return md5_finish_ctx (&ctx, resblock);
+}
+
+
+void
+md5_process_bytes (buffer, len, ctx)
+ const void *buffer;
+ size_t len;
+ struct md5_ctx *ctx;
+{
+ /* When we already have some bits in our internal buffer concatenate
+ both inputs first. */
+ if (ctx->buflen != 0)
+ {
+ size_t left_over = ctx->buflen;
+ size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+ memcpy (&ctx->buffer[left_over], buffer, add);
+ ctx->buflen += add;
+
+ if (left_over + add > 64)
+ {
+ md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx);
+ /* The regions in the following copy operation cannot overlap. */
+ memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+ (left_over + add) & 63);
+ ctx->buflen = (left_over + add) & 63;
+ }
+
+ buffer = (const char *) buffer + add;
+ len -= add;
+ }
+
+ /* Process available complete blocks. */
+ if (len > 64)
+ {
+ md5_process_block (buffer, len & ~63, ctx);
+ buffer = (const char *) buffer + (len & ~63);
+ len &= 63;
+ }
+
+ /* Move remaining bytes in internal buffer. */
+ if (len > 0)
+ {
+ memcpy (ctx->buffer, buffer, len);
+ ctx->buflen = len;
+ }
+}
+
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+ and defined in the RFC 1321. The first function is a little bit optimized
+ (as found in Colin Plumbs public domain implementation). */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+ It is assumed that LEN % 64 == 0. */
+
+void
+md5_process_block (buffer, len, ctx)
+ const void *buffer;
+ size_t len;
+ struct md5_ctx *ctx;
+{
+ md5_uint32 correct_words[16];
+ const md5_uint32 *words = buffer;
+ size_t nwords = len / sizeof (md5_uint32);
+ const md5_uint32 *endp = words + nwords;
+ md5_uint32 A = ctx->A;
+ md5_uint32 B = ctx->B;
+ md5_uint32 C = ctx->C;
+ md5_uint32 D = ctx->D;
+
+ /* First increment the byte count. RFC 1321 specifies the possible
+ length of the file up to 2^64 bits. Here we only compute the
+ number of bytes. Do a double word increment. */
+ ctx->total[0] += len;
+ if (ctx->total[0] < len)
+ ++ctx->total[1];
+
+ /* Process all bytes in the buffer with 64 bytes in each round of
+ the loop. */
+ while (words < endp)
+ {
+ md5_uint32 *cwp = correct_words;
+ md5_uint32 A_save = A;
+ md5_uint32 B_save = B;
+ md5_uint32 C_save = C;
+ md5_uint32 D_save = D;
+
+ /* First round: using the given function, the context and a constant
+ the next context is computed. Because the algorithms processing
+ unit is a 32-bit word and it is determined to work on words in
+ little endian byte order we perhaps have to change the byte order
+ before the computation. To reduce the work for the next steps
+ we store the swapped words in the array CORRECT_WORDS. */
+
+#define OP(a, b, c, d, s, T) \
+ do \
+ { \
+ a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
+ ++words; \
+ a = rol (a, s); \
+ a += b; \
+ } \
+ while (0)
+
+ /* Before we start, one word to the strange constants.
+ They are defined in RFC 1321 as
+
+ T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or
+ perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}'
+ */
+
+ /* Round 1. */
+ OP (A, B, C, D, 7, 0xd76aa478);
+ OP (D, A, B, C, 12, 0xe8c7b756);
+ OP (C, D, A, B, 17, 0x242070db);
+ OP (B, C, D, A, 22, 0xc1bdceee);
+ OP (A, B, C, D, 7, 0xf57c0faf);
+ OP (D, A, B, C, 12, 0x4787c62a);
+ OP (C, D, A, B, 17, 0xa8304613);
+ OP (B, C, D, A, 22, 0xfd469501);
+ OP (A, B, C, D, 7, 0x698098d8);
+ OP (D, A, B, C, 12, 0x8b44f7af);
+ OP (C, D, A, B, 17, 0xffff5bb1);
+ OP (B, C, D, A, 22, 0x895cd7be);
+ OP (A, B, C, D, 7, 0x6b901122);
+ OP (D, A, B, C, 12, 0xfd987193);
+ OP (C, D, A, B, 17, 0xa679438e);
+ OP (B, C, D, A, 22, 0x49b40821);
+
+ /* For the second to fourth round we have the possibly swapped words
+ in CORRECT_WORDS. Redefine the macro to take an additional first
+ argument specifying the function to use. */
+#undef OP
+#define OP(f, a, b, c, d, k, s, T) \
+ do \
+ { \
+ a += f (b, c, d) + correct_words[k] + T; \
+ a = rol (a, s); \
+ a += b; \
+ } \
+ while (0)
+
+ /* Round 2. */
+ OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
+ OP (FG, D, A, B, C, 6, 9, 0xc040b340);
+ OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+ OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
+ OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
+ OP (FG, D, A, B, C, 10, 9, 0x02441453);
+ OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+ OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
+ OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
+ OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
+ OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
+ OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
+ OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
+ OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
+ OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
+ OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+ /* Round 3. */
+ OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
+ OP (FH, D, A, B, C, 8, 11, 0x8771f681);
+ OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+ OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+ OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
+ OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
+ OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
+ OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+ OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
+ OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
+ OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
+ OP (FH, B, C, D, A, 6, 23, 0x04881d05);
+ OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
+ OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+ OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+ OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
+
+ /* Round 4. */
+ OP (FI, A, B, C, D, 0, 6, 0xf4292244);
+ OP (FI, D, A, B, C, 7, 10, 0x432aff97);
+ OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+ OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
+ OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
+ OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
+ OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+ OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
+ OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
+ OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+ OP (FI, C, D, A, B, 6, 15, 0xa3014314);
+ OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+ OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
+ OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+ OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
+ OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
+
+ /* Add the starting values of the context. */
+ A += A_save;
+ B += B_save;
+ C += C_save;
+ D += D_save;
+ }
+
+ /* Put checksum in context given as argument. */
+ ctx->A = A;
+ ctx->B = B;
+ ctx->C = C;
+ ctx->D = D;
+}
diff --git a/src/input/libdvdread/md5.h b/src/input/libdvdread/md5.h
new file mode 100644
index 000000000..3b7dea169
--- /dev/null
+++ b/src/input/libdvdread/md5.h
@@ -0,0 +1,161 @@
+/* md5.h - Declaration of functions and data types used for MD5 sum
+ computing library functions.
+ Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc.
+ NOTE: The canonical source of this file is maintained with the GNU C
+ Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _MD5_H
+#define _MD5_H 1
+
+#include <stdio.h>
+
+#if defined HAVE_LIMITS_H || _LIBC
+# include <limits.h>
+#endif
+
+/* The following contortions are an attempt to use the C preprocessor
+ to determine an unsigned integral type that is 32 bits wide. An
+ alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
+ doing that would require that the configure script compile and *run*
+ the resulting executable. Locally running cross-compiled executables
+ is usually not possible. */
+
+#ifdef _LIBC
+# include <sys/types.h>
+typedef u_int32_t md5_uint32;
+#else
+# if defined __STDC__ && __STDC__
+# define UINT_MAX_32_BITS 4294967295U
+# else
+# define UINT_MAX_32_BITS 0xFFFFFFFF
+# endif
+
+/* If UINT_MAX isn't defined, assume it's a 32-bit type.
+ This should be valid for all systems GNU cares about because
+ that doesn't include 16-bit systems, and only modern systems
+ (that certainly have <limits.h>) have 64+-bit integral types. */
+
+# ifndef UINT_MAX
+# define UINT_MAX UINT_MAX_32_BITS
+# endif
+
+# if UINT_MAX == UINT_MAX_32_BITS
+ typedef unsigned int md5_uint32;
+# else
+# if USHRT_MAX == UINT_MAX_32_BITS
+ typedef unsigned short md5_uint32;
+# else
+# if ULONG_MAX == UINT_MAX_32_BITS
+ typedef unsigned long md5_uint32;
+# else
+ /* The following line is intended to evoke an error.
+ Using #error is not portable enough. */
+ "Cannot determine unsigned 32-bit data type."
+# endif
+# endif
+# endif
+#endif
+
+#undef __P
+#if defined (__STDC__) && __STDC__
+#define __P(x) x
+#else
+#define __P(x) ()
+#endif
+
+/* Structure to save state of computation between the single steps. */
+struct md5_ctx
+{
+ md5_uint32 A;
+ md5_uint32 B;
+ md5_uint32 C;
+ md5_uint32 D;
+
+ md5_uint32 total[2];
+ md5_uint32 buflen;
+ char buffer[128];
+};
+
+/*
+ * The following three functions are build up the low level used in
+ * the functions `md5_stream' and `md5_buffer'.
+ */
+
+/* Initialize structure containing state of computation.
+ (RFC 1321, 3.3: Step 3) */
+extern void md5_init_ctx __P ((struct md5_ctx *ctx));
+
+/* Starting with the result of former calls of this function (or the
+ initialization function update the context for the next LEN bytes
+ starting at BUFFER.
+ It is necessary that LEN is a multiple of 64!!! */
+extern void md5_process_block __P ((const void *buffer, size_t len,
+ struct md5_ctx *ctx));
+
+/* Starting with the result of former calls of this function (or the
+ initialization function update the context for the next LEN bytes
+ starting at BUFFER.
+ It is NOT required that LEN is a multiple of 64. */
+extern void md5_process_bytes __P ((const void *buffer, size_t len,
+ struct md5_ctx *ctx));
+
+/* Process the remaining bytes in the buffer and put result from CTX
+ in first 16 bytes following RESBUF. The result is always in little
+ endian byte order, so that a byte-wise output yields to the wanted
+ ASCII representation of the message digest.
+
+ IMPORTANT: On some systems it is required that RESBUF be correctly
+ aligned for a 32 bits value. */
+extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf));
+
+
+/* Put result from CTX in first 16 bytes following RESBUF. The result is
+ always in little endian byte order, so that a byte-wise output yields
+ to the wanted ASCII representation of the message digest.
+
+ IMPORTANT: On some systems it is required that RESBUF is correctly
+ aligned for a 32 bits value. */
+extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf));
+
+
+/* Compute MD5 message digest for bytes read from STREAM. The
+ resulting message digest number will be written into the 16 bytes
+ beginning at RESBLOCK. */
+extern int md5_stream __P ((FILE *stream, void *resblock));
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
+ result is always in little endian byte order, so that a byte-wise
+ output yields to the wanted ASCII representation of the message
+ digest. */
+extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock));
+
+/* The following is from gnupg-1.0.2's cipher/bithelp.h. */
+/* Rotate a 32 bit integer by n bytes */
+#if defined __GNUC__ && defined __i386__
+static inline md5_uint32
+rol(md5_uint32 x, int n)
+{
+ __asm__("roll %%cl,%0"
+ :"=r" (x)
+ :"0" (x),"c" (n));
+ return x;
+}
+#else
+# define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
+#endif
+
+#endif
diff --git a/src/input/libdvdread/nav_print.c b/src/input/libdvdread/nav_print.c
index 210829a4c..842ebe44f 100644
--- a/src/input/libdvdread/nav_print.c
+++ b/src/input/libdvdread/nav_print.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Håkan Hjort <d95hjort@dtek.chalmers.se>
+ * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort <d95hjort@dtek.chalmers.se>
*
* Much of the contents in this file is based on VOBDUMP.
*
@@ -23,21 +23,21 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "config.h"
+
#include <stdio.h>
#include <inttypes.h>
-#include <assert.h>
-#include "config.h" /* Needed for WORDS_BIGENDIAN */
#include "nav_types.h"
#include "nav_print.h"
-
+#include "dvdread_internal.h"
static void print_time(dvd_time_t *dtime) {
const char *rate;
- assert((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa);
- assert((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa);
- assert((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa);
- assert((dtime->frame_u&0xf) < 0xa);
+ CHECK_VALUE((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa);
+ CHECK_VALUE((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa);
+ CHECK_VALUE((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa);
+ CHECK_VALUE((dtime->frame_u&0xf) < 0xa);
printf("%02x:%02x:%02x.%02x",
dtime->hour,
diff --git a/src/input/libdvdread/nav_read.c b/src/input/libdvdread/nav_read.c
index abaf94b13..67135173a 100644
--- a/src/input/libdvdread/nav_read.c
+++ b/src/input/libdvdread/nav_read.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Håkan Hjort <d95hjort@dtek.chalmers.se>
+ * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort <d95hjort@dtek.chalmers.se>
*
* 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
@@ -16,24 +16,21 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "config.h"
+
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
-#include <assert.h>
-#include "config.h" /* Needed for WORDS_BIGENDIAN */
#include "bswap.h"
#include "nav_types.h"
#include "nav_read.h"
-
-/*
-#define STRICT
-*/
+#include "dvdread_internal.h"
void navRead_PCI(pci_t *pci, unsigned char *buffer) {
int i, j;
- assert(sizeof(pci_t) == PCI_BYTES - 1); /* -1 for substream id */
+ CHECK_VALUE(sizeof(pci_t) == PCI_BYTES - 1); /* -1 for substream id */
memcpy(pci, buffer, sizeof(pci_t));
@@ -61,85 +58,99 @@ void navRead_PCI(pci_t *pci, unsigned char *buffer) {
for(j = 0; j < 2; j++)
B2N_32(pci->hli.btn_colit.btn_coli[i][j]);
-#if !defined(WORDS_BIGENDIAN)
+ /* NOTE: I've had to change the structure from the disk layout to get
+ * the packing to work with Sun's Forte C compiler. */
+
/* pci hli btni */
for(i = 0; i < 36; i++) {
- char tmp[6], swap;
- memcpy(tmp, &(pci->hli.btnit[i]), 6);
- /* This is a B2N_24() */
- swap = tmp[0]; tmp[0] = tmp[2]; tmp[2] = swap;
- /* This is a B2N_24() */
- swap = tmp[3]; tmp[3] = tmp[5]; tmp[5] = swap;
- memcpy(&(pci->hli.btnit[i]), tmp, 6);
- }
+ char tmp[sizeof(pci->hli.btnit[i])], swap;
+ memcpy(tmp, &(pci->hli.btnit[i]), sizeof(pci->hli.btnit[i]));
+ /* Byte 4 to 7 are 'rotated' was: ABCD EFGH IJ is: ABCG DEFH IJ */
+ swap = tmp[6];
+ tmp[6] = tmp[5];
+ tmp[5] = tmp[4];
+ tmp[4] = tmp[3];
+ tmp[3] = swap;
+
+ /* Then there are the two B2N_24(..) calls */
+#ifndef WORDS_BIGENDIAN
+ swap = tmp[0];
+ tmp[0] = tmp[2];
+ tmp[2] = swap;
+
+ swap = tmp[4];
+ tmp[4] = tmp[6];
+ tmp[6] = swap;
#endif
+ memcpy(&(pci->hli.btnit[i]), tmp, sizeof(pci->hli.btnit[i]));
+ }
-#ifdef STRICT
+#ifndef NDEBUG
/* Asserts */
/* pci pci gi */
- assert(pci->pci_gi.zero1 == 0);
+ CHECK_VALUE(pci->pci_gi.zero1 == 0);
/* pci hli hli_gi */
- assert(pci->hli.hl_gi.zero1 == 0);
- assert(pci->hli.hl_gi.zero2 == 0);
- assert(pci->hli.hl_gi.zero3 == 0);
- assert(pci->hli.hl_gi.zero4 == 0);
- assert(pci->hli.hl_gi.zero5 == 0);
+ CHECK_VALUE(pci->hli.hl_gi.zero1 == 0);
+ CHECK_VALUE(pci->hli.hl_gi.zero2 == 0);
+ CHECK_VALUE(pci->hli.hl_gi.zero3 == 0);
+ CHECK_VALUE(pci->hli.hl_gi.zero4 == 0);
+ CHECK_VALUE(pci->hli.hl_gi.zero5 == 0);
/* Are there buttons defined here? */
if((pci->hli.hl_gi.hli_ss & 0x03) != 0) {
- assert(pci->hli.hl_gi.btn_ns != 0);
- assert(pci->hli.hl_gi.btngr_ns != 0);
+ CHECK_VALUE(pci->hli.hl_gi.btn_ns != 0);
+ CHECK_VALUE(pci->hli.hl_gi.btngr_ns != 0);
} else {
- assert((pci->hli.hl_gi.btn_ns != 0 && pci->hli.hl_gi.btngr_ns != 0)
+ CHECK_VALUE((pci->hli.hl_gi.btn_ns != 0 && pci->hli.hl_gi.btngr_ns != 0)
|| (pci->hli.hl_gi.btn_ns == 0 && pci->hli.hl_gi.btngr_ns == 0));
}
/* pci hli btnit */
for(i = 0; i < pci->hli.hl_gi.btngr_ns; i++) {
for(j = 0; j < (36 / pci->hli.hl_gi.btngr_ns); j++) {
- int k;
int n = (36 / pci->hli.hl_gi.btngr_ns) * i + j;
- assert(pci->hli.btnit[n].zero1 == 0);
- assert(pci->hli.btnit[n].zero2 == 0);
- assert(pci->hli.btnit[n].zero3 == 0);
- assert(pci->hli.btnit[n].zero4 == 0);
- assert(pci->hli.btnit[n].zero5 == 0);
- assert(pci->hli.btnit[n].zero6 == 0);
+ CHECK_VALUE(pci->hli.btnit[n].zero1 == 0);
+ CHECK_VALUE(pci->hli.btnit[n].zero2 == 0);
+ CHECK_VALUE(pci->hli.btnit[n].zero3 == 0);
+ CHECK_VALUE(pci->hli.btnit[n].zero4 == 0);
+ CHECK_VALUE(pci->hli.btnit[n].zero5 == 0);
+ CHECK_VALUE(pci->hli.btnit[n].zero6 == 0);
if (j < pci->hli.hl_gi.btn_ns) {
- assert(pci->hli.btnit[n].x_start <= pci->hli.btnit[n].x_end);
- assert(pci->hli.btnit[n].y_start <= pci->hli.btnit[n].y_end);
- assert(pci->hli.btnit[n].up <= pci->hli.hl_gi.btn_ns);
- assert(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns);
- assert(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns);
- assert(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns);
- /* vmcmd_verify(pci->hli.btnit[n].cmd); */
+ CHECK_VALUE(pci->hli.btnit[n].x_start <= pci->hli.btnit[n].x_end);
+ CHECK_VALUE(pci->hli.btnit[n].y_start <= pci->hli.btnit[n].y_end);
+ CHECK_VALUE(pci->hli.btnit[n].up <= pci->hli.hl_gi.btn_ns);
+ CHECK_VALUE(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns);
+ CHECK_VALUE(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns);
+ CHECK_VALUE(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns);
+ /*vmcmd_verify(pci->hli.btnit[n].cmd);*/
} else {
- assert(pci->hli.btnit[n].btn_coln == 0);
- assert(pci->hli.btnit[n].auto_action_mode == 0);
- assert(pci->hli.btnit[n].x_start == 0);
- assert(pci->hli.btnit[n].y_start == 0);
- assert(pci->hli.btnit[n].x_end == 0);
- assert(pci->hli.btnit[n].y_end == 0);
- assert(pci->hli.btnit[n].up == 0);
- assert(pci->hli.btnit[n].down == 0);
- assert(pci->hli.btnit[n].left == 0);
- assert(pci->hli.btnit[n].right == 0);
+ int k;
+ CHECK_VALUE(pci->hli.btnit[n].btn_coln == 0);
+ CHECK_VALUE(pci->hli.btnit[n].auto_action_mode == 0);
+ CHECK_VALUE(pci->hli.btnit[n].x_start == 0);
+ CHECK_VALUE(pci->hli.btnit[n].y_start == 0);
+ CHECK_VALUE(pci->hli.btnit[n].x_end == 0);
+ CHECK_VALUE(pci->hli.btnit[n].y_end == 0);
+ CHECK_VALUE(pci->hli.btnit[n].up == 0);
+ CHECK_VALUE(pci->hli.btnit[n].down == 0);
+ CHECK_VALUE(pci->hli.btnit[n].left == 0);
+ CHECK_VALUE(pci->hli.btnit[n].right == 0);
for (k = 0; k < 8; k++)
- assert(pci->hli.btnit[n].cmd.bytes[k] == 0); /* CHECK_ZERO? */
+ CHECK_VALUE(pci->hli.btnit[n].cmd.bytes[k] == 0); /* CHECK_ZERO? */
}
}
}
-#endif
+#endif /* !NDEBUG */
}
void navRead_DSI(dsi_t *dsi, unsigned char *buffer) {
int i;
- assert(sizeof(dsi_t) == DSI_BYTES - 1); /* -1 for substream id */
+ CHECK_VALUE(sizeof(dsi_t) == DSI_BYTES - 1); /* -1 for substream id */
memcpy(dsi, buffer, sizeof(dsi_t));
@@ -185,11 +196,9 @@ void navRead_DSI(dsi_t *dsi, unsigned char *buffer) {
B2N_32(dsi->synci.sp_synca[i]);
-#ifdef STRICT
/* Asserts */
/* dsi dsi gi */
- assert(dsi->dsi_gi.zero1 == 0);
-#endif
+ CHECK_VALUE(dsi->dsi_gi.zero1 == 0);
}
diff --git a/src/input/libdvdread/nav_types.h b/src/input/libdvdread/nav_types.h
index 33bb6d559..3ad98947d 100644
--- a/src/input/libdvdread/nav_types.h
+++ b/src/input/libdvdread/nav_types.h
@@ -90,15 +90,21 @@ typedef struct {
/**
* Highlight General Information
+ *
+ * For btngrX_dsp_ty the bits have the following meaning:
+ * 000b: normal 4/3 only buttons
+ * XX1b: wide (16/9) buttons
+ * X1Xb: letterbox buttons
+ * 1XXb: pan&scan buttons
*/
typedef struct {
- uint16_t hli_ss; /**< status, only low 2 bits 0: no, 1: different 2: equal 3: eual except for button cmds */
+ uint16_t hli_ss; /**< status, only low 2 bits 0: no buttons, 1: different 2: equal 3: eual except for button cmds */
uint32_t hli_s_ptm; /**< start ptm of hli */
uint32_t hli_e_ptm; /**< end ptm of hli */
uint32_t btn_se_e_ptm; /**< end ptm of button select */
#ifdef WORDS_BIGENDIAN
unsigned int zero1 : 2; /**< reserved */
- unsigned int btngr_ns : 2; /**< number of button groups */
+ unsigned int btngr_ns : 2; /**< number of button groups 1, 2 or 3 with 36/18/12 buttons */
unsigned int zero2 : 1; /**< reserved */
unsigned int btngr1_dsp_ty : 3; /**< display type of subpic stream for button group 1 */
unsigned int zero3 : 1; /**< reserved */
@@ -115,9 +121,9 @@ typedef struct {
unsigned int btngr2_dsp_ty : 3;
unsigned int zero3 : 1;
#endif
- uint8_t btn_ofn; /**< button offset number */
- uint8_t btn_ns; /**< number of valid buttons (low 6 bits) */
- uint8_t nsl_btn_ns; /**< number of buttons selectable by U_BTNNi (low 6 bits) nsl_btn_ns <= btn_ns */
+ uint8_t btn_ofn; /**< button offset number range 0-255 */
+ uint8_t btn_ns; /**< number of valid buttons <= 36/18/12 (low 6 bits) */
+ uint8_t nsl_btn_ns; /**< number of buttons selectable by U_BTNNi (low 6 bits) nsl_btn_ns <= btn_ns */
uint8_t zero5; /**< reserved */
uint8_t fosl_btnn; /**< forcedly selected button (low 6 bits) */
uint8_t foac_btnn; /**< forcedly activated button (low 6 bits) */
@@ -138,6 +144,10 @@ typedef struct {
/**
* Button Information
+ *
+ * NOTE: I've had to change the structure from the disk layout to get
+ * the packing to work with Sun's Forte C compiler.
+ * The 4 and 7 bytes are 'rotated' was: ABC DEF GHIJ is: ABCG DEFH IJ
*/
typedef struct {
#ifdef WORDS_BIGENDIAN
@@ -145,13 +155,15 @@ typedef struct {
unsigned int x_start : 10; /**< x start offset within the overlay */
unsigned int zero1 : 2; /**< reserved */
unsigned int x_end : 10; /**< x end offset within the overlay */
+
+ unsigned int zero3 : 2; /**< reserved */
+ unsigned int up : 6; /**< button index when pressing up */
+
unsigned int auto_action_mode : 2; /**< 0: no, 1: activated if selected */
unsigned int y_start : 10; /**< y start offset within the overlay */
unsigned int zero2 : 2; /**< reserved */
unsigned int y_end : 10; /**< y end offset within the overlay */
- unsigned int zero3 : 2; /**< reserved */
- unsigned int up : 6; /**< button index when pressing up */
unsigned int zero4 : 2; /**< reserved */
unsigned int down : 6; /**< button index when pressing down */
unsigned int zero5 : 2; /**< reserved */
@@ -163,13 +175,15 @@ typedef struct {
unsigned int zero1 : 2;
unsigned int x_start : 10;
unsigned int btn_coln : 2;
+
+ unsigned int up : 6;
+ unsigned int zero3 : 2;
+
unsigned int y_end : 10;
unsigned int zero2 : 2;
unsigned int y_start : 10;
unsigned int auto_action_mode : 2;
- unsigned int up : 6;
- unsigned int zero3 : 2;
unsigned int down : 6;
unsigned int zero4 : 2;
unsigned int left : 6;