]> git.sesse.net Git - vlc/commitdiff
. Beginning of dvd_input.
authorStéphane Borel <stef@videolan.org>
Sun, 14 Jan 2001 07:08:00 +0000 (07:08 +0000)
committerStéphane Borel <stef@videolan.org>
Sun, 14 Jan 2001 07:08:00 +0000 (07:08 +0000)
. Parsing of ifo file almost completed.
. Still does not work well.

Makefile.in
include/config.h.in
include/input_ext-intf.h
include/main.h
src/input/dvd_ifo.c [new file with mode: 0644]
src/input/dvd_ifo.h [new file with mode: 0644]
src/input/input.c
src/input/input_dvd.c [new file with mode: 0644]
src/input/input_dvd.h [new file with mode: 0644]
src/interface/interface.c
src/interface/main.c

index 2df2272113fa90dfcf125f957c0abd36c45b4a46..17167cfaf6d366065d155ade959b2bd944d4dcc8 100644 (file)
@@ -186,6 +186,8 @@ INTERFACE = src/interface/main.o \
 
 INPUT =                src/input/input_ps.o \
                src/input/input_ts.o \
+               src/input/dvd_ifo.o \
+               src/input/input_dvd.o \
                src/input/mpeg_system.o \
                src/input/input_ext-dec.o \
                src/input/input_dec.o \
index 1064af527f6c408637f8ba8e6f96e2de50218773..4bed8ecc279ec063e3959e1092072456c976a569 100644 (file)
  * mark it to be presented */
 #define DEFAULT_PTS_DELAY               (.2*CLOCK_FREQ)
 
+#define INPUT_DVD_DEVICE_VAR            "vlc_dvd_device"
+#define INPUT_DVD_DEVICE_DEFAULT        "/dev/dvd"
 #define INPUT_DVD_AUDIO_VAR             "vlc_dvd_audio"
 #define INPUT_DVD_CHANNEL_VAR           "vlc_dvd_channel"
 #define INPUT_DVD_SUBTITLE_VAR          "vlc_dvd_subtitle"
 #define AOUT_STEREO_DEFAULT             1
 
 /* Volume */
-#define VOLUME_DEFAULT                  256
-#define VOLUME_STEP                     5
-#define VOLUME_MAX                      765
+#define VOLUME_DEFAULT                  512
+#define VOLUME_STEP                     128
+#define VOLUME_MAX                      1024
 
 /* Environment variable for output rate, and default value */
 #define AOUT_RATE_VAR                   "vlc_audio_rate"
index 74fe98b7b80768269d0804fb88e2a860dbbead70..e1fd3890ac4b50d5dd0b20a079f5247013b7cae1 100644 (file)
@@ -4,7 +4,7 @@
  * control the pace of reading. 
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_ext-intf.h,v 1.8 2000/12/21 19:24:26 massiot Exp $
+ * $Id: input_ext-intf.h,v 1.9 2001/01/14 07:08:00 stef Exp $
  *
  * Authors:
  *
@@ -255,6 +255,7 @@ typedef struct input_config_s
 /* Input methods */
 #define INPUT_METHOD_NONE           0            /* input thread is inactive */
 #define INPUT_METHOD_FILE          10   /* stream is read from file p_source */
+#define INPUT_METHOD_DVD           11      /* stream is read from dvd device */
 #define INPUT_METHOD_UCAST         20                         /* UDP unicast */
 #define INPUT_METHOD_MCAST         21                       /* UDP multicast */
 #define INPUT_METHOD_BCAST         22                       /* UDP broadcast */
index 2f072a601b6b9e01311abb0b1ec24c5daceb40c7..26780df2b33dfc8a67e44ab8cc17f5f5e13e029b 100644 (file)
@@ -44,6 +44,7 @@ typedef struct
     boolean_t              b_audio;             /* is audio output allowed ? */
     boolean_t              b_video;             /* is video output allowed ? */
     boolean_t              b_vlans;                 /* are vlans supported ? */
+    boolean_t              b_dvd;                              /* DVD mode ? */
 
     /* Unique threads */
     p_aout_thread_t        p_aout;                    /* audio output thread */
