[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