[DVDnav-discuss] [PATCH] Patch 1/5: Resend
Dominik 'Rathann' Mierzejewski
dominik at greysector.net
Thu Oct 6 17:51:06 CEST 2011
On Thursday, 06 October 2011 at 17:10, John Stebbins wrote:
> On 10/06/2011 07:11 AM, Dominik 'Rathann' Mierzejewski wrote:
> > On Sunday, 26 October 2008 at 23:21, Diego Biurrun wrote:
> >> On Tue, Oct 21, 2008 at 09:43:05AM +0200, Nico Sabbi wrote:
> >>> On Tuesday 21 October 2008 09:31:12 Diego Biurrun wrote:
> >>>> cosmetics
> >>>>
> >>>> Nico, do you want these committed separately or not at all?
> >>> separately, but I have to test the actual working of the code before
> >>> committing.
> >>> Don't bother resending
> >> I committed the cosmetics separately, here is the updated patch.
> > Could someone review? Nico, Erik, John ...?
> >
> I have no idea what this is referencing. I can't find any relevant messages in a search through my email history.
It's almost one year old. Reattaching. If you need me to resend other patches
I bumped up, just say a word.
Regards,
Dominik
--
Fedora http://fedoraproject.org/wiki/User:Rathann
RPMFusion http://rpmfusion.org | MPlayer http://mplayerhq.hu
"Faith manages."
-- Delenn to Lennier in Babylon 5:"Confessions and Lamentations"
-------------- next part --------------
Index: src/dvd_reader.c
===================================================================
--- src/dvd_reader.c (revision 1158)
+++ src/dvd_reader.c (working copy)
@@ -102,7 +102,7 @@
int css_title;
/* Information required for an image file. */
- uint32_t lb_start;
+ UDF_FILE udf_file;
uint32_t seek_pos;
/* Information required for a directory path drive. */
@@ -111,6 +111,10 @@
/* Calculated at open-time, size in blocks. */
ssize_t filesize;
+
+ /* Size of file in bytes. */
+ uint64_t filebytes;
+
};
int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
@@ -159,7 +163,9 @@
struct timeval all_s, all_e;
struct timeval t_s, t_e;
char filename[ MAX_UDF_FILE_NAME_LEN ];
- uint32_t start, len;
+ UDF_FILE udf_file;
+ uint32_t start;
+ uint64_t len;
int title;
char *nokeys_str = getenv("DVDREAD_NOKEYS");
@@ -179,9 +185,10 @@
} 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. */
+ start = UDFFileBlockPos(udf_file, 0);
fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
filename, start );
if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
@@ -192,14 +199,18 @@
(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 == 0 || len == 0 ) break;
/* Perform CSS key cracking for this title. */
+ start = UDFFileBlockPos(udf_file, 0);
fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
filename, start );
if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
@@ -216,6 +227,9 @@
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;
}
@@ -565,11 +579,12 @@
*/
static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename )
{
- uint32_t start, len;
+ UDF_FILE udf_file;
+ uint64_t len;
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;
}
@@ -580,11 +595,12 @@
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 ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
+ dvd_file->filebytes = len;
return dvd_file;
}
@@ -676,7 +692,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 ) );
@@ -690,6 +706,7 @@
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_devs[ 0 ] = dev;
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
+ dvd_file->filebytes = fileinfo.st_size;
return dvd_file;
}
@@ -697,7 +714,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;
+ UDF_FILE udf_file;
+ uint64_t len;
dvd_file_t *dvd_file;
if( title == 0 ) {
@@ -705,18 +723,19 @@
} 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;
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;
+ dvd_file->filebytes = len;
/* Calculate the complete file size for every file in the VOBS */
if( !menu ) {
@@ -755,11 +774,12 @@
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 ) );
dvd_file->filesize = 0;
+ dvd_file->filebytes = 0;
if( menu ) {
dvd_input_t dev;
@@ -884,6 +904,9 @@
}
}
+ if (dvd_file->udf_file)
+ UDFFreeFile(NULL, dvd_file->udf_file);
+
free( dvd_file );
dvd_file = 0;
}
@@ -922,7 +945,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 );
}
@@ -1014,7 +1038,7 @@
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 {
@@ -1046,6 +1070,15 @@
return offset;
}
+uint64_t DVDFileSize64( dvd_file_t *dvd_file )
+{
+ /* Check arguments. */
+ if( dvd_file == NULL )
+ return -1;
+
+ return dvd_file->filebytes;
+}
+
int DVDFileSeekForce(dvd_file_t *dvd_file, int offset, int force_size)
{
/* Check arguments. */
Index: src/dvd_reader.h
===================================================================
--- src/dvd_reader.h (revision 1158)
+++ src/dvd_reader.h (working copy)
@@ -196,6 +196,11 @@
ssize_t DVDFileSize( dvd_file_t * );
/**
+ * Define separate 64-bit version to be back-ward compatible.
+ */
+uint64_t DVDFileSize64( 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).
Index: src/dvd_udf.c
===================================================================
--- src/dvd_udf.c (revision 1158)
+++ src/dvd_udf.c (working copy)
@@ -88,6 +88,10 @@
uint32_t Length;
};
+/* Previously, dvdread re-used AD to carry up the filesize, resulting in
+ * a 64bit->32bit problem. This is acceptable on most DVD images (1GB VOB files)
+ * but not desirable. Now it has changed to use a FileAD when it is actually
+ * used for files, and AD otherwise. - Lund */
struct AD {
uint32_t Location;
uint32_t Length;
@@ -95,6 +99,25 @@
uint16_t Partition;
};
+/* Previously dvdread would assume files only had one AD chain, and since they
+ * are 1GB or less, this is most problably true. However, now we handle chains
+ * for large files. ECMA_167 does not specify the maximum number of chains, is
+ * it as many as can fit in a 2048 block? (minus ID 266 size), or some other
+ * limit. For now, I have assumed that;
+ * a 4.4GB file uses 5 AD chains. A BluRay disk can store 50GB of data, so the
+ * largest file should be 50 GB. So the maximum number of chains should be
+ * around 62. We could also change it to be allocated as needed.
+ */
+
+#define UDF_MAX_AD_CHAINS 50
+
+struct FileAD {
+ 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;
@@ -119,7 +142,7 @@
struct icbmap {
uint32_t lbn;
- struct AD file;
+ struct FileAD file;
uint8_t filetype;
};
@@ -142,6 +165,17 @@
PartitionCache, RootICBCache, LBUDFCache, MapCache, AVDPCache, PVDCache
} UDFCacheType;
+/*
+ * Release an allocated FileAD data. Technically you can just call free()
+ * but it is clean to stay modular. (Should we one day record further data.
+ */
+void UDFFreeFile(dvd_reader_t *device, struct FileAD *File)
+{
+ free(File);
+}
+
+
+
void FreeUDFCache(void *cache)
{
struct udf_cache *c = (struct udf_cache *)cache;
@@ -329,6 +363,15 @@
| ((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)
@@ -429,24 +472,35 @@
}
static int UDFFileEntry( uint8_t *data, uint8_t *FileType,
- struct Partition *partition, struct AD *ad )
+ struct Partition *partition, struct FileAD *fad )
{
uint16_t flags;
uint32_t L_EA, L_AD;
unsigned int p;
+ unsigned int curr_ad;
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 ); /* Was 4 bytes at 60, changed to 64-bit. */
L_EA = GETN4( 168 );
L_AD = GETN4( 172 );
p = 176 + L_EA;
+ curr_ad = 0;
+
+ /* Function changed to record all AD chains, not just the last one! */
while( p < 176 + L_EA + L_AD ) {
+ struct AD *ad;
+
+ if (curr_ad >= UDF_MAX_AD_CHAINS) return 0;
+
+ ad = &fad->AD_chain[curr_ad];
+ ad->Partition = partition->Number;
+ ad->Flags = 0;
+ // Increase AD chain ptr
+ curr_ad++;
+
switch( flags & 0x0007 ) {
case 0:
UDFShortAD( &data[ p ], ad, partition );
@@ -505,7 +559,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, struct FileAD *File )
{
uint8_t LogBlock_base[DVD_VIDEO_LB_LEN + 2048];
uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048);
@@ -546,7 +600,7 @@
* 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, struct FileAD Dir, char *FileName,
struct Partition *partition, struct AD *FileICB,
int cache_file_info)
{
@@ -564,13 +618,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);
@@ -598,15 +652,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;
+ struct FileAD tmpFile;
+ memset(&tmpFile, 0, sizeof(tmpFile));
+
if( !strcasecmp( FileName, filename ) ) {
memcpy(FileICB, &tmpICB, sizeof(tmpICB));
found = 1;
@@ -633,11 +689,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;
}
@@ -784,23 +840,89 @@
return part->valid;
}
-uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
- uint32_t *filesize )
+/*
+ * Translate between File logic block, and actual disk-block, taking into
+ * account for partition start, file block start, and chain position.
+ *
+ * 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
+ *
+ */
+uint32_t UDFFileBlockPos(struct FileAD *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);
+
+ }
+
+ // Beyond out chains of AD? We could return error, or just fall back to
+ // old behavior in case someone relies on the broken way.
+ if (i >= File->num_AD)
+ i = 0;
+
+ // Compute actual block number
+ result = File->Partition_Start
+ + File->AD_chain[i].Location
+ + file_block
+ - offset;
+
+
+#ifdef DEBUG
+ if (!(file_block % 10000))
+ fprintf(stderr, "libdvdread: File block %d -> %d (chain %d + offset %d : %d)\r\n",
+ file_block, result,
+ i,
+ file_block - offset,
+ (File->AD_chain[i].Length / DVD_VIDEO_LB_LEN));
+#endif
+ return result;
+
+}
+
+/*
+ * Find a File/Directory based on name.
+ * in: DVD Device *
+ * in: filename
+ * out: allocated UDF_FILE*, call UDFFreeFile() to release.
+ * out: Filesize. (Note: 64-bit)
+ * out: NULL to indicate error, File Not Found.
+ */
+UDF_FILE UDFFindFile( dvd_reader_t *device, char *filename,
+ uint64_t *filesize )
+{
uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ];
uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048);
uint32_t lbnum;
uint16_t TagID;
struct Partition partition;
- struct AD RootICB, File, ICB;
+ struct AD RootICB, ICB;
+ struct FileAD File;
char tokenline[ MAX_UDF_FILE_NAME_LEN ];
char *token;
uint8_t filetype;
+ struct FileAD *result;
*filesize = 0;
tokenline[0] = '\0';
strncat(tokenline, filename, MAX_UDF_FILE_NAME_LEN - 1);
memset(&ICB, 0, sizeof(ICB));
+ memset(&File, 0, sizeof(File));
if(!(GetUDFCache(device, PartitionCache, 0, &partition) &&
GetUDFCache(device, RootICBCache, 0, &RootICB))) {
@@ -824,17 +946,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 */
@@ -853,14 +975,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 new UDF_FILE and return it. */
+ result = (struct FileAD *) malloc(sizeof(*result));
+ if (!result) return NULL;
+
+ memcpy(result, &File, sizeof(*result));
+
+ result->Partition_Start = partition.Start;
+
+ return result;
+
}
Index: src/dvd_udf.h
===================================================================
--- src/dvd_udf.h (revision 1158)
+++ src/dvd_udf.h (working copy)
@@ -39,6 +39,8 @@
extern "C" {
#endif
+typedef struct FileAD *UDF_FILE;
+
/**
* 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,7 +48,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 UDFFindFile( dvd_reader_t *device, char *filename, uint64_t *size );
+void UDFFreeFile ( dvd_reader_t *device, UDF_FILE );
+uint32_t UDFFileBlockPos( UDF_FILE, uint32_t file_block);
void FreeUDFCache(void *cache);
int UDFGetVolumeIdentifier(dvd_reader_t *device,
More information about the DVDnav-discuss
mailing list