diff --git a/src/input/dvd_ifo.c b/src/input/dvd_ifo.c
new file mode 100644 (file)
index 0000000..9e5d0db
--- /dev/null
@@ -0,0 +1,1038 @@
+/*****************************************************************************
+ * dvd_ifo.c: Functions for ifo parsing
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ *
+ * 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
+ *****************************************************************************/
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <malloc.h>
+
+#include "common.h"
+
+#include "intf_msg.h"
+#include "dvd_ifo.h"
+
+/*
+ * IFO Management.
+ */
+
+/*****************************************************************************
+ * IfoFindStart : When reading directly on a device, finds the offset to the
+ * beginning of video_ts.ifo.
+ *****************************************************************************/
+static int IfoFindStart( ifo_t* p_ifo )
+{
+    char    psz_ifo_start[12] = "DVDVIDEO-VMG";
+    char    psz_test[12];
+
+    read( p_ifo->i_fd, psz_test, 12 );
+
+    while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 )
+    {
+        /* The start of ifo file is on a sector boundary */
+        p_ifo->i_pos = lseek( p_ifo->i_fd,
+                              p_ifo->i_pos + DVD_LB_SIZE,
+                              SEEK_SET );
+        read( p_ifo->i_fd, psz_test, 12 );
+    }
+    p_ifo->i_off = p_ifo->i_pos;
+
+fprintf( stderr, "VMG Off : %d\n", p_ifo->i_off );
+
+    return 0;
+}
+
+/*****************************************************************************
+ * IfoFindVTS : beginning of vts_*.ifo.
+ *****************************************************************************/
+static int IfoFindVTS( ifo_t* p_ifo )
+{
+    char    psz_ifo_start[12] = "DVDVIDEO-VTS";
+    char    psz_test[12];
+
+    read( p_ifo->i_fd, psz_test, 12 );
+
+    while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 )
+    {
+        /* The start of ifo file is on a sector boundary */
+        p_ifo->i_pos = lseek( p_ifo->i_fd,
+                              p_ifo->i_pos + DVD_LB_SIZE,
+                              SEEK_SET );
+        read( p_ifo->i_fd, psz_test, 12 );
+    }
+    p_ifo->i_off = p_ifo->i_pos;
+
+fprintf( stderr, "VTS Off : %d\n", p_ifo->i_off );
+
+    return 0;
+}
+
+/*****************************************************************************
+ * IfoInit : Creates an ifo structure and prepares for parsing directly
+ * on DVD device.
+ *****************************************************************************/
+ifo_t IfoInit( int i_fd )
+{
+    ifo_t       ifo;
+    
+    /* If we are here the dvd device has already been opened */
+    ifo.i_fd = i_fd;
+    /* No data at the beginning of the disk
+     * 512000 bytes is just another value :) */
+    ifo.i_pos = lseek( ifo.i_fd, 250 *DVD_LB_SIZE, SEEK_SET );
+    /* FIXME : use udf filesystem to find the beginning of the file */
+    IfoFindStart( &ifo );
+    
+    return ifo;
+}
+
+/*****************************************************************************
+ * IfoEnd : Frees all the memory allocated to ifo structures
+ *****************************************************************************/
+void IfoEnd( ifo_t* p_ifo )
+{
+    int     i,j;
+
+    /* Free structures from video title sets */
+    for( j=0 ; j<p_ifo->vmg.mat.i_tts_nb ; j++ )
+    {
+        free( p_ifo->p_vts[j].vobu_admap.pi_vobu_ssector );
+        free( p_ifo->p_vts[j].c_adt.p_cell_inf );
+        free( p_ifo->p_vts[j].m_vobu_admap.pi_vobu_ssector );
+        free( p_ifo->p_vts[j].m_c_adt.p_cell_inf );
+        for( i=0 ; i<p_ifo->p_vts[j].tmap_ti.i_nb ; i++ )
+        {
+            free( p_ifo->p_vts[j].tmap_ti.p_tmap[i].pi_sector );
+        }
+        free( p_ifo->p_vts[j].tmap_ti.pi_sbyte );
+        free( p_ifo->p_vts[j].tmap_ti.p_tmap );
+        free( p_ifo->p_vts[j].pgci_ti.p_lu_desc );
+        free( p_ifo->p_vts[j].pgci_ti.p_lu );
+        free( p_ifo->p_vts[j].pgci_ut.p_lu_desc );
+        free( p_ifo->p_vts[j].pgci_ut.p_lu );
+    }
+
+    free( p_ifo->p_vts );
+
+    /* Free structures from video manager */
+    free( p_ifo->vmg.vobu_admap.pi_vobu_ssector );
+    free( p_ifo->vmg.c_adt.p_cell_inf );
+    for( i=0 ; i<p_ifo->vmg.pgci_ut.i_lu_nb ; i++ )
+    {
+        free( p_ifo->vmg.pgci_ut.p_lu[i].p_srp );
+    }
+    free( p_ifo->vmg.pgci_ut.p_lu_desc );
+    free( p_ifo->vmg.pgci_ut.p_lu );
+    for( i=1 ; i<=8 ; i++ )
+    {
+        free( p_ifo->vmg.ptl_mait.p_ptl_mask->ppi_ptl_mask[i] );
+    }
+    free( p_ifo->vmg.ptl_mait.p_ptl_desc );
+    free( p_ifo->vmg.ptl_mait.p_ptl_mask );
+    free( p_ifo->vmg.vts_atrt.pi_vts_atrt_sbyte );
+    free( p_ifo->vmg.vts_atrt.p_vts_atrt );
+    free( p_ifo->vmg.pgc.p_cell_pos_inf );
+    free( p_ifo->vmg.pgc.p_cell_play_inf );
+    free( p_ifo->vmg.pgc.prg_map.pi_entry_cell );
+    free( p_ifo->vmg.pgc.com_tab.psz_cell_com );
+    free( p_ifo->vmg.pgc.com_tab.psz_post_com );
+    free( p_ifo->vmg.pgc.com_tab.psz_pre_com );
+
+    return;
+}
+
+/*
+ * Macros to process ifo files
+ */
+#define GET( p_field , i_len )                                              \
+    {                                                                       \
+        read( p_ifo->i_fd , p_field , i_len );                              \
+fprintf(stderr, "Pos : %d\n", p_ifo->i_pos - i_start);                      \
+        p_ifo->i_pos = lseek( p_ifo->i_fd , p_ifo->i_pos + i_len , SEEK_SET );\
+    }
+
+#define GETC( p_field )                                                     \
+    {                                                                       \
+        read( p_ifo->i_fd , p_field , 1 );                                  \
+fprintf(stderr, "Pos : %d Value : %d\n", p_ifo->i_pos - i_start,            \
+                                          *p_field );                       \
+        p_ifo->i_pos = lseek( p_ifo->i_fd , p_ifo->i_pos + 1 , SEEK_SET );  \
+    }
+
+#define GETS( p_field )                                                     \
+    {                                                                       \
+        read( p_ifo->i_fd , p_field , 2 );                                  \
+        *p_field = ntohs( *p_field );                                       \
+fprintf(stderr, "Pos : %d Value : %d\n", p_ifo->i_pos - i_start,            \
+                                          *p_field );                       \
+        p_ifo->i_pos = lseek( p_ifo->i_fd , p_ifo->i_pos + 2 , SEEK_SET );  \
+    }
+
+#define GETL( p_field )                                                     \
+    {                                                                       \
+        read( p_ifo->i_fd , p_field , 4 );                                  \
+        *p_field = ntohl( *p_field );                                       \
+fprintf(stderr, "Pos : %d Value : %d\n", p_ifo->i_pos - i_start,            \
+                                          *p_field );                       \
+        p_ifo->i_pos = lseek( p_ifo->i_fd , p_ifo->i_pos + 4 , SEEK_SET );  \
+    }
+
+#define GETLL( p_field )                                                    \
+    {                                                                       \
+        read( p_ifo->i_fd , p_field , 8 );                                  \
+        *p_field = ntoh64( *p_field );                                      \
+fprintf(stderr, "Pos : %d Value : %lld\n", p_ifo->i_pos - i_start,          \
+                                            *p_field );                     \
+        p_ifo->i_pos = lseek( p_ifo->i_fd , p_ifo->i_pos + 8 , SEEK_SET );  \
+    }
+
+#define FLUSH( i_len )                                                      \
+    {                                                                       \
+fprintf(stderr, "Pos : %d\n", p_ifo->i_pos - i_start );                     \
+        p_ifo->i_pos = lseek( p_ifo->i_fd , p_ifo->i_pos + i_len , SEEK_SET );\
+    }
+
+/*
+ * Function common to Video Manager and Video Title set Processing
+ */
+
+/*****************************************************************************
+ * ReadPGC : Fills the Program Chain structure.
+ *****************************************************************************/
+static pgc_t ReadPGC( ifo_t* p_ifo )
+{
+    pgc_t   pgc;
+    int     i;
+    int     i_start = p_ifo->i_pos;
+
+fprintf( stderr, "PGC\n" );
+
+    FLUSH(2);
+    GETC( &pgc.i_prg_nb );
+    GETC( &pgc.i_cell_nb );
+    GETL( &pgc.i_play_time );
+    GETL( &pgc.i_prohibited_user_op );
+    for( i=0 ; i<8 ; i++ )
+    {
+        GETS( &pgc.pi_audio_status[i] );
+    }
+    for( i=0 ; i<32 ; i++ )
+    {
+        GETL( &pgc.pi_subpic_status[i] );
+    }
+    GETS( &pgc.i_next_pgc_nb );
+    GETS( &pgc.i_prev_pgc_nb );
+    GETS( &pgc.i_goup_pgc_nb );
+    GETC( &pgc.i_still_time );
+    GETC( &pgc.i_play_mode );
+    for( i=0 ; i<16 ; i++ )
+    {
+        GETL( &pgc.pi_yuv_color[i] );
+        /* FIXME : We have to erase the extra bit */
+    }
+    GETS( &pgc.i_com_tab_sbyte );
+    GETS( &pgc.i_prg_map_sbyte );
+    GETS( &pgc.i_cell_play_inf_sbyte );
+    GETS( &pgc.i_cell_pos_inf_sbyte );
+
+    /* Parsing of pgc_com_tab_t */
+    if( pgc.i_com_tab_sbyte )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, i_start
+                            + pgc.i_com_tab_sbyte, SEEK_SET );
+        GETS( &pgc.com_tab.i_pre_com_nb );
+        GETS( &pgc.com_tab.i_post_com_nb );
+        GETS( &pgc.com_tab.i_cell_com_nb );
+        pgc.com_tab.psz_pre_com = malloc(sizeof(8*pgc.com_tab.i_pre_com_nb));
+        if( pgc.com_tab.psz_pre_com == NULL )
+        {
+            intf_ErrMsg( "Out of memory" );
+            p_ifo->b_error = 1;
+            return pgc;
+        }
+        GET( pgc.com_tab.psz_pre_com, 8*pgc.com_tab.i_pre_com_nb );
+        pgc.com_tab.psz_post_com = malloc(sizeof(8*pgc.com_tab.i_pre_com_nb));
+        if( pgc.com_tab.psz_post_com == NULL )
+        {
+            intf_ErrMsg( "Out of memory" );
+            p_ifo->b_error = 1;
+            return pgc;
+        }
+        GET( pgc.com_tab.psz_post_com, 8*pgc.com_tab.i_post_com_nb );
+        pgc.com_tab.psz_cell_com = malloc(sizeof(8*pgc.com_tab.i_pre_com_nb));
+        if( pgc.com_tab.psz_cell_com == NULL )
+        {
+            intf_ErrMsg( "Out of memory" );
+            p_ifo->b_error = 1;
+            return pgc;
+        }
+        GET( pgc.com_tab.psz_cell_com, 8*pgc.com_tab.i_cell_com_nb );
+    }
+    /* Parsing of pgc_prg_map_t */
+    if( pgc.i_prg_map_sbyte )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, i_start
+                            + pgc.i_prg_map_sbyte, SEEK_SET );
+        pgc.prg_map.pi_entry_cell = malloc( sizeof(pgc.i_prg_nb) );
+        if( pgc.prg_map.pi_entry_cell == NULL )
+        {
+            intf_ErrMsg( "Out of memory" );
+            p_ifo->b_error = 1;
+            return pgc;
+        }
+        GET( pgc.prg_map.pi_entry_cell, pgc.i_prg_nb );
+        /* FIXME : check endianness here */
+    }
+    /* Parsing of cell_play_inf_t */
+    if( pgc.i_cell_play_inf_sbyte )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, i_start
+                            + pgc.i_cell_play_inf_sbyte, SEEK_SET );
+        pgc.p_cell_play_inf = malloc( pgc.i_cell_nb *sizeof(cell_play_inf_t) );
+        if( pgc.p_cell_play_inf == NULL )
+        {
+            intf_ErrMsg( "Out of memory" );
+            p_ifo->b_error = 1;
+            return pgc;
+        }
+        for( i=0 ; i<pgc.i_cell_nb ; i++ )
+        {
+            GETS( &pgc.p_cell_play_inf[i].i_cat );
+            GETC( &pgc.p_cell_play_inf[i].i_still_time );
+            GETS( &pgc.p_cell_play_inf[i].i_com_nb );
+            GETL( &pgc.p_cell_play_inf[i].i_play_time );
+            GETL( &pgc.p_cell_play_inf[i].i_entry_sector );
+            GETL( &pgc.p_cell_play_inf[i].i_first_ilvu_vobu_esector );
+            GETL( &pgc.p_cell_play_inf[i].i_lvobu_ssector );
+            GETL( &pgc.p_cell_play_inf[i].i_lsector );
+        }
+    }
+    /* Parsing of cell_pos_inf_map */
+    if( pgc.i_cell_pos_inf_sbyte )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, i_start
+                            + pgc.i_cell_pos_inf_sbyte, SEEK_SET );
+        pgc.p_cell_pos_inf = malloc( pgc.i_cell_nb *sizeof(cell_pos_inf_t) );
+        if( pgc.p_cell_play_inf == NULL )
+        {
+            intf_ErrMsg( "Out of memory" );
+            p_ifo->b_error = 1;
+            return pgc;
+        }
+        for( i=0 ; i<pgc.i_cell_nb ; i++ )
+        {
+            GETS( &pgc.p_cell_pos_inf[i].i_vob_id );
+            FLUSH( 1 );
+            GETC( &pgc.p_cell_pos_inf[i].i_cell_id );
+        }
+    } 
+
+    return pgc;
+}
+
+/*****************************************************************************
+ * ReadUnitTable : Fills the Language Unit structure.
+ *****************************************************************************/
+static pgci_ut_t ReadUnitTable( ifo_t* p_ifo )
+{
+    pgci_ut_t       lang;
+    int             i, j;
+    int             i_start = p_ifo->i_pos;
+
+fprintf( stderr, "LU\n" );
+
+    GETS( &lang.i_lu_nb );
+    FLUSH( 2 );
+    GETL( &lang.i_ebyte );
+    lang.p_lu_desc = malloc( lang.i_lu_nb *sizeof(pgci_lu_desc_t) );
+    if( lang.p_lu_desc == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return lang;
+    }
+    for( i=0 ; i<lang.i_lu_nb ; i++ )
+    {
+        GETS( &lang.p_lu_desc[i].i_lang_code );
+        FLUSH( 1 );
+        GETC( &lang.p_lu_desc[i].i_existence_mask );
+        GETL( &lang.p_lu_desc[i].i_lu_sbyte );
+    }
+    lang.p_lu = malloc( lang.i_lu_nb *sizeof(pgci_lu_t) );
+    if( lang.p_lu == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return lang;
+    }
+    for( i=0 ; i<lang.i_lu_nb ; i++ )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
+                                lang.p_lu_desc[i].i_lu_sbyte,
+                                SEEK_SET );
+        GETS( &lang.p_lu[i].i_srp_nb );
+        FLUSH( 2 );
+        GETL( &lang.p_lu[i].i_lu_ebyte );
+        lang.p_lu[i].p_srp = malloc( lang.p_lu[i].i_srp_nb *
+                                         sizeof(pgci_srp_t) );
+        if( lang.p_lu[i].p_srp == NULL )
+        {
+            intf_ErrMsg( "Out of memory" );
+            p_ifo->b_error = 1;
+            return lang;
+        }
+        for( j=0 ; j<lang.p_lu[i].i_srp_nb ; j++ )
+        {
+            GETC( &lang.p_lu[i].p_srp[j].i_pgc_cat_mask );
+            GETC( &lang.p_lu[i].p_srp[j].i_pgc_cat );
+            GETS( &lang.p_lu[i].p_srp[j].i_par_mask );
+            GETL( &lang.p_lu[i].p_srp[j].i_pgci_sbyte );
+        }
+        for( j=0 ; j<lang.p_lu[i].i_srp_nb ; j++ )
+        {
+            p_ifo->i_pos = lseek( p_ifo->i_fd,
+                             i_start + lang.p_lu[i].p_srp[j].i_pgci_sbyte,
+                             SEEK_SET );
+            /* FIXME : Bad parsing somiewhere by here : various information
+             * don't match */
+            //lang.p_lu[i].p_srp[j].pgc = ReadPGC( p_ifo );
+        }
+    }
+
+    return lang;
+}
+
+/*****************************************************************************
+ * ReadCellInf : Fills the Cell Information structure.
+ *****************************************************************************/
+static c_adt_t ReadCellInf( ifo_t* p_ifo )
+{
+    c_adt_t         c_adt;
+    int             i, i_max;
+    int             i_start = p_ifo->i_pos;
+
+fprintf( stderr, "CELL ADD\n" );
+
+    GETS( &c_adt.i_vob_nb );
+    FLUSH( 2 );
+    GETL( &c_adt.i_ebyte );
+    i_max = ( i_start + c_adt.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(cell_inf_t);
+    c_adt.p_cell_inf = malloc( i_max *sizeof(cell_inf_t) );
+    if( c_adt.p_cell_inf == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return c_adt;
+    }
+    for( i=0 ; i<i_max ; i++ )
+    {
+        GETS( &c_adt.p_cell_inf[i].i_vob_id );
+        GETC( &c_adt.p_cell_inf[i].i_cell_id );
+        FLUSH( 1 );
+        GETL( &c_adt.p_cell_inf[i].i_ssector );
+        GETL( &c_adt.p_cell_inf[i].i_esector );
+    }
+    
+    return c_adt;
+}
+
+/*****************************************************************************
+ * ReadMap : Fills the VOBU Map structure.
+ *****************************************************************************/
+static vobu_admap_t ReadMap( ifo_t* p_ifo )
+{
+    vobu_admap_t        map;
+    int                 i, i_max;
+    int                 i_start = p_ifo->i_pos;
+    
+fprintf( stderr, "VOBU ADMAP\n" );
+
+    GETL( &map.i_ebyte );
+    i_max = ( i_start + map.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(u32);
+    map.pi_vobu_ssector = malloc( i_max *sizeof(u32) );
+    for( i=0 ; i<i_max ; i++ )
+    {
+        GETL( &map.pi_vobu_ssector[i] );
+    }
+
+    return map;
+}
+/*
+ * Video Manager Information Processing.
+ * This is what is contained in video_ts.ifo.
+ */
+
+/*****************************************************************************
+ * ReadVMGInfMat : Fills the Management Information structure.
+ *****************************************************************************/
+static vmgi_mat_t ReadVMGInfMat( ifo_t* p_ifo )
+{
+    vmgi_mat_t  mat;
+    int         i;
+    int         i_start = p_ifo->i_pos;
+
+fprintf( stderr, "VMGI\n" );
+
+    GET( mat.psz_id , 12 );
+    mat.psz_id[12] = '\0';
+    GETL( &mat.i_lsector );
+    FLUSH( 12 );
+    GETL( &mat.i_i_lsector );
+    FLUSH( 1 );
+    GETC( &mat.i_spec_ver );
+    GETL( &mat.i_cat );
+    GETS( &mat.i_vol_nb );
+    GETS( &mat.i_vol );
+    GETC( &mat.i_disc_side );
+    FLUSH( 19 );
+    GETS( &mat.i_tts_nb );
+    GET( mat.psz_provider_id, 32 );
+    GETLL( &mat.i_pos_code );
+    FLUSH( 24 );
+    GETL( &mat.i_i_mat_ebyte );
+    GETL( &mat.i_fp_pgc_sbyte );
+    FLUSH( 56 );
+    GETL( &mat.i_vobs_ssector );
+    GETL( &mat.i_ptt_srpt_ssector );
+    GETL( &mat.i_pgci_ut_ssector );
+    GETL( &mat.i_ptl_mait_ssector );
+    GETL( &mat.i_vts_atrt_ssector );
+    GETL( &mat.i_txtdt_mg_ssector );
+    GETL( &mat.i_c_adt_ssector );
+    GETL( &mat.i_vobu_admap_ssector );
+    FLUSH( 32 );
+    GETS( &mat.i_video_atrt );
+    FLUSH( 1 );
+    GETC( &mat.i_audio_nb );
+    for( i=0 ; i < 8 ; i++ )
+    {
+        GETLL( &mat.pi_audio_atrt[i] );
+    }
+    FLUSH( 17 );
+    GETC( &mat.i_subpic_nb );
+    for( i=0 ; i < mat.i_subpic_nb ; i++ )
+    {
+        GET( &mat.pi_subpic_atrt[i], 6 );
+        /* FIXME : take care of endianness */
+    }
+
+    return mat;
+}
+
+/*****************************************************************************
+ * ReadVMGTitlePointer : Fills the Part Of Title Search Pointer structure.
+ *****************************************************************************/
+static vmg_ptt_srpt_t ReadVMGTitlePointer( ifo_t* p_ifo )
+{
+    vmg_ptt_srpt_t  ptr;
+    int             i;
+    int             i_start = p_ifo->i_pos;
+
+fprintf( stderr, "PTR\n" );
+
+    GETS( &ptr.i_ttu_nb );
+    FLUSH( 2 );
+    GETL( &ptr.i_ebyte );
+    /* Parsing of tts */
+    ptr.p_tts = malloc( ptr.i_ttu_nb *sizeof(tts_t) );
+    if( ptr.p_tts == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return ptr;
+    }
+    for( i=0 ; i<ptr.i_ttu_nb ; i++ )
+    {
+        GETC( &ptr.p_tts[i].i_play_type );
+        GETC( &ptr.p_tts[i].i_angle_nb );
+        GETS( &ptr.p_tts[i].i_ptt_nb );
+        GETS( &ptr.p_tts[i].i_parental_id );
+        GETC( &ptr.p_tts[i].i_tts_nb );
+        GETC( &ptr.p_tts[i].i_vts_ttn );
+        GETL( &ptr.p_tts[i].i_ssector );
+    }
+
+    return ptr;
+}
+
+/*****************************************************************************
+ * ReadParentalInf : Fills the Parental Management structure.
+ *****************************************************************************/
+static vmg_ptl_mait_t ReadParentalInf( ifo_t* p_ifo )
+{
+    vmg_ptl_mait_t  par;
+    int             i, j, k;
+    int             i_start = p_ifo->i_pos;
+
+fprintf( stderr, "PTL\n" );
+
+    GETS( &par.i_country_nb );
+    GETS( &par.i_vts_nb );
+    GETL( &par.i_ebyte );
+    par.p_ptl_desc = malloc( par.i_country_nb *sizeof(vmg_ptl_mai_desc_t) );
+    if( par.p_ptl_desc == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return par;
+    }
+    for( i=0 ; i<par.i_country_nb ; i++ )
+    {
+        GETS( &par.p_ptl_desc[i].i_country_code );
+        FLUSH( 2 );
+        GETS( &par.p_ptl_desc[i].i_ptl_mai_sbyte );
+        FLUSH( 2 );
+    }
+    par.p_ptl_mask = malloc( par.i_country_nb *sizeof(vmg_ptl_mask_t) );
+    if( par.p_ptl_mask == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return par;
+    }
+    for( i=0 ; i<par.i_country_nb ; i++ )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
+                         par.p_ptl_desc[i].i_ptl_mai_sbyte, SEEK_SET );
+        for( j=1 ; j<=8 ; j++ )
+        {
+            par.p_ptl_mask[i].ppi_ptl_mask[j] =
+                                    malloc( par.i_vts_nb *sizeof(u16) );
+            if( par.p_ptl_mask[i].ppi_ptl_mask[j] == NULL )
+            {
+                intf_ErrMsg( "Out of memory" );
+                p_ifo->b_error = 1;
+                return par;
+            }        
+            for( k=0 ; k<par.i_vts_nb ; k++ )
+            {
+                GETS( &par.p_ptl_mask[i].ppi_ptl_mask[j][k] );
+            }
+        }
+    }
+
+    return par;
+}
+
+/*****************************************************************************
+ * ReadVTSAttr : Fills the structure about VTS attributes.
+ *****************************************************************************/
+static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo )
+{
+    vmg_vts_atrt_t  atrt;
+    int             i, j;
+    int             i_start = p_ifo->i_pos;
+
+fprintf( stderr, "VTS ATTR\n" );
+
+    GETS( &atrt.i_vts_nb );
+    FLUSH( 2 );
+    GETL( &atrt.i_ebyte );
+    atrt.pi_vts_atrt_sbyte = malloc( atrt.i_vts_nb *sizeof(u32) );
+    if( atrt.pi_vts_atrt_sbyte == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return atrt;
+    }
+    for( i=0 ; i<atrt.i_vts_nb ; i++ )
+    {
+        GETL( &atrt.pi_vts_atrt_sbyte[i] );
+    }
+    atrt.p_vts_atrt = malloc( atrt.i_vts_nb *sizeof(vts_atrt_t) );
+    if( atrt.p_vts_atrt == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return atrt;
+    }
+    for( i=0 ; i<atrt.i_vts_nb ; i++ )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, i_start + atrt.pi_vts_atrt_sbyte[i],
+                                SEEK_SET );
+        GETL( &atrt.p_vts_atrt[i].i_ebyte );
+        GETL( &atrt.p_vts_atrt[i].i_cat_app_type );
+        GETS( &atrt.p_vts_atrt[i].i_vtsm_video_atrt );
+        FLUSH( 1 );
+        GETC( &atrt.p_vts_atrt[i].i_vtsm_audio_nb );
+        for( j=0 ; j<atrt.p_vts_atrt[i].i_vtsm_audio_nb ; j++ )
+        {
+            GETLL( &atrt.p_vts_atrt[i].pi_vtsm_audio_atrt[j] );
+        }
+        FLUSH( 1 );
+        GETC( &atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
+        for( j=0 ; j<atrt.p_vts_atrt[i].i_vtsm_subpic_nb ; j++ )
+        {
+            GET( &atrt.p_vts_atrt[i].pi_vtsm_subpic_atrt[j], 6 );
+            /* FIXME : Fix endianness issue here */
+        }
+        GETS( &atrt.p_vts_atrt[i].i_vtstt_video_atrt );
+        FLUSH( 1 );
+        GETL( &atrt.p_vts_atrt[i].i_vtstt_audio_nb );
+        for( j=0 ; j<atrt.p_vts_atrt[i].i_vtstt_audio_nb ; j++ )
+        {
+            GETLL( &atrt.p_vts_atrt[i].pi_vtstt_audio_atrt[j] );
+        }
+        FLUSH( 1 );
+        GETC( &atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
+        for( j=0 ; j<atrt.p_vts_atrt[i].i_vtstt_subpic_nb ; j++ )
+        {
+            GET( &atrt.p_vts_atrt[i].pi_vtstt_subpic_atrt[j], 6 );
+            /* FIXME : Fix endianness issue here */
+        }
+    }
+
+    return atrt;
+}
+                           
+/*****************************************************************************
+ * ReadVMG : Parse video_ts.ifo file to fill the Video Manager structure.
+ *****************************************************************************/
+static vmg_t ReadVMG( ifo_t* p_ifo )
+{
+    vmg_t       vmg;
+
+    p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off, SEEK_SET);
+    vmg.mat = ReadVMGInfMat( p_ifo );
+    p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + 
+                              vmg.mat.i_fp_pgc_sbyte, SEEK_SET );
+    vmg.pgc = ReadPGC( p_ifo );
+    if( vmg.mat.i_ptt_srpt_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vmg.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vmg.ptt_srpt = ReadVMGTitlePointer( p_ifo );
+    }
+    if( vmg.mat.i_pgci_ut_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vmg.mat.i_pgci_ut_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vmg.pgci_ut = ReadUnitTable( p_ifo );
+    }
+    if( vmg.mat.i_ptl_mait_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vmg.mat.i_ptl_mait_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vmg.ptl_mait = ReadParentalInf( p_ifo );
+    }
+    if( vmg.mat.i_vts_atrt_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vmg.mat.i_vts_atrt_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vmg.vts_atrt = ReadVTSAttr( p_ifo );
+    }
+    if( vmg.mat.i_c_adt_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vmg.mat.i_c_adt_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vmg.c_adt = ReadCellInf( p_ifo );
+    }
+    if( vmg.mat.i_vobu_admap_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vmg.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vmg.vobu_admap = ReadMap( p_ifo );
+    }
+    return vmg;
+}
+
+/*
+ * Video Title Set Information Processing.
+ * This is what is contained in vts_*.ifo.
+ */
+
+/*****************************************************************************
+ * ReadVTSInfMat : Fills the Title Set Information structure.
+ *****************************************************************************/
+static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo )
+{
+    vtsi_mat_t  mat;
+    int         i;
+    int         i_start = p_ifo->i_pos;
+
+fprintf( stderr, "VTSI\n" );
+
+    GET( mat.psz_id , 12 );
+    mat.psz_id[12] = '\0';
+    GETL( &mat.i_lsector );
+    FLUSH( 12 );
+    GETL( &mat.i_i_lsector );
+    FLUSH( 1 );
+    GETC( &mat.i_spec_ver );
+    GETL( &mat.i_cat );
+    FLUSH( 90 );
+    GETL( &mat.i_mat_ebyte );
+    FLUSH( 60 );
+    GETL( &mat.i_m_vobs_ssector );
+    GETL( &mat.i_tt_vobs_ssector );
+    GETL( &mat.i_ptt_srpt_ssector );
+    GETL( &mat.i_pgcit_ssector );
+    GETL( &mat.i_m_pgci_ut_ssector );
+    GETL( &mat.i_tmap_ti_ssector );
+    GETL( &mat.i_m_c_adt_ssector );
+    GETL( &mat.i_m_vobu_admap_ssector );
+    GETL( &mat.i_c_adt_ssector );
+    GETL( &mat.i_vobu_admap_ssector );
+    FLUSH( 24 );
+    GETS( &mat.i_m_video_atrt );
+    FLUSH( 1 );
+    GETC( &mat.i_m_audio_nb );
+    for( i=0 ; i<8 ; i++ )
+    {
+        GETLL( &mat.pi_m_audio_atrt[i] );
+    }
+    FLUSH( 17 );
+    GETC( &mat.i_m_subpic_nb );
+    for( i=0 ; i<28 ; i++ )
+    {
+        GET( &mat.pi_m_subpic_atrt[i], 6 );
+        /* FIXME : take care of endianness */
+    }
+    FLUSH( 2 );
+    GETS( &mat.i_video_atrt );
+    FLUSH( 1 );
+    GETC( &mat.i_audio_nb );
+    for( i=0 ; i<8 ; i++ )
+    {
+        GETLL( &mat.pi_audio_atrt[i] );
+    }
+    FLUSH( 17 );
+    GETC( &mat.i_subpic_nb );
+    for( i=0 ; i<mat.i_subpic_nb ; i++ )
+    {
+        GET( &mat.pi_subpic_atrt[i], 6 );
+        /* FIXME : take care of endianness */
+    }
+
+    return mat;
+}
+
+/*****************************************************************************
+ * ReadVTSTitlePointer : Fills the Part Of Title Search Pointer structure.
+ *****************************************************************************/
+static vts_ptt_srpt_t ReadVTSTitlePointer( ifo_t* p_ifo )
+{
+    vts_ptt_srpt_t  ptr;
+    int             i;
+    int             i_start = p_ifo->i_pos;
+
+fprintf( stderr, "PTR\n" );
+
+    GETS( &ptr.i_ttu_nb );
+    FLUSH( 2 );
+    GETL( &ptr.i_ebyte );
+    ptr.pi_ttu_sbyte = malloc( ptr.i_ttu_nb *sizeof(u32) );
+    if( ptr.pi_ttu_sbyte == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return ptr;
+    }
+    for( i=0 ; i<ptr.i_ttu_nb ; i++ )
+    {
+        GETL( &ptr.pi_ttu_sbyte[i] );
+    }
+    /* Parsing of tts */
+    ptr.p_ttu = malloc( ptr.i_ttu_nb *sizeof(ttu_t) );
+    if( ptr.p_ttu == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return ptr;
+    }
+    for( i=0 ; i<ptr.i_ttu_nb ; i++ )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
+                        ptr.pi_ttu_sbyte[i], SEEK_SET );
+        GETS( &ptr.p_ttu[i].i_pgc_nb );
+        GETS( &ptr.p_ttu[i].i_prg_nb );
+    }
+
+    return ptr;
+}
+
+/*****************************************************************************
+ * ReadVTSTimeMap : Fills the time map table
+ *****************************************************************************/
+static vts_tmap_ti_t ReadVTSTimeMap( ifo_t* p_ifo )
+{
+    vts_tmap_ti_t   tmap;
+    int             i,j;
+    int             i_start = p_ifo->i_pos;
+
+fprintf( stderr, "TMAP\n" );
+
+    GETS( &tmap.i_nb );
+    FLUSH( 2 );
+    GETL( &tmap.i_ebyte );
+    tmap.pi_sbyte = malloc( tmap.i_nb *sizeof(u32) );
+    if( tmap.pi_sbyte == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return tmap;
+    }
+    for( i=0 ; i<tmap.i_nb ; i++ )
+    {    
+        GETL( &tmap.pi_sbyte[i] );
+    }
+    tmap.p_tmap = malloc( tmap.i_nb *sizeof(tmap_t) );
+    if( tmap.p_tmap == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return tmap;
+    }
+    for( i=0 ; i<tmap.i_nb ; i++ )
+    {    
+        GETC( &tmap.p_tmap[i].i_time_unit );
+        FLUSH( 1 );
+        GETS( &tmap.p_tmap[i].i_entry_nb );
+        tmap.p_tmap[i].pi_sector =
+                    malloc( tmap.p_tmap[i].i_entry_nb *sizeof(u32) );
+        if( tmap.p_tmap[i].pi_sector == NULL )
+        {
+            intf_ErrMsg( "Out of memory" );
+            p_ifo->b_error = 1;
+            return tmap;
+        }
+        for( j=0 ; j<tmap.p_tmap[i].i_entry_nb ; j++ )
+        {
+            GETL( &tmap.p_tmap[i].pi_sector[j] );
+        }
+    }
+
+    return tmap;
+}
+    
+
+/*****************************************************************************
+ * ReadVTS : Parse vts*.ifo files to fill the Video Title Set structure.
+ *****************************************************************************/
+static vts_t ReadVTS( ifo_t* p_ifo )
+{
+    vts_t       vts;
+
+    vts.i_pos = p_ifo->i_pos;
+
+    vts.mat = ReadVTSInfMat( p_ifo );
+    if( vts.mat.i_ptt_srpt_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vts.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vts.ptt_srpt = ReadVTSTitlePointer( p_ifo );
+    }
+    if( vts.mat.i_m_pgci_ut_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vts.mat.i_m_pgci_ut_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vts.pgci_ut = ReadUnitTable( p_ifo );
+    }
+    if( vts.mat.i_pgcit_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vts.mat.i_pgcit_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vts.pgci_ti = ReadUnitTable( p_ifo );
+    }
+    if( vts.mat.i_tmap_ti_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vts.mat.i_tmap_ti_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vts.tmap_ti = ReadVTSTimeMap( p_ifo );
+    }
+    if( vts.mat.i_m_c_adt_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vts.mat.i_m_c_adt_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vts.m_c_adt = ReadCellInf( p_ifo );
+    }
+    if( vts.mat.i_m_vobu_admap_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vts.mat.i_m_vobu_admap_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vts.m_vobu_admap = ReadMap( p_ifo );
+    }
+    if( vts.mat.i_c_adt_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vts.mat.i_c_adt_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vts.c_adt = ReadCellInf( p_ifo );
+    }
+    if( vts.mat.i_vobu_admap_ssector )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+                        vts.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
+                        SEEK_SET );
+        vts.vobu_admap = ReadMap( p_ifo );
+    }
+
+    return vts;
+}
+
+/*
+ * DVD Information Management
+ */
+
+/*****************************************************************************
+ * IfoRead : Function that fills structure and calls specified functions
+ * to do it.
+ *****************************************************************************/
+void IfoRead( ifo_t* p_ifo )
+{
+    int     i;
+    p_ifo->vmg = ReadVMG( p_ifo );
+    p_ifo->p_vts = malloc( p_ifo->vmg.mat.i_tts_nb *sizeof(vts_t) );
+    if( p_ifo->p_vts == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_ifo->b_error = 1;
+        return;
+    }
+    for( i=0 ; i<1/*p_ifo->vmg.mat.i_tts_nb*/ ; i++ )
+    {
+        p_ifo->i_pos = lseek( p_ifo->i_fd,
+                     p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector *DVD_LB_SIZE,
+                     SEEK_SET );
+        /* FIXME : use udf filesystem to avoid this */
+        IfoFindVTS( p_ifo );
+        p_ifo->p_vts[i] = ReadVTS( p_ifo );
+    }
+    return; 
+}
diff --git a/src/input/dvd_ifo.h b/src/input/dvd_ifo.h
new file mode 100644 (file)
index 0000000..5f2782e
--- /dev/null
@@ -0,0 +1,484 @@
+/*****************************************************************************
+ * ifo.h: Structures for ifo parsing
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ *
+ * 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
+ *****************************************************************************/
+#define DVD_LB_SIZE 2048
+
+/*****************************************************************************
+ * Common structures for Video Management and Video Title sets
+ *****************************************************************************/
+
+/*
+ * Program Chain structures
+ */
+
+/* Program Chain Command Table
+  - start at i_pgc_com_tab_sbyte */
+typedef struct pgc_com_tab_s
+{
+    u16             i_pre_com_nb;               // 2 bytes
+    u16             i_post_com_nb;              // 2 bytes
+    u16             i_cell_com_nb;              // 2 bytes
+//    char[2]         ???
+    char*           psz_pre_com;                // i_pre_com_nb * 8 bytes
+    char*           psz_post_com;               // i_post_com_nb * 8 bytes
+    char*           psz_cell_com;               // i_cell_com_nb * 8 bytes
+} pgc_com_tab_t;
+
+/* Program Chain Map Table
+ * - start at "i_pgc_prg_map_sbyte" */
+typedef struct pgc_prg_map_s
+{
+    u8*             pi_entry_cell;              // i_prg_nb * 1 byte 
+} pgc_prg_map_t;
+
+/* Cell Playback Information Table
+ * we have a pointer to such a structure for each cell  
+ * - first start at "i_cell_play_inf_sbyte" */
+typedef struct cell_play_inf_s
+{
+    /* This information concerns the currently selected cell */
+    u16             i_cat;                      // 2 bytes
+    u8              i_still_time;               // 1 byte; in seconds; ff=inf
+    u8              i_com_nb;                   // 1 byte; 0 = no com
+    u32             i_play_time;                // 4 bytes
+    u32             i_entry_sector;             // 4 bytes
+    u32             i_first_ilvu_vobu_esector;  // 4 bytes; ???
+    u32             i_lvobu_ssector;            // 4 bytes
+    u32             i_lsector;                  // 4 bytes
+} cell_play_inf_t;
+
+/* Cell Position Information Table
+ * we have a pointer to such a structure for each cell 
+ * - first start at "i_cell_pos_inf_sbyte" */
+typedef struct cell_pos_inf_s
+{
+    /* This information concerns the currently selected cell */
+    u16             i_vob_id;                   // 2 bytes
+//    char            ???
+    u8              i_cell_id;                  // 1 byte
+} cell_pos_inf_t;
+
+/* Main structure for Program Chain
+ * - start at i_fp_pgc_sbyte
+ * - or at i_vmgm_pgci_sbyte in vmgm_pgci_srp_t */
+typedef struct pgc_s
+{
+    /* Global features of program chain */
+//    char[2]         ???
+    u8              i_prg_nb;                   // 1 byte
+    u8              i_cell_nb;                  // 1 byte
+    u32             i_play_time;                // 4 bytes
+    u32             i_prohibited_user_op;       // 4 bytes
+    u16             pi_audio_status[8];         // 8*2 bytes
+    u32             pi_subpic_status[32];       // 32*4 bytes
+    u16             i_next_pgc_nb;              // 2 bytes
+    u16             i_prev_pgc_nb;              // 2 bytes
+    u16             i_goup_pgc_nb;              // 2 bytes
+    u8              i_still_time;               // 1 byte ; in seconds
+    u8              i_play_mode;                // 1 byte
+    /* In video_ts.ifo, the 3 significant bytes of each color are
+     * preceded by 1 unsignificant byte */
+    u32             pi_yuv_color[16];           // 16*3 bytes
+    /* Here come the start bytes of the following structures */
+    u16             i_com_tab_sbyte;            // 2 bytes
+    u16             i_prg_map_sbyte;            // 2 bytes
+    u16             i_cell_play_inf_sbyte;      // 2 bytes
+    u16             i_cell_pos_inf_sbyte;       // 2 bytes
+    /* Predefined structures */
+    pgc_com_tab_t   com_tab;
+    pgc_prg_map_t   prg_map;
+    cell_play_inf_t* p_cell_play_inf;           // i_cell_nb * 24 bytes
+    cell_pos_inf_t* p_cell_pos_inf;             // i_cell_nb * 4 bytes
+} pgc_t;
+
+/*
+ * Menu PGCI Unit Table
+ */
+
+/* Menu PGCI Language unit Descriptor */
+typedef struct pgci_lu_desc_s
+{
+    u16             i_lang_code;                // 2 bytes (ISO-xx)
+//    char            ???
+    u8              i_existence_mask;           // 1 byte
+    u32             i_lu_sbyte;                 // 4 bytes
+} pgci_lu_desc_t;
+
+typedef struct pgci_srp_s
+{
+    u8              i_pgc_cat_mask;             // 1 byte
+    u8              i_pgc_cat;                  // 1 byte
+    u16             i_par_mask;                 // 2 bytes
+    u32             i_pgci_sbyte;               // 4 bytes
+    pgc_t           pgc;
+} pgci_srp_t;
+
+/* Menu PGCI Language Unit Table 
+ * - start at i_lu_sbyte */
+typedef struct pgci_lu_s
+{
+    u16             i_srp_nb;                   // 2 bytes
+//    char[2]         ???
+    u32             i_lu_ebyte;                 // 4 bytes
+    pgci_srp_t*     p_srp;                      // i_srp_nb * 8 bytes
+} pgci_lu_t;
+
+/* Main Struct for Menu PGCI
+ * - start at i_*_pgci_ut_ssector */
+typedef struct pgci_ut_s
+{
+    u16             i_lu_nb;                    // 2 bytes; ???
+//    char[2]         ???
+    u32             i_ebyte;                    // 4 bytes
+    pgci_lu_desc_t* p_lu_desc;                  // i_lu_nb * 8 bytes
+    pgci_lu_t*      p_lu;                       // i_lu_nb * 8 bytes
+} pgci_ut_t;
+
+/*
+ * Cell Adress Table Information
+ */
+typedef struct cell_inf_s
+{
+    u16             i_vob_id;                   // 2 bytes
+    u8              i_cell_id;                  // 1 byte
+//    char            ???
+    u32             i_ssector;                  // 4 bytes
+    u32             i_esector;                  // 4 bytes
+} cell_inf_t;
+
+typedef struct c_adt_s
+{
+    u16             i_vob_nb;                   // 2 bytes
+//    char[2]         ???
+    u32             i_ebyte;                    // 4 bytes
+    cell_inf_t*     p_cell_inf;
+} c_adt_t;
+
+
+/*
+ * VOBU Adress Map Table
+ */
+typedef struct vobu_admap_s
+{
+    u32             i_ebyte;                    // 4 bytes
+    u32*            pi_vobu_ssector;            // (nb of vobu) * 4 bytes
+} vobu_admap_t;
+
+/*****************************************************************************
+ * Structures for Video Management (cf video_ts.ifo)
+ *****************************************************************************/
+
+/* 
+ * Video Manager Information Management Table
+ */ 
+typedef struct vmgi_mat_s
+{
+    char            psz_id[13];                 // 12 bytes (DVDVIDEO-VMG)
+    u32             i_lsector;                  // 4 bytes
+//    char[12]        ???
+    u32             i_i_lsector;                // 4 bytes
+//    char            ???
+    u8              i_spec_ver;                 // 1 byte
+    u32             i_cat;                      // 4 bytes
+    u16             i_vol_nb;                   // 2 bytes
+    u16             i_vol;                      // 2 bytes
+    u8              i_disc_side;                // 1 bytes
+//    char[20]        ???
+    u16             i_tts_nb;                   // 2 bytes
+    char            psz_provider_id[32];        // 32 bytes
+    u64             i_pos_code;                 // 8 bytes
+//    char[24]        ???
+    u32             i_i_mat_ebyte;              // 4 bytes
+    u32             i_fp_pgc_sbyte;             // 4 bytes
+//    char[56]        ???
+    u32             i_vobs_ssector;             // 4 bytes
+    u32             i_ptt_srpt_ssector;         // 4 bytes
+    u32             i_pgci_ut_ssector;          // 4 bytes
+    u32             i_ptl_mait_ssector;         // 4 bytes
+    u32             i_vts_atrt_ssector;         // 4 bytes
+    u32             i_txtdt_mg_ssector;         // 4 bytes
+    u32             i_c_adt_ssector;            // 4 bytes
+    u32             i_vobu_admap_ssector;       // 4 bytes
+//    char[2]         ???
+    u16             i_video_atrt;               // 2 bytes
+//    char            ???
+    u8              i_audio_nb;                 // 1 byte
+    u64             pi_audio_atrt[8];           // i_vmgm_audio_nb * 8 bytes
+//    char[16]        ???
+    u8              i_subpic_nb;                // 1 byte
+    u64             pi_subpic_atrt[32];         // i_subpic_nb * 6 bytes
+} vmgi_mat_t;
+
+
+/* 
+ * Part Of Title Search Pointer Table Information
+ */
+
+/* Title sets structure
+ * we have a pointer to this structure for each tts */
+typedef struct tts_s
+{
+    u8              i_play_type;                // 1 byte
+    u8              i_angle_nb;                 // 1 byte
+    u16             i_ptt_nb;                   // 2 bytes; Chapters/PGs
+    u16             i_parental_id;              // 2 bytes
+    u8              i_tts_nb;                   // 1 byte (VTS#)
+    u8              i_vts_ttn;                  // 1 byte ???
+    u32             i_ssector;                  // 4 bytes
+} tts_t;
+
+/* Main struct for tts
+ * - start at "i_vmg_ptt_srpt_ssector" */
+typedef struct vmg_ptt_srpt_s
+{
+    u16             i_ttu_nb;                   // 2 bytes
+//    char[2]         ???
+    u32             i_ebyte;                    // 4 bytes
+    tts_t*          p_tts;                      // i_ttu_nb * 12 bytes
+} vmg_ptt_srpt_t;
+
+/*
+ * Parental Management Information Table
+ */
+typedef struct vmg_ptl_mai_desc_s
+{
+    u16             i_country_code;             // 2 bytes
+//    char[2]         ???
+    u16             i_ptl_mai_sbyte;            // 2 bytes
+//    char[2]         ???
+} vmg_ptl_mai_desc_t;
+
+typedef struct vmg_ptl_mask_s
+{
+    u16*            ppi_ptl_mask[8];            // (i_vts_nb +1) * 8 * 2 bytes
+} vmg_ptl_mask_t;
+
+/* Main struct for parental management
+ * - start at i_vmg_ptl_mait_ssector */
+typedef struct vmg_ptl_mait_s
+{
+    u16             i_country_nb;               // 2 bytes
+    u16             i_vts_nb;                   // 2 bytes
+    u32             i_ebyte;                    // 4 bytes
+    vmg_ptl_mai_desc_t* p_ptl_desc;             // i_country_nb * 8 bytes
+    vmg_ptl_mask_t* p_ptl_mask;        // i_country_nb * sizeof(vmg_ptl_mask_t)
+} vmg_ptl_mait_t;
+
+/*
+ * Video Title Set Attribute Table
+ */
+
+/* Attribute structure : one for each vts
+ * - start at pi_atrt_sbyte */
+typedef struct vts_atrt_s
+{
+    u32             i_ebyte;                    // 4 bytes
+    u32             i_cat_app_type;             // 4 bytes
+    u16             i_vtsm_video_atrt;          // 2 bytes
+//    char            ???
+    u8              i_vtsm_audio_nb;            // 1 byte
+    u64             pi_vtsm_audio_atrt[8];      // i_vtsm_audio_nb * 8 bytes
+//    char            ???
+    u8              i_vtsm_subpic_nb;           // 1 byte
+    u64             pi_vtsm_subpic_atrt[32];    // i_vtsm_subpic_nb * 6 bytes
+    u16             i_vtstt_video_atrt;         // 2 bytes
+//    char            ???
+    u8              i_vtstt_audio_nb;           // 1 byte
+    u64             pi_vtstt_audio_atrt[8];     // i_vtstt_audio_nb * 8 bytes
+//    char            ???
+    u8              i_vtstt_subpic_nb;          // 1 byte
+    u64             pi_vtstt_subpic_atrt[32];   // i_vtstt_subpic_nb * 6 bytes
+} vts_atrt_t;
+
+/* Main struct for vts attributes
+ * - start at i_vmg_vts_atrt_ssector */
+typedef struct vmg_vts_atrt_s
+{
+    u16             i_vts_nb;                   // 2 bytes
+//    char[2]         ???
+    u32             i_ebyte;                    // 4 bytes
+    u32*            pi_vts_atrt_sbyte;          // i_vts_nb * 4 bytes
+    vts_atrt_t*     p_vts_atrt;
+} vmg_vts_atrt_t;
+
+/* 
+ * Global Structure for Video Manager
+ */
+typedef struct vmg_s 
+{
+    vmgi_mat_t      mat;
+    pgc_t           pgc;
+    vmg_ptt_srpt_t  ptt_srpt;
+    pgci_ut_t       pgci_ut;
+    vmg_ptl_mait_t  ptl_mait;
+    vmg_vts_atrt_t  vts_atrt;
+    c_adt_t         c_adt;
+    vobu_admap_t    vobu_admap;
+} vmg_t;
+
+/*****************************************************************************
+ * Structures for Video Title Sets (cf vts_*.ifo)
+ ****************************************************************************/
+
+/* 
+ * Video Title Sets Information Management Table
+ */ 
+typedef struct vtsi_mat_s
+{
+    char            psz_id[13];                 // 12 bytes (DVDVIDEO-VTS)
+    u32             i_lsector;                  // 4 bytes
+//    char[12]        ???
+    u32             i_i_lsector;                // 4 bytes
+//    char            ???
+    u8              i_spec_ver;                 // 1 byte
+    u32             i_cat;                      // 4 bytes
+//    char[90]        ???
+    u32             i_mat_ebyte;                // 4 bytes
+//    char[60]        ???
+    u32             i_m_vobs_ssector;           // 4 bytes
+    u32             i_tt_vobs_ssector;          // 4 bytes
+    u32             i_ptt_srpt_ssector;         // 4 bytes
+    u32             i_pgcit_ssector;            // 4 bytes
+    u32             i_m_pgci_ut_ssector;        // 4 bytes
+    u32             i_tmap_ti_ssector;          // 4 bytes
+    u32             i_m_c_adt_ssector;          // 4 bytes
+    u32             i_m_vobu_admap_ssector;     // 4 bytes
+    u32             i_c_adt_ssector;            // 4 bytes
+    u32             i_vobu_admap_ssector;       // 4 bytes
+//    char[24]        ???
+    u16             i_m_video_atrt;             // 2 bytes
+//    char            ???
+    u8              i_m_audio_nb;               // 1 byte
+    u64             pi_m_audio_atrt[8];         // i_vmgm_audio_nb * 8 bytes
+//    char[16]        ???
+    u8              i_m_subpic_nb;              // 1 byte
+    u64             pi_m_subpic_atrt[32];       // i_subpic_nb * 6 bytes
+                                                // !!! only 28 subpics ???
+//    char[2]         ???
+    u16             i_video_atrt;               // 2 bytes
+//    char            ???
+    u8              i_audio_nb;                 // 1 byte
+    u64             pi_audio_atrt[8];           // i_vmgm_audio_nb * 8 bytes
+//    char[16]        ???
+    u8              i_subpic_nb;                // 1 byte
+    u64             pi_subpic_atrt[32];         // i_subpic_nb * 6 bytes
+} vtsi_mat_t;
+
+/* 
+ * Part Of Title Search Pointer Table Information
+ */
+
+/* Title sets structure
+ * we have a pointer to this structure for each tts */
+typedef struct ttu_s
+{
+    u16             i_pgc_nb;                   // 2 bytes; Chapters/PGs
+    u16             i_prg_nb;                   // 2 bytes
+} ttu_t;
+
+/* Main struct for tts
+ * - start at "i_vts_ptt_srpt_ssector" */
+typedef struct vts_ptt_srpt_s
+{
+    u16             i_ttu_nb;                   // 2 bytes
+//    char[2]         ???
+    u32             i_ebyte;                    // 4 bytes
+    u32*            pi_ttu_sbyte;
+    ttu_t*          p_ttu;                      // i_ttu_nb * 4 bytes
+} vts_ptt_srpt_t;
+
+/*
+ * Time Map table information
+ */
+
+/* Time Map structure */
+typedef struct tmap_s
+{
+    u8              i_time_unit;                // 1 byte
+//    char            ???
+    u16             i_entry_nb;                 // 2 bytes
+    u32*            pi_sector;                  // i_entry_nb * 4 bytes
+} tmap_t;
+
+/* Main structure for tmap_ti
+ * - start at "i_tmap_ti_ssector" */
+typedef struct vts_tmap_ti_s
+{
+    u16             i_nb;                       // 2 bytes
+//    char[2]         ???
+    u32             i_ebyte;                    // 4 bytes
+    u32*            pi_sbyte;                   // i_tmap_nb * 4 bytes
+    tmap_t*         p_tmap;
+} vts_tmap_ti_t;
+
+/*
+ * Video Title Set 
+ */
+typedef struct vts_s
+{
+    u32             i_pos;
+    vtsi_mat_t      mat;
+    /* Part Of Title Search Pointer Table Info */
+    vts_ptt_srpt_t  ptt_srpt;
+    /* Video Title Set Menu PGCI Unit Table */
+    pgci_ut_t       pgci_ut;
+    /* Video Title Set Program Chain Info Table */
+    pgci_ut_t       pgci_ti;
+    /* Video Title Set Time Map Table */
+    vts_tmap_ti_t   tmap_ti;
+    /* VTSM Cell Adress Table Information */
+    c_adt_t         m_c_adt;
+    /* VTSM VOBU Adress Map Table */
+    vobu_admap_t    m_vobu_admap;
+    /* VTS Cell Adress Table Information */
+    c_adt_t         c_adt;
+    /* VTS VOBU Adress Map Table */
+    vobu_admap_t    vobu_admap;
+} vts_t;
+
+/*
+ *  Global Ifo Structure
+ */
+typedef struct ifo_s
+{
+    /* File descriptor for the device */
+    int             i_fd;
+    /* Offset to video_ts.ifo on the device */
+    u32             i_off;
+    /* Position of stream pointer */
+    u32             i_pos;
+    /* Error Management */
+    boolean_t       b_error;
+    /* Structure described in video_ts */
+    vmg_t           vmg;
+    /* Table of vts ifos */
+    vts_t *         p_vts;
+} ifo_t;
+
+/*****************************************************************************
+ * Prototypes in ifo.c
+ *****************************************************************************/
+ifo_t   IfoInit( int );
+void    IfoRead( ifo_t* );
index b02301d8f7e8eedb3943745c8d1dcc6661d94781..8b7d5849dbafb7c547c4ef2322f71e2d231bfbdc 100644 (file)
@@ -4,7 +4,7 @@
  * decoders.
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: input.c,v 1.67 2001/01/07 04:31:18 henri Exp $
+ * $Id: input.c,v 1.68 2001/01/14 07:08:00 stef Exp $
  *
  * Authors: 
  *
