1
mirror of https://code.videolan.org/videolan/vlc synced 2024-09-12 13:44:56 +02:00

. Beginning of dvd_input.

. Parsing of ifo file almost completed.
. Still does not work well.
This commit is contained in:
Stéphane Borel 2001-01-14 07:08:00 +00:00
parent e360e2a431
commit a9729877b7
11 changed files with 2173 additions and 17 deletions

View 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 \

View File

@ -211,6 +211,8 @@
* 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"
@ -243,9 +245,9 @@
#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"

View 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 */

View 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 */

1038
src/input/dvd_ifo.c Normal file

File diff suppressed because it is too large Load Diff

484
src/input/dvd_ifo.h Normal file
View File

@ -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* );

View 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 );
}

541
src/input/input_dvd.c Normal file
View File

@ -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 );
}

30
src/input/input_dvd.h Normal file
View File

@ -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;

View 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 );

View 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:"