* especially the 2048 bytes logical block size.
* It depends on: libdvdread for ifo files and block reading.
*****************************************************************************
- * Copyright (C) 2001 VideoLAN
- * $Id: input.c,v 1.9 2002/11/13 20:23:21 fenrir Exp $
+ * Copyright (C) 2001, 2003 VideoLAN
+ * $Id: input.c,v 1.23 2003/09/07 22:49:05 fenrir Exp $
*
* Author: Stéphane Borel <stef@via.ecp.fr>
*
* 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
* Local prototypes
*****************************************************************************/
/* called from outside */
-static int DvdReadDemux ( input_thread_t * );
-static int DvdReadRewind ( input_thread_t * );
+static int DvdReadDemux ( input_thread_t * );
+static int DvdReadRewind ( input_thread_t * );
-static int DvdReadSetArea ( input_thread_t *, input_area_t * );
-static int DvdReadSetProgram ( input_thread_t *, pgrm_descriptor_t * );
-static int DvdReadRead ( input_thread_t *, byte_t *, size_t );
-static void DvdReadSeek ( input_thread_t *, off_t );
+static int DvdReadSetArea ( input_thread_t *, input_area_t * );
+static int DvdReadSetProgram ( input_thread_t *, pgrm_descriptor_t * );
+static ssize_t DvdReadRead ( input_thread_t *, byte_t *, size_t );
+static void DvdReadSeek ( input_thread_t *, off_t );
/* called only from here */
-static void DvdReadLauchDecoders( input_thread_t * p_input );
-static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, u8 * p_data );
-static void DvdReadFindCell ( thread_dvd_data_t * p_dvd );
+static void DvdReadLauchDecoders( input_thread_t * p_input );
+static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, uint8_t * p_data );
+static void DvdReadFindCell ( thread_dvd_data_t * p_dvd );
/*
* Data demux functions
if( p_input->stream.i_method != INPUT_METHOD_DVD )
{
- return -1;
+ return VLC_EGENERIC;
}
p_demux = p_input->p_demux_data = malloc( sizeof(demux_sys_t ) );
if( p_demux == NULL )
{
- return -1;
+ return VLC_ENOMEM;
}
p_input->p_private = (void*)&p_demux->mpeg;
if( p_demux->p_module == NULL )
{
free( p_input->p_demux_data );
- return -1;
+ return VLC_ENOMOD;
}
p_input->pf_demux = DvdReadDemux;
+ p_input->pf_demux_control = demux_vaControlDefault;
p_input->pf_rewind = NULL;
vlc_mutex_lock( &p_input->stream.stream_lock );
-
+
DvdReadLauchDecoders( p_input );
-
+
vlc_mutex_unlock( &p_input->stream.stream_lock );
- return 0;
+ return VLC_SUCCESS;
}
/*****************************************************************************
i_result = input_Peek( p_input, &p_peek, SIZE ); \
if( i_result == -1 ) \
{ \
- return( -1 ); \
+ return -1; \
} \
else if( i_result < SIZE ) \
{ \
/* EOF */ \
- return( 0 ); \
+ return 0; \
}
static int DvdReadDemux( input_thread_t * p_input )
/* Read what we believe to be a packet header. */
PEEK( 4 );
-
- /* Default header */
+
+ /* Default header */
if( U32_AT( p_peek ) != 0x1BA )
{
/* That's the case for all packets, except pack header. */
/* In MPEG-2 pack headers we still have to read stuffing bytes. */
if( (p_data->p_demux_start[3] == 0xBA) && (i_packet_size == 8) )
{
- size_t i_stuffing = (p_data->p_demux_start[13] & 0x7);
+ ssize_t i_stuffing = (p_data->p_demux_start[13] & 0x7);
/* Force refill of the input buffer - though we don't care
* about p_peek. Please note that this is unoptimized. */
PEEK( i_stuffing );
}
p_input->p_demux_data->mpeg.pf_demux_ps( p_input, p_data );
-
+
}
return i;
*****************************************************************************/
static int DvdReadRewind( input_thread_t * p_input )
{
- return( -1 );
+ return -1;
}
/*
thread_dvd_data_t * p_dvd;
dvd_reader_t * p_dvdread;
input_area_t * p_area;
- int i_title = 1;
- int i_chapter = 1;
- int i_angle = 1;
- int i;
+ unsigned int i_title = 1;
+ unsigned int i_chapter = 1;
+ unsigned int i_angle = 1;
+ unsigned int i;
- psz_parser = psz_source = strdup( p_input->psz_name );
- if( !psz_source )
+ psz_source = strdup( p_input->psz_name );
+ if( psz_source == NULL )
{
- return( -1 );
+ return VLC_ENOMEM;
}
p_input->pf_read = DvdReadRead;
p_input->pf_set_area = DvdReadSetArea;
p_input->pf_set_program = DvdReadSetProgram;
- while( *psz_parser && *psz_parser != '@' )
- {
- psz_parser++;
- }
+ /* Start with the end, because you could have :
+ * dvdread:/Volumes/my@toto/VIDEO_TS@1,1
+ * (yes, this is kludgy). */
+ for ( psz_parser = psz_source + strlen(psz_source) - 1;
+ psz_parser >= psz_source && *psz_parser != '@';
+ psz_parser-- );
- if( *psz_parser == '@' )
+ if( psz_parser >= psz_source && *psz_parser == '@' )
{
/* Found options */
*psz_parser = '\0';
free( psz_source );
if( !p_input->psz_access )
{
- return -1;
+ return VLC_EGENERIC;
}
psz_source = config_GetPsz( p_input, "dvd" );
- if( !psz_source ) return -1;
+ if( !psz_source ) return VLC_EGENERIC;
}
if( stat( psz_source, &stat_info ) == -1 )
{
- msg_Err( p_input, "cannot stat() source `%s' (%s)",
- psz_source, strerror(errno));
+ msg_Warn( p_input, "cannot stat() source `%s' (%s)",
+ psz_source, strerror(errno) );
free( psz_source );
- return( -1 );
+ return VLC_EGENERIC;
}
if( !S_ISBLK(stat_info.st_mode) &&
!S_ISCHR(stat_info.st_mode) &&
{
msg_Warn( p_input, "dvdread module discarded (not a valid source)" );
free( psz_source );
- return -1;
+ return VLC_EGENERIC;
}
-
+
msg_Dbg( p_input, "dvdroot=%s title=%d chapter=%d angle=%d",
psz_source, i_title, i_chapter, i_angle );
-
+
p_dvdread = DVDOpen( psz_source );
if( ! p_dvdread )
{
msg_Err( p_input, "libdvdcss cannot open source" );
- return -1;
+ return VLC_EGENERIC;
}
/* set up input */
if( p_dvd == NULL )
{
msg_Err( p_input, "out of memory" );
- return -1;
+ return VLC_ENOMEM;
}
p_dvd->p_dvdread = p_dvdread;
/* Ifo allocation & initialisation */
if( ! ( p_dvd->p_vmg_file = ifoOpen( p_dvd->p_dvdread, 0 ) ) )
{
- msg_Err( p_input, "cannot open VMG info" );
+ msg_Warn( p_input, "cannot open VMG info" );
free( p_dvd );
- return -1;
+ return VLC_EGENERIC;
}
msg_Dbg( p_input, "VMG opened" );
p_input->stream.i_method = INPUT_METHOD_DVD;
/* If we are here we can control the pace... */
- p_input->stream.b_pace_control = 1;
- p_input->stream.b_seekable = 1;
-
+ p_input->stream.b_pace_control = VLC_TRUE;
+ p_input->stream.b_seekable = VLC_TRUE;
+
p_input->stream.p_selected_area->i_size = 0;
p_input->stream.p_selected_area->i_tell = 0;
* is reserved for video_ts.vob */
for( i = 1 ; i <= tt_srpt->nr_of_srpts ; i++ )
{
- input_AddArea( p_input );
-
/* Titles are Program Chains */
- area[i]->i_id = i;
+ input_AddArea( p_input, i, tt_srpt->title[i-1].nr_of_ptts );
/* Absolute start offset and size
* We can only set that with vts ifo, so we do it during the
area[i]->i_start = 0;
area[i]->i_size = 0;
- /* Number of chapters */
- area[i]->i_part_nb = tt_srpt->title[i-1].nr_of_ptts;
+ /* Default Chapter */
area[i]->i_part = 1;
area[i]->i_plugin_data = tt_srpt->title[i-1].title_set_nr;
p_dvd->i_chapter = i_chapter < p_area->i_part_nb ? i_chapter : 1;
p_area->i_part = p_dvd->i_chapter;
-
+
p_dvd->i_angle = i_angle;
/* set title, chapter, audio and subpic */
if( DvdReadSetArea( p_input, p_area ) )
{
vlc_mutex_unlock( &p_input->stream.stream_lock );
- return -1;
+ return VLC_EGENERIC;
}
vlc_mutex_unlock( &p_input->stream.stream_lock );
p_input->psz_demux = "dvdread";
}
- return 0;
+ return VLC_SUCCESS;
}
/*****************************************************************************
input_thread_t * p_input = (input_thread_t *)p_this;
thread_dvd_data_t * p_dvd = (thread_dvd_data_t *)p_input->p_access_data;
+ /* This is a very nasty side-effect in the DVD plug-in : language
+ * selection here influences language selection of other streams. So
+ * unset those variables (may not be what the user wants).
+ * FIXME FIXME FIXME FIXME FIXME FIXME FIXME --Meuuh */
+ config_PutInt( p_input, "audio-channel", -1 );
+ config_PutInt( p_input, "spu-channel", -1 );
+
/* close libdvdread */
DVDCloseFile( p_dvd->p_title );
ifoClose( p_dvd->p_vts_file );
if( p_input->stream.p_selected_program != p_program )
{
thread_dvd_data_t * p_dvd;
-
+ vlc_value_t val;
+
p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
p_dvd->i_angle = p_program->i_number;
p_input->stream.p_selected_program = p_program;
msg_Dbg( p_input, "angle %d selected", p_dvd->i_angle );
+
+ /* Update the navigation variables without triggering a callback */
+ val.i_int = p_program->i_number;
+ var_Change( p_input, "program", VLC_VAR_SETVALUE, &val, NULL );
}
- return 0;
+ return VLC_SUCCESS;
}
#define p_pgc p_dvd->p_cur_pgc
thread_dvd_data_t * p_dvd;
int pgc_id = 0;
int pgn = 0;
+ vlc_value_t val;
p_dvd = (thread_dvd_data_t*)p_input->p_access_data;
/* we can't use the interface slider until initilization is complete */
- p_input->stream.b_seekable = 0;
+ p_input->stream.b_seekable = VLC_FALSE;
if( p_area != p_input->stream.p_selected_area )
{
es_descriptor_t * p_es;
- int i_cell = 0;
- int i_audio_nb = 0;
- int i_spu_nb = 0;
- int i;
+ unsigned int i_cell = 0;
+ unsigned int i_audio_nb = 0;
+ unsigned int i_spu_nb = 0;
+ unsigned int i;
#define p_vmg p_dvd->p_vmg_file
#define p_vts p_dvd->p_vts_file
msg_Err( p_input, "fatal error in vts ifo" );
ifoClose( p_vmg );
DVDClose( p_dvd->p_dvdread );
- return -1;
+ return VLC_EGENERIC;
}
/* title position inside the selected vts */
*/
/* Remeber current chapter */
p_dvd->i_chapter = p_area->i_part;
- p_dvd->b_eoc = 0;
+ p_dvd->b_eoc = VLC_FALSE;
pgc_id = p_vts->vts_ptt_srpt->title[
p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgcn;
ifoClose( p_vts );
ifoClose( p_vmg );
DVDClose( p_dvd->p_dvdread );
- return -1;
+ return VLC_EGENERIC;
}
// IfoPrintTitle( p_dvd );
{
input_AddProgram( p_input, i+1, 0 );
}
-
+
DvdReadSetProgram( p_input,
- p_input->stream.pp_programs[p_dvd->i_angle-1] );
+ p_input->stream.pp_programs[p_dvd->i_angle-1] );
/* No PSM to read in DVD mode, we already have all information */
- p_input->stream.p_selected_program->b_is_ok = 1;
+ p_input->stream.p_selected_program->b_is_ok = VLC_TRUE;
p_es = NULL;
/* ES 0 -> video MPEG2 */
// IfoPrintVideo( p_dvd );
- p_es = input_AddES( p_input, NULL, 0xe0, 0 );
+ p_es = input_AddES( p_input, NULL, 0xe0, VIDEO_ES, NULL, 0 );
p_es->i_stream_id = 0xe0;
p_es->i_fourcc = VLC_FOURCC('m','p','g','v');
- p_es->i_cat = VIDEO_ES;
#define audio_control \
p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->audio_control[i-1]
for( i = 1 ; i <= p_vts->vtsi_mat->nr_of_vts_audio_streams ; i++ )
{
int i_position = 0;
- u16 i_id;
+ uint16_t i_id;
// IfoPrintAudio( p_dvd, i );
i_audio_nb++;
i_position = ( audio_control & 0x7F00 ) >> 8;
- msg_Dbg( p_input, "audio position %d", i_position );
+ msg_Dbg( p_input, "audio position %d", i_position );
switch( p_vts->vtsi_mat->vts_audio_attr[i-1].audio_format )
{
case 0x00: /* A52 */
i_id = ( ( 0x80 + i_position ) << 8 ) | 0xbd;
- p_es = input_AddES( p_input, NULL, i_id, 0 );
+ p_es = input_AddES( p_input, NULL, i_id, AUDIO_ES,
+ DecodeLanguage(
+ p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ), 0 );
p_es->i_stream_id = 0xbd;
p_es->i_fourcc = VLC_FOURCC('a','5','2','b');
- p_es->i_cat = AUDIO_ES;
- strcpy( p_es->psz_desc, DecodeLanguage(
- p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ) );
- strcat( p_es->psz_desc, " (A52)" );
break;
case 0x02:
case 0x03: /* MPEG audio */
i_id = 0xc0 + i_position;
- p_es = input_AddES( p_input, NULL, i_id, 0 );
+ p_es = input_AddES( p_input, NULL, i_id, AUDIO_ES,
+ DecodeLanguage(
+ p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ), 0 );
p_es->i_stream_id = i_id;
p_es->i_fourcc = VLC_FOURCC('m','p','g','a');
- p_es->i_cat = AUDIO_ES;
- strcpy( p_es->psz_desc, DecodeLanguage(
- p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ) );
- strcat( p_es->psz_desc, " (mpeg)" );
break;
case 0x04: /* LPCM */
i_id = ( ( 0xa0 + i_position ) << 8 ) | 0xbd;
- p_es = input_AddES( p_input, NULL, i_id, 0 );
+ p_es = input_AddES( p_input, NULL, i_id, AUDIO_ES,
+ DecodeLanguage(
+ p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ), 0 );
p_es->i_stream_id = i_id;
p_es->i_fourcc = VLC_FOURCC('l','p','c','b');
- p_es->i_cat = AUDIO_ES;
- strcpy( p_es->psz_desc, DecodeLanguage(
- p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ) );
- strcat( p_es->psz_desc, " (lpcm)" );
break;
case 0x06: /* DTS */
for( i = 1 ; i <= p_vts->vtsi_mat->nr_of_vts_subp_streams; i++ )
{
int i_position = 0;
- u16 i_id;
+ uint16_t i_id;
// IfoPrintSpu( p_dvd, i );
msg_Dbg( p_input, "spu %d 0x%02x", i, spu_control );
}
i_id = ( ( 0x20 + i_position ) << 8 ) | 0xbd;
- p_es = input_AddES( p_input, NULL, i_id, 0 );
+ p_es = input_AddES( p_input, NULL, i_id, SPU_ES,
+ DecodeLanguage(
+ p_vts->vtsi_mat->vts_subp_attr[i-1].lang_code ), 0 );
p_es->i_stream_id = 0xbd;
p_es->i_fourcc = VLC_FOURCC('s','p','u','b');
- p_es->i_cat = SPU_ES;
- strcpy( p_es->psz_desc, DecodeLanguage(
- p_vts->vtsi_mat->vts_subp_attr[i-1].lang_code ) );
}
}
#undef spu_control
{
DvdReadLauchDecoders( p_input );
}
-
+
+ /* Update the navigation variables without triggering a callback */
+ val.i_int = p_area->i_id;
+ var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
+ var_Change( p_input, "chapter", VLC_VAR_CLEARCHOICES, NULL, NULL );
+ for( i = 1; i <= p_area->i_part_nb; i++ )
+ {
+ val.i_int = i;
+ var_Change( p_input, "chapter", VLC_VAR_ADDCHOICE, &val, NULL );
+ }
+
} /* i_title >= 0 */
else
{
/* warn interface that something has changed */
p_area->i_tell = LB2OFF( p_dvd->i_next_vobu ) - p_area->i_start;
- p_input->stream.b_seekable = 1;
- p_input->stream.b_changed = 1;
+ p_input->stream.b_seekable = VLC_TRUE;
+ p_input->stream.b_changed = VLC_TRUE;
- return 0;
+ /* Update the navigation variables without triggering a callback */
+ val.i_int = p_area->i_part;
+ var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &val, NULL );
+
+ return VLC_SUCCESS;
}
/*****************************************************************************
- * DvdReadRead: reads data packets into the netlist.
+ * DvdReadRead: reads data packets.
*****************************************************************************
- * Returns -1 in case of error, 0 if everything went well, and 1 in case of
- * EOF.
+ * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
+ * bytes.
*****************************************************************************/
-static int DvdReadRead( input_thread_t * p_input,
- byte_t * p_buffer, size_t i_count )
+static ssize_t DvdReadRead( input_thread_t * p_input,
+ byte_t * p_buffer, size_t i_count )
{
thread_dvd_data_t * p_dvd;
byte_t * p_buf;
- int i_blocks_once;
- int i_blocks;
+ unsigned int i_blocks_once;
+ unsigned int i_blocks;
int i_read;
int i_read_total;
- vlc_bool_t b_eot = 0;
+ vlc_bool_t b_eot = VLC_FALSE;
p_dvd = (thread_dvd_data_t *)p_input->p_access_data;
p_buf = p_buffer;
while( i_blocks )
{
- /*
+ /*
* End of pack, we select the following one
*/
if( ! p_dvd->i_pack_len )
/* basic check to be sure we don't have a empty title
* go to next title if so */
//assert( p_buffer[41] == 0xbf && p_buffer[1027] == 0xbf );
-
+
/*
* Parse the contained dsi packet.
*/
DvdReadHandleDSI( p_dvd, p_buf );
- /* End of File */
+ /* End of title */
if( p_dvd->i_next_vobu >= p_dvd->i_end_block + 1 )
{
- return 1;
+ b_eot = 1;
+ break;
}
assert( p_dvd->i_pack_len < 1024 );
/*
* Compute the number of blocks to read
*/
- i_blocks_once = p_dvd->i_pack_len >= i_blocks
- ? i_blocks : p_dvd->i_pack_len;
+ i_blocks_once = __MIN( p_dvd->i_pack_len, i_blocks );
p_dvd->i_pack_len -= i_blocks_once;
/* Reads from DVD */
i_read = DVDReadBlocks( p_dvd->p_title, p_dvd->i_cur_block,
i_blocks_once, p_buf );
- if( i_read != i_blocks_once )
+ if( (unsigned int)i_read != i_blocks_once )
{
msg_Err( p_input, "read failed for %d/%d blocks at 0x%02x",
i_read, i_blocks_once, p_dvd->i_cur_block );
/* We modify i_part only at end of chapter not to erase
* some modification from the interface */
p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
- p_dvd->b_eoc = 0;
+ p_dvd->b_eoc = VLC_FALSE;
}
-
+
if( ( LB2OFF( p_dvd->i_cur_block )
- p_input->stream.p_selected_area->i_start )
>= p_input->stream.p_selected_area->i_size || b_eot )
{
- if( ( p_input->stream.p_selected_area->i_id + 1 ) >=
+ if( ( p_input->stream.p_selected_area->i_id + 1 ) >=
p_input->stream.i_area_nb )
{
/* EOF */
vlc_mutex_unlock( &p_input->stream.stream_lock );
- return 1;
+ return 0;
}
/* EOT */
msg_Dbg( p_input, "new title" );
DvdReadSetArea( p_input, p_input->stream.pp_areas[
p_input->stream.p_selected_area->i_id+1] );
- vlc_mutex_unlock( &p_input->stream.stream_lock );
- return 0;
}
vlc_mutex_unlock( &p_input->stream.stream_lock );
static void DvdReadSeek( input_thread_t * p_input, off_t i_off )
{
thread_dvd_data_t * p_dvd;
- int i_lb;
- int i_tmp;
- int i_chapter = 0;
- int i_cell = 0;
- int i_vobu = 0;
- int i_sub_cell = 0;
+ unsigned int i_lb;
+ unsigned int i_tmp;
+ unsigned int i_chapter = 0;
+ unsigned int i_cell = 0;
+ unsigned int i_vobu = 0;
+ unsigned int i_sub_cell = 0;
vlc_mutex_lock( &p_input->stream.stream_lock );
i_off += p_input->stream.p_selected_area->i_start;
vlc_mutex_unlock( &p_input->stream.stream_lock );
-
+
i_lb = OFF2LB( i_off );
p_dvd = ( thread_dvd_data_t * )p_input->p_access_data;
/*****************************************************************************
* DvdReadHandleDSI
*****************************************************************************/
-static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, u8 * p_data )
+static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, uint8_t * p_data )
{
navRead_DSI( &(p_dvd->dsi_pack), &(p_data[ DSI_START_BYTE ]) );
{
case 0x4:
/* interleaved unit with no angle */
- if( p_dvd->dsi_pack.sml_pbi.ilvu_sa != -1 )
+ if( p_dvd->dsi_pack.sml_pbi.ilvu_sa != 0 )
{
p_dvd->i_next_vobu = p_dvd->i_cur_block +
p_dvd->dsi_pack.sml_pbi.ilvu_sa;
p_dvd->dsi_pack.dsi_gi.vobu_vob_idn,
p_dvd->dsi_pack.dsi_gi.vobu_c_idn );
- msg_Dbg( p_input, 12, "cat 0x%02x ilvu_ea %d ilvu_sa %d size %d",
+ msg_Dbg( p_input, 12, "cat 0x%02x ilvu_ea %d ilvu_sa %d size %d",
p_dvd->dsi_pack.sml_pbi.category,
p_dvd->dsi_pack.sml_pbi.ilvu_ea,
p_dvd->dsi_pack.sml_pbi.ilvu_sa,
if( p_pgc->program_map[pgn-1] <= p_dvd->i_cur_cell )
{
p_dvd->i_chapter++;
- p_dvd->b_eoc = 1;
+ p_dvd->b_eoc = VLC_TRUE;
}
}