[libdvdnav-devel] [PATCH] add DVDOpenStream

Thomas Guillem tom at gllm.fr
Fri Oct 17 17:46:39 CEST 2014


open a DVD Device using external read/seek callbacks (see libdvdcss).
---
 src/dvd_input.c          | 23 ++++++++++++++++-----
 src/dvd_input.h          |  3 ++-
 src/dvd_reader.c         | 52 ++++++++++++++++++++++++++++++++++--------------
 src/dvdread/dvd_reader.h | 14 +++++++++++++
 4 files changed, 71 insertions(+), 21 deletions(-)

diff --git a/src/dvd_input.c b/src/dvd_input.c
index 9e6a0de..1487da7 100644
--- a/src/dvd_input.c
+++ b/src/dvd_input.c
@@ -30,7 +30,7 @@
 
 
 /* The function pointers that is the exported interface of this file. */
-dvd_input_t (*dvdinput_open)  (const char *);
+dvd_input_t (*dvdinput_open)  (const char *, void *, dvd_reader_stream_cb *);
 int         (*dvdinput_close) (dvd_input_t);
 int         (*dvdinput_seek)  (dvd_input_t, int);
 int         (*dvdinput_title) (dvd_input_t, int);
@@ -40,6 +40,8 @@ char *      (*dvdinput_error) (dvd_input_t);
 #ifdef HAVE_DVDCSS_DVDCSS_H
 /* linking to libdvdcss */
 # include <dvdcss/dvdcss.h>
+# define DVDcss_open_stream(a, b) \
+    dvdcss_open_stream((void*)(a), (dvdcss_stream_cb*)(b))
 # define DVDcss_open(a) dvdcss_open((char*)(a))
 # define DVDcss_close   dvdcss_close
 # define DVDcss_seek    dvdcss_seek
@@ -58,6 +60,8 @@ char *      (*dvdinput_error) (dvd_input_t);
 #endif
 
 typedef struct dvdcss_s *dvdcss_t;
+typedef struct dvdcss_stream_cb dvdcss_stream_cb;
+static dvdcss_t (*DVDcss_open_stream) (void *, dvdcss_stream_cb *);
 static dvdcss_t (*DVDcss_open)  (const char *);
 static int      (*DVDcss_close) (dvdcss_t);
 static int      (*DVDcss_seek)  (dvdcss_t, int, int);
