[libdvdcss-devel] [PATCH 1/1] add dvdcss_open_stream

Thomas Guillem tom at gllm.fr
Fri Oct 17 17:43:36 CEST 2014


open a DVD Device using external read/seek callbacks.
---
 src/device.c        | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/dvdcss/dvdcss.h |  12 ++++++
 src/libdvdcss.c     |  33 ++++++++++++++-
 src/libdvdcss.h     |   3 ++
 4 files changed, 161 insertions(+), 1 deletion(-)

diff --git a/src/device.c b/src/device.c
index f78ffc0..f33d0d7 100644
--- a/src/device.c
+++ b/src/device.c
@@ -82,6 +82,10 @@ static int libc_seek  ( dvdcss_t, int );
 static int libc_read  ( dvdcss_t, void *, int );
 static int libc_readv ( dvdcss_t, struct iovec *, int );
 
+static int stream_seek  ( dvdcss_t, int );
+static int stream_read  ( dvdcss_t, void *, int );
+static int stream_readv ( dvdcss_t, struct iovec *, int );
+
 #ifdef WIN32
 static int win2k_open ( dvdcss_t, char const * );
 static int aspi_open  ( dvdcss_t, char const * );
@@ -102,6 +106,9 @@ static int os2_open ( dvdcss_t, char const * );
 
 int _dvdcss_use_ioctls( dvdcss_t dvdcss )
 {
+    if( dvdcss->p_stream )
+        return 0;
+
 #if defined( WIN32 )
     if( dvdcss->b_file )
     {
@@ -200,6 +207,10 @@ void _dvdcss_check ( dvdcss_t dvdcss )
     int i, i_fd;
 #endif
 
+    /* If stream is set, return */
+    if( dvdcss->p_stream )
+        return;
+
     /* If the device name is non-null, return */
     if( dvdcss->psz_device[0] )
     {
@@ -358,6 +369,22 @@ int _dvdcss_open ( dvdcss_t dvdcss )
 
     print_debug( dvdcss, "opening target `%s'", psz_device );
 
+    /* if callback functions are initialized */
+    if( dvdcss->p_stream )
+    {
+#if defined( WIN32 )
+        /* Initialize readv temporary buffer */
+        dvdcss->p_readv_buffer   = NULL;
+        dvdcss->i_readv_buf_size = 0;
+#endif
+
+        print_debug( dvdcss, "using STREAM API for access" );
+        dvdcss->pf_seek  = stream_seek;
+        dvdcss->pf_read  = stream_read;
+        dvdcss->pf_readv = stream_readv;
+        return 0;
+    }
+
 #if defined( WIN32 )
     dvdcss->b_file = 1;
     /* If device is "X:" or "X:\", we are not actually opening a file. */
@@ -710,6 +737,33 @@ static int libc_seek( dvdcss_t dvdcss, int i_blocks )
     return dvdcss->i_pos;
 }
 
+static int stream_seek( dvdcss_t dvdcss, int i_blocks )
+{
+    off_t   i_seek;
+
+    if( !dvdcss->p_stream_cb->pf_seek )
+        return -1;
+
+    if( dvdcss->i_pos == i_blocks )
+    {
+        /* We are already in position */
+        return i_blocks;
+    }
+
+    i_seek = (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE;
+
+    if( dvdcss->p_stream_cb->pf_seek( dvdcss->p_stream, i_seek ) != 0 )
+    {
+        print_error( dvdcss, "seek error" );
+        dvdcss->i_pos = -1;
+        return -1;
+    }
+
+    dvdcss->i_pos = i_seek / DVDCSS_BLOCK_SIZE;
+
+    return dvdcss->i_pos;
+}
+
 #if defined( WIN32 )
 static int win2k_seek( dvdcss_t dvdcss, int i_blocks )
 {
@@ -809,6 +863,43 @@ static int libc_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks )
     return i_ret / DVDCSS_BLOCK_SIZE;
 }
 
+static int stream_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks )
+{
+    off_t i_size, i_ret;
+
+    if( !dvdcss->p_stream_cb->pf_read )
+        return -1;
+
+    i_size = (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE;
+    i_ret = dvdcss->p_stream_cb->pf_read( dvdcss->p_stream, p_buffer, i_size );
+
+    if( i_ret < 0 )
+    {
+        print_error( dvdcss, "read error" );
+        dvdcss->i_pos = -1;
+        return i_ret;
+    }
+
+    /* Handle partial reads */
+    if( i_ret != i_size )
+    {
+        int i_seek;
+
+        dvdcss->i_pos = -1;
+        i_seek = stream_seek( dvdcss, i_ret / DVDCSS_BLOCK_SIZE );
+        if( i_seek < 0 )
+        {
+            return i_seek;
+        }
+
+        /* We have to return now so that i_pos isn't clobbered */
+        return i_ret / DVDCSS_BLOCK_SIZE;
+    }
+
+    dvdcss->i_pos += i_ret / DVDCSS_BLOCK_SIZE;
+    return i_ret / DVDCSS_BLOCK_SIZE;
+}
+
 #if defined( WIN32 )
 static int win2k_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks )
 {
@@ -911,6 +1002,29 @@ static int libc_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks )
 #endif
 }
 
