[libdvdnav-devel] [PATCH] [RFC] Use libudfread

Petri Hintukainen phintuka at gmail.com
Wed May 20 13:15:08 CEST 2015


---

Note that this patch does not compile because of missing ifdefs in libudfread:
  UDFREAD_NO_DEFAULT_INPUT
    - disable file I/O in libudfread (not used with libdvdread)
    -> removes dependency on POSIX pread()
  UDFREAD_NO_REENTRANT
    - disable thread safety in libudfread (libdvdread is not thread safe)
    -> removes dependency on pthread / atomic operations
Alternative would be adding (pointless) configure checks for pread() and pthread.

Another change is in caching: libudfread always caches directory trees,
but it does not cache file entries. Caching could be made optional if
disabling caching is useful feature in libdvdread ?

 .gitmodules      |   3 ++
 Makefile.am      |  10 ++++-
 src/dvd_reader.c | 130 +++++++++++++++++++++++++++++++++++--------------------
 3 files changed, 94 insertions(+), 49 deletions(-)
 create mode 100644 .gitmodules

diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..e2722d7
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "contrib/libudfread"]
+	path = contrib/libudfread
+	url = git://git.videolan.org/libudfread.git
diff --git a/Makefile.am b/Makefile.am
index 57ca371..d99693e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
 ACLOCAL_AMFLAGS = -Im4
 