@@ -77,9 +81,10 @@ struct dvd_input_s {
 
 
 /**
- * initialize and open a DVD device or file.
+ * initialize and open a DVD (device or file or stream_cb)
  */
-static dvd_input_t css_open(const char *target)
+static dvd_input_t css_open(const char *target,
+                            void *stream, dvd_reader_stream_cb *stream_cb)
 {
   dvd_input_t dev;
 
@@ -91,7 +96,10 @@ static dvd_input_t css_open(const char *target)
   }
 
   /* Really open it with libdvdcss */
-  dev->dvdcss = DVDcss_open(target);
+  if(target)
+      dev->dvdcss = DVDcss_open(target);
+  else if(stream && stream_cb && DVDcss_open_stream != NULL)
+      dev->dvdcss = DVDcss_open_stream(stream, (dvdcss_stream_cb *)stream_cb);
   if(dev->dvdcss == 0) {
     fprintf(stderr, "libdvdread: Could not open %s with libdvdcss.\n", target);
     free(dev);
@@ -154,10 +162,13 @@ static int css_close(dvd_input_t dev)
 /**
  * initialize and open a DVD device or file.
  */
-static dvd_input_t file_open(const char *target)
+static dvd_input_t file_open(const char *target,
+                             void *stream, dvd_reader_stream_cb *stream_cb)
 {
   dvd_input_t dev;
 
+  if(target == NULL)
+    return NULL;
   /* Allocate the library structure */
   dev = malloc(sizeof(*dev));
   if(dev == NULL) {
@@ -299,6 +310,8 @@ int dvdinput_setup(void)
 #else
 #define U_S
 #endif
+    DVDcss_open_stream = (dvdcss_t (*)(void *, dvdcss_stream_cb *))
+      dlsym(dvdcss_library, U_S "dvdcss_open_stream");
     DVDcss_open = (dvdcss_t (*)(const char*))
       dlsym(dvdcss_library, U_S "dvdcss_open");
     DVDcss_close = (int (*)(dvdcss_t))
diff --git a/src/dvd_input.h b/src/dvd_input.h
index c22fada..2f8a546 100644
--- a/src/dvd_input.h
+++ b/src/dvd_input.h
@@ -55,7 +55,8 @@ typedef struct dvd_input_s *dvd_input_t;
  * Function pointers that will be filled in by the input implementation.
  * These functions provide the main API.
  */
-extern dvd_input_t (*dvdinput_open)  (const char *);
+extern dvd_input_t (*dvdinput_open)  (const char *,
+                                      void *, dvd_reader_stream_cb *);
 extern int         (*dvdinput_close) (dvd_input_t);
 extern int         (*dvdinput_seek)  (dvd_input_t, int);
 extern int         (*dvdinput_title) (dvd_input_t, int);
diff --git a/src/dvd_reader.c b/src/dvd_reader.c
index fb045b3..e400205 100644
--- a/src/dvd_reader.c
+++ b/src/dvd_reader.c
@@ -229,14 +229,17 @@ static int initAllCSSKeys( dvd_reader_t *dvd )
 
 
 /**
- * Open a DVD image or block device file.
+ * Open a DVD image or block device file or use stream_cb functions.
  */
-static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css )
+static dvd_reader_t *DVDOpenImageFile( const char *location,
+                                       void *stream,
+                                       dvd_reader_stream_cb *stream_cb,
+                                       int have_css )
 {
   dvd_reader_t *dvd;
   dvd_input_t dev;
 
-  dev = dvdinput_open( location );
+  dev = dvdinput_open( location, stream, stream_cb );
   if( !dev ) {
     fprintf( stderr, "libdvdread: Can't open %s for reading\n", location );
     return NULL;
@@ -343,8 +346,9 @@ static char *bsd_block2char( const char *path )
 }
 #endif
 
-
-dvd_reader_t *DVDOpen( const char *ppath )
+static dvd_reader_t *DVDOpenCommon( const char *ppath,
+                                    void *stream,
+                                    dvd_reader_stream_cb *stream_cb )
 {
   struct stat fileinfo;
   int ret, have_css, retval, cdir = -1;
@@ -356,6 +360,13 @@ dvd_reader_t *DVDOpen( const char *ppath )
       int len;
 #endif
 
+  /* Try to open DVD using stream_cb functions */
+  if( stream != NULL && stream_cb != NULL )
+  {
+    have_css = dvdinput_setup();
+    return DVDOpenImageFile( NULL, stream, stream_cb, have_css );
+  }
+
   if( ppath == NULL )
     goto DVDOpen_error;
 
@@ -383,7 +394,7 @@ dvd_reader_t *DVDOpen( const char *ppath )
 
     /* maybe "host:port" url? try opening it with acCeSS library */
     if( strchr(path,':') ) {
-                    ret_val = DVDOpenImageFile( path, have_css );
+                    ret_val = DVDOpenImageFile( path, NULL, NULL, have_css );
                     free(path);
             return ret_val;
     }
@@ -412,7 +423,7 @@ dvd_reader_t *DVDOpen( const char *ppath )
 #endif
     if(!dev_name)
         goto DVDOpen_error;
-    dvd = DVDOpenImageFile( dev_name, have_css );
+    dvd = DVDOpenImageFile( dev_name, NULL, NULL, have_css );
     free( dev_name );
     free(path);
     return dvd;
@@ -503,7 +514,7 @@ dvd_reader_t *DVDOpen( const char *ppath )
                         " mounted on %s for CSS authentication\n",
                         dev_name,
                         s[i].f_mntonname);
-                auth_drive = DVDOpenImageFile( dev_name, have_css );
+                auth_drive = DVDOpenImageFile( dev_name, NULL, NULL, have_css );
                 break;
             }
         }
@@ -516,7 +527,7 @@ dvd_reader_t *DVDOpen( const char *ppath )
                " mounted on %s for CSS authentication\n",
                dev_name,
                fe->fs_file );
-      auth_drive = DVDOpenImageFile( dev_name, have_css );
+      auth_drive = DVDOpenImageFile( dev_name, NULL, NULL, have_css );
     }
 #elif defined(__sun)
     mntfile = fopen( MNTTAB, "r" );
@@ -532,7 +543,7 @@ dvd_reader_t *DVDOpen( const char *ppath )
                    " mounted on %s for CSS authentication\n",
                    dev_name,
                    mp.mnt_mountp );
-          auth_drive = DVDOpenImageFile( dev_name, have_css );
+          auth_drive = DVDOpenImageFile( dev_name, NULL, NULL, have_css );
           break;
         }
       }
