[vlc-devel] [PATCH] dvdnav: add Demux submodule

Thomas Guillem thomas at gllm.fr
Thu Mar 12 11:14:14 CET 2015


It allows to use dvdnav via a VLC access.
---
 modules/access/dvdnav.c | 187 +++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 145 insertions(+), 42 deletions(-)

diff --git a/modules/access/dvdnav.c b/modules/access/dvdnav.c
index ad1240a..79ba939 100644
--- a/modules/access/dvdnav.c
+++ b/modules/access/dvdnav.c
@@ -76,7 +76,8 @@
 
 #define LANGUAGE_DEFAULT ("en")
 
-static int  Open ( vlc_object_t * );
+static int  AccessDemuxOpen ( vlc_object_t * );
+static int  DemuxOpen ( vlc_object_t * );
 static void Close( vlc_object_t * );
 
 vlc_module_begin ()
@@ -90,7 +91,14 @@ vlc_module_begin ()
         MENU_TEXT, MENU_LONGTEXT, false )
     set_capability( "access_demux", 5 )
     add_shortcut( "dvd", "dvdnav", "file" )
-    set_callbacks( Open, Close )
+    set_callbacks( AccessDemuxOpen, Close )
+    add_submodule()
+        set_description( N_("DVDnav demuxer") )
+        set_category( CAT_INPUT )
+        set_subcategory( SUBCAT_INPUT_DEMUX )
+        set_capability( "demux", 5 )
+        set_callbacks( DemuxOpen, Close )
+        add_shortcut( "iso" )
 vlc_module_end ()
 
 /* Shall we use libdvdnav's read ahead cache? */
@@ -160,6 +168,7 @@ static void ButtonUpdate( demux_t *, bool );
 
 static void ESNew( demux_t *, int );
 static int ProbeDVD( const char * );
+static int StreamProbeDVD( stream_t * );
 
 static char *DemuxGetLanguageCode( demux_t *p_demux, const char *psz_var );
 
@@ -173,66 +182,43 @@ static int EventIntf( vlc_object_t *, char const *,
                       vlc_value_t, vlc_value_t, void * );
 
 /*****************************************************************************
- * DemuxOpen:
+ * CommonOpen:
  *****************************************************************************/
