Could you resend the whole UDF patchset rediffed (if necessary) against
current SVN? Nico, please review it when you have some time. I seem to
remember that at least one patch was already OK'd by Nico.


I am dealing directly with Hovland to re-attempt my patches. I have sent him the first one to fix the AD chains. If that is accepted, I will do the 2nd one.

Lund

--
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)


Attached is patch "dvdread_patch_udf_file.txt".

The problem:

dvdread currently assumes that "file" in UDF have a starting block, and a length. The data is then contiguous from "start" until the final block.

In reality, UDF is split up into "AD chains" of contiguous segments, generally in increasing order.

UDF File:              dvdread file
 chain 0 start          file start
       |                    |
 chain 0 end                |
       |                    |
      gap                   |
       |                    |
 chain 1 start              |
       |                    |
 chain 1 end            file end
       |


This means that dvdread will incorrectly send the "gap blocks", as well as reach the "end" of the file sooner than it should. (Since gap blocks are counted).

This patch removes the view that a UDF file is start "starting block, and length", and creates a new "udf_file_t" structure to hold the number of AD chains, the AD chains and a few useful bits of information.

A new function has been written to convert the wanted block number inside the UDF file. Previously it was always "start_block + offset_block". Now it scans the AD chain for the chain in which "offset_block" is contained, and returns the correct RAW block offset from that AD chain's starting block.

UDF AD chains do not HAVE to be in incrementing order either, and you will find that some ARCcoS DVDs have the chains backwards. This patch will also fix this situation.

This patch mostly changes dvd_udf.c internally, with changes to dvd_reader.c to use the new udf_file_t instead of "lbnum". The patch should be transparent to software using dvdread. (Apart from no longer receiving GAP blocks, and receiving the full end blocks of VOBs larger than 1 AD chain).

This patch is required to allow larger files in UDF format, as the number of AD chains increases with filesize. For example, a 4GB file will use 5 AD chains.
Index: dvd_reader.c
===================================================================
--- dvd_reader.c        (revision 1181)
+++ 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: dvd_udf.c
===================================================================
--- dvd_udf.c   (revision 1181)
+++ dvd_udf.c   (working copy)
@@ -40,6 +40,7 @@
 #include "dvdread/dvd_reader.h"
 #include "dvdread/dvd_udf.h"
 
+
 /* Private but located in/shared with dvd_reader.c */
 extern int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
                              size_t block_count, unsigned char *data,
@@ -93,6 +94,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 +125,7 @@
 
 struct icbmap {
   uint32_t lbn;
-  struct AD file;
+  udf_file_t file;
   uint8_t filetype;
 };
 
@@ -327,6 +335,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 +443,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 +452,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 +526,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 +562,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 +585,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 +619,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 +656,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 +807,80 @@
   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;
+
+
+#ifdef DEBUG
+  if (!(file_block % 10000))
+    fprintf(stderr, "libdvdread: File block %d -> %d (chain %d/%d + offset %d 
: %d)\r\n", file_block, result,
+            i,
+            File->num_AD,
+            file_block - offset,
+            (File->AD_chain[i].Length / DVD_VIDEO_LB_LEN));
+#endif
+  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 +888,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 +921,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 +940,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 +950,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: dvdread/dvd_udf.h
===================================================================
--- dvdread/dvd_udf.h   (revision 1181)
+++ 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

Reply via email to