[libdvdcss-devel] [PATCH] Add dvdcss_open_stream() API function
Thomas Guillem
thomas at gllm.fr
Thu Oct 30 14:14:26 CET 2014
Thanks you very much for rebasing it on top of your work.
I didn't have the time yet to rewrite this patch, a bug fix on vlc took
more time than expected.
If I remember correctly, the only point we weren't sure was about seek
offset and read pos.
Use pos/offset in byte or in block (2048, right ?).
On Wed, Oct 29, 2014, at 22:18, Diego Biurrun wrote:
> From: Thomas Guillem <tom at gllm.fr>
>
> This allows opening a DVD device using external read/seek callbacks.
> ---
>
> A fresh version of the patch, rebased on top of my cleanup and with most
> of my review comments addressed so that we have a cleaner basis for
> further discussion.
>
> NEWS | 2 +
> src/device.c | 109
> +++++++++++++++++++++++++++++++++++++++++++++++++++-
> src/dvdcss/dvdcss.h | 12 ++++++
> src/libdvdcss.c | 30 +++++++++++++++
> src/libdvdcss.h | 3 ++
> 5 files changed, 154 insertions(+), 2 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index d3fdaed..e542020 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -7,6 +7,8 @@ Changes between 1.2.13 and 1.3.0:
> - the variable dvdcss_interface_2
> * Support for Android
> * Drop support for HP-UX, Solaris, BeOS, QNX, OS/2, and Windows 9x.
> + * Add dvdcss_open_stream() to public API. This allows installing
> custom
> + callback functions for accessing DVD, e.g. over the network.
> * Miscellaneous cleanups to code, documentation, build system.
>
>
> diff --git a/src/device.c b/src/device.c
> index ed2b710..8b4a50e 100644
> --- a/src/device.c
> +++ b/src/device.c
> @@ -74,6 +74,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, const char * );
> static int win2k_seek ( dvdcss_t, int );
> @@ -83,6 +87,9 @@ static int win2k_readv ( dvdcss_t, struct iovec *, int
> );
>
> int dvdcss_use_ioctls( dvdcss_t dvdcss )
> {
> + if( dvdcss->p_stream )
> + return 0;
> +
> #if defined( WIN32 )
> if( dvdcss->b_file )
> {
> @@ -141,8 +148,8 @@ void dvdcss_check_device ( dvdcss_t dvdcss )
> int i, i_fd;
> #endif
>
> - /* If the device name is non-null, return */
> - if( dvdcss->psz_device[0] )
> + /* If the device name is non-NULL or stream is set, return. */
> + if( dvdcss->psz_device[0] || dvdcss->p_stream )
> {
> return;
> }
> @@ -273,6 +280,16 @@ int dvdcss_open_device ( dvdcss_t dvdcss )
>
> print_debug( dvdcss, "opening target `%s'", psz_device );
>
> + /* if callback functions are initialized */
> + if( dvdcss->p_stream )
> + {
> + 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.
> */
> @@ -446,6 +463,31 @@ 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 = i_blocks * DVDCSS_BLOCK_SIZE;
> +
> + if( !dvdcss->p_stream_cb->pf_seek )
> + return -1;
> +
> + if( dvdcss->i_pos == i_blocks )
> + {
> + /* We are already in position */
> + return i_blocks;
> + }
> +
> + 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_blocks;
> +
> + return dvdcss->i_pos;
> +}
> +
> #if defined( WIN32 )
> static int win2k_seek( dvdcss_t dvdcss, int i_blocks )
> {
> @@ -514,6 +556,46 @@ static int libc_read ( dvdcss_t dvdcss, void
> *p_buffer, int i_blocks )
> return i_ret_blocks;
> }
>
> +static int stream_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks )
> +{
> + off_t i_size, i_ret, i_ret_blocks;
> +
> + i_size = i_blocks * DVDCSS_BLOCK_SIZE;
> +
> + if( !dvdcss->p_stream_cb->pf_read )
> + return -1;
> +
> + 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;
> + }
> +
> + i_ret_blocks = i_ret / DVDCSS_BLOCK_SIZE;
> +
> + /* Handle partial reads */
> + if( i_ret != i_size )
> + {
> + int i_seek;
> +
> + dvdcss->i_pos = -1;
> + i_seek = stream_seek( dvdcss, i_ret_blocks );
> + if( i_seek < 0 )
> + {
> + return i_seek;
> + }
> +
> + /* We have to return now so that i_pos isn't clobbered */
> + return i_ret_blocks;
> + }
> +
> + dvdcss->i_pos += i_ret_blocks;
> + return i_ret_blocks;
> +}
> +
> #if defined( WIN32 )
> static int win2k_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks )
> {
> @@ -605,6 +687,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 )
> /*****************************************************************************
> * win2k_readv: vectored read using ReadFile for Win2K
> diff --git a/src/dvdcss/dvdcss.h b/src/dvdcss/dvdcss.h
> index 64f95cf..5e1a77b 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
> @@ -73,6 +83,8 @@ typedef struct dvdcss_s* dvdcss_t;
> * Exported prototypes.
> */
> LIBDVDCSS_EXPORT dvdcss_t dvdcss_open ( const 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 ab5b665..6d622ac 100644
> --- a/src/libdvdcss.c
> +++ b/src/libdvdcss.c
> @@ -135,6 +135,8 @@
> #define mkdir(a, b) _mkdir(a)
> #endif
>
> +static dvdcss_t dvdcss_open_common ( const char *psz_target, void
> *p_stream,
> + dvdcss_stream_cb *p_stream_cb );
> static void set_verbosity( dvdcss_t dvdcss )
> {
> const char *psz_verbose = getenv( "DVDCSS_VERBOSE" );
> @@ -416,6 +418,27 @@ static void create_cache_dir( dvdcss_t dvdcss, const
> char *psz_cache )
> */
> LIBDVDCSS_EXPORT dvdcss_t dvdcss_open ( const 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 ( const char *psz_target, void
> *p_stream,
> + dvdcss_stream_cb *p_stream_cb )
> +{
> int i_ret;
>
> const char *psz_cache;
> @@ -423,6 +446,10 @@ LIBDVDCSS_EXPORT dvdcss_t dvdcss_open ( const char
> *psz_target )
> const char *psz_raw_device = getenv( "DVDCSS_RAW_DEVICE" );
> #endif
>
> + if( psz_target == NULL &&
> + ( p_stream == NULL || p_stream_cb == NULL ) )
> + return NULL;
> +
> /* Allocate the library structure */
> dvdcss_t dvdcss = malloc( sizeof( struct dvdcss_s ) );
> if( dvdcss == NULL )
> @@ -440,6 +467,9 @@ LIBDVDCSS_EXPORT dvdcss_t dvdcss_open ( const char
> *psz_target )
> dvdcss->i_method = DVDCSS_METHOD_KEY;
> dvdcss->psz_cachefile[0] = '\0';
>
> + dvdcss->p_stream = p_stream;
> + dvdcss->p_stream_cb = p_stream_cb;
> +
> /* Set library verbosity from DVDCSS_VERBOSE environment variable.
> */
> set_verbosity( dvdcss );
>
> diff --git a/src/libdvdcss.h b/src/libdvdcss.h
> index 4f1f4af..f2368fb 100644
> --- a/src/libdvdcss.h
> +++ b/src/libdvdcss.h
> @@ -72,6 +72,9 @@ struct dvdcss_s
> int i_readv_buf_size;
> #endif /* WIN32 */
>
> + void *p_stream;
> + dvdcss_stream_cb *p_stream_cb;
> +
> #ifdef DVDCSS_RAW_OPEN
> int i_raw_fd;
> #endif
> --
> 1.9.1
>
> _______________________________________________
> libdvdcss-devel mailing list
> libdvdcss-devel at videolan.org
> https://mailman.videolan.org/listinfo/libdvdcss-devel
More information about the libdvdcss-devel
mailing list