-AM_CPPFLAGS = -I$(top_srcdir)/src $(CSS_CFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/contrib/libudfread/src $(CSS_CFLAGS)
 
 dist_doc_DATA = AUTHORS ChangeLog COPYING NEWS README TODO
 
@@ -31,6 +31,14 @@ libdvdread_la_SOURCES = \
 	src/nav_print.c \
 	src/nav_read.c
 
+AM_CPPFLAGS += -DUDFREAD_NO_DEFAULT_INPUT -DUDFREAD_NO_REENTRANT
+libdvdread_la_SOURCES += \
+	contrib/libudfread/src/blockinput.h \
+	contrib/libudfread/src/ecma167.h \
+	contrib/libudfread/src/ecma167.c \
+	contrib/libudfread/src/udfread.h \
+	contrib/libudfread/src/udfread.c
+
 libdvdread_la_LIBADD = $(CSS_LIBS)
 
 libdvdread_la_LDFLAGS = -version-info $(DVDREAD_LTVERSION) \
diff --git a/src/dvd_reader.c b/src/dvd_reader.c
index 54a33b2..c323600 100644
--- a/src/dvd_reader.c
+++ b/src/dvd_reader.c
@@ -25,6 +25,7 @@
 #include <sys/stat.h>       /* stat */
 #include <sys/time.h>       /* For the timing of dvdcss_title crack. */
 #include <fcntl.h>          /* open */
+#include <stddef.h>         /* offsetof */
 #include <stdlib.h>         /* free */
 #include <stdio.h>          /* fprintf */
 #include <errno.h>          /* errno, EIN* */
@@ -70,6 +71,9 @@ static inline int _private_gettimeofday( struct timeval *tv, void *tz )
 # include <paths.h>
 #endif
 
+#include "udfread.h"
+#include "blockinput.h"
+
 #include "dvdread/dvd_udf.h"
 #include "dvdread/dvd_reader.h"
 #include "dvd_input.h"
@@ -77,11 +81,7 @@ static inline int _private_gettimeofday( struct timeval *tv, void *tz )
 #include "md5.h"
 #include "dvdread/ifo_read.h"
 
-#define DEFAULT_UDF_CACHE_LEVEL 1
-
 struct dvd_reader_s {
-  /* Basic information. */
-  int isImageFile;
 
   /* Hack for keeping track of the css status.
    * 0: no css, 1: perhaps (need init of keys), 2: have done init */
@@ -94,9 +94,9 @@ struct dvd_reader_s {
   /* Information required for a directory path drive. */
   char *path_root;
 
-  /* Filesystem cache */
-  int udfcache_level; /* 0 - turned off, 1 - on */
-  void *udfcache;
+  /* UDF filesystem access */
+  udfread *udf;
+  udfread_block_input udf_input;
 };
 
 #define TITLES_MAX 9
@@ -124,6 +124,7 @@ struct dvd_file_s {
   unsigned char *cache;
 };
 
+static
 int InternalUDFReadBlocksRaw( const dvd_reader_t *device, uint32_t lb_number,
                       size_t block_count, unsigned char *data,
                       int encrypted );
@@ -135,31 +136,10 @@ int InternalUDFReadBlocksRaw( const dvd_reader_t *device, uint32_t lb_number,
  */
 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;
+  // not used with libudfread
+  (void)device;
+  (void)level;
+  return 1;
 }
 
 
@@ -230,7 +210,56 @@ static int initAllCSSKeys( dvd_reader_t *dvd )
   return 0;
 }
 
+/* compability layer for old dvd_udf.c (and exposed dvd_udf.h API) */
+
+uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *size )
+{
+  uint32_t lba = 0;
+  UDFFILE *fp = udfread_file_open(device->udf, filename);
+  if (fp) {
+    *size = udfread_file_size(fp);
+    lba = udfread_file_lba(fp, 0);
+    udfread_file_close(fp);
+  }
+  return lba;
+}
+
+int UDFGetVolumeIdentifier(dvd_reader_t *device,
+                           char *volid, unsigned int volid_size)
+{
+  const char *id;
+  size_t volid_len = 0;
+
+  id = udfread_get_volume_id (device->udf);
+  if (id) {
+    volid_len = strlen(id);
+
+    if (volid_size > volid_len)
+      volid_size = volid_len;
 
+    memcpy(volid, id, volid_size);
+    volid[volid_size] = 0;
+  }
+
+  return volid_len;
+}
+
+int UDFGetVolumeSetIdentifier(dvd_reader_t *device,
+                              uint8_t *volsetid, unsigned int volsetid_size)
+{
+  return udfread_get_volume_set_id (device->udf, volsetid, volsetid_size);
+}
+
+/* */
+
+static int _bi_read(udfread_block_input *i, uint32_t lba, void *buf, uint32_t nblocks, int flags)
+{
+  dvd_reader_t *dvd = (void *)((intptr_t)i - offsetof(dvd_reader_t, udf_input));
+  if (dvdinput_seek(dvd->dev, lba) < 0) {
+    return -1;
+  }
+  return dvdinput_read(dvd->dev, buf, nblocks, flags);
+}
 
 /**
  * Open a DVD image or block device file or use stream_cb functions.
@@ -254,10 +283,16 @@ static dvd_reader_t *DVDOpenImageFile( const char *location,
     dvdinput_close(dev);
     return NULL;
   }
-  dvd->isImageFile = 1;
   dvd->dev = dev;
 
-  dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL;
+  dvd->udf = udfread_init();
+  //udfread_set_caching(dvd->udf, UDF_CACHE_FILE_ENTRY);
+  dvd->udf_input.read = _bi_read;
+  if (udfread_open_input(dvd->udf, &dvd->udf_input) < 0) {
+      fprintf(stderr, "failed opening UDF filesystem\n");
+      DVDClose( dvd );
+      return NULL;
+  }
 
   if( have_css ) {
     /* Only if DVDCSS_METHOD = title, a bit if it's disc or if
@@ -281,7 +316,6 @@ static dvd_reader_t *DVDOpenPath( const char *path_root )
     free(dvd);
     return NULL;
   }
-  dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL;
 
   return dvd;
 }
@@ -632,9 +666,9 @@ dvd_reader_t *DVDOpenStream( void *stream,
 void DVDClose( dvd_reader_t *dvd )
 {
   if( dvd ) {
+    if( dvd->udf ) udfread_close(dvd->udf);
     if( dvd->dev ) dvdinput_close( dvd->dev );
     if( dvd->path_root ) free( dvd->path_root );
-    if( dvd->udfcache ) FreeUDFCache( dvd->udfcache );
     free( dvd );
   }
 }
@@ -931,7 +965,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
     do_cache = 1;
     break;
   case DVD_READ_MENU_VOBS:
-    if( dvd->isImageFile ) {
+    if( dvd->udf ) {
       return DVDOpenVOBUDF( dvd, titlenum, 1 );
     } else {
       return DVDOpenVOBPath( dvd, titlenum, 1 );
@@ -939,7 +973,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
     break;
   case DVD_READ_TITLE_VOBS:
     if( titlenum == 0 ) return NULL;
-    if( dvd->isImageFile ) {
+    if( dvd->udf ) {
       return DVDOpenVOBUDF( dvd, titlenum, 0 );
     } else {
       return DVDOpenVOBPath( dvd, titlenum, 0 );
@@ -950,7 +984,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
     return NULL;
   }
 
-  if( dvd->isImageFile ) {
+  if( dvd->udf ) {
     return DVDOpenFileUDF( dvd, filename, do_cache );
   } else {
     return DVDOpenFilePath( dvd, filename );
@@ -960,7 +994,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
 void DVDCloseFile( dvd_file_t *dvd_file )
 {
   if( dvd_file && dvd_file->dvd ) {
-    if( !dvd_file->dvd->isImageFile ) {
+    if( !dvd_file->dvd->udf ) {
       int i;
 
       for( i = 0; i < TITLES_MAX; ++i ) {
@@ -1105,7 +1139,7 @@ int DVDFileStat( dvd_reader_t *dvd, int titlenum,
 
     break;
   case DVD_READ_MENU_VOBS:
-    if( dvd->isImageFile )
+    if( dvd->udf )
       return DVDFileStatVOBUDF( dvd, titlenum, 1, statbuf );
     else
       return DVDFileStatVOBPath( dvd, titlenum, 1, statbuf );
@@ -1115,7 +1149,7 @@ int DVDFileStat( dvd_reader_t *dvd, int titlenum,
     if( titlenum == 0 )
       return -1;
 
-    if( dvd->isImageFile )
+    if( dvd->udf )
       return DVDFileStatVOBUDF( dvd, titlenum, 0, statbuf );
     else
       return DVDFileStatVOBPath( dvd, titlenum, 0, statbuf );
@@ -1127,7 +1161,7 @@ int DVDFileStat( dvd_reader_t *dvd, int titlenum,
     return -1;
   }
 
-  if( dvd->isImageFile ) {
+  if( dvd->udf ) {
     if( UDFFindFile( dvd, filename, &size ) ) {
       statbuf->size = size;
       statbuf->nr_parts = 1;
@@ -1151,7 +1185,7 @@ int DVDFileStat( dvd_reader_t *dvd, int titlenum,
   return -1;
 }
 
-/* Internal, but used from dvd_udf.c */
+static
 int InternalUDFReadBlocksRaw( const dvd_reader_t *device, uint32_t lb_number,
                       size_t block_count, unsigned char *data,
                       int encrypted )
