]> git.sesse.net Git - vlc/commitdiff
* modules/access/dvdread, modules/access/dvdread.c:
authorGildas Bazin <gbazin@videolan.org>
Fri, 25 Jun 2004 00:09:41 +0000 (00:09 +0000)
committerGildas Bazin <gbazin@videolan.org>
Fri, 25 Jun 2004 00:09:41 +0000 (00:09 +0000)
  + major rewrite of the dvdread module.
  + dvdread is now an access_demux module.

configure.ac
modules/access/Modules.am
modules/access/dvdread.c [new file with mode: 0644]
modules/access/dvdread/Modules.am [deleted file]
modules/access/dvdread/dvdread.c [deleted file]
modules/access/dvdread/input.c [deleted file]
modules/access/dvdread/input.h [deleted file]

index c43998b8dec3829771b748a7758560553ed33e39..e02b0a8375d27b7c4083b0a493ab27231c4126f4 100644 (file)
@@ -1211,71 +1211,70 @@ if test "${enable_livedotcom}" = "yes"; then
   fi
 fi
 
-dnl 
-dnl dnl
-dnl dnl dvdread module: check for libdvdread
-dnl dnl
-dnl AC_ARG_ENABLE(dvdread,
-dnl [  --enable-dvdread        dvdread input module (default disabled)])
-dnl if test "${enable_dvdread}" != "no"
-dnl then
-dnl   AC_ARG_WITH(dvdread,
-dnl   [    --with-dvdread=PATH    libdvdread headers and libraries])
-dnl   AC_ARG_WITH(dvdread-tree,
-dnl   [    --with-dvdread-tree=PATH libdvdread tree for static linking])
-dnl   if test -z "${with_dvdread}"
-dnl   then
-dnl     if test -z "${with_dvdread_tree}"
-dnl     then
-dnl       AC_CHECK_HEADERS(dvdread/dvd_reader.h,
-dnl         [ AX_ADD_PLUGINS([dvdread])
-dnl           AX_ADD_LDFLAGS([dvdread],[-ldvdread ${LDFLAGS_dvdcss}])
-dnl         ],[
-dnl           if test -n "${enable_dvdread}"
-dnl           then
-dnl             AC_MSG_WARN([Please get libdvdread from http://www.dtek.chalmers.se/groups/dvd/downloads.shtml])
-dnl             AC_MSG_ERROR([cannot find libdvdread headers])
-dnl           fi
-dnl         ])
-dnl     else
-dnl       AC_MSG_CHECKING(for libdvdread.a in ${with_dvdread_tree})
-dnl       real_dvdread_tree="`cd ${with_dvdread_tree} 2>/dev/null && pwd`"
-dnl       if test -z "${real_dvdread_tree}"
-dnl       then
-dnl         dnl  The given directory can't be found
-dnl         AC_MSG_RESULT(no)
-dnl         AC_MSG_ERROR([cannot cd to ${with_dvdread_tree}])
-dnl       fi
-dnl       if test -f "${real_dvdread_tree}/dvdread/.libs/libdvdread.a"
-dnl       then
-dnl         dnl  Use a custom libdvdread
-dnl         AC_MSG_RESULT(${real_dvdread_tree}/dvdread/.libs/libdvdread.a)
-dnl         AX_ADD_BUILTINS([dvdread])
-dnl         AX_ADD_LDFLAGS([dvdread],[-L${real_dvdread_tree}/dvdread/.libs -ldvdread ${LDFLAGS_dvdcss}])
-dnl         AX_ADD_CPPFLAGS([dvdread],[-I${real_dvdread_tree}])
-dnl       else
-dnl         dnl  The given libdvdread wasn't built
-dnl         AC_MSG_RESULT(no)
-dnl         AC_MSG_ERROR([cannot find ${real_dvdread_tree}/dvdread/.libs/libdvdread.a, make sure you compiled libdvdread in ${with_dvdread_tree}])
-dnl       fi
-dnl     fi
-dnl   else
-dnl     AC_MSG_CHECKING(for dvdread headers in ${with_dvdread})
-dnl     if test -f ${with_dvdread}/include/dvdread/dvd_reader.h
-dnl     then
-dnl       dnl  Use ${with_dvdread}/include/dvdread/dvd_reader.h
-dnl       AC_MSG_RESULT(yes)
-dnl       AX_ADD_PLUGINS([dvdread])
-dnl       AX_ADD_LDFLAGS([dvdread],[-L${with_dvdread}/lib -ldvdread ${LDFLAGS_dvdcss}])
-dnl       AX_ADD_CPPFLAGS([dvdread],[-I${with_dvdread}/include])
-dnl     else
-dnl       dnl  No libdvdread could be found, sorry
-dnl       AC_MSG_RESULT(no)
-dnl       AC_MSG_ERROR([cannot find ${with_dvdread}/include/dvdread/dvd_reader.h])
-dnl     fi
-dnl   fi
-dnl fi
-dnl 
+
+dnl
+dnl dvdread module: check for libdvdread
+dnl
+AC_ARG_ENABLE(dvdread,
+[  --enable-dvdread        dvdread input module (default disabled)])
+if test "${enable_dvdread}" != "no"
+then
+  AC_ARG_WITH(dvdread,
+  [    --with-dvdread=PATH    libdvdread headers and libraries])
+  AC_ARG_WITH(dvdread-tree,
+  [    --with-dvdread-tree=PATH libdvdread tree for static linking])
+  if test -z "${with_dvdread}"
+  then
+    if test -z "${with_dvdread_tree}"
+    then
+      AC_CHECK_HEADERS(dvdread/dvd_reader.h,
+        [ AX_ADD_PLUGINS([dvdread])
+          AX_ADD_LDFLAGS([dvdread],[-ldvdread ${LDFLAGS_dvdcss}])
+        ],[
+          if test -n "${enable_dvdread}"
+          then
+            AC_MSG_WARN([Please get libdvdread from http://www.dtek.chalmers.se/groups/dvd/downloads.shtml])
+            AC_MSG_ERROR([cannot find libdvdread headers])
+          fi
+        ])
+    else
+      AC_MSG_CHECKING(for libdvdread.a in ${with_dvdread_tree})
+      real_dvdread_tree="`cd ${with_dvdread_tree} 2>/dev/null && pwd`"
+      if test -z "${real_dvdread_tree}"
+      then
+        dnl  The given directory can't be found
+        AC_MSG_RESULT(no)
+        AC_MSG_ERROR([cannot cd to ${with_dvdread_tree}])
+      fi
+      if test -f "${real_dvdread_tree}/dvdread/.libs/libdvdread.a"
+      then
+        dnl  Use a custom libdvdread
+        AC_MSG_RESULT(${real_dvdread_tree}/dvdread/.libs/libdvdread.a)
+        AX_ADD_BUILTINS([dvdread])
+        AX_ADD_LDFLAGS([dvdread],[-L${real_dvdread_tree}/dvdread/.libs -ldvdread ${LDFLAGS_dvdcss}])
+        AX_ADD_CPPFLAGS([dvdread],[-I${real_dvdread_tree}])
+      else
+        dnl  The given libdvdread wasn't built
+        AC_MSG_RESULT(no)
+        AC_MSG_ERROR([cannot find ${real_dvdread_tree}/dvdread/.libs/libdvdread.a, make sure you compiled libdvdread in ${with_dvdread_tree}])
+      fi
+    fi
+  else
+    AC_MSG_CHECKING(for dvdread headers in ${with_dvdread})
+    if test -f ${with_dvdread}/include/dvdread/dvd_reader.h
+    then
+      dnl  Use ${with_dvdread}/include/dvdread/dvd_reader.h
+      AC_MSG_RESULT(yes)
+      AX_ADD_PLUGINS([dvdread])
+      AX_ADD_LDFLAGS([dvdread],[-L${with_dvdread}/lib -ldvdread ${LDFLAGS_dvdcss}])
+      AX_ADD_CPPFLAGS([dvdread],[-I${with_dvdread}/include])
+    else
+      dnl  No libdvdread could be found, sorry
+      AC_MSG_RESULT(no)
+      AC_MSG_ERROR([cannot find ${with_dvdread}/include/dvdread/dvd_reader.h])
+    fi
+  fi
+fi
 
 dnl
 dnl  libdvdnav plugin
index 12dfb04c951e24582dd8049d2600eccbef7d3421..698415b2bb0a65d1758db41c2ef32a1de61c01b1 100644 (file)
@@ -4,8 +4,8 @@ SOURCES_access_udp = udp.c
 SOURCES_access_tcp = tcp.c
 SOURCES_access_http = http.c
 SOURCES_access_ftp = ftp.c
+SOURCES_dvdread = dvdread.c
 SOURCES_slp = slp.c
-SOURCES_access2 = access2.c
 SOURCES_cdda = \
         cdda.c \
         vcd/cdrom.c \
diff --git a/modules/access/dvdread.c b/modules/access/dvdread.c
new file mode 100644 (file)
index 0000000..3140680
--- /dev/null
@@ -0,0 +1,1269 @@
+/*****************************************************************************
+ * dvdread.c : DvdRead input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001-2004 VideoLAN
+ * $Id$
+ *
+ * Authors: Stéphane Borel <stef@via.ecp.fr>
+ *          Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <string.h>                                              /* strdup() */
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include "iso_lang.h"
+
+#include "../demux/ps.h"
+
+#ifdef HAVE_UNISTD_H
+#   include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#include <dvdread/dvd_reader.h>
+#include <dvdread/ifo_types.h>
+#include <dvdread/ifo_read.h>
+#include <dvdread/nav_read.h>
+#include <dvdread/nav_print.h>
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define CACHING_TEXT N_("caching value in ms")
+#define CACHING_LONGTEXT N_( \
+    "Allows you to modify the default caching value for DVDread streams. " \
+    "This value should be set in millisecond units." )
+
+#define CSSMETHOD_TEXT N_("Method used by libdvdcss for decryption")
+#define CSSMETHOD_LONGTEXT N_( \
+    "Set the method used by libdvdcss for key decryption.\n" \
+    "title: decrypted title key is guessed from the encrypted sectors of " \
+           "the stream. Thus it should work with a file as well as the " \
+           "DVD device. But it sometimes takes much time to decrypt a title " \
+           "key and may even fail. With this method, the key is only checked "\
+           "at the beginning of each title, so it won't work if the key " \
+           "changes in the middle of a title.\n" \
+    "disc: the disc key is first cracked, then all title keys can be " \
+           "decrypted instantly, which allows us to check them often.\n" \
+    "key: the same as \"disc\" if you don't have a file with player keys " \
+           "at compilation time. If you do, the decryption of the disc key " \
+           "will be faster with this method. It is the one that was used by " \
+           "libcss.\n" \
+    "The default method is: key.")
+
+static char *psz_css_list[] = { "title", "disc", "key" };
+static char *psz_css_list_text[] = { N_("title"), N_("Disc"), N_("Key") };
+
+static int  Open ( vlc_object_t * );
+static void Close( vlc_object_t * );
+
+vlc_module_begin();
+    set_description( _("DVDRead Input") );
+    add_integer( "dvdread-caching", DEFAULT_PTS_DELAY / 1000, NULL,
+        CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
+    add_string( "dvdread-css-method", NULL, NULL, CSSMETHOD_TEXT,
+                CSSMETHOD_LONGTEXT, VLC_TRUE );
+        change_string_list( psz_css_list, psz_css_list_text, 0 );
+    set_capability( "access_demux", 0 );
+    add_shortcut( "dvd" );
+    add_shortcut( "dvdread" );
+    set_callbacks( Open, Close );
+vlc_module_end();
+
+/* how many blocks DVDRead will read in each loop */
+#define DVD_BLOCK_READ_ONCE 64
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+
+struct demux_sys_t
+{
+    /* DVDRead state */
+    dvd_reader_t *p_dvdread;
+    dvd_file_t   *p_title;
+
+    ifo_handle_t *p_vmg_file;
+    ifo_handle_t *p_vts_file;
+
+    unsigned int i_title;
+    unsigned int i_chapter, i_chapters;
+    unsigned int i_angle, i_angles;
+
+    tt_srpt_t    *p_tt_srpt;
+    pgc_t        *p_cur_pgc;
+
+    dsi_t        dsi_pack;
+
+    int          i_ttn;
+
+    unsigned int i_pack_len;
+    unsigned int i_cur_block;
+    unsigned int i_next_vobu;
+
+    /* Current title start/end blocks */
+    unsigned int i_title_start_block;
+    unsigned int i_title_end_block;
+    unsigned int i_title_blocks;
+    unsigned int i_title_offset;
+
+    unsigned int i_title_start_cell;
+    unsigned int i_cur_cell;
+    unsigned int i_next_cell;
+
+    /* track */
+    ps_track_t  tk[PS_TK_COUNT];
+
+    /* for spu variables */
+    input_thread_t *p_input;
+
+    /* FIXME */
+    uint8_t     alpha[4];
+    uint32_t    clut[16];
+
+    /* */
+    int i_aspect;
+
+    int           i_titles;
+    input_title_t **titles;
+};
+
+static char *ParseCL( vlc_object_t *, char *, vlc_bool_t, int *, int *, int *);
+
+static int Control   ( demux_t *, int, va_list );
+static int Demux     ( demux_t * );
+static int DemuxBlock( demux_t *, uint8_t *, int );
+
+enum
+{
+    AR_SQUARE_PICTURE = 1,                          /* square pixels */
+    AR_3_4_PICTURE    = 2,                       /* 3:4 picture (TV) */
+    AR_16_9_PICTURE   = 3,             /* 16:9 picture (wide screen) */
+    AR_221_1_PICTURE  = 4,                 /* 2.21:1 picture (movie) */
+};
+
+static void DemuxTitles( demux_t *, int *, int *, int * );
+static void ESNew( demux_t *, int, int );
+
+static int  DvdReadSetArea  ( demux_t *, int, int, int );
+static void DvdReadSeek     ( demux_t *, int );
+static void DvdReadHandleDSI( demux_t *, uint8_t * );
+static void DvdReadFindCell ( demux_t * );
+
+/*****************************************************************************
+ * Open:
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+    demux_t      *p_demux = (demux_t*)p_this;
+    demux_sys_t  *p_sys;
+    int          i_title, i_chapter, i_angle;
+    char         *psz_name;
+    char         *psz_dvdcss_env;
+    dvd_reader_t *p_dvdread;
+    ifo_handle_t *p_vmg_file;
+
+    psz_name = ParseCL( VLC_OBJECT(p_demux), p_demux->psz_path, VLC_TRUE,
+                        &i_title, &i_chapter, &i_angle );
+    if( !psz_name )
+    {
+        return VLC_EGENERIC;
+    }
+
+    /* Override environment variable DVDCSS_METHOD with config option
+     * (FIXME: this creates a small memory leak) */
+    psz_dvdcss_env = config_GetPsz( p_demux, "dvdread-css-method" );
+    if( psz_dvdcss_env && *psz_dvdcss_env )
+    {
+        char *psz_env;
+
+        psz_env = malloc( strlen("DVDCSS_METHOD=") +
+                          strlen( psz_dvdcss_env ) + 1 );
+
+        if( !psz_env )
+        {
+            free( psz_dvdcss_env );
+            return VLC_ENOMEM;
+        }
+
+        sprintf( psz_env, "%s%s", "DVDCSS_METHOD=", psz_dvdcss_env );
+
+        putenv( psz_env );
+    }
+    if( psz_dvdcss_env ) free( psz_dvdcss_env );
+
+    /* Open dvdread */
+    if( !(p_dvdread = DVDOpen( psz_name )) )
+    {
+        msg_Err( p_demux, "DVDRead cannot open source: %s", psz_name );
+        free( psz_name );
+        return VLC_EGENERIC;
+    }
+    free( psz_name );
+
+    /* Ifo allocation & initialisation */
+    if( !( p_vmg_file = ifoOpen( p_dvdread, 0 ) ) )
+    {
+        msg_Warn( p_demux, "cannot open VMG info" );
+        return VLC_EGENERIC;
+    }
+    msg_Dbg( p_demux, "VMG opened" );
+
+    /* Fill p_demux field */
+    p_demux->pf_demux = Demux;
+    p_demux->pf_control = Control;
+    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
+    memset( p_sys, 0, sizeof( demux_sys_t ) );
+
+    ps_track_init( p_sys->tk );
+    p_sys->i_aspect = -1;
+
+    p_sys->p_dvdread = p_dvdread;
+    p_sys->p_vmg_file = p_vmg_file;
+    p_sys->p_title = NULL;
+    p_sys->p_vts_file = NULL;
+
+    p_sys->i_title = p_sys->i_chapter = -1;
+    p_sys->i_angle = i_angle;
+
+    DemuxTitles( p_demux, &i_title, &i_chapter, &i_angle );
+
+    DvdReadSetArea( p_demux, i_title - 1, i_chapter, i_angle );
+
+    /* Update default_pts to a suitable value for dvdread access */
+    var_Create( p_demux, "dvdread-caching",
+                VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close:
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+    demux_t     *p_demux = (demux_t*)p_this;
+    demux_sys_t *p_sys = p_demux->p_sys;
+    int i;
+
+    for( i = 0; i < PS_TK_COUNT; i++ )
+    {
+        ps_track_t *tk = &p_sys->tk[i];
+        if( tk->b_seen )
+        {
+            es_format_Clean( &tk->fmt );
+            if( tk->es ) es_out_Del( p_demux->out, tk->es );
+        }
+    }
+
+    /* Close libdvdread */
+    if( p_sys->p_title ) DVDCloseFile( p_sys->p_title );
+    if( p_sys->p_vts_file ) ifoClose( p_sys->p_vts_file );
+    if( p_sys->p_vmg_file ) ifoClose( p_sys->p_vmg_file );
+    DVDClose( p_sys->p_dvdread );
+
+    free( p_sys );
+}
+
+/*****************************************************************************
+ * Control:
+ *****************************************************************************/
+static int Control( demux_t *p_demux, int i_query, va_list args )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    double f, *pf;
+    vlc_bool_t *pb;
+    int64_t *pi64;
+    input_title_t ***ppp_title;
+    int *pi_int;
+    int i;
+
+    switch( i_query )
+    {
+        case DEMUX_GET_POSITION:
+        {
+            pf = (double*) va_arg( args, double* );
+
+            if( p_sys->i_title_blocks > 0 )
+                *pf = (double)p_sys->i_title_offset / p_sys->i_title_blocks;
+            else
+                *pf = 0.0;
+
+            return VLC_SUCCESS;
+        }
+        case DEMUX_SET_POSITION:
+        {
+            f = (double)va_arg( args, double );
+
+            DvdReadSeek( p_demux, f * p_sys->i_title_blocks );
+
+            return VLC_SUCCESS;
+        }
+
+        /* Special for access_demux */
+        case DEMUX_CAN_PAUSE:
+        case DEMUX_CAN_CONTROL_PACE:
+            /* TODO */
+            pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
+            *pb = VLC_TRUE;
+            return VLC_SUCCESS;
+
+        case DEMUX_SET_PAUSE_STATE:
+            return VLC_SUCCESS;
+
+        case DEMUX_GET_TITLE_INFO:
+            ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
+            pi_int    = (int*)va_arg( args, int* );
+
+            /* Duplicate title infos */
+            *pi_int = p_sys->i_titles;
+            *ppp_title = malloc( sizeof(input_title_t **) * p_sys->i_titles );
+            for( i = 0; i < p_sys->i_titles; i++ )
+            {
+                (*ppp_title)[i] = vlc_input_title_Duplicate(p_sys->titles[i]);
+            }
+            return VLC_SUCCESS;
+
+        case DEMUX_SET_TITLE:
+            i = (int)va_arg( args, int );
+            if( DvdReadSetArea( p_demux, i, 0, -1 ) != VLC_SUCCESS )
+            {
+                msg_Warn( p_demux, "cannot set title/chapter" );
+                return VLC_EGENERIC;
+            }
+            p_demux->info.i_update |=
+                INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
+            p_demux->info.i_title = i;
+            p_demux->info.i_seekpoint = 0;
+            return VLC_SUCCESS;
+
+        case DEMUX_SET_SEEKPOINT:
+            i = (int)va_arg( args, int );
+            if( DvdReadSetArea( p_demux, -1, i, -1 ) != VLC_SUCCESS )
+            {
+                msg_Warn( p_demux, "cannot set title/chapter" );
+                return VLC_EGENERIC;
+            }
+            p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
+            p_demux->info.i_seekpoint = i;
+            return VLC_SUCCESS;
+
+        case DEMUX_GET_PTS_DELAY:
+            pi64 = (int64_t*)va_arg( args, int64_t * );
+            *pi64 = (int64_t)var_GetInteger( p_demux, "dvdread-caching" )*1000;
+            return VLC_SUCCESS;
+
+        /* TODO implement others */
+        default:
+            return VLC_EGENERIC;
+    }
+}
+
+/*****************************************************************************
+ * Demux:
+ *****************************************************************************/
+static int Demux( demux_t *p_demux )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+
+    uint8_t p_buffer[DVD_VIDEO_LB_LEN * DVD_BLOCK_READ_ONCE];
+    int i_blocks_once, i_read;
+    int i;
+
+    /*
+     * Playback by cell in this pgc, starting at the cell for our chapter.
+     */
+
+    /*
+     * Check end of pack, and select the following one
+     */
+    if( !p_sys->i_pack_len )
+    {
+        /* Read NAV packet */
+        if( DVDReadBlocks( p_sys->p_title, p_sys->i_next_vobu,
+                           1, p_buffer ) != 1 )
+        {
+            msg_Err( p_demux, "read failed for block %d", p_sys->i_next_vobu );
+            return -1;
+        }
+
+        /* Basic check to be sure we don't have a empty title
+         * go to next title if so */
+        //assert( p_buffer[41] == 0xbf && p_buffer[1027] == 0xbf );
+
+        /* Parse the contained dsi packet */
+        DvdReadHandleDSI( p_demux, p_buffer );
+
+        /* End of title */
+        if( p_sys->i_next_vobu > p_sys->i_title_end_block )
+        {
+            if( p_sys->i_title + 1 >= p_sys->i_titles ) return 0; /* EOF */
+
+            DvdReadSetArea( p_demux, p_sys->i_title + 1, 0, -1 );
+        }
+
+        if( p_sys->i_pack_len <= 0 )
+        {
+            msg_Err( p_demux, "i_pack_len <= 0. This shouldn't happen!" );
+            return 0; /* EOF */
+        }
+
+        /* FIXME: Ugly kludge: we send the pack block to the input for it
+         * sometimes has a zero scr and restart the sync */
+        p_sys->i_cur_block++;
+        p_sys->i_title_offset++;
+
+        DemuxBlock( p_demux, p_buffer, DVD_VIDEO_LB_LEN );
+    }
+
+    if( p_sys->i_cur_block > p_sys->i_title_end_block )
+    {
+        if( p_sys->i_title + 1 >= p_sys->i_titles ) return 0; /* EOF */
+
+        DvdReadSetArea( p_demux, p_sys->i_title + 1, 0, -1 );
+    }
+
+    /*
+     * Read actual data
+     */
+    i_blocks_once = __MIN( p_sys->i_pack_len, DVD_BLOCK_READ_ONCE );
+    p_sys->i_pack_len -= i_blocks_once;
+
+    /* Reads from DVD */
+    i_read = DVDReadBlocks( p_sys->p_title, p_sys->i_cur_block,
+                            i_blocks_once, p_buffer );
+    if( i_read != i_blocks_once )
+    {
+        msg_Err( p_demux, "read failed for %d/%d blocks at 0x%02x",
+                 i_read, i_blocks_once, p_sys->i_cur_block );
+        return -1;
+    }
+
+    p_sys->i_cur_block += i_read;
+    p_sys->i_title_offset += i_read;
+
+#if 0
+    msg_Dbg( p_demux, "i_blocks: %d len: %d current: 0x%02x",
+             i_read, p_sys->i_pack_len, p_sys->i_cur_block );
+#endif
+
+    for( i = 0; i < i_read; i++ )
+    {
+        DemuxBlock( p_demux, p_buffer + i * DVD_VIDEO_LB_LEN,
+                    DVD_VIDEO_LB_LEN );
+    }
+
+#undef p_pgc
+
+    return 1;
+}
+
+/*****************************************************************************
+ * DemuxBlock: demux a given block
+ *****************************************************************************/
+static int DemuxBlock( demux_t *p_demux, uint8_t *pkt, int i_pkt )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    uint8_t     *p = pkt;
+
+    while( p < &pkt[i_pkt] )
+    {
+        int i_size = ps_pkt_size( p, &pkt[i_pkt] - p );
+        block_t *p_pkt;
+        if( i_size <= 0 )
+        {
+            break;
+        }
+
+        /* Create a block */
+        p_pkt = block_New( p_demux, i_size );
+        memcpy( p_pkt->p_buffer, p, i_size);
+
+        /* Parse it and send it */
+        switch( 0x100 | p[3] )
+        {
+        case 0x1b9:
+        case 0x1bb:
+        case 0x1bc:
+
+#ifdef DVDREAD_DEBUG
+            if( p[3] == 0xbc )
+            {
+                msg_Warn( p_demux, "received a PSM packet" );
+            }
+            else if( p[3] == 0xbb )
+            {
+                msg_Warn( p_demux, "received a SYSTEM packet" );
+            }
+#endif
+            block_Release( p_pkt );
+            break;
+
+        case 0x1ba:
+        {
+            int64_t i_scr;
+            int i_mux_rate;
+            if( !ps_pkt_parse_pack( p_pkt, &i_scr, &i_mux_rate ) )
+            {
+                es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_scr );
+            }
+            block_Release( p_pkt );
+            break;
+        }
+        default:
+        {
+            int i_id = ps_pkt_id( p_pkt );
+            if( i_id >= 0xc0 )
+            {
+                ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
+
+                if( !tk->b_seen )
+                {
+                    ESNew( p_demux, i_id, 0 );
+                }
+                if( tk->b_seen && tk->es &&
+                    !ps_pkt_parse_pes( p_pkt, tk->i_skip ) )
+                {
+                    es_out_Send( p_demux->out, tk->es, p_pkt );
+                }
+                else
+                {
+                    block_Release( p_pkt );
+                }
+            }
+            else
+            {
+                block_Release( p_pkt );
+            }
+            break;
+        }
+        }
+
+        p += i_size;
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * ESNew: register a new elementary stream
+ *****************************************************************************/
+static void ESNew( demux_t *p_demux, int i_id, int i_lang )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    ps_track_t  *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
+    char psz_language[3];
+
+    if( tk->b_seen ) return;
+
+    if( ps_track_fill( tk, i_id ) )
+    {
+        msg_Warn( p_demux, "unknown codec for id=0x%x", i_id );
+        return;
+    }
+
+    psz_language[0] = psz_language[1] = psz_language[2] = 0;
+    if( i_lang && i_lang != 0xffff )
+    {
+        psz_language[0] = (i_lang >> 8)&0xff;
+        psz_language[1] = (i_lang     )&0xff;
+    }
+
+    /* Add a new ES */
+    if( tk->fmt.i_cat == VIDEO_ES )
+    {
+        if( p_sys->i_aspect >= 0 )
+        {
+            tk->fmt.video.i_aspect = p_sys->i_aspect;
+        }
+    }
+    else if( tk->fmt.i_cat == AUDIO_ES )
+    {
+        int i_audio = -1;
+        /* find the audio number PLEASE find another way */
+        if( (i_id&0xbdf8) == 0xbd88 )       /* dts */
+        {
+            i_audio = i_id&0x07;
+        }
+        else if( (i_id&0xbdf0) == 0xbd80 )  /* a52 */
+        {
+            i_audio = i_id&0xf;
+        }
+        else if( (i_id&0xbdf0) == 0xbda0 )  /* lpcm */
+        {
+            i_audio = i_id&0x1f;
+        }
+        else if( ( i_id&0xe0 ) == 0xc0 )    /* mpga */
+        {
+            i_audio = i_id&0x1f;
+        }
+
+        if( psz_language[0] ) tk->fmt.psz_language = strdup( psz_language );
+    }
+    else if( tk->fmt.i_cat == SPU_ES )
+    {
+        /* Palette */
+        tk->fmt.subs.spu.palette[0] = 0xBeef;
+        memcpy( &tk->fmt.subs.spu.palette[1], p_sys->clut,
+                16 * sizeof( uint32_t ) );
+
+        if( psz_language[0] ) tk->fmt.psz_language = strdup( psz_language );
+    }
+
+    tk->es = es_out_Add( p_demux->out, &tk->fmt );
+    tk->b_seen = VLC_TRUE;
+}
+
+/*****************************************************************************
+ * DvdReadSetArea: initialize input data for title x, chapter y.
+ * It should be called for each user navigation request.
+ *****************************************************************************
+ * Take care that i_title and i_chapter start from 0.
+ *****************************************************************************/
+static int DvdReadSetArea( demux_t *p_demux, int i_title, int i_chapter,
+                           int i_angle )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    int         pgc_id = 0;
+    int         pgn = 0;
+    int         i;
+    vlc_value_t val;
+
+#define p_pgc p_sys->p_cur_pgc
+#define p_vmg p_sys->p_vmg_file
+#define p_vts p_sys->p_vts_file
+
+    if( i_title >= 0 && i_title < p_sys->i_titles &&
+        i_title != p_sys->i_title )
+    {
+        int i_start_cell, i_end_cell;
+
+        if( p_sys->p_title != NULL ) DVDCloseFile( p_sys->p_title );
+        if( p_vts != NULL ) ifoClose( p_vts );
+        p_sys->i_title = i_title;
+
+        /*
+         *  We have to load all title information
+         */
+        msg_Dbg( p_demux, "open VTS %d, for title %d",
+                 p_vmg->tt_srpt->title[i_title].title_set_nr, i_title + 1 );
+
+        /* Ifo vts */
+        if( !( p_vts = ifoOpen( p_sys->p_dvdread,
+               p_vmg->tt_srpt->title[i_title].title_set_nr ) ) )
+        {
+            msg_Err( p_demux, "fatal error in vts ifo" );
+            return VLC_EGENERIC;
+        }
+
+        /* Title position inside the selected vts */
+        p_sys->i_ttn = p_vmg->tt_srpt->title[i_title].vts_ttn;
+
+        /* Find title start/end */
+        pgc_id = p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].ptt[0].pgcn;
+        pgn = p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].ptt[0].pgn;
+        p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
+
+        p_sys->i_title_start_cell =
+            i_start_cell = p_pgc->program_map[pgn - 1] - 1;
+        p_sys->i_title_start_block =
+            p_pgc->cell_playback[i_start_cell].first_sector;
+
+        i_end_cell = p_pgc->nr_of_cells - 1;
+        p_sys->i_title_end_block =
+            p_pgc->cell_playback[i_end_cell].last_sector;
+
+        p_sys->i_title_offset = 0;
+
+        p_sys->i_title_blocks = 0;
+        for( i = i_start_cell; i <= i_end_cell; i++ )
+        {
+            p_sys->i_title_blocks += p_pgc->cell_playback[i].last_sector -
+                p_pgc->cell_playback[i].first_sector + 1;
+        }
+
+        msg_Dbg( p_demux, "title %d vts_title %d pgc %d pgn %d "
+                 "start %d end %d blocks: %d",
+                 i_title + 1, p_sys->i_ttn, pgc_id, pgn,
+                 p_sys->i_title_start_block, p_sys->i_title_end_block,
+                 p_sys->i_title_blocks );
+
+        /*
+         * Set properties for current chapter
+         */
+        p_sys->i_chapter = 0;
+        p_sys->i_chapters =
+            p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].nr_of_ptts;
+
+        pgc_id = p_vts->vts_ptt_srpt->title[
+                    p_sys->i_ttn - 1].ptt[p_sys->i_chapter].pgcn;
+        pgn = p_vts->vts_ptt_srpt->title[
+                    p_sys->i_ttn - 1].ptt[p_sys->i_chapter].pgn;
+
+        p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
+        p_sys->i_pack_len = 0;
+        p_sys->i_next_cell =
+            p_sys->i_cur_cell = p_pgc->program_map[pgn - 1] - 1;
+        DvdReadFindCell( p_demux );
+
+        p_sys->i_next_vobu = p_sys->i_cur_block =
+            p_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
+
+        /*
+         * Angle management
+         */
+        p_sys->i_angles = p_vmg->tt_srpt->title[i_title].nr_of_angles;
+        if( p_sys->i_angle > p_sys->i_angles ) p_sys->i_angle = 1;
+
+        /*
+         * We've got enough info, time to open the title set data.
+         */
+        if( !( p_sys->p_title = DVDOpenFile( p_sys->p_dvdread,
+            p_vmg->tt_srpt->title[i_title].title_set_nr,
+            DVD_READ_TITLE_VOBS ) ) )
+        {
+            msg_Err( p_demux, "cannot open title (VTS_%02d_1.VOB)",
+                     p_vmg->tt_srpt->title[i_title].title_set_nr );
+            return VLC_EGENERIC;
+        }
+
+        //IfoPrintTitle( p_demux );
+
+        /*
+         * Destroy obsolete ES by reinitializing program 0
+         * and find all ES in title with ifo data
+         */
+        es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
+
+        for( i = 0; i < PS_TK_COUNT; i++ )
+        {
+            ps_track_t *tk = &p_sys->tk[i];
+            if( tk->b_seen )
+            {
+                es_format_Clean( &tk->fmt );
+                if( tk->es ) es_out_Del( p_demux->out, tk->es );
+            }
+            tk->b_seen = VLC_FALSE;
+        }
+
+        if( p_demux->info.i_title != i_title )
+        {
+            p_demux->info.i_update |=
+                INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
+            p_demux->info.i_title = i_title;
+            p_demux->info.i_seekpoint = 0;
+        }
+
+        /* TODO: re-add angles */
+
+
+        ESNew( p_demux, 0xe0, 0 ); /* Video, FIXME ? */
+
+#define audio_control \
+    p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->audio_control[i-1]
+
+        /* Audio ES, in the order they appear in the .ifo */
+        for( i = 1; i <= p_vts->vtsi_mat->nr_of_vts_audio_streams; i++ )
+        {
+            int i_position = 0;
+            uint16_t i_id;
+
+            //IfoPrintAudio( p_demux, i );
+
+            /* Audio channel is active if first byte is 0x80 */
+            if( audio_control & 0x8000 )
+            {
+                i_position = ( audio_control & 0x7F00 ) >> 8;
+
+                msg_Dbg( p_demux, "audio position  %d", i_position );
+                switch( p_vts->vtsi_mat->vts_audio_attr[i - 1].audio_format )
+                {
+                case 0x00: /* A52 */
+                    i_id = (0x80 + i_position) | 0xbd00;
+                    break;
+                case 0x02:
+                case 0x03: /* MPEG audio */
+                    i_id = 0xc000 + i_position;
+                    break;
+                case 0x04: /* LPCM */
+                    i_id = (0xa0 + i_position) | 0xbd00;
+                    break;
+                case 0x06: /* DTS */
+                    i_id = (0x88 + i_position) | 0xbd00;
+                    break;
+                default:
+                    i_id = 0;
+                    msg_Err( p_demux, "unknown audio type %.2x",
+                        p_vts->vtsi_mat->vts_audio_attr[i - 1].audio_format );
+                }
+
+                ESNew( p_demux, i_id, p_sys->p_vts_file->vtsi_mat->
+                       vts_audio_attr[i - 1].lang_code );
+            }
+        }
+#undef audio_control
+
+#define spu_control \
+    p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->subp_control[i-1]
+
+        /* Sub Picture ES */
+        for( i = 1; i <= p_vts->vtsi_mat->nr_of_vts_subp_streams; i++ )
+        {
+            int i_position = 0;
+            uint16_t i_id;
+
+            //IfoPrintSpu( p_sys, i );
+            msg_Dbg( p_demux, "spu %d 0x%02x", i, spu_control );
+
+            if( spu_control & 0x80000000 )
+            {
+                /*  there are several streams for one spu */
+                if( p_vts->vtsi_mat->vts_video_attr.display_aspect_ratio )
+                {
+                    /* 16:9 */
+                    switch( p_vts->vtsi_mat->vts_video_attr.permitted_df )
+                    {
+                    case 1:
+                        i_position = spu_control & 0xff;
+                        break;
+                    case 2:
+                        i_position = ( spu_control >> 8 ) & 0xff;
+                        break;
+                    default:
+                        i_position = ( spu_control >> 16 ) & 0xff;
+                        break;
+                    }
+                }
+                else
+                {
+                    /* 4:3 */
+                    i_position = ( spu_control >> 24 ) & 0x7F;
+                }
+
+                i_id = (0x20 + i_position) | 0xbd00;
+
+                ESNew( p_demux, i_id, p_sys->p_vts_file->vtsi_mat->
+                       vts_subp_attr[i - 1].lang_code );
+            }
+        }
+#undef spu_control
+
+    }
+    else
+    {
+        /* TODO: update input ? */
+    }
+
+    /*
+     * Chapter selection
+     */
+
+    if( i_chapter >= 0 && i_chapter <= p_sys->i_chapters &&
+        i_chapter != p_sys->i_chapter )
+    {
+        pgc_id = p_vts->vts_ptt_srpt->title[
+                     p_sys->i_ttn - 1].ptt[i_chapter].pgcn;
+        pgn = p_vts->vts_ptt_srpt->title[
+                  p_sys->i_ttn - 1].ptt[i_chapter].pgn;
+
+        p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
+
+        p_sys->i_cur_cell = p_pgc->program_map[pgn - 1] - 1;
+        p_sys->i_chapter = i_chapter;
+        DvdReadFindCell( p_demux );
+
+        p_sys->i_title_offset = 0;
+        for( i = p_sys->i_title_start_cell; i < p_sys->i_cur_cell; i++ )
+        {
+            p_sys->i_title_offset += p_pgc->cell_playback[i].last_sector -
+                p_pgc->cell_playback[i].first_sector + 1;
+        }
+
+        p_sys->i_pack_len = 0;
+        p_sys->i_next_vobu = p_sys->i_cur_block =
+            p_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
+
+        if( p_demux->info.i_seekpoint != i_chapter )
+        {
+            p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
+            p_demux->info.i_seekpoint = i_chapter;
+        }
+    }
+
+#undef p_pgc
+#undef p_vts
+#undef p_vmg
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * DvdReadSeek : Goes to a given position on the stream.
+ *****************************************************************************
+ * This one is used by the input and translate chronological position from
+ * input to logical position on the device.
+ *****************************************************************************/
+static void DvdReadSeek( demux_t *p_demux, int i_block_offset )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    unsigned int i_tmp;
+    unsigned int i_chapter = 0;
+    unsigned int i_cell = 0;
+    unsigned int i_vobu = 0;
+    unsigned int i_sub_cell = 0;
+    int i_block;
+
+#define p_pgc p_sys->p_cur_pgc
+#define p_vts p_sys->p_vts_file
+
+    /* Find cell */
+    p_sys->i_title_offset = i_block = i_block_offset;
+    while( i_block >= (int)p_pgc->cell_playback[i_cell].last_sector -
+           (int)p_pgc->cell_playback[i_cell].first_sector + 1 )
+    {
+        i_cell++;
+
+        i_block -= p_pgc->cell_playback[i_cell].last_sector -
+            p_pgc->cell_playback[i_cell].first_sector + 1;
+    }
+
+    i_block += p_pgc->cell_playback[i_cell].first_sector;
+
+    /* Find chapter */
+    do
+    {
+        int pgc_id, pgn;
+
+        i_chapter++;
+        pgc_id = p_vts->vts_ptt_srpt->title[
+                    p_sys->i_ttn - 1].ptt[i_chapter].pgcn;
+        pgn = p_vts->vts_ptt_srpt->title[
+                    p_sys->i_ttn - 1].ptt[i_chapter].pgn;
+
+        i_tmp = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc->program_map[pgn-1];
+
+    } while( i_tmp <= i_cell );
+
+    /* Find vobu */
+    while( p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu] <= i_block )
+    {
+        i_vobu++;
+    }
+
+    /* Find sub_cell */
+    while( p_vts->vts_c_adt->cell_adr_table[i_sub_cell].start_sector <
+           p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu-1] )
+    {
+        i_sub_cell++;
+    }
+
+#if 1
+    msg_Dbg( p_demux, "cell %d i_sub_cell %d chapter %d vobu %d "
+             "cell_sector %d vobu_sector %d sub_cell_sector %d",
+             i_cell, i_sub_cell,i_chapter, i_vobu,
+             p_sys->p_cur_pgc->cell_playback[i_cell].first_sector,
+             p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu],
+             p_vts->vts_c_adt->cell_adr_table[i_sub_cell - 1].start_sector);
+#endif
+
+    p_sys->i_cur_block = i_block;
+    p_sys->i_next_vobu = p_vts->vts_vobu_admap->vobu_start_sectors[i_vobu];
+    p_sys->i_pack_len = p_sys->i_next_vobu - i_block;
+    p_sys->i_cur_cell = i_cell;
+    p_sys->i_chapter = i_chapter;
+    DvdReadFindCell( p_demux );
+
+#undef p_vts
+#undef p_pgc
+
+    return;
+}
+
+/*****************************************************************************
+ * DvdReadHandleDSI
+ *****************************************************************************/
+static void DvdReadHandleDSI( demux_t *p_demux, uint8_t *p_data )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+
+    navRead_DSI( &p_sys->dsi_pack, &p_data[DSI_START_BYTE] );
+
+    /*
+     * Determine where we go next.  These values are the ones we mostly
+     * care about.
+     */
+    p_sys->i_cur_block = p_sys->dsi_pack.dsi_gi.nv_pck_lbn;
+
+    /*
+     * If we're not at the end of this cell, we can determine the next
+     * VOBU to display using the VOBU_SRI information section of the
+     * DSI.  Using this value correctly follows the current angle,
+     * avoiding the doubled scenes in The Matrix, and makes our life
+     * really happy.
+     */
+    if( p_sys->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL )
+    {
+        switch( ( p_sys->dsi_pack.sml_pbi.category & 0xf000 ) >> 12 )
+        {
+        case 0x4:
+            /* Interleaved unit with no angle */
+            if( p_sys->dsi_pack.sml_pbi.ilvu_sa != 0 )
+            {
+                p_sys->i_next_vobu = p_sys->i_cur_block +
+                    p_sys->dsi_pack.sml_pbi.ilvu_sa;
+                p_sys->i_pack_len = p_sys->dsi_pack.sml_pbi.ilvu_ea;
+            }
+            else
+            {
+                p_sys->i_next_vobu = p_sys->i_cur_block +
+                    p_sys->dsi_pack.dsi_gi.vobu_ea + 1;
+                p_sys->i_pack_len = p_sys->dsi_pack.dsi_gi.vobu_ea;
+            }
+            break;
+        case 0x5:
+            /* vobu is end of ilvu */
+            if( p_sys->dsi_pack.sml_agli.data[p_sys->i_angle-1].address )
+            {
+                p_sys->i_next_vobu = p_sys->i_cur_block +
+                    p_sys->dsi_pack.sml_agli.data[p_sys->i_angle-1].address;
+                p_sys->i_pack_len = p_sys->dsi_pack.sml_pbi.ilvu_ea;
+
+                break;
+            }
+        case 0x6:
+            /* vobu is beginning of ilvu */
+        case 0x9:
+            /* next scr is 0 */
+        case 0xa:
+            /* entering interleaved section */
+        case 0x8:
+            /* non interleaved cells in interleaved section */
+        default:
+            p_sys->i_next_vobu = p_sys->i_cur_block +
+                ( p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
+            p_sys->i_pack_len = p_sys->dsi_pack.dsi_gi.vobu_ea;
+            break;
+        }
+    }
+    else
+    {
+        p_sys->i_cur_cell = p_sys->i_next_cell;
+        DvdReadFindCell( p_demux );
+
+        p_sys->i_pack_len = p_sys->dsi_pack.dsi_gi.vobu_ea;
+        p_sys->i_next_vobu =
+            p_sys->p_cur_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
+    }
+
+#if 0
+    msg_Dbg( p_input, 12, "scr %d lbn 0x%02x vobu_ea %d vob_id %d c_id %d",
+             p_sys->dsi_pack.dsi_gi.nv_pck_scr,
+             p_sys->dsi_pack.dsi_gi.nv_pck_lbn,
+             p_sys->dsi_pack.dsi_gi.vobu_ea,
+             p_sys->dsi_pack.dsi_gi.vobu_vob_idn,
+             p_sys->dsi_pack.dsi_gi.vobu_c_idn );
+
+    msg_Dbg( p_input, 12, "cat 0x%02x ilvu_ea %d ilvu_sa %d size %d",
+             p_sys->dsi_pack.sml_pbi.category,
+             p_sys->dsi_pack.sml_pbi.ilvu_ea,
+             p_sys->dsi_pack.sml_pbi.ilvu_sa,
+             p_sys->dsi_pack.sml_pbi.size );
+
+    msg_Dbg( p_input, 12, "next_vobu %d next_ilvu1 %d next_ilvu2 %d",
+             p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff,
+             p_sys->dsi_pack.sml_agli.data[ p_sys->i_angle - 1 ].address,
+             p_sys->dsi_pack.sml_agli.data[ p_sys->i_angle ].address);
+#endif
+}
+
+/*****************************************************************************
+ * DvdReadFindCell
+ *****************************************************************************/
+static void DvdReadFindCell( demux_t *p_demux )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+
+    pgc_t *p_pgc;
+    int   pgc_id, pgn;
+    int   i = 0;
+
+#define cell p_sys->p_cur_pgc->cell_playback
+
+    if( cell[p_sys->i_cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK )
+    {
+#if 0
+        p_sys->i_next_cell = p_sys->i_cur_cell + p_sys->i_angle_nb;
+        p_sys->i_cur_cell += p_sys->i_angle - 1;
+#else
+        p_sys->i_cur_cell += p_sys->i_angle - 1;
+
+        while( cell[p_sys->i_cur_cell+i].block_mode != BLOCK_MODE_LAST_CELL )
+        {
+            i++;
+        }
+        p_sys->i_next_cell = p_sys->i_cur_cell + i + 1;
+#endif
+    }
+    else
+    {
+        p_sys->i_next_cell = p_sys->i_cur_cell + 1;
+    }
+
+#undef cell
+
+    pgc_id = p_sys->p_vts_file->vts_ptt_srpt->title[
+                p_sys->i_ttn - 1].ptt[p_sys->i_chapter].pgcn;
+    pgn = p_sys->p_vts_file->vts_ptt_srpt->title[
+              p_sys->i_ttn - 1].ptt[p_sys->i_chapter].pgn;
+    p_pgc = p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id - 1].pgc;
+
+    if( p_pgc->program_map[pgn - 1] <= p_sys->i_cur_cell )
+    {
+        p_sys->i_chapter++;
+
+        if( p_sys->i_chapter < p_sys->i_chapters &&
+            p_demux->info.i_seekpoint != p_sys->i_chapter )
+        {
+            p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
+            p_demux->info.i_seekpoint = p_sys->i_chapter;
+        }
+    }
+}
+
+/*****************************************************************************
+ * DemuxTitles: get the titles/chapters structure
+ *****************************************************************************/
+static void DemuxTitles( demux_t *p_demux,
+                         int *pi_title, int *pi_chapter, int *pi_angle )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    input_title_t *t;
+    seekpoint_t *s;
+    int32_t i_titles;
+    int i;
+
+    /* Find out number of titles/chapters */
+#define tt_srpt p_sys->p_vmg_file->tt_srpt
+
+    i_titles = tt_srpt->nr_of_srpts;
+    msg_Dbg( p_demux, "number of titles: %d", i_titles );
+
+    for( i = 0; i < i_titles; i++ )
+    {
+        int32_t i_chapters = 0;
+        int j;
+
+        i_chapters = tt_srpt->title[i].nr_of_ptts;
+        msg_Dbg( p_demux, "title %d has %d chapters", i, i_chapters );
+
+        t = vlc_input_title_New();
+        for( j = 0; j < __MAX( i_chapters, 1 ); j++ )
+        {
+            s = vlc_seekpoint_New();
+            TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
+        }
+
+        TAB_APPEND( p_sys->i_titles, p_sys->titles, t );
+    }
+
+    /* Set forced title/chapter/angle */
+    *pi_title = (*pi_title >= 1 && *pi_title <= i_titles) ? *pi_title : 1;
+    *pi_chapter = (*pi_chapter >= 0 && *pi_chapter <
+        tt_srpt->title[*pi_title].nr_of_ptts) ? *pi_chapter : 0;
+
+#undef tt_srpt
+}
+
+/*****************************************************************************
+ * ParseCL: parse command line
+ *****************************************************************************/
+static char *ParseCL( vlc_object_t *p_this, char *psz_name, vlc_bool_t b_force,
+                      int *i_title, int *i_chapter, int *i_angle )
+{
+    char *psz_parser, *psz_source, *psz_next;
+
+    psz_source = strdup( psz_name );
+    if( psz_source == NULL ) return NULL;
+
+    *i_title = 0;
+    *i_chapter = 0;
+    *i_angle = 1;
+
+    /* Start with the end, because you could have :
+     * dvdnav:/Volumes/my@toto/VIDEO_TS@1,1
+     * (yes, this is kludgy). */
+    for( psz_parser = psz_source + strlen(psz_source) - 1;
+         psz_parser >= psz_source && *psz_parser != '@';
+         psz_parser-- );
+
+    if( psz_parser >= psz_source && *psz_parser == '@' )
+    {
+        /* Found options */
+        *psz_parser = '\0';
+        ++psz_parser;
+
+        *i_title = (int)strtol( psz_parser, &psz_next, 10 );
+        if( *psz_next )
+        {
+            psz_parser = psz_next + 1;
+            *i_chapter = (int)strtol( psz_parser, &psz_next, 10 );
+            if( *psz_next )
+            {
+                *i_angle = (int)strtol( psz_next + 1, NULL, 10 );
+            }
+        }
+    }
+
+    *i_title   = *i_title >= 0 ? *i_title : 0;
+    *i_chapter = *i_chapter    ? *i_chapter : 0;
+    *i_angle   = *i_angle      ? *i_angle : 1;
+
+    if( !*psz_source )
+    {
+        free( psz_source );
+        if( !b_force )
+        {
+            return NULL;
+        }
+        psz_source = config_GetPsz( p_this, "dvd" );
+        if( !psz_source ) return NULL;
+    }
+
+#ifdef WIN32
+    if( psz_source[0] && psz_source[1] == ':' &&
+        psz_source[2] == '\\' && psz_source[3] == '\0' )
+    {
+        psz_source[2] = '\0';
+    }
+#endif
+
+    msg_Dbg( p_this, "dvdroot=%s title=%d chapter=%d angle=%d",
+             psz_source, *i_title, *i_chapter, *i_angle );
+
+    return psz_source;
+}
diff --git a/modules/access/dvdread/Modules.am b/modules/access/dvdread/Modules.am
deleted file mode 100644 (file)
index b1f0612..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-SOURCES_dvdread = \
-       dvdread.c \
-       input.c \
-       input.h \
-       $(NULL)
-
diff --git a/modules/access/dvdread/dvdread.c b/modules/access/dvdread/dvdread.c
deleted file mode 100644 (file)
index fccf632..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*****************************************************************************
- * dvdread.c : DvdRead input module for vlc
- *****************************************************************************
- * Copyright (C) 2001 VideoLAN
- * $Id: dvdread.c,v 1.7 2003/06/17 16:09:16 gbazin Exp $
- *
- * Authors: Samuel Hocevar <sam@zoy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <stdlib.h>                                      /* malloc(), free() */
-#include <string.h>                                              /* strdup() */
-
-#include <vlc/vlc.h>
-
-/*****************************************************************************
- * External prototypes
- *****************************************************************************/
-int  E_(OpenDVD)   ( vlc_object_t * );
-void E_(CloseDVD)  ( vlc_object_t * );
-
-int  E_(InitDVD)   ( vlc_object_t * );
-void E_(EndDVD)    ( vlc_object_t * );
-
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-vlc_module_begin();
-    set_description( _("DVD input (using libdvdread)") );
-    set_capability( "access", 110 );
-    set_callbacks( E_(OpenDVD), E_(CloseDVD) );
-    add_submodule();
-        set_capability( "demux", 0 );
-        set_callbacks( E_(InitDVD), E_(EndDVD) );
-vlc_module_end();
-
diff --git a/modules/access/dvdread/input.c b/modules/access/dvdread/input.c
deleted file mode 100644 (file)
index 2f206dc..0000000
+++ /dev/null
@@ -1,1268 +0,0 @@
-/*****************************************************************************
- * input.c: DvdRead plugin.
- *****************************************************************************
- * This plugins should handle all the known specificities of the DVD format,
- * especially the 2048 bytes logical block size.
- * It depends on: libdvdread for ifo files and block reading.
- *****************************************************************************
- * Copyright (C) 2001, 2003 VideoLAN
- * $Id: input.c,v 1.24 2004/03/03 20:39:51 gbazin Exp $
- *
- * Author: Stéphane Borel <stef@via.ecp.fr>
- *
- * Some code taken form the play_title.c by Billy Biggs <vektor@dumbterm.net>
- * in libdvdread.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <vlc/vlc.h>
-#include <vlc/input.h>
-
-#include "../../demux/mpeg/system.h"
-
-#ifdef HAVE_UNISTD_H
-#   include <unistd.h>
-#endif
-
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-
-#ifdef STRNCASECMP_IN_STRINGS_H
-#   include <strings.h>
-#endif
-
-#if defined( WIN32 )
-#   include <io.h>                                                 /* read() */
-#endif
-
-#include <dvdread/dvd_reader.h>
-#include <dvdread/ifo_types.h>
-#include <dvdread/ifo_read.h>
-#include <dvdread/nav_read.h>
-#include <dvdread/nav_print.h>
-
-#include "input.h"
-
-#include "iso_lang.h"
-
-/* how many blocks DVDRead will read in each loop */
-#define DVD_BLOCK_READ_ONCE 64
-
-/*****************************************************************************
- * Private structure
- *****************************************************************************/
-struct demux_sys_t
-{
-    module_t *   p_module;
-    mpeg_demux_t mpeg;
-};
-
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
-/* called from outside */
-static int     DvdReadDemux    ( input_thread_t * );
-static int     DvdReadRewind   ( input_thread_t * );
-
-static int     DvdReadSetArea    ( input_thread_t *, input_area_t * );
-static int     DvdReadSetProgram ( input_thread_t *, pgrm_descriptor_t * );
-static ssize_t DvdReadRead       ( input_thread_t *, byte_t *, size_t );
-static void    DvdReadSeek       ( input_thread_t *, off_t );
-
-/* called only from here */
-static void    DvdReadLauchDecoders( input_thread_t * p_input );
-static void    DvdReadHandleDSI( thread_dvd_data_t * p_dvd, uint8_t * p_data );
-static void    DvdReadFindCell ( thread_dvd_data_t * p_dvd );
-
-/*
- * Data demux functions
- */
-
-/*****************************************************************************
- * InitDVD: initialize DVD structures
- *****************************************************************************/
-int E_(InitDVD) ( vlc_object_t *p_this )
-{
-    input_thread_t *p_input = (input_thread_t *)p_this;
-    demux_sys_t *   p_demux;
-
-    if( p_input->stream.i_method != INPUT_METHOD_DVD )
-    {
-        return VLC_EGENERIC;
-    }
-
-    p_demux = p_input->p_demux_data = malloc( sizeof(demux_sys_t ) );
-    if( p_demux == NULL )
-    {
-        return VLC_ENOMEM;
-    }
-
-    p_input->p_private = (void*)&p_demux->mpeg;
-    p_demux->p_module = module_Need( p_input, "mpeg-system", NULL, 0 );
-    if( p_demux->p_module == NULL )
-    {
-        free( p_input->p_demux_data );
-        return VLC_ENOMOD;
-    }
-
-    p_input->pf_demux = DvdReadDemux;
-    p_input->pf_demux_control = demux_vaControlDefault;
-    p_input->pf_rewind = NULL;
-
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-
-    DvdReadLauchDecoders( p_input );
-
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * EndDVD: end DVD structures
- *****************************************************************************/
-void E_(EndDVD) ( vlc_object_t *p_this )
-{
-    input_thread_t *p_input = (input_thread_t *)p_this;
-
-    module_Unneed( p_input, p_input->p_demux_data->p_module );
-    free( p_input->p_demux_data );
-}
-
-/*****************************************************************************
- * DvdReadDemux
- *****************************************************************************/
-#define PEEK( SIZE )                                                        \
-    i_result = input_Peek( p_input, &p_peek, SIZE );                        \
-    if( i_result == -1 )                                                    \
-    {                                                                       \
-        return -1;                                                          \
-    }                                                                       \
-    else if( i_result < SIZE )                                              \
-    {                                                                       \
-        /* EOF */                                                           \
-        return 0;                                                           \
-    }
-
-static int DvdReadDemux( input_thread_t * p_input )
-{
-    int                 i;
-    byte_t *            p_peek;
-    data_packet_t *     p_data;
-    ssize_t             i_result;
-    int                 i_packet_size;
-
-
-    /* Read headers to compute payload length */
-    for( i = 0 ; i < DVD_BLOCK_READ_ONCE ; i++ )
-    {
-
-        /* Read what we believe to be a packet header. */
-        PEEK( 4 );
-
-        /* Default header */
-        if( U32_AT( p_peek ) != 0x1BA )
-        {
-            /* That's the case for all packets, except pack header. */
-            i_packet_size = U16_AT( p_peek + 4 );
-        }
-        else
-        {
-            /* MPEG-2 Pack header. */
-            i_packet_size = 8;
-        }
-
-        /* Fetch a packet of the appropriate size. */
-        i_result = input_SplitBuffer( p_input, &p_data, i_packet_size + 6 );
-        if( i_result <= 0 )
-        {
-            return( i_result );
-        }
-
-        /* In MPEG-2 pack headers we still have to read stuffing bytes. */
-        if( (p_data->p_demux_start[3] == 0xBA) && (i_packet_size == 8) )
-        {
-            ssize_t i_stuffing = (p_data->p_demux_start[13] & 0x7);
-            /* Force refill of the input buffer - though we don't care
-             * about p_peek. Please note that this is unoptimized. */
-            PEEK( i_stuffing );
-            p_input->p_current_data += i_stuffing;
-        }
-
-        p_input->p_demux_data->mpeg.pf_demux_ps( p_input, p_data );
-
-    }
-
-    return i;
-}
-
-/*****************************************************************************
- * DVDRewind : reads a stream backward
- *****************************************************************************/
-static int DvdReadRewind( input_thread_t * p_input )
-{
-    return -1;
-}
-
-/*
- * Data access functions
- */
-
-/*****************************************************************************
- * OpenDVD: open libdvdread
- *****************************************************************************/
-int E_(OpenDVD) ( vlc_object_t *p_this )
-{
-    input_thread_t *        p_input = (input_thread_t *)p_this;
-    char *                  psz_parser;
-    char *                  psz_source;
-    char *                  psz_next;
-    struct stat             stat_info;
-    thread_dvd_data_t *     p_dvd;
-    dvd_reader_t *          p_dvdread;
-    input_area_t *          p_area;
-    unsigned int            i_title = 1;
-    unsigned int            i_chapter = 1;
-    unsigned int            i_angle = 1;
-    unsigned int            i;
-
-    psz_source = strdup( p_input->psz_name );
-    if( psz_source == NULL )
-    {
-        return VLC_ENOMEM;
-    }
-
-    p_input->pf_read = DvdReadRead;
-    p_input->pf_seek = DvdReadSeek;
-    p_input->pf_set_area = DvdReadSetArea;
-    p_input->pf_set_program = DvdReadSetProgram;
-
-    /* Start with the end, because you could have :
-     * dvdread:/Volumes/my@toto/VIDEO_TS@1,1
-     * (yes, this is kludgy). */
-    for ( psz_parser = psz_source + strlen(psz_source) - 1;
-          psz_parser >= psz_source && *psz_parser != '@';
-          psz_parser-- );
-
-    if( psz_parser >= psz_source && *psz_parser == '@' )
-    {
-        /* Found options */
-        *psz_parser = '\0';
-        ++psz_parser;
-
-        i_title = (int)strtol( psz_parser, &psz_next, 10 );
-        if( *psz_next )
-        {
-            psz_parser = psz_next + 1;
-            i_chapter = (int)strtol( psz_parser, &psz_next, 10 );
-            if( *psz_next )
-            {
-                i_angle = (int)strtol( psz_next + 1, NULL, 10 );
-            }
-        }
-
-        i_title = i_title ? i_title : 1;
-        i_chapter = i_chapter ? i_chapter : 1;
-        i_angle = i_angle ? i_angle : 1;
-    }
-
-    if( !*psz_source )
-    {
-        free( psz_source );
-        if( !p_input->psz_access )
-        {
-            return VLC_EGENERIC;
-        }
-        psz_source = config_GetPsz( p_input, "dvd" );
-        if( !psz_source ) return VLC_EGENERIC;
-    }
-
-    if( stat( psz_source, &stat_info ) == -1 )
-    {
-        msg_Warn( p_input, "cannot stat() source `%s' (%s)",
-                           psz_source, strerror(errno) );
-        free( psz_source );
-        return VLC_EGENERIC;
-    }
-    if( !S_ISBLK(stat_info.st_mode) &&
-        !S_ISCHR(stat_info.st_mode) &&
-        !S_ISDIR(stat_info.st_mode) )
-    {
-        msg_Warn( p_input, "dvdread module discarded (not a valid source)" );
-        free( psz_source );
-        return VLC_EGENERIC;
-    }
-
-    msg_Dbg( p_input, "dvdroot=%s title=%d chapter=%d angle=%d",
-                      psz_source, i_title, i_chapter, i_angle );
-
-
-    p_dvdread = DVDOpen( psz_source );
-
-    /* free allocated strings */
-    free( psz_source );
-
-    if( ! p_dvdread )
-    {
-        msg_Err( p_input, "libdvdcss cannot open source" );
-        return VLC_EGENERIC;
-    }
-
-    /* set up input  */
-    p_input->i_mtu = 0;
-
-    p_dvd = malloc( sizeof(thread_dvd_data_t) );
-    if( p_dvd == NULL )
-    {
-        msg_Err( p_input, "out of memory" );
-        return VLC_ENOMEM;
-    }
-
-    p_dvd->p_dvdread = p_dvdread;
-    p_dvd->p_title = NULL;
-    p_dvd->p_vts_file = NULL;
-
-
-    p_input->p_access_data = (void *)p_dvd;
-
-    /* Ifo allocation & initialisation */
-    if( ! ( p_dvd->p_vmg_file = ifoOpen( p_dvd->p_dvdread, 0 ) ) )
-    {
-        msg_Warn( p_input, "cannot open VMG info" );
-        free( p_dvd );
-        return VLC_EGENERIC;
-    }
-    msg_Dbg( p_input, "VMG opened" );
-
-    /* Set stream and area data */
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-
-    p_input->stream.i_method = INPUT_METHOD_DVD;
-
-    /* If we are here we can control the pace... */
-    p_input->stream.b_pace_control = VLC_TRUE;
-    p_input->stream.b_seekable = VLC_TRUE;
-
-    p_input->stream.p_selected_area->i_size = 0;
-    p_input->stream.p_selected_area->i_tell = 0;
-
-    /* Initialize ES structures */
-    input_InitStream( p_input, sizeof( stream_ps_data_t ) );
-
-    /* disc input method */
-    p_input->stream.i_method = INPUT_METHOD_DVD;
-
-#define tt_srpt p_dvd->p_vmg_file->tt_srpt
-    msg_Dbg( p_input, "number of titles: %d", tt_srpt->nr_of_srpts );
-
-#define area p_input->stream.pp_areas
-    /* We start from 1 here since the default area 0
-     * is reserved for video_ts.vob */
-    for( i = 1 ; i <= tt_srpt->nr_of_srpts ; i++ )
-    {
-        /* Titles are Program Chains */
-        input_AddArea( p_input, i, tt_srpt->title[i-1].nr_of_ptts );
-
-        /* Absolute start offset and size
-         * We can only set that with vts ifo, so we do it during the
-         * first call to DVDSetArea */
-        area[i]->i_start = 0;
-        area[i]->i_size = 0;
-
-        /* Default Chapter */
-        area[i]->i_part = 1;
-
-        area[i]->i_plugin_data = tt_srpt->title[i-1].title_set_nr;
-    }
-#undef area
-
-    p_dvd->i_title = i_title <= tt_srpt->nr_of_srpts ? i_title : 1;
-#undef tt_srpt
-
-    p_area = p_input->stream.pp_areas[p_dvd->i_title];
-    p_dvd->i_chapter = i_chapter;
-
-    p_dvd->i_chapter = i_chapter < p_area->i_part_nb ? i_chapter : 1;
-    p_area->i_part = p_dvd->i_chapter;
-
-    p_dvd->i_angle = i_angle;
-
-    /* set title, chapter, audio and subpic */
-    if( DvdReadSetArea( p_input, p_area ) )
-    {
-        vlc_mutex_unlock( &p_input->stream.stream_lock );
-        return VLC_EGENERIC;
-    }
-
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
-
-    if( !p_input->psz_demux || !*p_input->psz_demux )
-    {
-        p_input->psz_demux = "dvdread";
-    }
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * CloseDVD: close libdvdread
- *****************************************************************************/
-void E_(CloseDVD) ( vlc_object_t *p_this )
-{
-    input_thread_t *    p_input = (input_thread_t *)p_this;
-    thread_dvd_data_t * p_dvd = (thread_dvd_data_t *)p_input->p_access_data;
-
-    /* This is a very nasty side-effect in the DVD plug-in : language
-     * selection here influences language selection of other streams. So
-     * unset those variables (may not be what the user wants).
-     * FIXME FIXME FIXME FIXME FIXME FIXME FIXME --Meuuh */
-    config_PutInt( p_input, "audio-channel", -1 );
-    config_PutInt( p_input, "spu-channel", -1 );
-
-    /* close libdvdread */
-    DVDCloseFile( p_dvd->p_title );
-    ifoClose( p_dvd->p_vts_file );
-    ifoClose( p_dvd->p_vmg_file );
-
-    DVDClose( p_dvd->p_dvdread );
-    free( p_dvd );
-    p_input->p_access_data = NULL;
-
-}
-
-/*****************************************************************************
- * DvdReadSetProgram: Does nothing, a DVD is mono-program
- *****************************************************************************/
-static int DvdReadSetProgram( input_thread_t * p_input,
-                              pgrm_descriptor_t * p_program )
-{
-    if( p_input->stream.p_selected_program != p_program )
-    {
-        thread_dvd_data_t *  p_dvd;
-        vlc_value_t val;
-
-        p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
-        p_dvd->i_angle = p_program->i_number;
-
-        memcpy( p_program, p_input->stream.p_selected_program,
-                sizeof(pgrm_descriptor_t) );
-        p_program->i_number = p_dvd->i_angle;
-        p_input->stream.p_selected_program = p_program;
-
-        msg_Dbg( p_input, "angle %d selected", p_dvd->i_angle );
-
-        /* Update the navigation variables without triggering a callback */
-        val.i_int = p_program->i_number;
-        var_Change( p_input, "program", VLC_VAR_SETVALUE, &val, NULL );
-    }
-
-    return VLC_SUCCESS;
-}
-
-#define p_pgc         p_dvd->p_cur_pgc
-
-/*****************************************************************************
- * DvdReadSetArea: initialize input data for title x, chapter y.
- * It should be called for each user navigation request.
- *****************************************************************************
- * Take care that i_title starts from 0 (vmg) and i_chapter start from 1.
- * Note that you have to take the lock before entering here.
- *****************************************************************************/
-static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
-{
-    thread_dvd_data_t *  p_dvd;
-    int                  pgc_id = 0;
-    int                  pgn = 0;
-    vlc_value_t          val;
-
-    p_dvd = (thread_dvd_data_t*)p_input->p_access_data;
-
-    /* we can't use the interface slider until initilization is complete */
-    p_input->stream.b_seekable = VLC_FALSE;
-
-    if( p_area != p_input->stream.p_selected_area )
-    {
-        es_descriptor_t *    p_es;
-        unsigned int         i_cell = 0;
-        unsigned int         i_audio_nb = 0;
-        unsigned int         i_spu_nb = 0;
-        unsigned int         i;
-
-#define p_vmg         p_dvd->p_vmg_file
-#define p_vts         p_dvd->p_vts_file
-        if( p_dvd->p_title != NULL )
-        {
-            DVDCloseFile( p_dvd->p_title );
-        }
-
-        if( p_vts != NULL )
-        {
-            ifoClose( p_vts );
-        }
-
-        /* Reset the Chapter position of the old title */
-        p_input->stream.p_selected_area->i_part = 1;
-
-        /*
-         *  We have to load all title information
-         */
-        /* Change the default area */
-        p_input->stream.p_selected_area = p_area;
-
-        msg_Dbg( p_input, "open VTS %d, for title %d",
-            p_vmg->tt_srpt->title[ p_area->i_id - 1 ].title_set_nr,
-            p_area->i_id );
-
-        /* ifo vts */
-        if( ! ( p_vts = ifoOpen( p_dvd->p_dvdread,
-                p_vmg->tt_srpt->title[ p_area->i_id - 1 ].title_set_nr ) ) )
-        {
-            msg_Err( p_input, "fatal error in vts ifo" );
-            ifoClose( p_vmg );
-            DVDClose( p_dvd->p_dvdread );
-            return VLC_EGENERIC;
-        }
-
-        /* title position inside the selected vts */
-        p_dvd->i_ttn = p_vmg->tt_srpt->title[ p_area->i_id - 1 ].vts_ttn;
-
-        /*
-         * Set selected title start
-         */
-        pgc_id = p_vts->vts_ptt_srpt->title[p_dvd->i_ttn-1].ptt[0].pgcn;
-        pgn = p_vts->vts_ptt_srpt->title[p_dvd->i_ttn-1].ptt[0].pgn;
-        p_pgc = p_vts->vts_pgcit->pgci_srp[ pgc_id - 1 ].pgc;
-        i_cell = p_pgc->program_map[ pgn - 1 ] - 1;
-
-        p_area->i_start =
-            LB2OFF( p_dvd->p_cur_pgc->cell_playback[ i_cell ].first_sector );
-
-        msg_Dbg( p_input, "start %d vts_title %d pgc %d pgn %d",
-                  p_area->i_id, p_dvd->i_ttn, pgc_id, pgn );
-
-        /*
-         * Find title end
-         */
-        i_cell = p_dvd->p_cur_pgc->nr_of_cells - 1;
-
-        p_dvd->i_end_block = p_pgc->cell_playback[ i_cell ].last_sector;
-        p_area->i_size = LB2OFF( p_dvd->i_end_block )- p_area->i_start;
-
-        msg_Dbg( p_input, "start "I64Fd" size "I64Fd" end %d",
-                  p_area->i_start , p_area->i_size, p_dvd->i_end_block );
-
-        /*
-         * Set properties for current chapter
-         */
-        /* Remeber current chapter */
-        p_dvd->i_chapter = p_area->i_part;
-        p_dvd->b_eoc = VLC_FALSE;
-
-        pgc_id = p_vts->vts_ptt_srpt->title[
-                    p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgcn;
-        pgn = p_vts->vts_ptt_srpt->title[
-                    p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgn;
-
-        p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id-1].pgc;
-        p_dvd->i_pack_len = 0;
-        p_dvd->i_next_cell = p_dvd->i_cur_cell = p_pgc->program_map[pgn-1] - 1;
-        DvdReadFindCell( p_dvd );
-
-        p_dvd->i_next_vobu = p_dvd->i_cur_block =
-            p_pgc->cell_playback[p_dvd->i_cur_cell].first_sector;
-
-        /*
-         * Angle management
-         */
-        p_dvd->i_angle_nb = p_vmg->tt_srpt->title[p_area->i_id-1].nr_of_angles;
-
-        if( p_dvd->i_angle > p_dvd->i_angle_nb )
-        {
-            p_dvd->i_angle = 1;
-        }
-
-        /*
-         * We've got enough info, time to open the title set data.
-         */
-        if( ! ( p_dvd->p_title = DVDOpenFile( p_dvd->p_dvdread,
-            p_vmg->tt_srpt->title[ p_area->i_id - 1 ].title_set_nr,
-            DVD_READ_TITLE_VOBS ) ) )
-        {
-            msg_Err( p_input, "cannot open title (VTS_%02d_1.VOB)",
-                     p_vmg->tt_srpt->title[p_area->i_id-1].title_set_nr );
-            ifoClose( p_vts );
-            ifoClose( p_vmg );
-            DVDClose( p_dvd->p_dvdread );
-            return VLC_EGENERIC;
-        }
-
-//        IfoPrintTitle( p_dvd );
-
-        /*
-         * Destroy obsolete ES by reinitializing program 0
-         * and find all ES in title with ifo data
-         */
-        if( p_input->stream.pp_programs != NULL )
-        {
-            /* We don't use input_EndStream here since
-             * we keep area structures */
-
-            while( p_input->stream.i_es_number )
-            {
-                input_DelES( p_input, p_input->stream.pp_es[0] );
-            }
-
-            while( p_input->stream.i_pgrm_number )
-            {
-                input_DelProgram( p_input, p_input->stream.pp_programs[0] );
-            }
-
-            if( p_input->stream.pp_selected_es )
-            {
-                free( p_input->stream.pp_selected_es );
-                p_input->stream.pp_selected_es = NULL;
-            }
-            p_input->stream.i_selected_es_number = 0;
-        }
-
-        input_AddProgram( p_input, 1, sizeof( stream_ps_data_t ) );
-        p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
-
-        for( i = 1 ; i < p_dvd->i_angle_nb ; i++ )
-        {
-            input_AddProgram( p_input, i+1, 0 );
-        }
-
-        DvdReadSetProgram( p_input,
-                           p_input->stream.pp_programs[p_dvd->i_angle-1] );
-
-        /* No PSM to read in DVD mode, we already have all information */
-        p_input->stream.p_selected_program->b_is_ok = VLC_TRUE;
-
-        p_es = NULL;
-
-        /* ES 0 -> video MPEG2 */
-//        IfoPrintVideo( p_dvd );
-
-        p_es = input_AddES( p_input, NULL, 0xe0, VIDEO_ES, NULL, 0 );
-        p_es->i_stream_id = 0xe0;
-        p_es->i_fourcc = VLC_FOURCC('m','p','g','v');
-
-#define audio_control \
-    p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->audio_control[i-1]
-        /* Audio ES, in the order they appear in .ifo */
-        for( i = 1 ; i <= p_vts->vtsi_mat->nr_of_vts_audio_streams ; i++ )
-        {
-            int i_position = 0;
-            uint16_t i_id;
-
-//            IfoPrintAudio( p_dvd, i );
-
-            /* audio channel is active if first byte is 0x80 */
-            if( audio_control & 0x8000 )
-            {
-                i_audio_nb++;
-                i_position = ( audio_control & 0x7F00 ) >> 8;
-
-                msg_Dbg( p_input, "audio position  %d", i_position );
-                switch( p_vts->vtsi_mat->vts_audio_attr[i-1].audio_format )
-                {
-                case 0x00:              /* A52 */
-                    i_id = ( ( 0x80 + i_position ) << 8 ) | 0xbd;
-                    p_es = input_AddES( p_input, NULL, i_id, AUDIO_ES,
-                                        DecodeLanguage(
-                        p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ), 0 );
-                    p_es->i_stream_id = 0xbd;
-                    p_es->i_fourcc = VLC_FOURCC('a','5','2','b');
-
-                    break;
-                case 0x02:
-                case 0x03:              /* MPEG audio */
-                    i_id = 0xc0 + i_position;
-                    p_es = input_AddES( p_input, NULL, i_id, AUDIO_ES,
-                                        DecodeLanguage(
-                        p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ), 0 );
-                    p_es->i_stream_id = i_id;
-                    p_es->i_fourcc = VLC_FOURCC('m','p','g','a');
-
-                    break;
-                case 0x04:              /* LPCM */
-
-                    i_id = ( ( 0xa0 + i_position ) << 8 ) | 0xbd;
-                    p_es = input_AddES( p_input, NULL, i_id, AUDIO_ES,
-                                        DecodeLanguage(
-                        p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ), 0 );
-                    p_es->i_stream_id = i_id;
-                    p_es->i_fourcc = VLC_FOURCC('l','p','c','b');
-
-                    break;
-                case 0x06:              /* DTS */
-                    i_id = ( ( 0x88 + i_position ) << 8 ) | 0xbd;
-                    msg_Err( p_input, "DTS audio not handled yet"
-                                      "(0x%x)", i_id );
-                    break;
-                default:
-                    i_id = 0;
-                    msg_Err( p_input, "unknown audio type %.2x",
-                          p_vts->vtsi_mat->vts_audio_attr[i-1].audio_format );
-                }
-            }
-        }
-#undef audio_control
-#define spu_control \
-    p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->subp_control[i-1]
-
-        /* Sub Picture ES */
-
-        for( i = 1 ; i <= p_vts->vtsi_mat->nr_of_vts_subp_streams; i++ )
-        {
-            int i_position = 0;
-            uint16_t i_id;
-
-//            IfoPrintSpu( p_dvd, i );
-            msg_Dbg( p_input, "spu %d 0x%02x", i, spu_control );
-
-            if( spu_control & 0x80000000 )
-            {
-                i_spu_nb++;
-
-                /*  there are several streams for one spu */
-                if(  p_vts->vtsi_mat->vts_video_attr.display_aspect_ratio )
-                {
-                    /* 16:9 */
-                    switch( p_vts->vtsi_mat->vts_video_attr.permitted_df )
-                    {
-                    case 1:
-                        i_position = spu_control & 0xff;
-                        break;
-                    case 2:
-                        i_position = ( spu_control >> 8 ) & 0xff;
-                        break;
-                    default:
-                        i_position = ( spu_control >> 16 ) & 0xff;
-                        break;
-                    }
-                }
-                else
-                {
-                    /* 4:3 */
-                    i_position = ( spu_control >> 24 ) & 0x7F;
-                }
-
-                i_id = ( ( 0x20 + i_position ) << 8 ) | 0xbd;
-                p_es = input_AddES( p_input, NULL, i_id, SPU_ES,
-                                    DecodeLanguage(
-                    p_vts->vtsi_mat->vts_subp_attr[i-1].lang_code ), 0 );
-                p_es->i_stream_id = 0xbd;
-                p_es->i_fourcc = VLC_FOURCC('s','p','u','b');
-            }
-        }
-#undef spu_control
-
-        /* FIXME: hack to check that the demuxer is ready, and set
-         * the decoders */
-        if( p_input->p_demux )
-        {
-            DvdReadLauchDecoders( p_input );
-        }
-
-        /* Update the navigation variables without triggering a callback */
-        val.i_int = p_area->i_id;
-        var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
-        var_Change( p_input, "chapter", VLC_VAR_CLEARCHOICES, NULL, NULL );
-        for( i = 1; i <= p_area->i_part_nb; i++ )
-        {
-            val.i_int = i;
-            var_Change( p_input, "chapter", VLC_VAR_ADDCHOICE, &val, NULL );
-        }
-
-    } /* i_title >= 0 */
-    else
-    {
-        p_area = p_input->stream.p_selected_area;
-    }
-
-    /*
-     * Chapter selection
-     */
-
-    if( p_area->i_part != p_dvd->i_chapter )
-    {
-        if( ( p_area->i_part > 0 ) &&
-            ( p_area->i_part <= p_area->i_part_nb ))
-        {
-            p_dvd->i_ttn = p_vmg->tt_srpt->title[p_area->i_id-1].vts_ttn;
-            pgc_id = p_vts->vts_ptt_srpt->title[
-                        p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgcn;
-            pgn = p_vts->vts_ptt_srpt->title[
-                        p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgn;
-
-            p_pgc = p_vts->vts_pgcit->pgci_srp[ pgc_id - 1 ].pgc;
-
-            p_dvd->i_cur_cell = p_pgc->program_map[ pgn - 1 ] - 1;
-            p_dvd->i_chapter = p_area->i_part;
-            DvdReadFindCell( p_dvd );
-
-            p_dvd->i_pack_len = 0;
-            p_dvd->i_next_vobu = p_dvd->i_cur_block =
-                    p_pgc->cell_playback[p_dvd->i_cur_cell].first_sector;
-        }
-        else
-        {
-            p_area->i_part = p_dvd->i_chapter;
-        }
-    }
-#undef p_vts
-#undef p_vmg
-
-    /* warn interface that something has changed */
-    p_area->i_tell = LB2OFF( p_dvd->i_next_vobu ) - p_area->i_start;
-    p_input->stream.b_seekable = VLC_TRUE;
-    p_input->stream.b_changed = VLC_TRUE;
-
-    /* Update the navigation variables without triggering a callback */
-    val.i_int = p_area->i_part;
-    var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &val, NULL );
-
-    return VLC_SUCCESS;
-}
-
-
-/*****************************************************************************
- * DvdReadRead: reads data packets.
- *****************************************************************************
- * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
- * bytes.
- *****************************************************************************/
-static ssize_t DvdReadRead( input_thread_t * p_input,
-                            byte_t * p_buffer, size_t i_count )
-{
-    thread_dvd_data_t *     p_dvd;
-    byte_t *                p_buf;
-    unsigned int            i_blocks_once;
-    unsigned int            i_blocks;
-    int                     i_read;
-    int                     i_read_total;
-    vlc_bool_t              b_eot = VLC_FALSE;
-
-    p_dvd = (thread_dvd_data_t *)p_input->p_access_data;
-    p_buf = p_buffer;
-
-    /*
-     * Playback by cell in this pgc, starting at the cell for our chapter.
-     */
-    i_blocks = OFF2LB( i_count );
-    i_read_total = 0;
-    i_read = 0;
-
-    while( i_blocks )
-    {
-        /*
-         * End of pack, we select the following one
-         */
-        if( ! p_dvd->i_pack_len )
-        {
-            /*
-             * Read NAV packet.
-             */
-            if( ( i_read = DVDReadBlocks( p_dvd->p_title, p_dvd->i_next_vobu,
-                           1, p_buf ) ) != 1 )
-            {
-                msg_Err( p_input, "read failed for block %d",
-                                  p_dvd->i_next_vobu );
-                return -1;
-            }
-
-            /* basic check to be sure we don't have a empty title
-             * go to next title if so */
-            //assert( p_buffer[41] == 0xbf && p_buffer[1027] == 0xbf );
-
-            /*
-             * Parse the contained dsi packet.
-             */
-
-            DvdReadHandleDSI( p_dvd, p_buf );
-
-            /* End of title */
-            if( p_dvd->i_next_vobu >= p_dvd->i_end_block + 1 )
-            {
-                b_eot = 1;
-                break;
-            }
-
-            assert( p_dvd->i_pack_len < 1024 );
-            /* FIXME: Ugly kludge: we send the pack block to the input for it
-             * sometimes has a zero scr and restart the sync */
-            p_dvd->i_cur_block ++;
-            //p_dvd->i_pack_len++;
-
-            i_read_total++;
-            p_buf += DVD_VIDEO_LB_LEN;
-            i_blocks--;
-        }
-
-        /*
-         * Compute the number of blocks to read
-         */
-        i_blocks_once = __MIN( p_dvd->i_pack_len, i_blocks );
-        p_dvd->i_pack_len -= i_blocks_once;
-
-        /* Reads from DVD */
-        i_read = DVDReadBlocks( p_dvd->p_title, p_dvd->i_cur_block,
-                                i_blocks_once, p_buf );
-        if( (unsigned int)i_read != i_blocks_once )
-        {
-            msg_Err( p_input, "read failed for %d/%d blocks at 0x%02x",
-                              i_read, i_blocks_once, p_dvd->i_cur_block );
-            return -1;
-        }
-
-        i_blocks -= i_read;
-        i_read_total += i_read;
-        p_dvd->i_cur_block += i_read;
-        p_buf += LB2OFF( i_read );
-
-    }
-/*
-    msg_Dbg( p_input, "i_blocks: %d len: %d current: 0x%02x", i_read, p_dvd->i_pack_len, p_dvd->i_cur_block );
-*/
-
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-
-    if( p_dvd->b_eoc )
-    {
-        /* We modify i_part only at end of chapter not to erase
-         * some modification from the interface */
-        p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
-        p_dvd->b_eoc = VLC_FALSE;
-    }
-
-    if( ( LB2OFF( p_dvd->i_cur_block )
-          - p_input->stream.p_selected_area->i_start )
-            >= p_input->stream.p_selected_area->i_size || b_eot )
-    {
-        if( ( p_input->stream.p_selected_area->i_id + 1 ) >=
-                        p_input->stream.i_area_nb )
-        {
-            /* EOF */
-            vlc_mutex_unlock( &p_input->stream.stream_lock );
-            return 0;
-        }
-
-        /* EOT */
-        msg_Dbg( p_input, "new title" );
-        DvdReadSetArea( p_input, p_input->stream.pp_areas[
-                        p_input->stream.p_selected_area->i_id+1] );
-    }
-
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
-
-    return LB2OFF( i_read_total );
-}
-#undef p_pgc
-
-/*****************************************************************************
- * DvdReadSeek : Goes to a given position on the stream.
- *****************************************************************************
- * This one is used by the input and translate chronological position from
- * input to logical position on the device.
- * The lock should be taken before calling this function.
- *****************************************************************************/
-static void DvdReadSeek( input_thread_t * p_input, off_t i_off )
-{
-    thread_dvd_data_t *     p_dvd;
-    unsigned int            i_lb;
-    unsigned int            i_tmp;
-    unsigned int            i_chapter = 0;
-    unsigned int            i_cell = 0;
-    unsigned int            i_vobu = 0;
-    unsigned int            i_sub_cell = 0;
-
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-    i_off += p_input->stream.p_selected_area->i_start;
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
-
-    i_lb = OFF2LB( i_off );
-    p_dvd = ( thread_dvd_data_t * )p_input->p_access_data;
-
-    /* find cell */
-    while( p_dvd->p_cur_pgc->cell_playback[i_cell].last_sector < i_lb )
-    {
-        i_cell++;
-    }
-
-    /* find chapter */
-    do
-    {
-        pgc_t *     p_pgc;
-        int         pgc_id, pgn;
-
-        i_chapter++;
-        pgc_id = p_dvd->p_vts_file->vts_ptt_srpt->title[
-                    p_dvd->i_ttn-1].ptt[i_chapter-1].pgcn;
-        pgn = p_dvd->p_vts_file->vts_ptt_srpt->title[
-                    p_dvd->i_ttn-1].ptt[i_chapter-1].pgn;
-
-        p_pgc = p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc;
-        i_tmp = p_pgc->program_map[pgn-1];
-
-    } while( i_tmp <= i_cell );
-
-    /* find vobu */
-    while( p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu]
-            <= i_lb )
-    {
-        i_vobu++;
-    }
-
-    /* find sub_cell */
-    while( p_dvd->p_vts_file->vts_c_adt->cell_adr_table[i_sub_cell].start_sector <
-            p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu-1] )
-    {
-        i_sub_cell++;
-    }
-
-/*
-    msg_Dbg( p_input, "cell %d i_sub_cell %d chapter %d vobu %d cell_sector %d vobu_sector %d sub_cell_sector %d",
-            i_cell, i_sub_cell,i_chapter, i_vobu,
-            p_dvd->p_cur_pgc->cell_playback[i_cell].first_sector,
-            p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu],
-            p_dvd->p_vts_file->vts_c_adt->cell_adr_table[i_sub_cell-1].start_sector);
-*/
-    p_dvd->i_cur_block = i_lb;
-    p_dvd->i_next_vobu =
-        p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu];
-    p_dvd->i_pack_len = p_dvd->i_next_vobu - i_lb;
-    p_dvd->i_cur_cell = i_cell;
-    p_dvd->i_chapter = i_chapter;
-    DvdReadFindCell( p_dvd );
-
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-    p_input->stream.p_selected_area->i_tell =
-        LB2OFF ( p_dvd->i_cur_block )
-         - p_input->stream.p_selected_area->i_start;
-    p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
-
-    return;
-}
-
-/*****************************************************************************
- * DvdReadHandleDSI
- *****************************************************************************/
-static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, uint8_t * p_data )
-{
-    navRead_DSI( &(p_dvd->dsi_pack), &(p_data[ DSI_START_BYTE ]) );
-
-    /*
-     * Determine where we go next.  These values are the ones we mostly
-     * care about.
-     */
-    p_dvd->i_cur_block = p_dvd->dsi_pack.dsi_gi.nv_pck_lbn;
-
-    /*
-     * If we're not at the end of this cell, we can determine the next
-     * VOBU to display using the VOBU_SRI information section of the
-     * DSI.  Using this value correctly follows the current angle,
-     * avoiding the doubled scenes in The Matrix, and makes our life
-     * really happy.
-     */
-    if( p_dvd->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL )
-    {
-#if 1
-        switch( ( p_dvd->dsi_pack.sml_pbi.category & 0xf000 ) >> 12 )
-        {
-            case 0x4:
-                /* interleaved unit with no angle */
-                if( p_dvd->dsi_pack.sml_pbi.ilvu_sa != 0 )
-                {
-                    p_dvd->i_next_vobu = p_dvd->i_cur_block +
-                        p_dvd->dsi_pack.sml_pbi.ilvu_sa;
-                    p_dvd->i_pack_len = p_dvd->dsi_pack.sml_pbi.ilvu_ea;
-                }
-                else
-                {
-                    p_dvd->i_next_vobu = p_dvd->i_cur_block +
-                        p_dvd->dsi_pack.dsi_gi.vobu_ea + 1;
-                    p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;
-                }
-                break;
-            case 0x5:
-                /* vobu is end of ilvu */
-                if( p_dvd->dsi_pack.sml_agli.data[p_dvd->i_angle-1].address )
-                {
-                    p_dvd->i_next_vobu = p_dvd->i_cur_block +
-                        p_dvd->dsi_pack.sml_agli.data[p_dvd->i_angle-1].address;
-                    p_dvd->i_pack_len = p_dvd->dsi_pack.sml_pbi.ilvu_ea;
-
-                    break;
-                }
-            case 0x6:
-                /* vobu is beginning of ilvu */
-            case 0x9:
-                /* next scr is 0 */
-            case 0xa:
-                /* entering interleaved section */
-            case 0x8:
-                /* non interleaved cells in interleaved section */
-            default:
-                p_dvd->i_next_vobu = p_dvd->i_cur_block +
-                    ( p_dvd->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
-                p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;
-                break;
-        }
-#else
-        p_dvd->i_next_vobu = p_dvd->i_cur_block +
-            ( p_dvd->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
-        p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;
-#endif
-    }
-    else
-    {
-        p_dvd->i_cur_cell = p_dvd->i_next_cell;
-        DvdReadFindCell( p_dvd );
-
-        p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;
-        p_dvd->i_next_vobu =
-            p_dvd->p_cur_pgc->cell_playback[p_dvd->i_cur_cell].first_sector;
-    }
-
-#if 0
-    msg_Dbg( p_input, 12, "scr %d lbn 0x%02x vobu_ea %d vob_id %d c_id %d",
-             p_dvd->dsi_pack.dsi_gi.nv_pck_scr,
-             p_dvd->dsi_pack.dsi_gi.nv_pck_lbn,
-             p_dvd->dsi_pack.dsi_gi.vobu_ea,
-             p_dvd->dsi_pack.dsi_gi.vobu_vob_idn,
-             p_dvd->dsi_pack.dsi_gi.vobu_c_idn );
-
-    msg_Dbg( p_input, 12, "cat 0x%02x ilvu_ea %d ilvu_sa %d size %d",
-             p_dvd->dsi_pack.sml_pbi.category,
-             p_dvd->dsi_pack.sml_pbi.ilvu_ea,
-             p_dvd->dsi_pack.sml_pbi.ilvu_sa,
-             p_dvd->dsi_pack.sml_pbi.size );
-
-    msg_Dbg( p_input, 12, "next_vobu %d next_ilvu1 %d next_ilvu2 %d",
-             p_dvd->dsi_pack.vobu_sri.next_vobu & 0x7fffffff,
-             p_dvd->dsi_pack.sml_agli.data[ p_dvd->i_angle - 1 ].address,
-             p_dvd->dsi_pack.sml_agli.data[ p_dvd->i_angle ].address);
-#endif
-}
-
-/*****************************************************************************
- * DvdReadFindCell
- *****************************************************************************/
-static void DvdReadFindCell( thread_dvd_data_t * p_dvd )
-{
-    int         pgc_id, pgn;
-    int         i = 0;
-    pgc_t *     p_pgc;
-#define cell p_dvd->p_cur_pgc->cell_playback
-    if( cell[p_dvd->i_cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK )
-    {
-#if 0
-        p_dvd->i_next_cell = p_dvd->i_cur_cell + p_dvd->i_angle_nb;
-        p_dvd->i_cur_cell += p_dvd->i_angle - 1;
-#else
-        p_dvd->i_cur_cell += p_dvd->i_angle - 1;
-
-        while( cell[p_dvd->i_cur_cell+i].block_mode != BLOCK_MODE_LAST_CELL )
-        {
-            i++;
-        }
-        p_dvd->i_next_cell = p_dvd->i_cur_cell + i + 1;
-#endif
-    }
-    else
-    {
-        p_dvd->i_next_cell = p_dvd->i_cur_cell + 1;
-    }
-#undef cell
-    pgc_id = p_dvd->p_vts_file->vts_ptt_srpt->title[
-                p_dvd->i_ttn-1].ptt[p_dvd->i_chapter-1].pgcn;
-    pgn = p_dvd->p_vts_file->vts_ptt_srpt->title[
-                p_dvd->i_ttn-1].ptt[p_dvd->i_chapter-1].pgn;
-    p_pgc = p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc;
-
-    if( p_pgc->program_map[pgn-1] <= p_dvd->i_cur_cell )
-    {
-        p_dvd->i_chapter++;
-        p_dvd->b_eoc = VLC_TRUE;
-    }
-}
-
-/*****************************************************************************
- * DvdReadLaunchDecoders
- *****************************************************************************/
-static void DvdReadLauchDecoders( input_thread_t * p_input )
-{
-    thread_dvd_data_t * p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
-    int i_audio, i_spu;
-
-    input_SelectES( p_input, p_input->stream.pp_es[0] );
-
-    /* For audio: first one if none or a not existing one specified */
-    i_audio = config_GetInt( p_input, "audio-channel" );
-    if( i_audio < 0 /*|| i_audio > i_audio_nb*/ )
-    {
-        config_PutInt( p_input, "audio-channel", 1 );
-        i_audio = 1;
-    }
-    if( i_audio > 0/* && i_audio_nb > 0*/ )
-    {
-        if( config_GetInt( p_input, "audio-type" ) == REQUESTED_A52 )
-        {
-            int     i_a52 = i_audio;
-            while( ( p_input->stream.pp_es[i_a52]->i_fourcc !=
-                   VLC_FOURCC('a','5','2','b') ) && ( i_a52 <=
-                   p_dvd->p_vts_file->vtsi_mat->nr_of_vts_audio_streams ) )
-            {
-                i_a52++;
-            }
-            if( p_input->stream.pp_es[i_a52]->i_fourcc
-                 == VLC_FOURCC('a','5','2','b') )
-            {
-                input_SelectES( p_input, p_input->stream.pp_es[i_a52] );
-            }
-        }
-        else
-        {
-            input_SelectES( p_input, p_input->stream.pp_es[i_audio] );
-        }
-    }
-
-    /* for spu, default is none */
-    i_spu = config_GetInt( p_input, "spu-channel" );
-    if( i_spu < 0 /*|| i_spu > i_spu_nb*/ )
-    {
-        config_PutInt( p_input, "spu-channel", 0 );
-        i_spu = 0;
-    }
-    if( i_spu > 0 /*&& i_spu_nb > 0*/ )
-    {
-        i_spu += p_dvd->p_vts_file->vtsi_mat->nr_of_vts_audio_streams;
-        input_SelectES( p_input, p_input->stream.pp_es[i_spu] );
-    }
-}
diff --git a/modules/access/dvdread/input.h b/modules/access/dvdread/input.h
deleted file mode 100644 (file)
index 3c40a88..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*****************************************************************************
- * input.h: thread structure of the DVD plugin
- *****************************************************************************
- * Copyright (C) 1999-2001 VideoLAN
- * $Id: input.h,v 1.2 2003/01/23 15:52:04 sam Exp $
- *
- * Author: Stéphane Borel <stef@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-
-/* Logical block size for DVD-VIDEO */
-#define LB2OFF(x) ((off_t)(x) * (off_t)(DVD_VIDEO_LB_LEN))
-#define OFF2LB(x) ((x) >> 11)
-
-/*****************************************************************************
- * thread_dvd_data_t: extension of input_thread_t for DVD specificity.
- *****************************************************************************/
-typedef struct thread_dvd_data_s
-{
-    dvd_reader_t *          p_dvdread;
-    dvd_file_t *            p_title;
-
-    ifo_handle_t *          p_vmg_file;
-    ifo_handle_t *          p_vts_file;
-
-    unsigned int            i_title;
-    unsigned int            i_chapter;
-    unsigned int            i_angle;
-    unsigned int            i_angle_nb;
-
-    tt_srpt_t *             p_tt_srpt;
-    pgc_t *                 p_cur_pgc;
-
-    dsi_t                   dsi_pack;
-
-    int                     i_ttn;
-
-    unsigned int            i_pack_len;
-    unsigned int            i_cur_block;
-    unsigned int            i_next_vobu;
-    unsigned int            i_end_block;
-
-    unsigned int            i_cur_cell;
-    unsigned int            i_next_cell;
-    vlc_bool_t              b_eoc;
-} thread_dvd_data_t;
-