@@ -62,6 +62,7 @@ static void ErrorThread ( input_thread_t *p_input );
 static void EndThread   ( input_thread_t *p_input );
 static void NetworkOpen ( input_thread_t *p_input );
 static void FileOpen    ( input_thread_t *p_input );
+static void DvdOpen     ( input_thread_t *p_input );
 
 /*****************************************************************************
  * input_CreateThread: creates a new input thread
@@ -223,6 +224,7 @@ static void RunThread( input_thread_t *p_input )
  * InitThread: init the input thread
  *****************************************************************************/
 input_capabilities_t * PSKludge( void );
+input_capabilities_t * DVDKludge( void );
 static void InitThread( input_thread_t * p_input )
 {
     /* Initialize default settings for spawned decoders */
@@ -243,6 +245,13 @@ static void InitThread( input_thread_t * p_input )
     {
     case INPUT_METHOD_FILE:                                  /* file methods */
         FileOpen( p_input );
+        /* Probe plugin (FIXME: load plugins before & write this) */
+        p_input->p_plugin = PSKludge();
+       break;
+    case INPUT_METHOD_DVD:                                     /* DVD method */
+        DvdOpen( p_input );
+        /* DVD plugin */
+        p_input->p_plugin = DVDKludge();
         break;
     case INPUT_METHOD_VLAN_BCAST:                     /* vlan network method */
 /*        if( !p_main->b_vlans )
@@ -269,8 +278,6 @@ static void InitThread( input_thread_t * p_input )
 
     free( p_input->p_config );
 
-    /* Probe plugin (FIXME: load plugins before & write this) */
-    p_input->p_plugin = PSKludge();
     p_input->p_plugin->pf_init( p_input );
 
     *p_input->pi_status = THREAD_READY;
@@ -398,3 +405,27 @@ static void FileOpen( input_thread_t * p_input )
 
 #undef p_config
 }
+
+/*****************************************************************************
+ * DvdOpen : open the dvd device
+ *****************************************************************************/
+static void DvdOpen( input_thread_t * p_input )
+{
+    intf_Msg( "Opening DVD %s", p_input->p_config->p_source );
+    if( (p_input->i_handle = open( p_input->p_config->p_source,
+                                   O_RDONLY|O_LARGEFILE )) == (-1) )
+    {
+        intf_ErrMsg( "input error: cannot open device %s", strerror(errno) );
+        p_input->b_error = 1;
+        return;
+    }
+
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+
+    p_input->stream.b_pace_control = 1;
+    p_input->stream.b_seekable = 1;
+    p_input->stream.i_size = 0;
+    p_input->stream.i_tell = 0;
+
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+}
diff --git a/src/input/input_dvd.c b/src/input/input_dvd.c
new file mode 100644 (file)
index 0000000..5fd2b4d
--- /dev/null
@@ -0,0 +1,541 @@
+/*****************************************************************************
+ * input_dvd.c: DVD reading
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ *
+ * 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
+ *****************************************************************************/
+#include "defs.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <errno.h>
+#include <malloc.h>
+
+#include "config.h"
+#include "common.h"
+#include "threads.h"
+#include "mtime.h"
+
+#include "intf_msg.h"
+
+#include "main.h"
+
+#include "stream_control.h"
+#include "input_ext-intf.h"
+#include "input_ext-dec.h"
+
+#include "input.h"
+
+#include "dvd_ifo.h"
+#include "input_dvd.h"
+#include "mpeg_system.h"
+
+#include "debug.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int  DVDProbe     ( struct input_thread_s * );
+static int  DVDRead      ( struct input_thread_s *,
+                          data_packet_t * p_packets[INPUT_READ_ONCE] );
+static void DVDInit      ( struct input_thread_s * );
+static void DVDEnd       ( struct input_thread_s * );
+static int  DVDSeek      ( struct input_thread_s *, off_t );
+static int  DVDRewind    ( struct input_thread_s * );
+static struct data_packet_s * NewPacket ( void *, size_t );
+static void DeletePacket( void *, struct data_packet_s * );
+static void DeletePES   ( void *, struct pes_packet_s * );
+
+/*
+ * Data reading functions
+ */
+
+/*****************************************************************************
+ * DVDProbe: check the stream
+ *****************************************************************************/
+static int DVDProbe( input_thread_t * p_input )
+{
+    /* verify that the first three bytes are 0x000001, or unscramble and
+     * re-do. */
+    return 1;
+}
+
+/*****************************************************************************
+ * DVDInit: initializes DVD structures
+ *****************************************************************************/
+static void DVDInit( input_thread_t * p_input )
+{
+    thread_dvd_data_t *  p_method;
+    u32                  i_start;// = 2048*90000;
+
+    if( (p_method = malloc( sizeof(thread_dvd_data_t) )) == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_input->b_error = 1;
+        return;
+    }
+
+    p_input->p_plugin_data = (void *)p_method;
+
+    lseek( p_input->i_handle, 0, SEEK_SET );
+
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+
+    p_method->ifo = IfoInit( p_input->i_handle );
+    IfoRead( &(p_method->ifo) );
+
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+    i_start = p_method->ifo.p_vts[0].i_pos +
+              p_method->ifo.p_vts[0].mat.i_tt_vobs_ssector *DVD_LB_SIZE;
+    fprintf(stderr, "Begin at : %d\n", i_start );
+
+    lseek( p_input->i_handle, i_start, SEEK_SET );
+
+    input_InitStream( p_input, sizeof( stream_ps_data_t ) );
+    input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
+
+    if( p_input->stream.b_seekable )
+    {
+        stream_ps_data_t * p_demux_data =
+             (stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data;
+
+        /* Pre-parse the stream to gather stream_descriptor_t. */
+        p_input->stream.pp_programs[0]->b_is_ok = 0;
+        p_demux_data->i_PSM_version = EMPTY_PSM_VERSION;
+
+        while( !p_input->b_die && !p_input->b_error
+                && !p_demux_data->b_has_PSM )
+        {
+            int                 i_result, i;
+            data_packet_t *     pp_packets[INPUT_READ_ONCE];
+
+            i_result = DVDRead( p_input, pp_packets );
+            if( i_result == 1 )
+            {
+                /* EOF */
+                vlc_mutex_lock( &p_input->stream.stream_lock );
+                p_input->stream.pp_programs[0]->b_is_ok = 1;
+                vlc_mutex_unlock( &p_input->stream.stream_lock );
+                break;
+            }
+            if( i_result == -1 )
+            {
+                p_input->b_error = 1;
+                break;
+            }
+
+            for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
+            {
+                /* FIXME: use i_p_config_t */
+                input_ParsePS( p_input, pp_packets[i] );
+                DeletePacket( p_input->p_method_data, pp_packets[i] );
+            }
+
+            /* File too big. */
+            if( p_input->stream.i_tell > INPUT_PREPARSE_LENGTH )
+            {
+                break;
+            }
+        }
+        lseek( p_input->i_handle, i_start, SEEK_SET );
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+        p_input->stream.i_tell = 0;
+        if( p_demux_data->b_has_PSM )
+        {
+            /* (The PSM decoder will care about spawning the decoders) */
+            p_input->stream.pp_programs[0]->b_is_ok = 1;
+        }
+#ifdef AUTO_SPAWN
+        else
+        {
+            /* (We have to do it ourselves) */
+            int                 i_es;
+
+            /* FIXME: we should do multiple passes in case an audio type
+             * is not present */
+            for( i_es = 0;
+                 i_es < p_input->stream.pp_programs[0]->i_es_number;
+                 i_es++ )
+            {
+#define p_es p_input->stream.pp_programs[0]->pp_es[i_es]
+                switch( p_es->i_type )
+                {
+                    case MPEG1_VIDEO_ES:
+                    case MPEG2_VIDEO_ES:
+                        input_SelectES( p_input, p_es );
+                        break;
+
+                    case MPEG1_AUDIO_ES:
+                    case MPEG2_AUDIO_ES:
+                        if( main_GetIntVariable( INPUT_DVD_AUDIO_VAR, 0 )
+                                == REQUESTED_MPEG 
+                            && main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 )
+                                == (p_es->i_id & 0x1F) )
+                        {
+                            input_SelectES( p_input, p_es );
+                        }
+                        break;
+
+                    case AC3_AUDIO_ES:
+                        if( main_GetIntVariable( INPUT_DVD_AUDIO_VAR, 0 )
+                                == REQUESTED_AC3
+                            && main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 )
+                                == ((p_es->i_id & 0xF00) >> 8) )
+                        {
+                            input_SelectES( p_input, p_es );
+                        }
+                        break;
+
+                    case DVD_SPU_ES:
+                        if( main_GetIntVariable( INPUT_DVD_SUBTITLE_VAR, -1 )
+                                == ((p_es->i_id & 0x1F00) >> 8) )
+                        {
+                            input_SelectES( p_input, p_es );
+                        }
+                        break;
+
+                    case LPCM_AUDIO_ES:
+                        /* FIXME ! */
+                        break;
+                }
+            }
+                    
+        }
+#endif
+#ifdef STATS
+        input_DumpStream( p_input );
+#endif
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+    }
+    else
+    {
+        /* The programs will be added when we read them. */
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+        p_input->stream.pp_programs[0]->b_is_ok = 0;
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+    }
+}
+
+/*****************************************************************************
+ * DVDEnd: frees unused data
+ *****************************************************************************/
+static void DVDEnd( input_thread_t * p_input )
+{
+    free( p_input->stream.p_demux_data );
+    free( p_input->p_plugin_data );
+}
+
+/*****************************************************************************
+ * SafeRead: reads a chunk of stream and correctly detects errors
+ *****************************************************************************/
+static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer,
+                                size_t i_len )
+{
+    thread_dvd_data_t * p_method;
+    int                 i_nb;
+
+    p_method = (thread_dvd_data_t *)p_input->p_plugin_data;
+    i_nb = read( p_input->i_handle, p_buffer, i_len );
+    switch( i_nb )
+    {
+        case 0:
+            /* End of File */
+            return( 1 );
+        case -1:
+            intf_ErrMsg( "Read failed (%s)", strerror(errno) );
+            return( -1 );
+        default:
+            break;
+    }
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    p_input->stream.i_tell += i_nb;
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+    return( 0 );
+}
+
+/*****************************************************************************
+ * DVDRead: reads data packets
+ *****************************************************************************
+ * Returns -1 in case of error, 0 if everything went well, and 1 in case of
+ * EOF.
+ *****************************************************************************/
+static int DVDRead( input_thread_t * p_input,
+                   data_packet_t * pp_packets[INPUT_READ_ONCE] )
+{
+    byte_t              p_header[6];
+    data_packet_t *     p_data;
+    size_t              i_packet_size;
+    int                 i_packet, i_error;
+    thread_dvd_data_t * p_method;
+
+    p_method = (thread_dvd_data_t *)p_input->p_plugin_data;
+
+    memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
+    for( i_packet = 0; i_packet < INPUT_READ_ONCE; i_packet++ )
+    {
+        /* Read what we believe to be a packet header. */
+        if( (i_error = SafeRead( p_input, p_header, 6 )) )
+        {
+            return( i_error );
+        }
+
+        if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L )
+        {
+            /* This is not the startcode of a packet. Read the stream
+             * until we find one. */
+            u32         i_startcode = U32_AT(p_header);
+            int         i_dummy,i_nb;
+
+            if( i_startcode )
+            {
+                /* It is common for MPEG-1 streams to pad with zeros
+                 * (although it is forbidden by the recommendation), so
+                 * don't bother everybody in this case. */
+                intf_WarnMsg( 1, "Garbage at input (%x)", i_startcode );
+            }
+
+            while( (i_startcode & 0xFFFFFF00) != 0x100L )
+            {
+                i_startcode <<= 8;
+                if( (i_nb = read( p_input->i_handle, &i_dummy, 1 )) != 0 )
+                {
+                    i_startcode |= i_dummy;
+fprintf(stderr, "tut :%d %d\n", i_dummy, i_nb );
+                }
+                else
+                {
+fprintf(stderr, "poc\n" );
+                    return( 1 );
+                }
+            }
+
+            /* Packet found. */
+            *(u32 *)p_header = U32_AT(&i_startcode);
+            if( (i_error = SafeRead( p_input, p_header + 4, 2 )) )
+            {
+                return( i_error );
+            }
+        }
+
+        if( U32_AT(p_header) != 0x1BA )
+        {
+            /* That's the case for all packets, except pack header. */
+            i_packet_size = U16_AT(&p_header[4]);
+        }
+        else
+        {
+            /* Pack header. */
+            if( (p_header[4] & 0xC0) == 0x40 )
+            {
+                /* MPEG-2 */
+                i_packet_size = 8;
+            }
+            else if( (p_header[4] & 0xF0) == 0x20 )
+            {
+                /* MPEG-1 */
+                i_packet_size = 6;
+            }
+            else
+            {
+                intf_ErrMsg( "Unable to determine stream type" );
+                return( -1 );
+            }
+        }
+
+        /* Fetch a packet of the appropriate size. */
+        if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL )
+        {
+            intf_ErrMsg( "Out of memory" );
+            return( -1 );
+        }
+
+        /* Copy the header we already read. */
+        memcpy( p_data->p_buffer, p_header, 6 );
+
+        /* Read the remaining of the packet. */
+        if( i_packet_size && (i_error =
+                SafeRead( p_input, p_data->p_buffer + 6, i_packet_size )) )
+        {
+            return( i_error );
+        }
+
+        /* In MPEG-2 pack headers we still have to read stuffing bytes. */
+        if( U32_AT(p_header) == 0x1BA )
+        {
+            if( i_packet_size == 8 && (p_data->p_buffer[13] & 0x7) != 0 )
+            {
+                /* MPEG-2 stuffing bytes */
+                byte_t      p_garbage[8];
+                if( (i_error = SafeRead( p_input, p_garbage,
+                                         p_data->p_buffer[13] & 0x7)) )
+                {
+                    return( i_error );
+                }
+            }
+        }
+
+        /* Give the packet to the other input stages. */
+        pp_packets[i_packet] = p_data;
+    }
+
+    return( 0 );
+}
+
+
+/*****************************************************************************
+ * DVDRewind : reads a stream backward
+ *****************************************************************************/
+static int DVDRewind( input_thread_t * p_input )
+{
+    return( -1 );
+}
+
+/*****************************************************************************
+ * DVDSeek : Goes to a given position on the stream
+ *****************************************************************************/
+static int DVDSeek( input_thread_t * p_input, off_t i_off )
+{
+    return( -1 );
+}
+
+/*
+ * Packet management utilities
+ */
+
+/*****************************************************************************
+ * NewPacket: allocates a data packet
+ *****************************************************************************/
+static struct data_packet_s * NewPacket( void * p_garbage,
+                                         size_t i_size )
+{
+    data_packet_t * p_data;
+
+    /* Safety check */
+    if( i_size > INPUT_MAX_PACKET_SIZE )
+    {
+        intf_ErrMsg( "Packet too big (%d)", i_size );
+        return NULL;
+    }
+
+    if( (p_data = (data_packet_t *)malloc( sizeof(data_packet_t) )) == NULL )
+    {
+        intf_DbgMsg( "Out of memory" );
+        return NULL;
+    }
+
+    if( (p_data->p_buffer = (byte_t *)malloc( i_size )) == NULL )
+    {
+        intf_DbgMsg( "Out of memory" );
+        free( p_data );
+        return NULL;
+    }
+
+    /* Initialize data */
+    p_data->p_next = NULL;
+    p_data->b_discard_payload = 0;
+
+    p_data->p_payload_start = p_data->p_buffer;
+    p_data->p_payload_end = p_data->p_buffer + i_size;
+
+    return( p_data );
+}
+
+/*****************************************************************************
+ * NewPES: allocates a pes packet
+ *****************************************************************************/
+static pes_packet_t * NewPES( void * p_garbage )
+{
+    pes_packet_t * p_pes;
+
+    if( (p_pes = (pes_packet_t *)malloc( sizeof(pes_packet_t) )) == NULL )
+    {
+        intf_DbgMsg( "Out of memory" );
+        return NULL;
+    }
+
+    p_pes->b_messed_up = p_pes->b_data_alignment = p_pes->b_discontinuity =
+        p_pes->i_pts = p_pes->i_dts = 0;
+    p_pes->i_pes_size = 0;
+    p_pes->p_first = NULL;
+
+    return( p_pes );
+}
+
+/*****************************************************************************
+ * DeletePacket: deletes a data packet
+ *****************************************************************************/
+static void DeletePacket( void * p_garbage,
+                          data_packet_t * p_data )
+{
+    ASSERT(p_data);
+    ASSERT(p_data->p_buffer);
+    free( p_data->p_buffer );
+    free( p_data );
+}
+
+/*****************************************************************************
+ * DeletePES: deletes a PES packet and associated data packets
+ *****************************************************************************/
+static void DeletePES( void * p_garbage, pes_packet_t * p_pes )
+{
+    data_packet_t *     p_data;
+    data_packet_t *     p_next;
+
+    p_data = p_pes->p_first;
+
+    while( p_data != NULL )
+    {
+        p_next = p_data->p_next;
+        free( p_data->p_buffer );
+        free( p_data );
+        p_data = p_next;
+    }
+
+    free( p_pes );
+}
+
+/*****************************************************************************
+ * DVDKludge: fakes a DVD plugin (FIXME)
+ *****************************************************************************/
+input_capabilities_t * DVDKludge( void )
+{
+    input_capabilities_t *  p_plugin;
+
+    p_plugin = (input_capabilities_t *)malloc( sizeof(input_capabilities_t) );
+    p_plugin->pf_probe = DVDProbe;
+    p_plugin->pf_init = DVDInit;
+    p_plugin->pf_end = DVDEnd;
+    p_plugin->pf_read = DVDRead;
+    p_plugin->pf_demux = input_DemuxPS; /* FIXME: use i_p_config_t ! */
+    p_plugin->pf_new_packet = NewPacket;
+    p_plugin->pf_new_pes = NewPES;
+    p_plugin->pf_delete_packet = DeletePacket;
+    p_plugin->pf_delete_pes = DeletePES;
+    p_plugin->pf_rewind = DVDRewind;
+    p_plugin->pf_seek = DVDSeek;
+
+    return( p_plugin );
+}
diff --git a/src/input/input_dvd.h b/src/input/input_dvd.h
new file mode 100644 (file)
index 0000000..42f8991
--- /dev/null
@@ -0,0 +1,30 @@
+/*****************************************************************************
+ * input_dvd.h: thread structure of the DVD plugin
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * thread_dvd_data_t: extension of input_thread_t for DVD specificity
+ *****************************************************************************/
+typedef struct thread_dvd_data_s
+{
+    /* Structure that contains all information of the DVD */
+    struct ifo_s            ifo;
+} thread_dvd_data_t;
index 7e08aa0e2eceab19be94f8595387413ffbbbec9f..01289d2d45639883539400c49a3224b2b4bd759e 100644 (file)
@@ -202,6 +202,23 @@ void intf_Run( intf_thread_t *p_intf )
             p_intf->p_input = input_CreateThread( p_input_config, NULL );
         }
     }