@@ -1292,7 +1326,7 @@ ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
   /* Hack, and it will still fail for multiple opens in a threaded app ! */
   if( dvd_file->dvd->css_title != dvd_file->css_title ) {
     dvd_file->dvd->css_title = dvd_file->css_title;
-    if( dvd_file->dvd->isImageFile ) {
+    if( dvd_file->dvd->udf ) {
       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
@@ -1301,7 +1335,7 @@ ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
     }*/
   }
 
-  if( dvd_file->dvd->isImageFile ) {
+  if( dvd_file->dvd->udf ) {
     ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset,
                             block_count, data, DVDINPUT_READ_DECRYPT );
   } else {
@@ -1331,7 +1365,7 @@ int DVDFileSeekForce(dvd_file_t *dvd_file, int offset, int force_size)
   if( dvd_file == NULL || offset <= 0 )
       return -1;
 
-  if( dvd_file->dvd->isImageFile ) {
+  if( dvd_file->dvd->udf ) {
     if( force_size < 0 )
       force_size = (offset - 1) / DVD_VIDEO_LB_LEN + 1;
     if( dvd_file->filesize < force_size ) {
@@ -1371,7 +1405,7 @@ ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
   }
   secbuf = (unsigned char *)(((uintptr_t)secbuf_base & ~((uintptr_t)2047)) + 2048);
 
-  if( dvd_file->dvd->isImageFile ) {
+  if( dvd_file->dvd->udf ) {
     ret = DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector,
                             (size_t) numsec, secbuf, DVDINPUT_NOFLAGS );
   } else {
-- 
2.1.4



More information about the libdvdnav-devel mailing list