Re: [libdvdcss-devel] [PATCH] Add dvdcss_open_stream() API function
Thomas Guillem <[email protected]>
| Newsgroups | gmane.comp.video.videolan.libdvdcss,gmane.comp.video.videolan.libdvdcss.devel |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> > > 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 > [email protected] > https://mailman.videolan.org/listinfo/libdvdcss-devel _______________________________________________ libdvdcss-devel mailing list [email protected] https://mailman.videolan.org/listinfo/libdvdcss-devel