+    /* DVD mode */
+    else if( p_main->b_dvd )
+    {
+        if( (p_input_config =
+              (input_config_t *)malloc( sizeof(input_config_t) )) == NULL )
+        {
+            intf_ErrMsg( "intf error: cannot create input_config_t" );
+        }
+        else
+        {
+            p_input_config->i_method = INPUT_METHOD_DVD;
+            p_input_config->p_source = main_GetPszVariable( INPUT_DVD_DEVICE_VAR, INPUT_DVD_DEVICE_DEFAULT );
+            p_input_config->p_default_aout = p_main->p_aout;
+            p_input_config->p_default_vout = p_intf->p_vout;
+            p_intf->p_input = input_CreateThread( p_input_config, NULL );
+        }
+    }
     /* Or if a file was specified */
     else if( p_main->p_playlist->p_list != NULL )
     {
@@ -452,15 +469,15 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key )
          * its own error messages */
         intf_SelectChannel( p_intf, k_reply.param );
         break;
-    case INTF_KEY_INC_VOLUME:                                                    /* volume + */
+    case INTF_KEY_INC_VOLUME:                                    /* volume + */
         if( (p_main->p_aout != NULL) && (p_main->p_aout->vol < VOLUME_MAX) )
             p_main->p_aout->vol += VOLUME_STEP;
         break;
