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, ...@@ -183,7 +183,22 @@ static void PSRead( input_thread_t * p_input,
} }
else 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 ) if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL )
...@@ -217,13 +232,24 @@ static void PSRead( input_thread_t * p_input, ...@@ -217,13 +232,24 @@ static void PSRead( input_thread_t * p_input,
if( U32_AT(p_header) == 0x1BA ) if( U32_AT(p_header) == 0x1BA )
{ {
/* stuffing_bytes */ if( i_packet_size == 8 )
byte_t p_garbage[8]; {
/* FIXME: catch EINTR ! */ /* MPEG-2 stuffing bytes */
if( (p_data->p_buffer[13] & 0x3) != 0 ) 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, /* FIXME: kludge to avoid SCR to block everything (SCR
p_method->stream ); * 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 ) ...@@ -68,6 +68,18 @@ void input_DecodePES( input_thread_t * p_input, es_descriptor_t * p_es )
if( p_es->p_decoder_fifo != NULL ) if( p_es->p_decoder_fifo != NULL )
{ {
vlc_mutex_lock( &p_es->p_decoder_fifo->data_lock ); 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 ) ) if( !DECODER_FIFO_ISFULL( *p_es->p_decoder_fifo ) )
{ {
//intf_DbgMsg("Putting %p into fifo %p/%d\n", //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 ) ...@@ -190,21 +202,123 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
break; break;
default: default:
/* The PES header contains at least 3 more bytes. */ if( (p_header[6] & 0xC0) == 0x80 )
p_pes->b_data_alignment = p_header[6] & 0x04; {
p_pes->b_has_pts = p_header[7] & 0x80; /* MPEG-2 : the PES header contains at least 3 more bytes. */
i_pes_header_size = p_header[8] + 9; 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 p_pts[i] = *p_byte;
* the 14 bytes). */ }
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 ) 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 ) switch( p_es->p_pgrm->i_synchro_state )
{ {
case SYNCHRO_NOT_STARTED: case SYNCHRO_NOT_STARTED:
...@@ -609,6 +723,8 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -609,6 +723,8 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
{ {
/* Convert the SCR in microseconds. */ /* Convert the SCR in microseconds. */
mtime_t scr_time; mtime_t scr_time;
/* FIXME : this calculus is broken with MPEG-1 ! */
scr_time = (( ((mtime_t)(p_data->p_buffer[4] & 0x38) << 27) | 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[4] & 0x3) << 26) |
((mtime_t)(p_data->p_buffer[5]) << 20) | ((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 ) ...@@ -779,7 +895,8 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
b_trash = 1; b_trash = 1;
#endif #endif
} }
else
if( p_es != NULL )
{ {
#ifdef STATS #ifdef STATS
p_es->c_packets++; p_es->c_packets++;
......
...@@ -344,9 +344,9 @@ static void EndThread( vpar_thread_t *p_vpar ) ...@@ -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[P_CODING_TYPE],
p_vpar->pc_malformed_pictures[B_CODING_TYPE]); p_vpar->pc_malformed_pictures[B_CODING_TYPE]);
#define S p_vpar->sequence #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.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", intf_Msg("vpar info: %s, %s, matrix_coeff: %d\n",
S.b_progressive ? "Progressive" : "Non-progressive", S.b_progressive ? "Progressive" : "Non-progressive",
S.i_scalable_mode ? "scalable" : "non-scalable", S.i_scalable_mode ? "scalable" : "non-scalable",
......
...@@ -239,7 +239,7 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type, ...@@ -239,7 +239,7 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type,
{ {
case I_CODING_TYPE: case I_CODING_TYPE:
/* Stream structure changes */ /* Stream structure changes */
if( S.i_n_p ) if( S.i_eta_p )
S.i_n_p = S.i_eta_p; S.i_n_p = S.i_eta_p;
if( S.backward_pts ) if( S.backward_pts )
...@@ -271,7 +271,7 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type, ...@@ -271,7 +271,7 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type,
case P_CODING_TYPE: case P_CODING_TYPE:
/* Stream structure changes */ /* Stream structure changes */
if( S.i_n_b ) if( S.i_eta_b )
S.i_n_b = S.i_eta_b; S.i_n_b = S.i_eta_b;
if( S.i_eta_p + 1 > S.i_n_p ) if( S.i_eta_p + 1 > S.i_n_p )
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