Removed Cosmetics, changed indentation to be "tighter" but kept Free call.
--
Jorgen Lundman | <[email protected]>
Unix Administrator | +81 (0)3 -5456-2687 ext 1017 (work)
Shibuya-ku, Tokyo | +81 (0)90-5578-8500 (cell)
Japan | +81 (0)3 -3375-1767 (home)
Index: src/dvd_reader.c
===================================================================
--- src/dvd_reader.c (revision 1181)
+++ src/dvd_reader.c (working copy)
@@ -100,7 +100,7 @@
int css_title;
/* Information required for an image file. */
- uint32_t lb_start;
+ udf_file_t *udf_file;
uint32_t seek_pos;
/* Information required for a directory path drive. */
@@ -163,7 +163,8 @@
struct timeval all_s, all_e;
struct timeval t_s, t_e;
char filename[ MAX_UDF_FILE_NAME_LEN ];
- uint32_t start, len;
+ uint32_t len;
+ udf_file_t *udf_file;
int title;
char *nokeys_str = getenv("DVDREAD_NOKEYS");
@@ -183,31 +184,33 @@
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 );
}
- start = UDFFindFile( dvd, filename, &len );
- if( start != 0 && len != 0 ) {
+ udf_file = UDFFindFile( dvd, filename, &len );
+ if( udf_file != NULL && len != 0 ) {
/* 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 ) {
- fprintf( stderr, "libdvdread: Error cracking CSS key for %s
(0x%08x)\n", filename, start);
+ filename, UDFFileBlockPos(udf_file, 0) );
+ if( dvdinput_title( dvd->dev, (int)UDFFileBlockPos(udf_file, 0) ) < 0 ) {
+ fprintf( stderr, "libdvdread: Error cracking CSS key for %s
(0x%08x)\n", filename, UDFFileBlockPos(udf_file, 0));
}
gettimeofday( &t_e, NULL );
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
(long int) t_e.tv_sec - t_s.tv_sec );
}
+ UDFFreeFile(dvd, udf_file); udf_file = NULL;
+
if( title == 0 ) continue;
gettimeofday( &t_s, NULL );
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 );
- start = UDFFindFile( dvd, filename, &len );
- if( start == 0 || len == 0 ) break;
+ udf_file = UDFFindFile( dvd, filename, &len );
+ if( udf_file == NULL || len == 0 ) break;
/* 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 ) {
- fprintf( stderr, "libdvdread: Error cracking CSS key for %s
(0x%08x)!!\n", filename, start);
+ filename, UDFFileBlockPos(udf_file, 0) );
+ if( dvdinput_title( dvd->dev, (int)UDFFileBlockPos(udf_file, 0) ) < 0 ) {
+ fprintf( stderr, "libdvdread: Error cracking CSS key for %s
(0x%08x)!!\n", filename, UDFFileBlockPos(udf_file, 0));
}
gettimeofday( &t_e, NULL );
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
@@ -220,6 +223,8 @@
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
(long int) all_e.tv_sec - all_s.tv_sec );
+ UDFFreeFile(dvd, udf_file); udf_file = NULL;
+
return 0;
}
@@ -587,22 +592,24 @@
*/
static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename )
{
- uint32_t start, len;
+ uint32_t len;
+ udf_file_t *udf_file;
dvd_file_t *dvd_file;
- start = UDFFindFile( dvd, filename, &len );
- if( !start ) {
+ udf_file = UDFFindFile( dvd, filename, &len );
+ if( !udf_file ) {
fprintf( stderr, "libdvdnav:DVDOpenFileUDF:UDFFindFile %s failed\n",
filename );
return NULL;
}
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) {
+ UDFFreeFile(dvd, udf_file);
fprintf( stderr, "libdvdnav:DVDOpenFileUDF:malloc failed\n" );
return NULL;
}
dvd_file->dvd = dvd;
- dvd_file->lb_start = start;
+ dvd_file->udf_file = udf_file;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
@@ -698,7 +705,7 @@
return NULL;
}
dvd_file->dvd = dvd;
- dvd_file->lb_start = 0;
+ dvd_file->udf_file = NULL;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
@@ -719,7 +726,8 @@
static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
- uint32_t start, len;
+ uint32_t len;
+ udf_file_t *udf_file;
dvd_file_t *dvd_file;
if( title == 0 ) {
@@ -727,18 +735,22 @@
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
}
- start = UDFFindFile( dvd, filename, &len );
- if( start == 0 ) return NULL;
+ udf_file = UDFFindFile( dvd, filename, &len );
+ if( udf_file == NULL ) return NULL;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
- if( !dvd_file ) return NULL;
+ if( !dvd_file ) {
+ UDFFreeFile(dvd, udf_file);
+ return NULL;
+ }
dvd_file->dvd = dvd;
/*Hack*/ dvd_file->css_title = title << 1 | menu;
- dvd_file->lb_start = start;
+ dvd_file->udf_file = udf_file;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
+ udf_file = NULL;
/* Calculate the complete file size for every file in the VOBS */
if( !menu ) {
@@ -746,7 +758,8 @@
for( cur = 2; cur < 10; cur++ ) {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
- if( !UDFFindFile( dvd, filename, &len ) ) break;
+ if( !(udf_file = UDFFindFile( dvd, filename, &len )) ) break;
+ UDFFreeFile(dvd, udf_file);
dvd_file->filesize += len / DVD_VIDEO_LB_LEN;
}
}
@@ -777,7 +790,7 @@
if( !dvd_file ) return NULL;
dvd_file->dvd = dvd;
/*Hack*/ dvd_file->css_title = title << 1 | menu;
- dvd_file->lb_start = 0;
+ dvd_file->udf_file = NULL;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
@@ -904,6 +917,8 @@
}
}
+ if( dvd_file->udf_file ) UDFFreeFile( dvd_file->dvd, dvd_file->udf_file );
+
free( dvd_file );
dvd_file = 0;
}
@@ -918,14 +933,16 @@
off_t parts_size[ 9 ];
int nr_parts = 0;
int n;
+ udf_file_t *udf_file;
if( title == 0 )
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
else
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
- if( !UDFFindFile( dvd, filename, &size ) )
+ if( !(udf_file = UDFFindFile( dvd, filename, &size ) ) )
return -1;
+ UDFFreeFile(dvd, udf_file);
tot_size = size;
nr_parts = 1;
@@ -936,8 +953,9 @@
for( cur = 2; cur < 10; cur++ ) {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
- if( !UDFFindFile( dvd, filename, &size ) )
+ if( !(udf_file = UDFFindFile( dvd, filename, &size ) ) )
break;
+ UDFFreeFile(dvd, udf_file);
parts_size[ nr_parts ] = size;
tot_size += size;
@@ -1016,6 +1034,7 @@
char full_path[ PATH_MAX + 1 ];
struct stat fileinfo;
uint32_t size;
+ udf_file_t *udf_file;
/* Check arguments. */
if( dvd == NULL || titlenum < 0 ) {
@@ -1062,10 +1081,11 @@
}
if( dvd->isImageFile ) {
- if( UDFFindFile( dvd, filename, &size ) ) {
+ if( (udf_file = UDFFindFile( dvd, filename, &size ) ) ) {
statbuf->size = size;
statbuf->nr_parts = 1;
statbuf->parts_size[ 0 ] = size;
+ UDFFreeFile(dvd, udf_file);
return 0;
}
} else {
@@ -1116,7 +1136,8 @@
size_t block_count, unsigned char *data,
int encrypted )
{
- return UDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset,
+ return UDFReadBlocksRaw( dvd_file->dvd,
+ UDFFileBlockPos(dvd_file->udf_file, offset),
block_count, data, encrypted );
}
@@ -1208,11 +1229,11 @@
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 );
+ dvdinput_title( dvd_file->dvd->dev,
(int)UDFFileBlockPos(dvd_file->udf_file, 0) );
}
/* 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 );
+ dvdinput_title( dvd_file->title_devs[ 0 ],
(int)UDFFileBlockPos(dvd_file->udf_file, 0) );
}*/
}
Index: src/dvd_udf.c
===================================================================
--- src/dvd_udf.c (revision 1181)
+++ src/dvd_udf.c (working copy)
@@ -93,6 +93,13 @@
uint16_t Partition;
};
+struct UDF_FILE {
+ uint64_t Length;
+ uint32_t num_AD;
+ uint32_t Partition_Start;
+ struct AD AD_chain[UDF_MAX_AD_CHAINS];
+};
+
struct extent_ad {
uint32_t location;
uint32_t length;
@@ -117,7 +124,7 @@
struct icbmap {
uint32_t lbn;
- struct AD file;
+ udf_file_t file;
uint8_t filetype;
};
@@ -327,6 +334,14 @@
| ((uint32_t)data[(p) + 1] << 8) \
| ((uint32_t)data[(p) + 2] << 16) \
| ((uint32_t)data[(p) + 3] << 24))
+#define GETN8(p) ((uint64_t)data[p] \
+ | ((uint64_t)data[(p) + 1] << 8) \
+ | ((uint64_t)data[(p) + 2] << 16) \
+ | ((uint64_t)data[(p) + 3] << 24) \
+ | ((uint64_t)data[(p) + 4] << 32) \
+ | ((uint64_t)data[(p) + 5] << 40) \
+ | ((uint64_t)data[(p) + 6] << 48) \
+ | ((uint64_t)data[(p) + 7] << 56))
/* This is wrong with regard to endianess */
#define GETN(p, n, target) memcpy(target, &data[p], n)
@@ -427,7 +442,7 @@
}
static int UDFFileEntry( uint8_t *data, uint8_t *FileType,
- struct Partition *partition, struct AD *ad )
+ struct Partition *partition, udf_file_t *fad )
{
uint16_t flags;
uint32_t L_EA, L_AD;
@@ -436,15 +451,22 @@
UDFICB( &data[ 16 ], FileType, &flags );
/* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */
- ad->Length = GETN4( 60 ); /* Really 8 bytes a 56 */
- ad->Flags = 0;
- ad->Location = 0; /* what should we put here? */
- ad->Partition = partition->Number; /* use number of current partition */
+ fad->Length = GETN8( 56 ); /* Really 8 bytes at 56 */
L_EA = GETN4( 168 );
L_AD = GETN4( 172 );
p = 176 + L_EA;
+ fad->num_AD = 0;
while( p < 176 + L_EA + L_AD ) {
+ struct AD *ad;
+
+ if (fad->num_AD >= UDF_MAX_AD_CHAINS) return 0;
+
+ ad = &fad->AD_chain[fad->num_AD];
+ ad->Partition = partition->Number;
+ ad->Flags = 0;
+ fad->num_AD++;
+
switch( flags & 0x0007 ) {
case 0:
UDFShortAD( &data[ p ], ad, partition );
@@ -503,7 +525,7 @@
* return 1 on success, 0 on error;
*/
static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType,
- struct Partition *partition, struct AD *File )
+ struct Partition *partition, udf_file_t *File )
{
uint8_t LogBlock_base[DVD_VIDEO_LB_LEN + 2048];
uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base &
~((uintptr_t)2047)) + 2048);
@@ -539,12 +561,12 @@
}
/**
- * Dir: Location of directory to scan
+ * Dir: Location of directory to scan (This is not a struct-ptr, so not ANSI C)
* FileName: Name of file to look for
* FileICB: Location of ICB of the found file
* return 1 on success, 0 on error;
*/
-static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
+static int UDFScanDir( dvd_reader_t *device, udf_file_t Dir, char *FileName,
struct Partition *partition, struct AD *FileICB,
int cache_file_info)
{
@@ -562,13 +584,13 @@
int in_cache = 0;
/* Scan dir for ICB of file */
- lbnum = partition->Start + Dir.Location;
+ lbnum = partition->Start + Dir.AD_chain[0].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;
+ dir_lba = (Dir.AD_chain[0].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 *)(((uintptr_t)cached_dir_base &
~((uintptr_t)2047)) + 2048);
@@ -596,15 +618,17 @@
p = 0;
- while( p < Dir.Length ) {
+ while( p < Dir.AD_chain[0].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;
+ udf_file_t tmpFile;
+ memset(&tmpFile, 0, sizeof(tmpFile));
+
if( !strcasecmp( FileName, filename ) ) {
memcpy(FileICB, &tmpICB, sizeof(tmpICB));
found = 1;
@@ -631,11 +655,11 @@
return 0;
p = 0;
- while( p < Dir.Length ) {
+ while( p < Dir.AD_chain[0].Length ) {
if( p > DVD_VIDEO_LB_LEN ) {
++lbnum;
p -= DVD_VIDEO_LB_LEN;
- Dir.Length -= DVD_VIDEO_LB_LEN;
+ Dir.AD_chain[0].Length -= DVD_VIDEO_LB_LEN;
if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
return 0;
}
@@ -782,7 +806,58 @@
return part->valid;
}
-uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
+
+/*
+ * Release a UDF file descriptor
+ */
+void UDFFreeFile(dvd_reader_t *device, udf_file_t *File)
+{
+ free(File);
+}
+
+
+/*
+ * The API users will refer to block 0 as start of file and going up
+ * we need to convert that to actual disk block; partition_start +
+ * file_start + offset, but keep in mind that file_start is chained,
+ * and not contiguous.
+ *
+ * We return "0" as error, since a File can not start at physical block 0
+ *
+ * It is perhaps unfortunate that Location is in blocks, but Length is
+ * in bytes..? Can bytes be uneven blocksize in the middle of a chain?
+ *
+ */
+uint32_t UDFFileBlockPos(udf_file_t *File, uint32_t file_block)
+{
+ uint32_t result, i, offset;
+
+ if (!File) return 0;
+
+ /* Look through the chain to see where this block would belong. */
+ for (i = 0, offset = 0; i < File->num_AD; i++) {
+ /* Is "file_block" inside this chain? Then use this chain. */
+ if (file_block < (offset +
+ (File->AD_chain[i].Length / DVD_VIDEO_LB_LEN))) break;
+ offset += (File->AD_chain[i].Length / DVD_VIDEO_LB_LEN);
+ }
+
+ /* If it is not defined in the AD chains, we should return an error, but
+ * in the interest of being backward (in)compatible with the original
+ * libdvdread, we revert back to the traditional view that UDF file are
+ * one contiguous long chain, in case some API software out there relies on
+ * this incorrect behavior.
+ */
+ if (i >= File->num_AD) i = 0;
+
+ result = File->Partition_Start + File->AD_chain[i].Location + file_block -
offset;
+ return result;
+}
+
+
+
+
+udf_file_t *UDFFindFile( dvd_reader_t *device, char *filename,
uint32_t *filesize )
{
uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ];
@@ -790,11 +865,12 @@
uint32_t lbnum;
uint16_t TagID;
struct Partition partition;
- struct AD RootICB, File, ICB;
+ struct AD RootICB, ICB;
+ udf_file_t File, *result;
char tokenline[ MAX_UDF_FILE_NAME_LEN ];
char *token;
uint8_t filetype;
-
+ memset(&File, 0, sizeof(File));
*filesize = 0;
tokenline[0] = '\0';
strncat(tokenline, filename, MAX_UDF_FILE_NAME_LEN - 1);
@@ -822,17 +898,17 @@
/* Sanity checks. */
if( TagID != 256 )
- return 0;
+ return NULL;
if( RootICB.Partition != 0 )
- return 0;
+ return NULL;
SetUDFCache(device, RootICBCache, 0, &RootICB);
}
/* Find root dir */
if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) )
- return 0;
+ return NULL;
if( filetype != 4 )
- return 0; /* Root dir should be dir */
+ return NULL; /* Root dir should be dir */
{
int cache_file_info = 0;
/* Tokenize filepath */
@@ -841,9 +917,9 @@
while( token != NULL ) {
if( !UDFScanDir( device, File, token, &partition, &ICB,
cache_file_info))
- return 0;
+ return NULL;
if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) )
- return 0;
+ return NULL;
if(!strcmp(token, "VIDEO_TS"))
cache_file_info = 1;
token = strtok( NULL, "/" );
@@ -851,14 +927,23 @@
}
/* Sanity check. */
- if( File.Partition != 0 )
- return 0;
+ if( File.AD_chain[0].Partition != 0 )
+ return NULL;
*filesize = File.Length;
/* Hack to not return partition.Start for empty files. */
- if( !File.Location )
- return 0;
- else
- return partition.Start + File.Location;
+ if( !File.AD_chain[0].Location )
+ return NULL;
+
+ // Allocate a UDF_FILE node for the API user
+ result = (udf_file_t *) malloc(sizeof(*result));
+ if (!result) return NULL;
+
+ // Copy over the information
+ memcpy(result, &File, sizeof(*result));
+
+ result->Partition_Start = partition.Start;
+
+ return result;
}
Index: src/dvdread/dvd_udf.h
===================================================================
--- src/dvdread/dvd_udf.h (revision 1181)
+++ src/dvdread/dvd_udf.h (working copy)
@@ -39,6 +39,32 @@
extern "C" {
#endif
+
+
+/*
+ *
+ * UDF defines struct AD, which dvdread unfortunately overloads to refer to
+ * a file, creating problems with chained ADs. We need to define a generic
+ * UDF_FILE structure to hold the information required.
+ * It could be worth a separate struct for Directories, since they are
(probably)
+ * only ever in 1 chain.
+ *
+ * Is there a real max number of chains? What can fit in 2048?
+ * My 4.4GB file example uses 5 chains. A BD ISO can store 50GB of data, so
+ * potentially we could have a 50GB file, so we would need to be able to
+ * support 62 chains.
+ *
+ */
+
+#ifndef UDF_MAX_AD_CHAINS // Allow MAX to be increased by API.
+#define UDF_MAX_AD_CHAINS 50
+#endif
+
+
+typedef struct UDF_FILE udf_file_t;
+
+
+
/**
* Looks for a file on the UDF disc/imagefile and returns the block number
* where it begins, or 0 if it is not found. The filename should be an
@@ -46,8 +72,9 @@
* '/VIDEO_TS/VTS_01_1.IFO'. On success, filesize will be set to the size of
* the file in bytes.
*/
-uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *size );
-
+udf_file_t *UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *size
);
+void UDFFreeFile( dvd_reader_t *device, udf_file_t *udf_file );
+uint32_t UDFFileBlockPos( udf_file_t *udf_file, uint32_t file_block);
void FreeUDFCache(void *cache);
int UDFGetVolumeIdentifier(dvd_reader_t *device,
char *volid, unsigned int volid_size);
_______________________________________________
DVDnav-discuss mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/dvdnav-discuss