-    case INTF_KEY_DEC_VOLUME:                                                    /* volume - */
+    case INTF_KEY_DEC_VOLUME:                                    /* volume - */
         if( (p_main->p_aout != NULL) && (p_main->p_aout->vol > VOLUME_STEP) )
             p_main->p_aout->vol -= VOLUME_STEP;
         break;
-    case INTF_KEY_TOGGLE_VOLUME:                                                 /* toggle mute */
+    case INTF_KEY_TOGGLE_VOLUME:                              /* toggle mute */
         if( (p_main->p_aout != NULL) && (p_main->p_aout->vol))
         {
             i_volbackup = p_main->p_aout->vol;
@@ -469,7 +486,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key )
         else if( (p_main->p_aout != NULL) && (!p_main->p_aout->vol))
             p_main->p_aout->vol = i_volbackup;
         break;
-    case INTF_KEY_DEC_GAMMA:                                                     /* gamma - */
+    case INTF_KEY_DEC_GAMMA:                                      /* gamma - */
         if( (p_intf->p_vout != NULL) && (p_intf->p_vout->f_gamma > -INTF_GAMMA_LIMIT) )
         {
             vlc_mutex_lock( &p_intf->p_vout->change_lock );
@@ -478,7 +495,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key )
             vlc_mutex_unlock( &p_intf->p_vout->change_lock );
         }
         break;
