Commit 7bd6b4e9 authored by Christophe Massiot's avatar Christophe Massiot

* Support for MPEG-1 .mpg files.

* Fixed a bug in the synchro with non-P5/B1 streams.
parent 8d211185
......@@ -183,7 +183,22 @@ static void PSRead( input_thread_t * p_input,
}
else
{
i_packet_size = 8;
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" );
p_input->b_error = 1;
return;
}
}
if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL )
......@@ -217,13 +232,24 @@ static void PSRead( input_thread_t * p_input,
if( U32_AT(p_header) == 0x1BA )
{
/* stuffing_bytes */
byte_t p_garbage[8];
/* FIXME: catch EINTR ! */
if( (p_data->p_buffer[13] & 0x3) != 0 )
if( i_packet_size == 8 )
{
/* MPEG-2 stuffing bytes */
byte_t p_garbage[8];
if( (p_data->p_buffer[13] & 0x7) != 0 )
{
/* FIXME: catch EINTR ! */
fread( p_garbage, p_garbage[0] & 0x7, 1,
p_method->stream );
}
}
else
{
fread( p_garbage, p_garbage[0] & 0x3, 1,
p_method->stream );
/* FIXME: kludge to avoid SCR to block everything (SCR
* calculus appears to be wrong). */
p_data->p_buffer[4] = p_data->p_buffer[5] =
p_data->p_buffer[6] = p_data->p_buffer[7] =
p_data->p_buffer[8] = 0;
}
}
......
......@@ -68,6 +68,18 @@ void input_DecodePES( input_thread_t * p_input, es_descriptor_t * p_es )
if( p_es->p_decoder_fifo != NULL )
{
vlc_mutex_lock( &p_es->p_decoder_fifo->data_lock );
if( p_input->stream.b_pace_control )
{
/* FIXME : normally we shouldn't need this... */
while( DECODER_FIFO_ISFULL( *p_es->p_decoder_fifo ) )
{
vlc_mutex_unlock( &p_es->p_decoder_fifo->data_lock );
msleep( 20000 );
vlc_mutex_lock( &p_es->p_decoder_fifo->data_lock );
}
}
if( !DECODER_FIFO_ISFULL( *p_es->p_decoder_fifo ) )
{
//intf_DbgMsg("Putting %p into fifo %p/%d\n",
......@@ -190,21 +202,123 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
break;
default:
/* The PES header contains at least 3 more bytes. */
p_pes->b_data_alignment = p_header[6] & 0x04;
p_pes->b_has_pts = p_header[7] & 0x80;
i_pes_header_size = p_header[8] + 9;
if( (p_header[6] & 0xC0) == 0x80 )
{
/* MPEG-2 : the PES header contains at least 3 more bytes. */
p_pes->b_data_alignment = p_header[6] & 0x04;
p_pes->b_has_pts = p_header[7] & 0x80;
i_pes_header_size = p_header[8] + 9;
/* Now parse the optional header extensions (in the limit of
* the 14 bytes). */
if( p_pes->b_has_pts )
{
p_pes->i_pts =
( ((mtime_t)(p_header[9] & 0x0E) << 29) |
(((mtime_t)U16_AT(p_header + 10) << 14) - (1 << 14)) |
((mtime_t)U16_AT(p_header + 12) >> 1) ) * 300;
p_pes->i_pts /= 27;
}
}
else
{
/* Probably MPEG-1 */
byte_t * p_byte;
data_packet_t * p_data;
i_pes_header_size = 6;
p_data = p_pes->p_first;
p_byte = p_data->p_buffer + 6;
while( *p_byte == 0xFF && i_pes_header_size < 22 )
{
i_pes_header_size++;
p_byte++;
if( p_byte >= p_data->p_payload_end )
{
p_data = p_data->p_next;
if( p_data == NULL )
{
intf_ErrMsg( "MPEG-1 packet too short for header" );
p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
p_pes = NULL;
return;
}
p_byte = p_data->p_payload_start;
}
}
if( i_pes_header_size == 22 )
{
intf_ErrMsg( "Too much MPEG-1 stuffing" );
p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
p_pes = NULL;
return;
}
if( (*p_byte & 0xC0) == 0x40 )
{
/* Don't ask why... --Meuuh */
p_byte += 2;
i_pes_header_size += 2;
if( p_byte >= p_data->p_payload_end )
{
int i_plus = p_byte - p_data->p_payload_end;
p_data = p_data->p_next;
if( p_data == NULL )
{
intf_ErrMsg( "MPEG-1 packet too short for header" );
p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
p_pes = NULL;
return;
}
p_byte = p_data->p_payload_start + i_plus;
}
}
i_pes_header_size++;
p_pes->b_has_pts = *p_byte & 0x20;
if( *p_byte & 0x10 )
{
/* DTS */
i_pes_header_size += 5;
}
if( *p_byte & 0x20 )
{
/* PTS */
byte_t p_pts[5];
int i;
i_pes_header_size += 4;
p_pts[0] = *p_byte;
for( i = 1; i < 5; i++ )
{
p_byte++;
if( p_byte >= p_data->p_payload_end )
{
p_data = p_data->p_next;
if( p_data == NULL )
{
intf_ErrMsg( "MPEG-1 packet too short for header" );
p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
p_pes = NULL;
return;
}
p_byte = p_data->p_payload_start;
}
/* Now parse the optional header extensions (in the limit of
* the 14 bytes). */
p_pts[i] = *p_byte;
}
p_pes->i_pts =
( ((mtime_t)(p_pts[0] & 0x0E) << 29) |
(((mtime_t)U16_AT(p_pts + 1) << 14) - (1 << 14)) |
((mtime_t)U16_AT(p_pts + 3) >> 1) ) * 300;
p_pes->i_pts /= 27;
}
}
/* PTS management */
if( p_pes->b_has_pts )
{
p_pes->i_pts =
( ((mtime_t)(p_header[9] & 0x0E) << 29) |
(((mtime_t)U16_AT(p_header + 10) << 14) - (1 << 14)) |
((mtime_t)U16_AT(p_header + 12) >> 1) ) * 300;
p_pes->i_pts /= 27;
switch( p_es->p_pgrm->i_synchro_state )
{
case SYNCHRO_NOT_STARTED:
......@@ -609,6 +723,8 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
{
/* Convert the SCR in microseconds. */
mtime_t scr_time;
/* FIXME : this calculus is broken with MPEG-1 ! */
scr_time = (( ((mtime_t)(p_data->p_buffer[4] & 0x38) << 27) |
((mtime_t)(p_data->p_buffer[4] & 0x3) << 26) |
((mtime_t)(p_data->p_buffer[5]) << 20) |
......@@ -779,7 +895,8 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
b_trash = 1;
#endif
}
else
if( p_es != NULL )
{
#ifdef STATS
p_es->c_packets++;
......
......@@ -344,9 +344,9 @@ static void EndThread( vpar_thread_t *p_vpar )
p_vpar->pc_malformed_pictures[P_CODING_TYPE],
p_vpar->pc_malformed_pictures[B_CODING_TYPE]);
#define S p_vpar->sequence
intf_Msg("vpar info: %s stream (%dx%d), %d/1001 pi/s\n",
intf_Msg("vpar info: %s stream (%dx%d), %d pi/s\n",
S.b_mpeg2 ? "MPEG-2" : "MPEG-1",
S.i_width, S.i_height, S.i_frame_rate);
S.i_width, S.i_height, S.i_frame_rate/1001);
intf_Msg("vpar info: %s, %s, matrix_coeff: %d\n",
S.b_progressive ? "Progressive" : "Non-progressive",
S.i_scalable_mode ? "scalable" : "non-scalable",
......
......@@ -239,7 +239,7 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type,
{
case I_CODING_TYPE:
/* Stream structure changes */
if( S.i_n_p )
if( S.i_eta_p )
S.i_n_p = S.i_eta_p;
if( S.backward_pts )
......@@ -271,7 +271,7 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type,
case P_CODING_TYPE:
/* Stream structure changes */
if( S.i_n_b )
if( S.i_eta_b )
S.i_n_b = S.i_eta_b;
if( S.i_eta_p + 1 > S.i_n_p )
S.i_n_p++;
......
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