+/*****************************************************************************
+ * stream_readv: vectored read
+ *****************************************************************************/
+static int stream_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks )
+{
+    int i_read;
+
+    if( !dvdcss->p_stream_cb->pf_readv )
+        return -1;
+    
+    i_read = dvdcss->p_stream_cb->pf_readv( dvdcss->p_stream, p_iovec,
+                                                i_blocks );
+
+    if( i_read < 0 )
+    {
+        dvdcss->i_pos = -1;
+        return i_read;
+    }
+
+    dvdcss->i_pos += i_read / DVDCSS_BLOCK_SIZE;
+    return i_read / DVDCSS_BLOCK_SIZE;
+}
+
 #if defined( WIN32 )
 /*****************************************************************************
  * win_readv: vectored read using ReadFile for Win2K and ASPI for win9x
diff --git a/src/dvdcss/dvdcss.h b/src/dvdcss/dvdcss.h
index 7c9c733..973122f 100644
--- a/src/dvdcss/dvdcss.h
+++ b/src/dvdcss/dvdcss.h
@@ -31,6 +31,8 @@
 #define DVDCSS_DVDCSS_H 1
 #endif
 
+#include <stdint.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -38,6 +40,14 @@ extern "C" {
 /** Library instance handle, to be used for each library call. */
 typedef struct dvdcss_s* dvdcss_t;
 
+struct dvdcss_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 dvdcss_stream_cb dvdcss_stream_cb;
+
 
 /** The block size of a DVD. */
 #define DVDCSS_BLOCK_SIZE      2048
@@ -70,6 +80,8 @@ typedef struct dvdcss_s* dvdcss_t;
  * Exported prototypes.
  */
 LIBDVDCSS_EXPORT dvdcss_t dvdcss_open  ( char *psz_target );
+LIBDVDCSS_EXPORT dvdcss_t dvdcss_open_stream( void *p_stream,
+                                              dvdcss_stream_cb *p_stream_cb );
 LIBDVDCSS_EXPORT int      dvdcss_close ( dvdcss_t );
 LIBDVDCSS_EXPORT int      dvdcss_seek  ( dvdcss_t,
                                int i_blocks,
diff --git a/src/libdvdcss.c b/src/libdvdcss.c
index 6c4befc..9b2f64b 100644
--- a/src/libdvdcss.c
+++ b/src/libdvdcss.c
@@ -136,6 +136,8 @@
 #define mkdir(a, b) _mkdir(a)
 #endif
 
+static dvdcss_t dvdcss_open_common ( char *psz_target, void *p_stream,
+                                     dvdcss_stream_cb *p_stream_cb );
 /**
  * \brief Open a DVD device or directory and return a dvdcss instance.
  *
@@ -152,6 +154,27 @@
  */
 LIBDVDCSS_EXPORT dvdcss_t dvdcss_open ( char *psz_target )
 {
+    return dvdcss_open_common( psz_target, NULL, NULL );
+}
+
+/**
+ * \brief Open a DVD device using dvdcss_stream_cb
+ *
+ * \param p_stream a private handle used by p_stream_cb
+ * \param p_stream_cb a struct containing seek and read functions
+ * \return a handle to a dvdcss instance or NULL on error.
+ *
+ * see dvdcss_open
+ */
+LIBDVDCSS_EXPORT dvdcss_t dvdcss_open_stream ( void *p_stream,
+                                               dvdcss_stream_cb *p_stream_cb )
+{
+    return dvdcss_open_common( NULL, p_stream, p_stream_cb );
+}
+
+static dvdcss_t dvdcss_open_common ( char *psz_target, void *p_stream,
+                                     dvdcss_stream_cb *p_stream_cb )
+{
     char psz_buffer[PATH_MAX];
     int i_ret;
 
@@ -164,6 +187,10 @@ LIBDVDCSS_EXPORT dvdcss_t dvdcss_open ( char *psz_target )
 
     dvdcss_t dvdcss;
 
+    if( psz_target == NULL &&
+      ( p_stream == NULL || p_stream_cb == NULL ) )
+        return NULL;
+
     /*
      *  Allocate the library structure
      */
@@ -180,13 +207,17 @@ LIBDVDCSS_EXPORT dvdcss_t dvdcss_open ( char *psz_target )
     dvdcss->i_raw_fd = -1;
 #endif
     dvdcss->p_titles = NULL;
-    dvdcss->psz_device = (char *)strdup( psz_target );
+    dvdcss->psz_device = psz_target != NULL ?
+                         (char *)strdup( psz_target ) : NULL;
     dvdcss->psz_error = "no error";
     dvdcss->i_method = DVDCSS_METHOD_KEY;
     dvdcss->psz_cachefile[0] = '\0';
     dvdcss->b_debug = 0;
     dvdcss->b_errors = 0;
 
+    dvdcss->p_stream = p_stream;
+    dvdcss->p_stream_cb = p_stream_cb;
+
     /*
      *  Find verbosity from DVDCSS_VERBOSE environment variable
      */
diff --git a/src/libdvdcss.h b/src/libdvdcss.h
index e89cff4..2a78414 100644
--- a/src/libdvdcss.h
+++ b/src/libdvdcss.h
@@ -66,6 +66,9 @@ struct dvdcss_s
     int    i_readv_buf_size;
 #endif
 
+    void                *p_stream;
+    dvdcss_stream_cb    *p_stream_cb;
+
 #ifdef DVDCSS_RAW_OPEN
     int    i_raw_fd;
 #endif
-- 
2.1.0



More information about the libdvdcss-devel mailing list