-    case INTF_KEY_INC_GAMMA:                                                     /* gamma + */
+    case INTF_KEY_INC_GAMMA:                                      /* gamma + */
         if( (p_intf->p_vout != NULL) && (p_intf->p_vout->f_gamma < INTF_GAMMA_LIMIT) )
         {
             vlc_mutex_lock( &p_intf->p_vout->change_lock );
@@ -487,7 +504,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key )
             vlc_mutex_unlock( &p_intf->p_vout->change_lock );
         }
         break;
-    case INTF_KEY_TOGGLE_GRAYSCALE:                                            /* toggle grayscale */
+    case INTF_KEY_TOGGLE_GRAYSCALE:                      /* toggle grayscale */
         if( p_intf->p_vout != NULL )
         {
             vlc_mutex_lock( &p_intf->p_vout->change_lock );
@@ -496,7 +513,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key )
             vlc_mutex_unlock( &p_intf->p_vout->change_lock );
         }
         break;
-    case INTF_KEY_TOGGLE_INTERFACE:                                            /* toggle interface */
+    case INTF_KEY_TOGGLE_INTERFACE:                      /* toggle interface */
         if( p_intf->p_vout != NULL )
         {
             vlc_mutex_lock( &p_intf->p_vout->change_lock );
@@ -505,7 +522,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key )
             vlc_mutex_unlock( &p_intf->p_vout->change_lock );
         }
         break;