@@ -550,7 +561,7 @@ dvd_reader_t *DVDOpen( const char *ppath )
                    " mounted on %s for CSS authentication\n",
                    me->mnt_fsname,
                    me->mnt_dir );
-          auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css );
+          auth_drive = DVDOpenImageFile( me->mnt_fsname, NULL, NULL, have_css );
           dev_name = strdup(me->mnt_fsname);
           break;
         }
@@ -564,7 +575,7 @@ dvd_reader_t *DVDOpen( const char *ppath )
         ( !path[2] ||
           ((path[2] == '\\' || path[2] == '/') && !path[3])))
 #endif
-    auth_drive = DVDOpenImageFile( path, have_css );
+    auth_drive = DVDOpenImageFile( path, NULL, NULL, have_css );
 #endif
 
 #if !defined(_WIN32) && !defined(__OS2__)
@@ -612,6 +623,17 @@ DVDOpen_error:
   return NULL;
 }
 
+dvd_reader_t *DVDOpen( const char *ppath )
+{
+    return DVDOpenCommon( ppath, NULL, NULL );
+}
+
+dvd_reader_t *DVDOpenStream( void *stream,
+                             dvd_reader_stream_cb *stream_cb )
+{
+    return DVDOpenCommon( NULL, stream, stream_cb );
+}
+
 void DVDClose( dvd_reader_t *dvd )
 {
   if( dvd ) {
@@ -725,7 +747,7 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
     return NULL;
   }
 
-  dev = dvdinput_open( full_path );
+  dev = dvdinput_open( full_path, NULL, NULL );
   if( !dev ) {
     fprintf( stderr, "libdvdread:DVDOpenFilePath:dvdinput_open %s failed\n", full_path );
     return NULL;
@@ -837,7 +859,7 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu )
       return NULL;
     }
 
-    dev = dvdinput_open( full_path );
+    dev = dvdinput_open( full_path, NULL, NULL );
     if( dev == NULL ) {
       free( dvd_file );
       return NULL;
@@ -868,7 +890,7 @@ 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 );
+      dvd_file->title_devs[ i ] = dvdinput_open( full_path, NULL, NULL );
       dvdinput_title( dvd_file->title_devs[ i ], 0 );
       dvd_file->filesize += dvd_file->title_sizes[ i ];
     }
diff --git a/src/dvdread/dvd_reader.h b/src/dvdread/dvd_reader.h
index 0e6d395..051eda0 100644
--- a/src/dvdread/dvd_reader.h
+++ b/src/dvdread/dvd_reader.h
@@ -69,6 +69,14 @@ typedef struct dvd_reader_s dvd_reader_t;
  */
 typedef struct dvd_file_s dvd_file_t;
 
+struct dvd_reader_stream_cb
+{
+    int ( *pf_seek )  ( void *p_stream,  uint64_t i_pos);
+    int ( *pf_read )  ( void *p_stream, void* buffer, int i_read);
+    int ( *pf_readv ) ( void *p_stream, void *p_iovec, int i_blocks);
+};
+typedef struct dvd_reader_stream_cb dvd_reader_stream_cb;
+
 /**
  * Public type that is used to provide statistics on a handle.
  */
@@ -81,6 +89,8 @@ typedef struct {
 /**
  * Opens a block device of a DVD-ROM file, or an image file, or a directory
  * name for a mounted DVD or HD copy of a DVD.
+ * The second form of Open function (DVDOpenStream) can be used to
+ * provide custom stream_cb functions to access the DVD (see libdvdcss).
  *
  * If the given file is a block device, or is the mountpoint for a block
  * device, then that device is used for CSS authentication using libdvdcss.
@@ -96,11 +106,15 @@ typedef struct {
  *   path/vts_01_1.vob
  *
  * @param path Specifies the the device, file or directory to be used.
+ * @param stream is a private handle used by stream_cb
+ * @param stream_cb is a struct containing seek and read functions
  * @return If successful a a read handle is returned. Otherwise 0 is returned.
  *
  * dvd = DVDOpen(path);
+ * dvd = DVDOpenStream(stream, &stream_cb);
  */
 dvd_reader_t *DVDOpen( const char * );
+dvd_reader_t *DVDOpenStream( void *, dvd_reader_stream_cb * );
 
 /**
  * Closes and cleans up the DVD reader object.
-- 
2.1.0



More information about the libdvdnav-devel mailing list