-static int Open( vlc_object_t *p_this )
+static int CommonOpen( vlc_object_t *p_this, const char *psz_file,
+                       void *p_dvd_stream,
+                       dvdnav_stream_cb *p_dvd_stream_cb )
 {
     demux_t     *p_demux = (demux_t*)p_this;
     demux_sys_t *p_sys;
     dvdnav_t    *p_dvdnav;
     int         i_angle;
-    char        *psz_file;
     char        *psz_code;
-    bool forced = false;
-
-    if( p_demux->psz_access != NULL
-     && !strncmp(p_demux->psz_access, "dvd", 3) )
-        forced = true;
 
-    if( !p_demux->psz_file || !*p_demux->psz_file )
-    {
-        /* Only when selected */
-        if( !forced )
-            return VLC_EGENERIC;
-
-        psz_file = var_InheritString( p_this, "dvd" );
-    }
-    else
-        psz_file = strdup( p_demux->psz_file );
+    if( unlikely( psz_file == NULL &&
+        ( p_dvd_stream == NULL || p_dvd_stream_cb == NULL ) ) )
+        return VLC_EGENERIC;
 
-#if defined( _WIN32 ) || defined( __OS2__ )
-    if( psz_file != NULL )
+    if( p_dvd_stream != NULL )
     {
-        /* Remove trailing backslash, otherwise dvdnav_open will fail */
-        size_t flen = strlen( psz_file );
-        if( flen > 0 && psz_file[flen - 1] == '\\' )
-            psz_file[flen - 1] = '\0';
+        /* Open dvdnav */
+        if( dvdnav_open_stream( &p_dvdnav, p_dvd_stream,
+                                p_dvd_stream_cb ) != DVDNAV_STATUS_OK )
+            p_dvdnav = NULL;
     }
     else
-        psz_file = strdup("");
-#endif
-    if( unlikely(psz_file == NULL) )
-        return VLC_EGENERIC;
-
-    /* Try some simple probing to avoid going through dvdnav_open too often */
-    if( !forced && ProbeDVD( psz_file ) != VLC_SUCCESS )
     {
-        free( psz_file );
-        return VLC_EGENERIC;
+        /* Open dvdnav */
+        const char *psz_path = ToLocale( psz_file );
+        if( dvdnav_open( &p_dvdnav, psz_path ) != DVDNAV_STATUS_OK )
+            p_dvdnav = NULL;
+        LocaleFree( psz_path );
     }
 
-    /* Open dvdnav */
-    const char *psz_path = ToLocale( psz_file );
-    if( dvdnav_open( &p_dvdnav, psz_path ) != DVDNAV_STATUS_OK )
-        p_dvdnav = NULL;
-    LocaleFree( psz_path );
     if( p_dvdnav == NULL )
     {
         msg_Warn( p_demux, "cannot open DVD (%s)", psz_file);
-        free( psz_file );
         return VLC_EGENERIC;
     }
-    free( psz_file );
 
     /* Fill p_demux field */
     DEMUX_INIT_COMMON(); p_sys = p_demux->p_sys;
@@ -370,6 +356,94 @@ static int Open( vlc_object_t *p_this )
 }
 
 /*****************************************************************************
+ * AccessDemuxOpen:
+ *****************************************************************************/
+static int AccessDemuxOpen ( vlc_object_t *p_this )
+{
+    demux_t *p_demux = (demux_t*)p_this;
+    char *psz_file;
+    int i_ret;
+    bool forced = false;
+
+    if( p_demux->psz_access != NULL
+     && !strncmp(p_demux->psz_access, "dvd", 3) )
+        forced = true;
+
+    if( !p_demux->psz_file || !*p_demux->psz_file )
+    {
+        /* Only when selected */
+        if( !forced )
+            return VLC_EGENERIC;
+
+        psz_file = var_InheritString( p_this, "dvd" );
+    }
+    else
+        psz_file = strdup( p_demux->psz_file );
+
+#if defined( _WIN32 ) || defined( __OS2__ )
+    if( psz_file != NULL )
+    {
+        /* Remove trailing backslash, otherwise dvdnav_open will fail */
+        size_t flen = strlen( psz_file );
+        if( flen > 0 && psz_file[flen - 1] == '\\' )
+            psz_file[flen - 1] = '\0';
+    }
+    else
+        psz_file = strdup("");
+#endif
+
+    /* Try some simple probing to avoid going through dvdnav_open too often */
+    if( !forced && psz_file != NULL && ProbeDVD( psz_file ) != VLC_SUCCESS )
+    {
+        free( psz_file );
+        return VLC_EGENERIC;
+    }
+
+    i_ret = CommonOpen( p_this, psz_file, NULL, NULL );
+    free( psz_file );
+    return i_ret;
+}
+
+/*****************************************************************************
+ * dvdnav stream callbacks
+ *****************************************************************************/
+static int stream_cb_seek( void *s, uint64_t pos )
+{
+    return stream_Seek( (stream_t *)s, pos );
+}
+
+static int stream_cb_read( void *s, void* buffer, int size )
+{
+    return stream_Read( (stream_t *)s, buffer, size );
+}
+
+/*****************************************************************************
+ * DemuxOpen:
+ *****************************************************************************/
+static int DemuxOpen ( vlc_object_t *p_this )
+{
+    demux_t *p_demux = (demux_t*)p_this;
+    bool forced = false;
+
+    if( p_demux->psz_access != NULL
+     && !strncmp(p_demux->psz_access, "dvd", 3) )
+        forced = true;
+
+    static dvdnav_stream_cb stream_cb =
+    {
+        .pf_seek = stream_cb_seek,
+        .pf_read = stream_cb_read,
+        .pf_readv = NULL,
+    };
+
+    /* Try some simple probing to avoid going through dvdnav_open too often */
+    if( !forced && StreamProbeDVD( p_demux->s ) != VLC_SUCCESS )
+        return VLC_EGENERIC;
+
+    return CommonOpen( p_this, NULL, p_demux->s, &stream_cb );
+}
+
+/*****************************************************************************
  * Close:
  *****************************************************************************/
 static void Close( vlc_object_t *p_this )
@@ -1482,3 +1556,32 @@ bailout:
     close( fd );
     return ret;
 }
+
+/*****************************************************************************
+ * StreamProbeDVD: very weak probing that avoids going too often into a dvdnav_open()
+ *****************************************************************************/
+static int StreamProbeDVD( stream_t *s )
+{
+    int64_t i_init_pos;
+    int ret = VLC_EGENERIC;
+
+    i_init_pos = stream_Tell( s );
+    /* ISO 9660 volume descriptor */
+    char iso_dsc[6];
+    if( stream_Seek( s, 0x8000 + 1 ) != VLC_SUCCESS
+     || stream_Read( s, iso_dsc, sizeof (iso_dsc) ) < (int)sizeof (iso_dsc)
+     || memcmp( iso_dsc, "CD001\x01", 6 ) )
+        goto bailout;
+
+    /* Try to find the anchor (2 bytes at LBA 256) */
+    uint16_t anchor;
+
+    if( stream_Seek( s, 256 * DVD_VIDEO_LB_LEN ) == VLC_SUCCESS
+     && stream_Read( s, &anchor, 2 ) == 2
+     && GetWLE( &anchor ) == 2 )
+        ret = VLC_SUCCESS; /* Found a potential anchor */
+
+bailout:
+    stream_Seek( s, i_init_pos );
+    return ret;
+}
-- 
2.1.3




More information about the vlc-devel mailing list