-    case INTF_KEY_TOGGLE_INFO:                                                 /* toggle info */
+    case INTF_KEY_TOGGLE_INFO:                                /* toggle info */
         if( p_intf->p_vout != NULL )
         {
             vlc_mutex_lock( &p_intf->p_vout->change_lock );
@@ -514,7 +531,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key )
             vlc_mutex_unlock( &p_intf->p_vout->change_lock );
         }
         break;
-    case INTF_KEY_TOGGLE_SCALING:                                              /* toggle scaling */
+    case INTF_KEY_TOGGLE_SCALING:                          /* toggle scaling */
         if( p_intf->p_vout != NULL )
         {
             vlc_mutex_lock( &p_intf->p_vout->change_lock );
index bbf7f382b2089746097f1681ce2b135bc9a03fcb..a32976ec69336eeb5a05089faa044b7a959d16dc 100644 (file)
@@ -85,6 +85,7 @@
 #define OPT_SERVER              171
 #define OPT_PORT                172
 #define OPT_BROADCAST           173
+#define OPT_DVD                 174
 
 #define OPT_SYNCHRO             180
 
@@ -132,6 +133,7 @@ static const struct option longopts[] =
     {   "server",           1,          0,      OPT_SERVER },
     {   "port",             1,          0,      OPT_PORT },
     {   "broadcast",        0,          0,      OPT_BROADCAST },
+    {   "dvd",              0,          0,      OPT_DVD },
 
     /* Synchro options */
     {   "synchro",          1,          0,      OPT_SYNCHRO },
@@ -458,6 +460,7 @@ static void SetDefaultConfiguration( void )
     p_main->b_audio  = 1;
     p_main->b_video  = 1;
     p_main->b_vlans  = 0;
+    p_main->b_dvd    = 0;
 }
 
 /*****************************************************************************
@@ -589,6 +592,9 @@ static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
         case OPT_BROADCAST:                                   /* --broadcast */
             main_PutIntVariable( INPUT_BROADCAST_VAR, 1 );
             break;
