Commit 17a54d55 authored by Stéphane Borel's avatar Stéphane Borel

-New ES detection based on .ifo for DVD module. It might fail (I have

found one DVD for which ifo seems false).

-Title and chapter selection on the command line (see -t and -T options)
It will allow to watch some DVD that went through menus by default.

-beginning of menus in gnome interface.
parent 4b1da9cc
...@@ -213,6 +213,8 @@ ...@@ -213,6 +213,8 @@
#define INPUT_DVD_DEVICE_VAR "vlc_dvd_device" #define INPUT_DVD_DEVICE_VAR "vlc_dvd_device"
#define INPUT_DVD_DEVICE_DEFAULT "/dev/dvd" #define INPUT_DVD_DEVICE_DEFAULT "/dev/dvd"
#define INPUT_TITLE_VAR "vlc_input_title"
#define INPUT_CHAPTER_VAR "vlc_input_chapter"
#define INPUT_AUDIO_VAR "vlc_input_audio" #define INPUT_AUDIO_VAR "vlc_input_audio"
#define INPUT_CHANNEL_VAR "vlc_input_channel" #define INPUT_CHANNEL_VAR "vlc_input_channel"
#define INPUT_SUBTITLE_VAR "vlc_input_subtitle" #define INPUT_SUBTITLE_VAR "vlc_input_subtitle"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input.h: structures of the input not exported to other modules * input.h: structures of the input not exported to other modules
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: input.h,v 1.30 2001/02/20 02:53:13 stef Exp $ * $Id: input.h,v 1.31 2001/02/22 08:44:45 stef Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -66,6 +66,7 @@ struct es_descriptor_s * input_AddES ( struct input_thread_s *, ...@@ -66,6 +66,7 @@ struct es_descriptor_s * input_AddES ( struct input_thread_s *,
size_t ); size_t );
void input_DelES ( struct input_thread_s *, struct es_descriptor_s * ); void input_DelES ( struct input_thread_s *, struct es_descriptor_s * );
int input_SelectES ( struct input_thread_s *, struct es_descriptor_s * ); int input_SelectES ( struct input_thread_s *, struct es_descriptor_s * );
int input_UnSelectES( struct input_thread_s *, struct es_descriptor_s * );
/***************************************************************************** /*****************************************************************************
* Prototypes from input_dec.c * Prototypes from input_dec.c
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dvd_css.c: Functions for DVD authentification and unscrambling * dvd_css.c: Functions for DVD authentification and unscrambling
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_css.c,v 1.14 2001/02/20 23:30:15 sam Exp $ * $Id: dvd_css.c,v 1.15 2001/02/22 08:44:45 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -1199,7 +1199,7 @@ int CSSGetKey( css_t * p_css ) ...@@ -1199,7 +1199,7 @@ int CSSGetKey( css_t * p_css )
* produces multiple keys (RT) * produces multiple keys (RT)
*/ */
intf_WarnMsg( 3, "CSS: Title %d key: %02X %02X %02X %02X %02X", intf_WarnMsg( 3, "CSS: Title %d key: %02X %02X %02X %02X %02X",
i_title + 1, i_title,
p_title_key[i_highest].pi_key[0], p_title_key[i_highest].pi_key[0],
p_title_key[i_highest].pi_key[1], p_title_key[i_highest].pi_key[1],
p_title_key[i_highest].pi_key[2], p_title_key[i_highest].pi_key[2],
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dvd_ifo.c: Functions for ifo parsing * dvd_ifo.c: Functions for ifo parsing
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_ifo.c,v 1.13 2001/02/20 07:49:12 sam Exp $ * $Id: dvd_ifo.c,v 1.14 2001/02/22 08:44:45 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -528,6 +528,7 @@ static vobu_admap_t ReadMap( ifo_t* p_ifo ) ...@@ -528,6 +528,7 @@ static vobu_admap_t ReadMap( ifo_t* p_ifo )
static vmgi_mat_t ReadVMGInfMat( ifo_t* p_ifo ) static vmgi_mat_t ReadVMGInfMat( ifo_t* p_ifo )
{ {
vmgi_mat_t mat; vmgi_mat_t mat;
u64 i_temp;
int i; int i;
// off_t i_start = p_ifo->i_pos; // off_t i_start = p_ifo->i_pos;
...@@ -561,20 +562,21 @@ static vmgi_mat_t ReadVMGInfMat( ifo_t* p_ifo ) ...@@ -561,20 +562,21 @@ static vmgi_mat_t ReadVMGInfMat( ifo_t* p_ifo )
GETL( &mat.i_c_adt_ssector ); GETL( &mat.i_c_adt_ssector );
GETL( &mat.i_vobu_admap_ssector ); GETL( &mat.i_vobu_admap_ssector );
FLUSH( 32 ); FLUSH( 32 );
GETS( &mat.i_video_atrt ); // GETS( &mat.video_atrt );
FLUSH(2);
FLUSH( 1 ); FLUSH( 1 );
GETC( &mat.i_audio_nb ); GETC( &mat.i_audio_nb );
//fprintf( stderr, "vmgi audio nb : %d\n", mat.i_audio_nb ); //fprintf( stderr, "vmgi audio nb : %d\n", mat.i_audio_nb );
for( i=0 ; i < 8 ; i++ ) for( i=0 ; i < 8 ; i++ )
{ {
GETLL( &mat.pi_audio_atrt[i] ); GETLL( &i_temp );
} }
FLUSH( 17 ); FLUSH( 17 );
GETC( &mat.i_subpic_nb ); GETC( &mat.i_subpic_nb );
//fprintf( stderr, "vmgi subpic nb : %d\n", mat.i_subpic_nb ); //fprintf( stderr, "vmgi subpic nb : %d\n", mat.i_subpic_nb );
for( i=0 ; i < mat.i_subpic_nb ; i++ ) for( i=0 ; i < mat.i_subpic_nb ; i++ )
{ {
GET( &mat.pi_subpic_atrt[i], 6 ); GET( &i_temp, 6 );
/* FIXME : take care of endianness */ /* FIXME : take care of endianness */
} }
...@@ -685,6 +687,7 @@ static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo ) ...@@ -685,6 +687,7 @@ static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo )
{ {
vmg_vts_atrt_t atrt; vmg_vts_atrt_t atrt;
int i, j; int i, j;
u64 i_temp;
off_t i_start = p_ifo->i_pos; off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "VTS ATTR\n" ); //fprintf( stderr, "VTS ATTR\n" );
...@@ -718,37 +721,39 @@ static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo ) ...@@ -718,37 +721,39 @@ static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo )
SEEK_SET ); SEEK_SET );
GETL( &atrt.p_vts_atrt[i].i_ebyte ); GETL( &atrt.p_vts_atrt[i].i_ebyte );
GETL( &atrt.p_vts_atrt[i].i_cat_app_type ); GETL( &atrt.p_vts_atrt[i].i_cat_app_type );
GETS( &atrt.p_vts_atrt[i].i_vtsm_video_atrt ); // GETS( &atrt.p_vts_atrt[i].vtsm_video_atrt );
FLUSH(2);
FLUSH( 1 ); FLUSH( 1 );
GETC( &atrt.p_vts_atrt[i].i_vtsm_audio_nb ); GETC( &atrt.p_vts_atrt[i].i_vtsm_audio_nb );
//fprintf( stderr, "m audio nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_audio_nb ); //fprintf( stderr, "m audio nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_audio_nb );
for( j=0 ; j<8 ; j++ ) for( j=0 ; j<8 ; j++ )
{ {
GETLL( &atrt.p_vts_atrt[i].pi_vtsm_audio_atrt[j] ); GETLL( &i_temp );
} }
FLUSH( 17 ); FLUSH( 17 );
GETC( &atrt.p_vts_atrt[i].i_vtsm_subpic_nb ); GETC( &atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
//fprintf( stderr, "m subp nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_subpic_nb ); //fprintf( stderr, "m subp nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
for( j=0 ; j<28 ; j++ ) for( j=0 ; j<28 ; j++ )
{ {
GET( &atrt.p_vts_atrt[i].pi_vtsm_subpic_atrt[j], 6 ); GET( &i_temp, 6 );
/* FIXME : Fix endianness issue here */ /* FIXME : Fix endianness issue here */
} }
FLUSH( 2 ); FLUSH( 2 );
GETS( &atrt.p_vts_atrt[i].i_vtstt_video_atrt ); // GETS( &atrt.p_vts_atrt[i].vtstt_video_atrt );
FLUSH(2);
FLUSH( 1 ); FLUSH( 1 );
GETL( &atrt.p_vts_atrt[i].i_vtstt_audio_nb ); GETL( &atrt.p_vts_atrt[i].i_vtstt_audio_nb );
//fprintf( stderr, "tt audio nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_audio_nb ); //fprintf( stderr, "tt audio nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_audio_nb );
for( j=0 ; j<8 ; j++ ) for( j=0 ; j<8 ; j++ )
{ {
GETLL( &atrt.p_vts_atrt[i].pi_vtstt_audio_atrt[j] ); GETLL( &i_temp );
} }
FLUSH( 17 ); FLUSH( 17 );
GETC( &atrt.p_vts_atrt[i].i_vtstt_subpic_nb ); GETC( &atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
//fprintf( stderr, "tt subp nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_subpic_nb ); //fprintf( stderr, "tt subp nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
for( j=0 ; j<28/*atrt.p_vts_atrt[i].i_vtstt_subpic_nb*/ ; j++ ) for( j=0 ; j<28/*atrt.p_vts_atrt[i].i_vtstt_subpic_nb*/ ; j++ )
{ {
GET( &atrt.p_vts_atrt[i].pi_vtstt_subpic_atrt[j], 6 ); GET( &i_temp, 6 );
/* FIXME : Fix endianness issue here */ /* FIXME : Fix endianness issue here */
} }
} }
...@@ -825,6 +830,7 @@ static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo ) ...@@ -825,6 +830,7 @@ static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo )
{ {
vtsi_mat_t mat; vtsi_mat_t mat;
int i; int i;
u64 i_temp;
// off_t i_start = p_ifo->i_pos; // off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "VTSI\n" ); //fprintf( stderr, "VTSI\n" );
...@@ -851,36 +857,61 @@ static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo ) ...@@ -851,36 +857,61 @@ static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo )
GETL( &mat.i_c_adt_ssector ); GETL( &mat.i_c_adt_ssector );
GETL( &mat.i_vobu_admap_ssector ); GETL( &mat.i_vobu_admap_ssector );
FLUSH( 24 ); FLUSH( 24 );
GETS( &mat.i_m_video_atrt ); // GETS( &mat.m_video_atrt );
FLUSH(2);
FLUSH( 1 ); FLUSH( 1 );
GETC( &mat.i_m_audio_nb ); GETC( &mat.i_m_audio_nb );
for( i=0 ; i<8 ; i++ ) for( i=0 ; i<8 ; i++ )
{ {
GETLL( &mat.pi_m_audio_atrt[i] ); GETLL( &i_temp );
} }
FLUSH( 17 ); FLUSH( 17 );
GETC( &mat.i_m_subpic_nb ); GETC( &mat.i_m_subpic_nb );
for( i=0 ; i<28 ; i++ ) for( i=0 ; i<28 ; i++ )
{ {
GET( &mat.pi_m_subpic_atrt[i], 6 ); GET( &i_temp, 6 );
/* FIXME : take care of endianness */ /* FIXME : take care of endianness */
} }
FLUSH( 2 ); FLUSH( 2 );
GETS( &mat.i_video_atrt ); // GETS( &mat.video_atrt );
FLUSH(2);
FLUSH( 1 ); FLUSH( 1 );
GETC( &mat.i_audio_nb ); GETC( &mat.i_audio_nb );
//fprintf( stderr, "vtsi audio nb : %d\n", mat.i_audio_nb ); //fprintf( stderr, "vtsi audio nb : %d\n", mat.i_audio_nb );
for( i=0 ; i<8 ; i++ ) for( i=0 ; i<8 ; i++ )
{ {
GETLL( &mat.pi_audio_atrt[i] ); GETLL( &i_temp );
//fprintf( stderr, "Audio %d: %llx\n", i, i_temp );
i_temp >>= 32;
mat.p_audio_atrt[i].i_lang_code = i_temp & 0xffff;
i_temp >>= 16;
mat.p_audio_atrt[i].i_num_channels = i_temp & 0x7;
i_temp >>= 4;
mat.p_audio_atrt[i].i_sample_freq = i_temp & 0x3;
i_temp >>= 2;
mat.p_audio_atrt[i].i_quantization = i_temp & 0x3;
i_temp >>= 2;
mat.p_audio_atrt[i].i_appl_mode = i_temp & 0x3;
i_temp >>= 2;
mat.p_audio_atrt[i].i_type = i_temp & 0x3;
i_temp >>= 2;
mat.p_audio_atrt[i].i_multichannel_extension = i_temp & 0x1;
i_temp >>= 1;
mat.p_audio_atrt[i].i_coding_mode = i_temp & 0x7;
} }
FLUSH( 17 ); FLUSH( 17 );
GETC( &mat.i_subpic_nb ); GETC( &mat.i_subpic_nb );
//fprintf( stderr, "vtsi subpic nb : %d\n", mat.i_subpic_nb ); //fprintf( stderr, "vtsi subpic nb : %d\n", mat.i_subpic_nb );
for( i=0 ; i<mat.i_subpic_nb ; i++ ) for( i=0 ; i<mat.i_subpic_nb ; i++ )
{ {
GET( &mat.pi_subpic_atrt[i], 6 ); GET( &i_temp, 6 );
/* FIXME : take care of endianness */ i_temp = hton64( i_temp ) >> 16;
//fprintf( stderr, "Subpic %d: %llx\n", i, i_temp );
mat.p_subpic_atrt[i].i_caption = i_temp & 0xff;
i_temp >>= 16;
mat.p_subpic_atrt[i].i_lang_code = i_temp & 0xffff;
i_temp >>= 16;
mat.p_subpic_atrt[i].i_prefix = i_temp & 0xffff;
} }
return mat; return mat;
...@@ -999,7 +1030,8 @@ int IfoReadVTS( ifo_t* p_ifo ) ...@@ -999,7 +1030,8 @@ int IfoReadVTS( ifo_t* p_ifo )
intf_WarnMsg( 2, "ifo: initializing VTS %d", p_ifo->i_title ); intf_WarnMsg( 2, "ifo: initializing VTS %d", p_ifo->i_title );
i_title = p_ifo->i_title; i_title = p_ifo->i_title;
i_off = (off_t)( p_ifo->vmg.ptt_srpt.p_tts[i_title].i_ssector ) *DVD_LB_SIZE i_off = (off_t)( p_ifo->vmg.ptt_srpt.p_tts[i_title-1].i_ssector )
* DVD_LB_SIZE
+ p_ifo->i_off; + p_ifo->i_off;
p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET ); p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dvd_ifo.h: Structures for ifo parsing * dvd_ifo.h: Structures for ifo parsing
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_ifo.h,v 1.7 2001/02/20 02:53:13 stef Exp $ * $Id: dvd_ifo.h,v 1.8 2001/02/22 08:44:45 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -33,6 +33,47 @@ ...@@ -33,6 +33,47 @@
/* /*
* Program Chain structures * Program Chain structures
*/ */
typedef struct ifo_video_s
{
u8 i_compression ;// 2;
u8 i_system ;// 2;
u8 i_ratio ;// 2;
u8 i_perm_displ ;// 2;
u8 i_line21_1 ;// 1;
u8 i_line21_2 ;// 1;
u8 i_source_res ;// 2;
u8 i_letterboxed ;// 1;
u8 i_mode ;// 1;
} ifo_video_t;
/* Audio type information */
typedef struct ifo_audio_s
{
u8 i_coding_mode ;// 3;
u8 i_multichannel_extension ;// 1;
u8 i_type ;// 2;
u8 i_appl_mode ;// 2;
u8 i_quantization ;// 2;
u8 i_sample_freq ;// 2;
// u8 ;// 1;
u8 i_num_channels ;// 3;
u16 i_lang_code ;// 16; // <char> description
u8 i_foo ;// 8; // 0x00000000 ?
u8 i_caption ;// 8;
u8 i_bar ;// 8; // 0x00000000 ?
} ifo_audio_t;
typedef struct ifo_spu_t
{
u16 i_prefix ;// 16; // 0x0100 ?
u16 i_lang_code ;// 16; // <char> description
u8 i_foo ;// 8; // dont know
u8 i_caption ;// 8; // 0x00 ?
} ifo_spu_t;
/* Ifo vitual machine Commands */ /* Ifo vitual machine Commands */
typedef struct ifo_command_s typedef struct ifo_command_s
...@@ -241,13 +282,13 @@ typedef struct vmgi_mat_s ...@@ -241,13 +282,13 @@ typedef struct vmgi_mat_s
u32 i_c_adt_ssector; // 4 bytes u32 i_c_adt_ssector; // 4 bytes
u32 i_vobu_admap_ssector; // 4 bytes u32 i_vobu_admap_ssector; // 4 bytes
// char[2] ??? // char[2] ???
u16 i_video_atrt; // 2 bytes ifo_video_t video_atrt; // 2 bytes
// char ??? // char ???
u8 i_audio_nb; // 1 byte u8 i_audio_nb; // 1 byte
u64 pi_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes ifo_audio_t p_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes
// char[16] ??? // char[16] ???
u8 i_subpic_nb; // 1 byte u8 i_subpic_nb; // 1 byte
u64 pi_subpic_atrt[32]; // i_subpic_nb * 6 bytes ifo_spu_t p_subpic_atrt[32]; // i_subpic_nb * 6 bytes
} vmgi_mat_t; } vmgi_mat_t;
...@@ -315,21 +356,21 @@ typedef struct vts_atrt_s ...@@ -315,21 +356,21 @@ typedef struct vts_atrt_s
{ {
u32 i_ebyte; // 4 bytes u32 i_ebyte; // 4 bytes
u32 i_cat_app_type; // 4 bytes u32 i_cat_app_type; // 4 bytes
u16 i_vtsm_video_atrt; // 2 bytes ifo_video_t vtsm_video_atrt; // 2 bytes
// char ??? // char ???
u8 i_vtsm_audio_nb; // 1 byte u8 i_vtsm_audio_nb; // 1 byte
u64 pi_vtsm_audio_atrt[8]; // 8 * 8 bytes ifo_audio_t p_vtsm_audio_atrt[8]; // 8 * 8 bytes
// char[17] ??? // char[17] ???
u8 i_vtsm_subpic_nb; // 1 byte u8 i_vtsm_subpic_nb; // 1 byte
u64 pi_vtsm_subpic_atrt[28]; // i_vtsm_subpic_nb * 6 bytes ifo_spu_t p_vtsm_subpic_atrt[28]; // i_vtsm_subpic_nb * 6 bytes
// char[2] ??? // char[2] ???
u16 i_vtstt_video_atrt; // 2 bytes ifo_video_t vtstt_video_atrt; // 2 bytes
// char ??? // char ???
u8 i_vtstt_audio_nb; // 1 byte u8 i_vtstt_audio_nb; // 1 byte
u64 pi_vtstt_audio_atrt[8]; // 8 * 8 bytes ifo_audio_t p_vtstt_audio_atrt[8]; // 8 * 8 bytes
// char[17] ??? // char[17] ???
u8 i_vtstt_subpic_nb; // 1 byte u8 i_vtstt_subpic_nb; // 1 byte
u64 pi_vtstt_subpic_atrt[28]; // i_vtstt_subpic_nb * 6 bytes ifo_spu_t p_vtstt_subpic_atrt[28]; // i_vtstt_subpic_nb * 6 bytes
} vts_atrt_t; } vts_atrt_t;
/* Main struct for vts attributes /* Main struct for vts attributes
...@@ -388,22 +429,22 @@ typedef struct vtsi_mat_s ...@@ -388,22 +429,22 @@ typedef struct vtsi_mat_s
u32 i_c_adt_ssector; // 4 bytes u32 i_c_adt_ssector; // 4 bytes
u32 i_vobu_admap_ssector; // 4 bytes u32 i_vobu_admap_ssector; // 4 bytes
// char[24] ??? // char[24] ???
u16 i_m_video_atrt; // 2 bytes ifo_video_t m_video_atrt; // 2 bytes
// char ??? // char ???
u8 i_m_audio_nb; // 1 byte u8 i_m_audio_nb; // 1 byte
u64 pi_m_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes ifo_audio_t p_m_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes
// char[16] ??? // char[16] ???
u8 i_m_subpic_nb; // 1 byte u8 i_m_subpic_nb; // 1 byte
u64 pi_m_subpic_atrt[32]; // i_subpic_nb * 6 bytes ifo_spu_t p_m_subpic_atrt[32]; // i_subpic_nb * 6 bytes
// !!! only 28 subpics ??? // !!! only 28 subpics ???
// char[2] ??? // char[2] ???
u16 i_video_atrt; // 2 bytes ifo_video_t video_atrt; // 2 bytes
// char ??? // char ???
u8 i_audio_nb; // 1 byte u8 i_audio_nb; // 1 byte
u64 pi_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes ifo_audio_t p_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes
// char[16] ??? // char[16] ???
u8 i_subpic_nb; // 1 byte u8 i_subpic_nb; // 1 byte
u64 pi_subpic_atrt[32]; // i_subpic_nb * 6 bytes ifo_spu_t p_subpic_atrt[32]; // i_subpic_nb * 6 bytes
} vtsi_mat_t; } vtsi_mat_t;
/* /*
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* -dvd_udf to find files * -dvd_udf to find files
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: input_dvd.c,v 1.18 2001/02/20 23:30:15 sam Exp $ * $Id: input_dvd.c,v 1.19 2001/02/22 08:44:45 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -278,11 +278,12 @@ void _M( input_getfunctions )( function_list_t * p_function_list ) ...@@ -278,11 +278,12 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
/***************************************************************************** /*****************************************************************************
* Language: gives the long language name from the two-letters ISO-639 code * Language: gives the long language name from the two-letters ISO-639 code
*****************************************************************************/ *****************************************************************************/
static char * Language( char * p_code ) static char * Language( u16 i_code )
{ {
int i = 0; int i = 0;
while( !memcmp( lang_tbl[i].p_code, p_code, 2 ) && lang_tbl[i].p_lang_long ) while( memcmp( lang_tbl[i].p_code, &i_code, 2 ) &&
lang_tbl[i].p_lang_long[0] )
{ {
i++; i++;
} }
...@@ -335,33 +336,93 @@ static int DVDCheckCSS( input_thread_t * p_input ) ...@@ -335,33 +336,93 @@ static int DVDCheckCSS( input_thread_t * p_input )
return CSSTest( p_input->i_handle ); return CSSTest( p_input->i_handle );
} }
/*****************************************************************************
* DVDChapterSelect: find the cell corresponding to requested chapter
*****************************************************************************/
static int DVDChapterSelect( thread_dvd_data_t * p_dvd, int i_chapter )
{
pgc_t * p_pgc;
int i_start_cell;
int i_end_cell;
int i_index;
int i_cell;
p_pgc = &p_dvd->ifo.vts.pgci_ti.p_srp[0].pgc;
/* Find cell index in Program chain for current chapter */
i_index = p_pgc->prg_map.pi_entry_cell[i_chapter-1] - 1;
/* Search for cell_index in cell adress_table */
i_cell = 0;
while( p_pgc->p_cell_pos_inf[i_index].i_vob_id >
p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_vob_id )
{
i_cell++;
}
while( p_pgc->p_cell_pos_inf[i_index].i_cell_id >
p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_cell_id )
{
i_cell++;
}
i_start_cell = i_cell;
p_dvd->i_start = p_dvd->ifo.vts.i_pos + DVD_LB_SIZE *
(off_t)( p_dvd->ifo.vts.mat.i_tt_vobs_ssector +
p_dvd->ifo.vts.c_adt.p_cell_inf[i_start_cell].i_ssector );
if( i_chapter == 1 )
{
i_end_cell = i_start_cell + p_pgc->i_cell_nb - 1;
p_dvd->i_size = (off_t)DVD_LB_SIZE *
( p_dvd->ifo.vts.c_adt.p_cell_inf[i_end_cell].i_esector -
p_dvd->ifo.vts.c_adt.p_cell_inf[i_start_cell].i_ssector + 1 );
p_dvd->i_chapter_nb = p_pgc->i_cell_nb;
intf_WarnMsg( 3, "DVD: Start cell: %d End Cell: %d",
i_start_cell, i_end_cell );
}
return 0;
}
/***************************************************************************** /*****************************************************************************
* DVDSetArea: initialize input data for title x, chapter y. * DVDSetArea: initialize input data for title x, chapter y.
* It should be called for each user navigation request, and to change * It should be called for each user navigation request, and to change
* audio or sub-picture streams. * audio or sub-picture streams.
* --- * ---
* Take care that i_title and i_chapter start from 0. * Take care that i_title starts from 0 (vmg) and i_chapter start from 1.
* i_audio, i_spu start from 1 ; 0 means off.
* A negative value for an argument means it does not change
*****************************************************************************/ *****************************************************************************/
static int DVDSetArea( input_thread_t * p_input, static int DVDSetArea( input_thread_t * p_input,
int i_title, int i_chapter, int i_title, int i_chapter,
int i_audio, int i_spu ) int i_audio, int i_spu )
{ {
thread_dvd_data_t * p_method; thread_dvd_data_t * p_method;
// es_descriptor_t * p_es; es_descriptor_t * p_es;
off_t i_start;
off_t i_size;
pgc_t * p_pgc;
int i_start_cell;
int i_end_cell;
int i_index; int i_index;
int i_cell; int i_nb;
// int i_nb; u16 i_id;
// int i_id; u8 i_ac3;
// int i; u8 i_mpeg;
u8 i_sub_pic;
u8 i;
boolean_t b_last;
p_method = (thread_dvd_data_t*)p_input->p_plugin_data; p_method = (thread_dvd_data_t*)p_input->p_plugin_data;
/* Ifo structures reading */ vlc_mutex_lock( &p_input->stream.stream_lock );
if( i_title >= 0 )
{
/*
* We have to load all title information
*/
/* Change the default area */
p_input->stream.p_selected_area = p_input->stream.pp_areas[i_title];
/* Ifo VTS, and CSS reading */
p_method->ifo.i_title = i_title; p_method->ifo.i_title = i_title;
IfoReadVTS( &(p_method->ifo) ); IfoReadVTS( &(p_method->ifo) );
intf_WarnMsg( 2, "Ifo: VTS initialized" ); intf_WarnMsg( 2, "Ifo: VTS initialized" );
...@@ -376,251 +437,216 @@ static int DVDSetArea( input_thread_t * p_input, ...@@ -376,251 +437,216 @@ static int DVDSetArea( input_thread_t * p_input,
intf_WarnMsg( 2, "CSS: VTS key initialized" ); intf_WarnMsg( 2, "CSS: VTS key initialized" );
} }
/* Set selected title start and size */ /*
p_pgc = &p_method->ifo.vts.pgci_ti.p_srp[0].pgc; * Set selected title start and size
*/
/* Find cell index in Program chain */ DVDChapterSelect( p_method, 1 );
i_index = p_pgc->prg_map.pi_entry_cell[i_chapter] - 1;
/* Search for cell_index in cell adress_table */ /* start is : beginning of vts + offset to vobs + offset to vob x */
i_cell = 0;
while( p_pgc->p_cell_pos_inf[i_index].i_vob_id >
p_method->ifo.vts.c_adt.p_cell_inf[i_cell].i_vob_id )
{
i_cell++;
}
while( p_pgc->p_cell_pos_inf[i_index].i_cell_id >
p_method->ifo.vts.c_adt.p_cell_inf[i_cell].i_cell_id )
{
i_cell++;
}
i_start_cell = i_cell;
i_end_cell = i_start_cell + p_pgc->i_cell_nb - 1;
intf_WarnMsg( 3, "DVD: Start cell: %d End Cell: %d", p_method->i_start =
i_start_cell, i_end_cell ); lseek( p_input->i_handle, p_method->i_start, SEEK_SET );
p_method->i_start_cell = i_start_cell; intf_WarnMsg( 2, "DVD: vobstart at: %lld", p_method->i_start );
p_method->i_end_cell = i_end_cell; intf_WarnMsg( 2, "DVD: stream size: %lld", p_method->i_size );
intf_WarnMsg( 2, "DVD: number of chapters: %lld",
p_method->i_chapter_nb );
/* start is : beginning of vts + offset to vobs + offset to vob x */ /* Area definition */
i_start = p_method->ifo.vts.i_pos + DVD_LB_SIZE * p_input->stream.p_selected_area->i_start = p_method->i_start;
( p_method->ifo.vts.mat.i_tt_vobs_ssector + p_input->stream.p_selected_area->i_size = p_method->i_size;
p_method->ifo.vts.c_adt.p_cell_inf[i_start_cell].i_ssector ); p_input->stream.p_selected_area->i_part_nb = p_method->i_chapter_nb;
i_start = lseek( p_input->i_handle, i_start, SEEK_SET ); /*
intf_WarnMsg( 2, "DVD: VOBstart at: %lld", i_start ); * Destroy obsolete ES by reinitializing program 0
* and find all ES in title with ifo data
*/
if( p_input->stream.pp_programs != NULL )
{
input_DelProgram( p_input, p_input->stream.pp_programs[0] );
}
i_size = (off_t) input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
( p_method->ifo.vts.c_adt.p_cell_inf[i_end_cell].i_esector -
p_method->ifo.vts.c_adt.p_cell_inf[i_start_cell].i_ssector + 1 )
*DVD_LB_SIZE;
intf_WarnMsg( 2, "DVD: stream size: %lld", i_size );
#if 0
p_es = NULL; p_es = NULL;
vlc_mutex_lock( &p_input->stream.stream_lock );
/* ES 0 -> video MPEG2 */ /* ES 0 -> video MPEG2 */
intf_WarnMsg( 1, "DVD: Video MPEG2 stream" );
p_es = input_AddES( p_input, p_input->stream.pp_programs[0], 0xe0, 0 ); p_es = input_AddES( p_input, p_input->stream.pp_programs[0], 0xe0, 0 );
p_es->i_stream_id = 0xe0; p_es->i_stream_id = 0xe0;
p_es->i_type = MPEG2_VIDEO_ES; p_es->i_type = MPEG2_VIDEO_ES;
input_SelectES( p_input, p_es ); input_SelectES( p_input, p_es );
intf_WarnMsg( 1, "DVD: Video MPEG2 stream" );
/* Audio ES, in the order they appear in .ifo */ /* Audio ES, in the order they appear in .ifo */
i_nb = p_method->ifo.vts.mat.i_audio_nb; i_nb = p_method->ifo.vts.mat.i_audio_nb;
intf_WarnMsg( 1, "DVD: Audio streams %d", i_nb );
for( i = 0 ; i < i_nb ; i++ ) i_ac3 = 0x80;
i_mpeg = 0xc0;
for( i = 1 ; i <= i_nb ; i++ )
{ {
i_id = ( ( 0x80 + i ) << 8 ) | 0xbd;
#if 0
fprintf( stderr, "Audio %d: %x %x %x %x %x %x\n", i,
p_method->ifo.vts.mat.p_audio_atrt[i].i_coding_mode,
p_method->ifo.vts.mat.p_audio_atrt[i].i_multichannel_extension,
p_method->ifo.vts.mat.p_audio_atrt[i].i_type,
p_method->ifo.vts.mat.p_audio_atrt[i].i_appl_mode,
p_method->ifo.vts.mat.p_audio_atrt[i].i_foo,
p_method->ifo.vts.mat.p_audio_atrt[i].i_bar );
#endif
switch( p_method->ifo.vts.mat.p_audio_atrt[i].i_coding_mode )
{
case 0x00: /* AC3 */
i_id = ( ( 0x7f + i ) << 8 ) | 0xbd;
p_es = input_AddES( p_input, p_es = input_AddES( p_input,
p_input->stream.pp_programs[0], i_id, 0 ); p_input->stream.pp_programs[0], i_id, 0 );
p_es->i_stream_id = 0xbd; p_es->i_stream_id = 0xbd;
p_es->i_type = AC3_AUDIO_ES; p_es->i_type = AC3_AUDIO_ES;
p_es->b_audio = 1; p_es->b_audio = 1;
// p_es->psz_desc = p_method->ifo.vts.mat.pi_audio_attr[i]; strcpy( p_es->psz_desc, Language( hton16(
if( i == 0 ) p_method->ifo.vts.mat.p_audio_atrt[i-1].i_lang_code ) ) );
{
input_SelectES( p_input, p_es ); break;
case 0x02:
case 0x03: /* MPEG audio */
i_id = 0xbf + i;
p_es = input_AddES( p_input,
p_input->stream.pp_programs[0], i_id, 0 );
p_es->i_stream_id = i_id;
p_es->i_type = MPEG2_AUDIO_ES;
p_es->b_audio = 1;
strcpy( p_es->psz_desc, Language( hton16(
p_method->ifo.vts.mat.p_audio_atrt[i-1].i_lang_code ) ) );
break;
case 0x04: /* LPCM */
i_id = 0;
intf_ErrMsg( "DVD: LPCM audio not handled yet" );
break;
case 0x06: /* DTS */
i_id = 0;
intf_ErrMsg( "DVD: DTS audio not handled yet" );
break;
default:
i_id = 0;
intf_ErrMsg( "DVD: unkown audio" );
} }
intf_WarnMsg( 1, "DVD: Audio stream %d %s\t(0x%x)",
i, p_es->psz_desc, i_id );
} }
/* Sub Picture ES */ /* Sub Picture ES */
i_nb = p_method->ifo.vts.mat.i_subpic_nb; i_nb = p_method->ifo.vts.mat.i_subpic_nb;
intf_WarnMsg( 1, "DVD: Subpic streams %d", i_nb );
for( i = 0 ; i < i_nb ; i++ ) b_last = 0;
i_sub_pic = 0x20;
for( i = 1 ; i <= i_nb ; i++ )
{ {
i_id = ( ( 0x20 + i ) << 8 ) | 0xbd; if( !b_last )
{
i_id = ( i_sub_pic++ << 8 ) | 0xbd;
p_es = input_AddES( p_input, p_es = input_AddES( p_input,
p_input->stream.pp_programs[0], i_id, 0 ); p_input->stream.pp_programs[0], i_id, 0 );
p_es->i_stream_id = 0xbd; p_es->i_stream_id = 0xbd;
p_es->i_type = DVD_SPU_ES; p_es->i_type = DVD_SPU_ES;
// p_es->psz_desc = p_method->ifo.vts.mat.pi_subpic_attr[i]; strcpy( p_es->psz_desc, Language( hton16(
if( i == 12 ) p_method->ifo.vts.mat.p_subpic_atrt[i-1].i_lang_code ) ) );
{ intf_WarnMsg( 1, "DVD: SPU stream %d %s\t(0x%x)",
input_SelectES( p_input, p_es ); i, p_es->psz_desc, i_id );
}
/* The before the last spu has a 0x0 prefix */
b_last =
( p_method->ifo.vts.mat.p_subpic_atrt[i].i_prefix == 0 );
}
} }
/* area definition */ } // i_title >= 0
p_input->stream.pp_areas[i_title]->i_start = i_start;
p_input->stream.pp_areas[i_title]->i_size = i_size;
/* No PSM to read in DVD mode */
p_input->stream.pp_programs[0]->b_is_ok = 1;
/* Init has been successfull ; change the default area */
p_input->stream.p_selected_area = p_input->stream.pp_areas[i_title];
vlc_mutex_unlock( &p_input->stream.stream_lock ); /*
* Select requested ES
#else */
p_input->stream.p_selected_area = p_input->stream.pp_areas[0]; if( ( i_audio >= 0 ) || ( i_title >= 0 ) )
{
if( p_input->stream.b_seekable ) /* Audio: we check it is in the range and
* default it to the first if not */
if( i_audio > p_method->ifo.vts.mat.i_audio_nb )
{ {
stream_ps_data_t * p_demux_data = i_audio = 1;
(stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data; }
/* Pre-parse the stream to gather stream_descriptor_t. */ p_es = p_input->stream.pp_programs[0]->pp_es[i_audio];
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 /* We can only have one audio channel */
&& !p_demux_data->b_has_PSM ) /* Look for a preselected one */
i_index = -1;
for( i = 0 ; i < p_input->stream.i_selected_es_number ; i++ )
{ {
int i_result, i; if( p_input->stream.pp_selected_es[i]->b_audio )
data_packet_t * pp_packets[INPUT_READ_ONCE];
i_result = DVDRead( p_input, pp_packets );
if( i_result == 1 )
{ {
/* EOF */ i_index = i;
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; break;
} }
if( i_result == -1 )
{
p_input->b_error = 1;
break;
} }
for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ ) if( i_index != -1 )
{ {
/* FIXME: use i_p_config_t */
input_ParsePS( p_input, pp_packets[i] );
input_NetlistDeletePacket( p_input->p_method_data,
pp_packets[i] );
}
/* File too big. */ if( p_input->stream.pp_selected_es[i_index] != p_es )
if( p_input->stream.p_selected_area->i_tell >
INPUT_PREPARSE_LENGTH )
{ {
break; input_UnSelectES( p_input,
} p_input->stream.pp_selected_es[i_index] );
input_SelectES( p_input, p_es );
intf_WarnMsg( 1, "DVD: Audio %d selected -> %s (0x%x)",
i_audio, p_es->psz_desc, p_es->i_id );
} }
lseek( p_input->i_handle, i_start, SEEK_SET );
vlc_mutex_lock( &p_input->stream.stream_lock );
/* i_tell is an indicator from the beginning of the stream,
* not of the DVD */
p_input->stream.p_selected_area->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 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_CHANNEL_VAR, 0 )
== (p_es->i_id & 0x1F) )
switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) )
{
case 0:
main_PutIntVariable( INPUT_AUDIO_VAR,
REQUESTED_MPEG );
case REQUESTED_MPEG:
input_SelectES( p_input, p_es ); input_SelectES( p_input, p_es );
intf_WarnMsg( 1, "DVD: Audio %d selected -> %s (0x%x)",
i_audio, p_es->psz_desc, p_es->i_id );
} }
break;
case AC3_AUDIO_ES:
if( main_GetIntVariable( INPUT_CHANNEL_VAR, 0 )
== ((p_es->i_id & 0xF00) >> 8) )
switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) )
{
case 0:
main_PutIntVariable( INPUT_AUDIO_VAR,
REQUESTED_AC3 );
case REQUESTED_AC3:
input_SelectES( p_input, p_es );
} }
break;
case DVD_SPU_ES: if( ( i_spu >= 0 ) || ( i_title >= 0 ) )
if( main_GetIntVariable( INPUT_SUBTITLE_VAR, -1 )
== ((p_es->i_id & 0x1F00) >> 8) )
{ {
input_SelectES( p_input, p_es ); /* For spu: no one if none or a not existed one requested */
} if( ( i_spu <= p_method->ifo.vts.mat.i_subpic_nb ) && ( i_spu > 0 ) )
break; {
input_SelectES( p_input, ( p_es = p_input->stream.pp_programs[0]->
pp_es[ i_spu + p_method->ifo.vts.mat.i_audio_nb ] ) );
case LPCM_AUDIO_ES: intf_WarnMsg( 1, "DVD: SPU %d selected -> %s (0x%x)",
/* FIXME ! */ i_spu, p_es->psz_desc, p_es->i_id );
break;
} }
} }
} /*
#endif * Chapter selection
#ifdef STATS */
input_DumpStream( p_input );
#endif if( ( i_chapter > 0 ) &&
( i_chapter <= p_input->stream.p_selected_area->i_part_nb ) )
{
DVDChapterSelect( p_method, i_chapter );
/* FIXME : ugly kludge */ p_input->stream.p_selected_area->i_part = i_chapter;
p_input->stream.p_selected_area->i_size = i_size;
vlc_mutex_unlock( &p_input->stream.stream_lock ); DVDSeek( p_input, p_method->i_start -
p_input->stream.p_selected_area->i_start );
intf_WarnMsg( 2, "DVD: Chapter %d start at: %lld", i_chapter,
p_input->stream.p_selected_area->i_tell );
} }
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;
/* FIXME : ugly kludge */ /* No PSM to read in DVD mode, we already have all information */
p_input->stream.p_selected_area->i_size = i_size; p_input->stream.pp_programs[0]->b_is_ok = 1;
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
}
#endif
return 0; return 0;
} }
...@@ -631,6 +657,10 @@ static int DVDSetArea( input_thread_t * p_input, ...@@ -631,6 +657,10 @@ static int DVDSetArea( input_thread_t * p_input,
static void DVDInit( input_thread_t * p_input ) static void DVDInit( input_thread_t * p_input )
{ {
thread_dvd_data_t * p_method; thread_dvd_data_t * p_method;
int i_title;
int i_chapter;
int i_audio;
int i_spu;
int i; int i;
if( (p_method = malloc( sizeof(thread_dvd_data_t) )) == NULL ) if( (p_method = malloc( sizeof(thread_dvd_data_t) )) == NULL )
...@@ -674,7 +704,6 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -674,7 +704,6 @@ static void DVDInit( input_thread_t * p_input )
/* Initialize ES structures */ /* Initialize ES structures */
input_InitStream( p_input, sizeof( stream_ps_data_t ) ); input_InitStream( p_input, sizeof( stream_ps_data_t ) );
input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
/* Set stream and area data */ /* Set stream and area data */
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
...@@ -682,9 +711,12 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -682,9 +711,12 @@ static void DVDInit( input_thread_t * p_input )
/* FIXME: We consider here that one title is one title set /* FIXME: We consider here that one title is one title set
* it is not true !!! */ * it is not true !!! */
intf_WarnMsg( 2, "DVD: Number of titles: %d\n",
p_method->ifo.vmg.mat.i_tts_nb );
#define area p_input->stream.pp_areas #define area p_input->stream.pp_areas
/* We start from 1 here since area 0 is reserved for video_ts.vob */ /* We start from 1 here since area 0 is reserved for video_ts.vob */
for( i = 1 ; i < p_method->ifo.vmg.mat.i_tts_nb ; i++ ) for( i = 1 ; i <= p_method->ifo.vmg.mat.i_tts_nb ; i++ )
{ {
input_AddArea( p_input ); input_AddArea( p_input );
...@@ -709,10 +741,32 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -709,10 +741,32 @@ static void DVDInit( input_thread_t * p_input )
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
/* By default, set all parameters to 0 */ /* Get requested title - if none try to find one where is the movie */
/* FIXME: wrong kludge to get first title number */ i_title = main_GetIntVariable( INPUT_TITLE_VAR,
DVDSetArea( p_input, p_method->ifo.vmg.ptt_srpt.p_tts[0].i_tts_nb - 1, p_method->ifo.vmg.ptt_srpt.p_tts[0].i_tts_nb );
0, 0, 0 ); if( i_title <= 0 || i_title >= p_method->ifo.vmg.mat.i_tts_nb )
{
i_title = p_method->ifo.vmg.ptt_srpt.p_tts[0].i_tts_nb;
}
/* Get requested chapter - if none defaults to first one */
i_chapter = main_GetIntVariable( INPUT_CHAPTER_VAR, 1 );
if( i_chapter <= 0 )
{
i_chapter = 1;
}
/* For audio: first one if none or a not existing one specified */
i_audio = main_GetIntVariable( INPUT_CHANNEL_VAR, 1 );
if( i_audio <= 0 )
{
main_PutIntVariable( INPUT_CHANNEL_VAR, 1 );
i_audio = 1;
}
i_spu = main_GetIntVariable( INPUT_SUBTITLE_VAR, 0 );
DVDSetArea( p_input, i_title, i_chapter, i_audio, i_spu );
return; return;
} }
...@@ -739,67 +793,74 @@ static void DVDEnd( input_thread_t * p_input ) ...@@ -739,67 +793,74 @@ static void DVDEnd( input_thread_t * p_input )
static int DVDRead( input_thread_t * p_input, static int DVDRead( input_thread_t * p_input,
data_packet_t ** pp_packets ) data_packet_t ** pp_packets )
{ {
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; thread_dvd_data_t * p_method;
netlist_t * p_netlist;
struct iovec * p_vec;
struct data_packet_s * p_data;
u8 * pi_cur;
int i_packet_size;
int i_packet;
int i_pos;
int i;
boolean_t b_first_packet;
p_method = ( thread_dvd_data_t * ) p_input->p_plugin_data; p_method = (thread_dvd_data_t *)p_input->p_plugin_data;
p_netlist = ( netlist_t * ) p_input->p_method_data;
/* Get an iovec pointer */ memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
if( ( p_vec = input_NetlistGetiovec( p_netlist ) ) == NULL ) 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 )) )
{ {
intf_ErrMsg( "DVD: read error" ); return( i_error );
return -1;
} }
/* Reads from DVD */ if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L )
readv( p_input->i_handle, p_vec, p_method->i_read_once ); {
/* This is not the startcode of a packet. Read the stream
* until we find one. */
u32 i_startcode = U32_AT(p_header);
int i_nb;
byte_t i_dummy;
if( p_method->b_encrypted ) 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 = SafeRead( p_input, &i_dummy, 1 )) != 0 )
{ {
for( i=0 ; i<p_method->i_read_once ; i++ ) i_startcode |= i_dummy;
}
else
{ {
CSSDescrambleSector( p_method->css.pi_title_key, return( 1 );
p_vec[i].iov_base );
((u8*)(p_vec[i].iov_base))[0x14] &= 0x8F;
} }
} }
/* Update netlist indexes */ /* Packet found. */
input_NetlistMviovec( p_netlist, p_method->i_read_once, &p_data ); *(u32 *)p_header = U32_AT(&i_startcode);
if( (i_error = SafeRead( p_input, p_header + 4, 2 )) )
i_packet = 0;
/* Read headers to compute payload length */
for( i = 0 ; i < p_method->i_read_once ; i++ )
{
i_pos = 0;
b_first_packet = 1;
while( i_pos < p_netlist->i_buffer_size )
{ {
pi_cur = (u8*)(p_vec[i].iov_base + i_pos); return( i_error );
/*default header */ }
if( U32_AT( pi_cur ) != 0x1BA ) }
if( U32_AT(p_header) != 0x1BA )
{ {
/* That's the case for all packets, except pack header. */ /* That's the case for all packets, except pack header. */
i_packet_size = U16_AT( pi_cur + 4 ); i_packet_size = U16_AT(&p_header[4]);
} }
else else
{ {
/* Pack header. */ /* Pack header. */
if( ( pi_cur[4] & 0xC0 ) == 0x40 ) if( (p_header[4] & 0xC0) == 0x40 )
{ {
/* MPEG-2 */ /* MPEG-2 */
i_packet_size = 8; i_packet_size = 8;
} }
else if( ( pi_cur[4] & 0xF0 ) == 0x20 ) else if( (p_header[4] & 0xF0) == 0x20 )
{ {
/* MPEG-1 */ /* MPEG-1 */
i_packet_size = 6; i_packet_size = 6;
...@@ -810,31 +871,42 @@ static int DVDRead( input_thread_t * p_input, ...@@ -810,31 +871,42 @@ static int DVDRead( input_thread_t * p_input,
return( -1 ); return( -1 );
} }
} }
if( b_first_packet )
/* Fetch a packet of the appropriate size. */
if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL )
{ {
p_data->b_discard_payload = 0; intf_ErrMsg( "Out of memory" );
b_first_packet = 0; return( -1 );
} }
else
/* 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 )) )
{ {
p_data = input_NetlistNewPacket( p_netlist , return( i_error );
i_packet_size + 6 );
memcpy( p_data->p_buffer,
p_vec[i].iov_base + i_pos , i_packet_size + 6 );
} }
p_data->p_payload_end = p_data->p_payload_start + i_packet_size + 6; /* In MPEG-2 pack headers we still have to read stuffing bytes. */
pp_packets[i_packet] = p_data; if( U32_AT(p_header) == 0x1BA )
i_packet++; {
i_pos += i_packet_size + 6; 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 );
}
} }
} }
pp_packets[i_packet] = NULL;
vlc_mutex_lock( &p_input->stream.stream_lock ); /* Give the packet to the other input stages. */
p_input->stream.p_selected_area->i_tell += pp_packets[i_packet] = p_data;
p_method->i_read_once *DVD_LB_SIZE; }
vlc_mutex_unlock( &p_input->stream.stream_lock );
return( 0 ); return( 0 );
} }
......
...@@ -35,9 +35,9 @@ typedef struct thread_dvd_data_s ...@@ -35,9 +35,9 @@ typedef struct thread_dvd_data_s
boolean_t b_encrypted; // CSS encryption boolean_t b_encrypted; // CSS encryption
int i_read_once; // NB of bytes read by DVDRead int i_read_once; // NB of bytes read by DVDRead
int i_start_byte; int i_chapter_nb;
int i_start_cell; off_t i_start;
int i_end_cell; off_t i_size;
/* Scrambling Information */ /* Scrambling Information */
struct css_s css; struct css_s css;
......
...@@ -584,3 +584,51 @@ on_intf_window_drag_data_received (GtkWidget *widget, ...@@ -584,3 +584,51 @@ on_intf_window_drag_data_received (GtkWidget *widget,
} }
} }
void
on_menubar_audio_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
}
void
on_menubar_subtitles_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
}
void
on_popup_title_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
}
void
on_popup_chapter_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
}
void
on_popup_audio_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
}
void
on_popup_subtitle_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
}
...@@ -197,3 +197,27 @@ on_intf_window_drag_data_received (GtkWidget *widget, ...@@ -197,3 +197,27 @@ on_intf_window_drag_data_received (GtkWidget *widget,
guint info, guint info,
guint time, guint time,
gpointer user_data); gpointer user_data);
void
on_menubar_audio_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_menubar_subtitles_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_popup_title_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_popup_chapter_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_popup_audio_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_popup_subtitle_activate (GtkMenuItem *menuitem,
gpointer user_data);
...@@ -46,6 +46,21 @@ static GnomeUIInfo menubar_view_menu_uiinfo[] = ...@@ -46,6 +46,21 @@ static GnomeUIInfo menubar_view_menu_uiinfo[] =
static GnomeUIInfo menubar_settings_menu_uiinfo[] = static GnomeUIInfo menubar_settings_menu_uiinfo[] =
{ {
{
GNOME_APP_UI_ITEM, N_("_Audio"),
N_("Select audio channel"),
(gpointer) on_menubar_audio_activate, NULL, NULL,
GNOME_APP_PIXMAP_NONE, NULL,
0, (GdkModifierType) 0, NULL
},
{
GNOME_APP_UI_ITEM, N_("_Subtitles"),
N_("Select subtitle unit"),
(gpointer) on_menubar_subtitles_activate, NULL, NULL,
GNOME_APP_PIXMAP_NONE, NULL,
0, (GdkModifierType) 0, NULL
},
GNOMEUIINFO_SEPARATOR,
GNOMEUIINFO_MENU_PREFERENCES_ITEM (on_menubar_preferences_activate, NULL), GNOMEUIINFO_MENU_PREFERENCES_ITEM (on_menubar_preferences_activate, NULL),
GNOMEUIINFO_END GNOMEUIINFO_END
}; };
...@@ -143,10 +158,25 @@ create_intf_window (void) ...@@ -143,10 +158,25 @@ create_intf_window (void)
(GtkDestroyNotify) gtk_widget_unref); (GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (menubar_settings_menu_uiinfo[0].widget); gtk_widget_ref (menubar_settings_menu_uiinfo[0].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_preferences", gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_audio",
menubar_settings_menu_uiinfo[0].widget, menubar_settings_menu_uiinfo[0].widget,
(GtkDestroyNotify) gtk_widget_unref); (GtkDestroyNotify) gtk_widget_unref);
gtk_widget_set_sensitive (menubar_settings_menu_uiinfo[0].widget, FALSE);
gtk_widget_ref (menubar_settings_menu_uiinfo[1].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_subtitles",
menubar_settings_menu_uiinfo[1].widget,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (menubar_settings_menu_uiinfo[2].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator5",
menubar_settings_menu_uiinfo[2].widget,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (menubar_settings_menu_uiinfo[3].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_preferences",
menubar_settings_menu_uiinfo[3].widget,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_set_sensitive (menubar_settings_menu_uiinfo[3].widget, FALSE);
gtk_widget_ref (menubar_uiinfo[3].widget); gtk_widget_ref (menubar_uiinfo[3].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_help", gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_help",
...@@ -394,6 +424,18 @@ create_intf_window (void) ...@@ -394,6 +424,18 @@ create_intf_window (void)
return intf_window; return intf_window;
} }
static GnomeUIInfo popup_title_menu_uiinfo[] =
{
{
GNOME_APP_UI_ITEM, N_("_Chapter"),
NULL,
(gpointer) on_popup_chapter_activate, NULL, NULL,
GNOME_APP_PIXMAP_NONE, NULL,
0, (GdkModifierType) 0, NULL
},
GNOMEUIINFO_END
};
static GnomeUIInfo intf_popup_uiinfo[] = static GnomeUIInfo intf_popup_uiinfo[] =
{ {
{ {
...@@ -427,6 +469,28 @@ static GnomeUIInfo intf_popup_uiinfo[] = ...@@ -427,6 +469,28 @@ static GnomeUIInfo intf_popup_uiinfo[] =
GNOMEUIINFO_SEPARATOR, GNOMEUIINFO_SEPARATOR,
GNOMEUIINFO_MENU_OPEN_ITEM (on_popup_open_activate, NULL), GNOMEUIINFO_MENU_OPEN_ITEM (on_popup_open_activate, NULL),
GNOMEUIINFO_SEPARATOR, GNOMEUIINFO_SEPARATOR,
{
GNOME_APP_UI_SUBTREE, N_("_Title"),
N_("Select Title"),
popup_title_menu_uiinfo, NULL, NULL,
GNOME_APP_PIXMAP_NONE, NULL,
0, (GdkModifierType) 0, NULL
},
{
GNOME_APP_UI_ITEM, N_("Audio"),
N_("Select audio channel"),
(gpointer) on_popup_audio_activate, NULL, NULL,
GNOME_APP_PIXMAP_NONE, NULL,
0, (GdkModifierType) 0, NULL
},
{
GNOME_APP_UI_ITEM, N_("_Subtitle"),
NULL,
(gpointer) on_popup_subtitle_activate, NULL, NULL,
GNOME_APP_PIXMAP_NONE, NULL,
0, (GdkModifierType) 0, NULL
},
GNOMEUIINFO_SEPARATOR,
GNOMEUIINFO_MENU_ABOUT_ITEM (on_popup_about_activate, NULL), GNOMEUIINFO_MENU_ABOUT_ITEM (on_popup_about_activate, NULL),
GNOMEUIINFO_MENU_EXIT_ITEM (on_popup_exit_activate, NULL), GNOMEUIINFO_MENU_EXIT_ITEM (on_popup_exit_activate, NULL),
GNOMEUIINFO_END GNOMEUIINFO_END
...@@ -478,15 +542,40 @@ create_intf_popup (void) ...@@ -478,15 +542,40 @@ create_intf_popup (void)
(GtkDestroyNotify) gtk_widget_unref); (GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (intf_popup_uiinfo[7].widget); gtk_widget_ref (intf_popup_uiinfo[7].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_about", gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_title",
intf_popup_uiinfo[7].widget, intf_popup_uiinfo[7].widget,
(GtkDestroyNotify) gtk_widget_unref); (GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (popup_title_menu_uiinfo[0].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_chapter",
popup_title_menu_uiinfo[0].widget,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (intf_popup_uiinfo[8].widget); gtk_widget_ref (intf_popup_uiinfo[8].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_exit", gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_audio",
intf_popup_uiinfo[8].widget, intf_popup_uiinfo[8].widget,
(GtkDestroyNotify) gtk_widget_unref); (GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (intf_popup_uiinfo[9].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_subtitle",
intf_popup_uiinfo[9].widget,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (intf_popup_uiinfo[10].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_popup), "separator4",
intf_popup_uiinfo[10].widget,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (intf_popup_uiinfo[11].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_about",
intf_popup_uiinfo[11].widget,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (intf_popup_uiinfo[12].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_exit",
intf_popup_uiinfo[12].widget,
(GtkDestroyNotify) gtk_widget_unref);
return intf_popup; return intf_popup;
} }
......
...@@ -162,6 +162,38 @@ ...@@ -162,6 +162,38 @@
<class>GtkMenu</class> <class>GtkMenu</class>
<name>menubar_settings_menu</name> <name>menubar_settings_menu</name>
<widget>
<class>GtkMenuItem</class>
<name>menubar_audio</name>
<tooltip>Select audio channel</tooltip>
<signal>
<name>activate</name>
<handler>on_menubar_audio_activate</handler>
<last_modification_time>Thu, 22 Feb 2001 05:42:43 GMT</last_modification_time>
</signal>
<label>_Audio</label>
<right_justify>False</right_justify>
</widget>
<widget>
<class>GtkMenuItem</class>
<name>menubar_subtitles</name>
<tooltip>Select subtitle unit</tooltip>
<signal>
<name>activate</name>
<handler>on_menubar_subtitles_activate</handler>
<last_modification_time>Thu, 22 Feb 2001 05:42:43 GMT</last_modification_time>
</signal>
<label>_Subtitles</label>
<right_justify>False</right_justify>
</widget>
<widget>
<class>GtkMenuItem</class>
<name>separator5</name>
<right_justify>False</right_justify>
</widget>
<widget> <widget>
<class>GtkPixmapMenuItem</class> <class>GtkPixmapMenuItem</class>
<name>menubar_preferences</name> <name>menubar_preferences</name>
...@@ -559,6 +591,67 @@ ...@@ -559,6 +591,67 @@
<right_justify>False</right_justify> <right_justify>False</right_justify>
</widget> </widget>
<widget>
<class>GtkMenuItem</class>
<name>popup_title</name>
<tooltip>Select Title</tooltip>
<signal>
<name>activate</name>
<handler>on_popup_title_activate</handler>
<last_modification_time>Thu, 22 Feb 2001 05:35:57 GMT</last_modification_time>
</signal>
<label>_Title</label>
<right_justify>False</right_justify>
<widget>
<class>GtkMenu</class>
<name>popup_title_menu</name>
<widget>
<class>GtkMenuItem</class>
<name>popup_chapter</name>
<signal>
<name>activate</name>
<handler>on_popup_chapter_activate</handler>
<last_modification_time>Thu, 22 Feb 2001 05:48:48 GMT</last_modification_time>
</signal>
<label>_Chapter</label>
<right_justify>False</right_justify>
</widget>
</widget>
</widget>
<widget>
<class>GtkMenuItem</class>
<name>popup_audio</name>
<tooltip>Select audio channel</tooltip>
<signal>
<name>activate</name>
<handler>on_popup_audio_activate</handler>
<last_modification_time>Thu, 22 Feb 2001 05:35:57 GMT</last_modification_time>
</signal>
<label>Audio</label>
<right_justify>False</right_justify>
</widget>
<widget>
<class>GtkMenuItem</class>
<name>popup_subtitle</name>
<signal>
<name>activate</name>
<handler>on_popup_subtitle_activate</handler>
<last_modification_time>Thu, 22 Feb 2001 05:35:57 GMT</last_modification_time>
</signal>
<label>_Subtitle</label>
<right_justify>False</right_justify>
</widget>
<widget>
<class>GtkMenuItem</class>
<name>separator4</name>
<right_justify>False</right_justify>
</widget>
<widget> <widget>
<class>GtkPixmapMenuItem</class> <class>GtkPixmapMenuItem</class>
<name>popup_about</name> <name>popup_about</name>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_programs.c: es_descriptor_t, pgrm_descriptor_t management * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: input_programs.c,v 1.33 2001/02/20 08:47:25 stef Exp $ * $Id: input_programs.c,v 1.34 2001/02/22 08:44:45 stef Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -263,7 +263,7 @@ input_area_t * input_AddArea( input_thread_t * p_input ) ...@@ -263,7 +263,7 @@ input_area_t * input_AddArea( input_thread_t * p_input )
p_input->stream.pp_areas[i_area_index]->i_start = 0; p_input->stream.pp_areas[i_area_index]->i_start = 0;
p_input->stream.pp_areas[i_area_index]->i_size = 0; p_input->stream.pp_areas[i_area_index]->i_size = 0;
p_input->stream.pp_areas[i_area_index]->i_tell = 0; p_input->stream.pp_areas[i_area_index]->i_tell = 0;
p_input->stream.pp_areas[i_area_index]->i_seek = 0; p_input->stream.pp_areas[i_area_index]->i_seek = NO_SEEK;
p_input->stream.pp_areas[i_area_index]->i_part_nb = 0; p_input->stream.pp_areas[i_area_index]->i_part_nb = 0;
p_input->stream.pp_areas[i_area_index]->i_part= 0; p_input->stream.pp_areas[i_area_index]->i_part= 0;
...@@ -281,7 +281,7 @@ void input_DelArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -281,7 +281,7 @@ void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
ASSERT( p_area ); ASSERT( p_area );
intf_DbgMsg("Deleting description for area %d", p_area->i_number); intf_DbgMsg("Deleting description for area %d", p_area->i_nb );
/* Find the area in the areas table */ /* Find the area in the areas table */
for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb; for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb;
...@@ -303,7 +303,7 @@ void input_DelArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -303,7 +303,7 @@ void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
if( p_input->stream.i_area_nb && p_input->stream.pp_areas == NULL) if( p_input->stream.i_area_nb && p_input->stream.pp_areas == NULL)
{ {
intf_ErrMsg( "input error: unable to realloc area list" intf_ErrMsg( "input error: unable to realloc area list"
" in input_Delarea" ); " in input_DelArea" );
} }
/* Free the description of this area */ /* Free the description of this area */
...@@ -680,3 +680,49 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -680,3 +680,49 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
} }
return( 0 ); return( 0 );
} }
/*****************************************************************************
* input_UnSelectES: removes an ES from the list of selected ES
*****************************************************************************/
int input_UnSelectES( input_thread_t * p_input, es_descriptor_t * p_es )
{
int i_index = 0;
#ifdef DEBUG_INPUT
intf_DbgMsg( "UnSelecting ES 0x%x", p_es->i_id );
#endif
if( p_es->p_decoder_fifo == NULL )
{
intf_ErrMsg( "ES %d is not selected", p_es->i_id );
return( -1 );
}
input_EndDecoder( p_input, p_es );
if( p_es->p_decoder_fifo == NULL )
{
p_input->stream.i_selected_es_number--;
while( ( i_index < p_input->stream.i_selected_es_number ) &&
( p_input->stream.pp_selected_es[i_index] != p_es ) )
{
i_index++;
}
p_input->stream.pp_selected_es[i_index] =
p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number];
p_input->stream.pp_selected_es = realloc(
p_input->stream.pp_selected_es,
p_input->stream.i_selected_es_number
* sizeof(es_descriptor_t *) );
if( p_input->stream.pp_selected_es == NULL )
{
intf_ErrMsg( "Unable to realloc memory in input_SelectES" );
return(-1);
}
}
return( 0 );
}
...@@ -140,6 +140,8 @@ static const struct option longopts[] = ...@@ -140,6 +140,8 @@ static const struct option longopts[] =
{ "overlay", 0, 0, OPT_OVERLAY }, { "overlay", 0, 0, OPT_OVERLAY },
/* DVD options */ /* DVD options */
{ "dvdtitle", 1, 0, 't' },
{ "dvdchapter", 1, 0, 'T' },
{ "dvdaudio", 1, 0, 'a' }, { "dvdaudio", 1, 0, 'a' },
{ "dvdchannel", 1, 0, 'c' }, { "dvdchannel", 1, 0, 'c' },
{ "dvdsubtitle", 1, 0, 's' }, { "dvdsubtitle", 1, 0, 's' },
...@@ -157,7 +159,7 @@ static const struct option longopts[] = ...@@ -157,7 +159,7 @@ static const struct option longopts[] =
}; };
/* Short options */ /* Short options */
static const char *psz_shortopts = "hHvga:s:c:"; static const char *psz_shortopts = "hHvgt:T:a:s:c:";
#endif #endif
...@@ -624,6 +626,12 @@ static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] ) ...@@ -624,6 +626,12 @@ static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
break; break;
/* DVD options */ /* DVD options */
case 't':
main_PutIntVariable( INPUT_TITLE_VAR, atoi(optarg) );
break;
case 'T':
main_PutIntVariable( INPUT_CHAPTER_VAR, atoi(optarg) );
break;
case 'a': case 'a':
if ( ! strcmp(optarg, "ac3") ) if ( ! strcmp(optarg, "ac3") )
main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_AC3 ); main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_AC3 );
...@@ -734,6 +742,8 @@ static void Usage( int i_fashion ) ...@@ -734,6 +742,8 @@ static void Usage( int i_fashion )
"\n --yuv <module> \tYUV method" "\n --yuv <module> \tYUV method"
"\n --synchro <type> \tforce synchro algorithm" "\n --synchro <type> \tforce synchro algorithm"
"\n" "\n"
"\n -t, --dvdtitle <num> \tchoose DVD title"
"\n -T, --dvdchapter <num> \tchoose DVD chapter"
"\n -a, --dvdaudio <type> \tchoose DVD audio type" "\n -a, --dvdaudio <type> \tchoose DVD audio type"
"\n -c, --dvdchannel <channel> \tchoose DVD audio channel" "\n -c, --dvdchannel <channel> \tchoose DVD audio channel"
"\n -s, --dvdsubtitle <channel> \tchoose DVD subtitle channel" "\n -s, --dvdsubtitle <channel> \tchoose DVD subtitle channel"
...@@ -783,6 +793,8 @@ static void Usage( int i_fashion ) ...@@ -783,6 +793,8 @@ static void Usage( int i_fashion )
/* DVD parameters */ /* DVD parameters */
intf_MsgImm( "\nDVD parameters:" intf_MsgImm( "\nDVD parameters:"
"\n " INPUT_DVD_DEVICE_VAR "=<device> \tDVD device" "\n " INPUT_DVD_DEVICE_VAR "=<device> \tDVD device"
"\n " INPUT_TITLE_VAR "=<title> \ttitle number"
"\n " INPUT_CHAPTER_VAR "=<chapter> \tchapter number"
"\n " INPUT_AUDIO_VAR "={ac3|lpcm|mpeg|off} \taudio type" "\n " INPUT_AUDIO_VAR "={ac3|lpcm|mpeg|off} \taudio type"
"\n " INPUT_CHANNEL_VAR "=[0-15] \taudio channel" "\n " INPUT_CHANNEL_VAR "=[0-15] \taudio channel"
"\n " INPUT_SUBTITLE_VAR "=[0-31] \tsubtitle channel" ); "\n " INPUT_SUBTITLE_VAR "=[0-31] \tsubtitle channel" );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment