* mpeg_system.c: TS, PS and PES management
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: mpeg_system.c,v 1.38 2001/02/21 04:38:59 henri Exp $
+ * $Id: mpeg_system.c,v 1.45 2001/03/15 01:42:20 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Michel Lespinasse <walken@via.ecp.fr>
*****************************************************************************
* Small utility function used to parse discontinuous headers safely. Copies
* i_buf_len bytes of data to a buffer and returns the size copied.
+ * It also solves some alignment problems on non-IA-32, non-PPC processors.
* This is a variation on the theme of input_ext-dec.h:GetChunk().
*****************************************************************************/
static __inline__ size_t MoveChunk( byte_t * p_dest,
}
p_pes->i_pts = input_ClockGetTS( p_input, p_es->p_pgrm,
( ((mtime_t)(p_full_header[2] & 0x0E) << 29) |
- (((mtime_t)U16_AT(p_full_header + 3) << 14) - (1 << 14)) |
- ((mtime_t)U16_AT(p_full_header + 5) >> 1) ) );
+ ((mtime_t)(p_full_header[3]) << 22) |
+ ((mtime_t)(p_full_header[4] & 0xFE) << 14) |
+ ((mtime_t)p_full_header[5] << 7) |
+ ((mtime_t)p_full_header[6] >> 1) ) );
if( b_has_dts )
{
/* Cannot fail because the previous one succeeded. */
MoveChunk( NULL, &p_data, &p_byte, 6 );
- while( *p_byte == 0xFF && i_pes_header_size < 22 )
+ while( *p_byte == 0xFF && i_pes_header_size < 23 )
{
i_pes_header_size++;
if( MoveChunk( NULL, &p_data, &p_byte, 1 ) != 1 )
return;
}
}
- if( i_pes_header_size == 22 )
+ if( i_pes_header_size == 23 )
{
intf_ErrMsg( "Too much MPEG-1 stuffing" );
p_input->pf_delete_pes( p_input->p_method_data, p_pes );
}
p_pes->i_pts = input_ClockGetTS( p_input, p_es->p_pgrm,
- ( ((mtime_t)(p_ts[0] & 0x0E) << 29) |
- (((mtime_t)U16_AT(p_ts + 1) << 14) - (1 << 14)) |
- ((mtime_t)U16_AT(p_ts + 3) >> 1) ) );
+ ( ((mtime_t)(p_ts[0] & 0x0E) << 29) |
+ (((mtime_t)U32_AT(p_ts) & 0xFFFE00) << 6) |
+ ((mtime_t)p_ts[3] << 7) |
+ ((mtime_t)p_ts[4] >> 1) ) );
if( b_has_dts )
{
p_pes->i_dts = input_ClockGetTS( p_input,
p_es->p_pgrm,
( ((mtime_t)(p_ts[0] & 0x0E) << 29) |
- (((mtime_t)U16_AT(p_ts + 1) << 14) - (1 << 14)) |
- ((mtime_t)U16_AT(p_ts + 3) >> 1) ) );
+ (((mtime_t)U32_AT(p_ts) & 0xFFFE00) << 6) |
+ ((mtime_t)p_ts[3] << 7) |
+ ((mtime_t)p_ts[4] >> 1) ) );
}
}
}
{
u16 i_id;
- i_id = p_data->p_buffer[3]; /* stream_id */
+ i_id = p_data->p_payload_start[3]; /* stream_id */
if( i_id == 0xBD )
{
+ /* FIXME : this is not valid if the header is split in multiple
+ * packets */
/* stream_private_id */
- i_id |= p_data->p_buffer[ 9 + p_data->p_buffer[8] ] << 8;
+ i_id |= p_data->p_payload_start[ 9 + p_data->p_payload_start[8] ] << 8;
}
return( i_id );
}
/*****************************************************************************
* DecodePSM: Decode the Program Stream Map information
+ *****************************************************************************
+ * FIXME : loads are not aligned in this function
*****************************************************************************/
static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
{
}
if( p_demux->b_has_PSM
- && p_demux->i_PSM_version == (p_data->p_buffer[6] & 0x1F) )
+ && p_demux->i_PSM_version == (p_data->p_payload_start[6] & 0x1F) )
{
/* Already got that one. */
return;
intf_DbgMsg( "Building PSM" );
p_demux->b_has_PSM = 1;
- p_demux->i_PSM_version = p_data->p_buffer[6] & 0x1F;
+ p_demux->i_PSM_version = p_data->p_payload_start[6] & 0x1F;
/* Go to elementary_stream_map_length, jumping over
* program_stream_info. */
u32 i_code;
es_descriptor_t * p_es = NULL;
- i_code = U32_AT( p_data->p_buffer );
- if( i_code > 0x1BC ) /* ES start code */
+ i_code = p_data->p_payload_start[3];
+ if( i_code > 0xBC ) /* ES start code */
{
u16 i_id;
int i_dummy;
i_id, 0 );
if( p_es != NULL )
{
- p_es->i_stream_id = p_data->p_buffer[3];
+ p_es->i_stream_id = p_data->p_payload_start[3];
/* Set stream type and auto-spawn. */
if( (i_id & 0xF0) == 0xE0 )
{
/* Subtitles video (0x20->0x3F) */
p_es->i_type = DVD_SPU_ES;
+ p_es->b_spu = 1;
#ifdef AUTO_SPAWN
if( main_GetIntVariable( INPUT_SUBTITLE_VAR, -1 )
== ((p_es->i_id & 0x1F00) >> 8) )
boolean_t b_trash = 0;
es_descriptor_t * p_es = NULL;
- i_code = U32_AT( p_data->p_buffer );
+ i_code = U32_AT( p_data->p_payload_start );
if( i_code <= 0x1BC )
{
switch( i_code )
mtime_t scr_time;
u32 i_mux_rate;
- if( (p_data->p_buffer[4] & 0xC0) == 0x40 )
+ if( (p_data->p_payload_start[4] & 0xC0) == 0x40 )
{
/* MPEG-2 */
+ byte_t p_header[14];
+ byte_t * p_byte;
+ p_byte = p_data->p_payload_start;
+
+ if( MoveChunk( p_header, &p_data, &p_byte, 14 ) != 14 )
+ {
+ intf_WarnMsg( 3, "Packet too short to have a header" );
+ b_trash = 1;
+ break;
+ }
scr_time =
- ((mtime_t)(p_data->p_buffer[4] & 0x38) << 27) |
- ((mtime_t)(U32_AT(p_data->p_buffer + 4) & 0x03FFF800)
+ ((mtime_t)(p_header[4] & 0x38) << 27) |
+ ((mtime_t)(U32_AT(p_header + 4) & 0x03FFF800)
<< 4) |
- ((mtime_t)(U32_AT(p_data->p_buffer + 6) & 0x03FFF800)
+ ((( ((mtime_t)U16_AT(p_header + 6) << 16)
+ | (mtime_t)U16_AT(p_header + 8) ) & 0x03FFF800)
>> 11);
/* mux_rate */
- i_mux_rate = (U32_AT(p_data->p_buffer + 10) & 0xFFFFFC00);
+ i_mux_rate = ((u32)U16_AT(p_header + 10) << 6)
+ | (p_header[12] >> 2);
}
else
{
/* MPEG-1 SCR is like PTS. */
+ byte_t p_header[12];
+ byte_t * p_byte;
+ p_byte = p_data->p_payload_start;
+
+ if( MoveChunk( p_header, &p_data, &p_byte, 12 ) != 12 )
+ {
+ intf_WarnMsg( 3, "Packet too short to have a header" );
+ b_trash = 1;
+ break;
+ }
scr_time =
- ((mtime_t)(p_data->p_buffer[4] & 0x0E) << 29) |
- (((mtime_t)U16_AT(p_data->p_buffer + 5) << 14)
- - (1 << 14)) |
- ((mtime_t)U16_AT(p_data->p_buffer + 7) >> 1);
+ ((mtime_t)(p_header[4] & 0x0E) << 29) |
+ (((mtime_t)U32_AT(p_header + 4) & 0xFFFE00) << 6) |
+ ((mtime_t)p_header[7] << 7) |
+ ((mtime_t)p_header[8] >> 1);
/* mux_rate */
- i_mux_rate = (U32_AT(p_data->p_buffer + 8) & 0x8FFFFE);
+ i_mux_rate = (U32_AT(p_header + 8) & 0x7FFFFE) >> 1;
}
/* Call the pace control. */
input_ClockManageRef( p_input, p_input->stream.pp_programs[0],
default:
/* This should not happen */
b_trash = 1;
- intf_WarnMsg( 1, "Unwanted packet received with start code %x",
+ intf_WarnMsg( 1, "Unwanted packet received with start code 0x%.8x",
i_code );
}
}
pgrm_ts_data_t * p_pgrm_demux = NULL;
#define p (p_data->p_buffer)
-
/* Extract flags values from TS common header. */
i_pid = U16_AT(&p[1]) & 0x1fff;
b_unit_start = (p[1] & 0x40);
/* Find out the elementary stream. */
vlc_mutex_lock( &p_input->stream.stream_lock );
-
p_es= input_FindES( p_input, i_pid );
if( p_es_demux->b_psi )
b_psi = 1;
+ else
+ p_pgrm_demux = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data;
}
vlc_mutex_lock( &p_input->stream.control.control_lock );
-
if( ( p_es == NULL ) || (p_es->b_audio && p_input->stream.control.b_mute) )
{
/* Not selected. Just read the adaptation field for a PCR. */
vlc_mutex_unlock( &p_input->stream.stream_lock );
+ /* Don't change the order of the tests : if b_psi then p_pgrm_demux
+ * may still be null. Who said it was ugly ? */
if( ( p_es != NULL ) &&
((p_es->p_decoder_fifo != NULL) || b_psi
|| (p_pgrm_demux->i_pcr_pid == i_pid) ) )
{
- p_es_demux = (es_ts_data_t *)p_es->p_demux_data;
-
- if( ! p_es_demux->b_psi )
- {
- p_pgrm_demux = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data;
- }
-
#ifdef STATS
p_es->c_packets++;
#endif
stream_ts_data_t * p_stream_data;
es_ts_data_t * p_demux_data;
-
p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
p_current_data = p_psi->buffer;
p_pgrm_data->i_pcr_pid = U16_AT(p_current_section + 8) & 0x1fff;
+
+ /* Lock stream information */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
/* Delete all ES in this program except the PSI */
for( i_loop=0; i_loop < p_es->p_pgrm->i_es_number; i_loop++ )
/* We want to decode */
input_SelectES( p_input, p_new_es );
-
p_current_data += 5 + i_es_info_length;
}
}
#undef p_psi
+
+ /* Remove lock */
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
}