+        case OPT_DVD:                                               /* --dvd */
+            p_main->b_dvd = 1;
+            break;
 
         /* Synchro options */
         case OPT_SYNCHRO:                                      
@@ -658,6 +664,7 @@ static void Usage( int i_fashion )
               "\n      --server <host>            \tvideo server address"
               "\n      --port <port>              \tvideo server port"
               "\n      --broadcast                \tlisten to a broadcast"
+              "\n      --dvd                      \tread dvd"
               "\n"
               "\n      --synchro <type>           \tforce synchro algorithm"
               "\n"
@@ -705,7 +712,9 @@ static void Usage( int i_fashion )
               "\n  " INPUT_IFACE_VAR "=<interface>          \tnetwork interface"
               "\n  " INPUT_BROADCAST_VAR "={1|0}            \tbroadcast mode"
               "\n  " INPUT_VLAN_SERVER_VAR "=<hostname>     \tvlan server"
-              "\n  " INPUT_VLAN_PORT_VAR "=<port>           \tvlan server port" );
+              "\n  " INPUT_VLAN_PORT_VAR "=<port>           \tvlan server port"
+              "\n  " INPUT_DVD_DEVICE_VAR "=<device>        \tDVD device"
+ );
 
     /* Synchro parameters */
     intf_Msg( "\nSynchro parameters:"