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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.