Commit 50118171 authored by Christophe Massiot's avatar Christophe Massiot

* Big cleanup of the PS input plugin ;

* Fixed a bug in AC3 initialization ;
* PS streams are now pre-parsed (this can take a while) if possible ;

./configure is required after this update.
parent d719269b
......@@ -183,6 +183,9 @@
/* Maximum number of selected ES in an input thread */
#define INPUT_MAX_SELECTED_ES 10
/* Maximum size of a data packet (128 kB) */
#define INPUT_MAX_PACKET_SIZE 131072
/* Maximum number of TS packets in the client at any time
* INPUT_MAX_TS + 1 must be a power of 2, to optimize the %(INPUT_MAX_TS+1)
* operation with a &INPUT_MAX_TS in the case of a fifo netlist.
......
/* Structures exported to the interface */
/*****************************************************************************
* input_ext-intf.h: structures of the input exported to the interface
* This header provides structures to read the stream descriptors and
* control the pace of reading.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-intf.h,v 1.4 2000/12/20 16:04:31 massiot Exp $
*
* Authors:
*
* 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.
*****************************************************************************/
/*
* Communication input -> interface
......@@ -54,8 +77,10 @@ typedef struct es_descriptor_s
#define MPEG1_AUDIO_ES 0x03
#define MPEG2_AUDIO_ES 0x04
#define AC3_AUDIO_ES 0x81
#define DVD_SPU_ES 0x82 /* 0x82 might violate the norm */
/* These ones might violate the norm : */
#define DVD_SPU_ES 0x82
#define LPCM_AUDIO_ES 0x83
#define UNKNOWN_ES 0xFF
/*****************************************************************************
* pgrm_descriptor_t
......
......@@ -126,6 +126,17 @@ static int InitThread (ac3dec_thread_t * p_ac3dec)
intf_DbgMsg ("ac3dec debug: initializing ac3 decoder thread %p\n", p_ac3dec);
/* Get the first data packet. */
vlc_mutex_lock( &p_ac3dec->p_fifo->data_lock );
while ( DECODER_FIFO_ISEMPTY( *p_ac3dec->p_fifo ) )
{
if ( p_ac3dec->p_fifo->b_die )
{
vlc_mutex_unlock( &p_ac3dec->p_fifo->data_lock );
return -1;
}
vlc_cond_wait( &p_ac3dec->p_fifo->data_wait, &p_ac3dec->p_fifo->data_lock );
}
p_ac3dec->p_data = DECODER_FIFO_START(*p_ac3dec->p_fifo)->p_first;
byte_stream = ac3_byte_stream (&p_ac3dec->ac3_decoder);
byte_stream->p_byte = p_ac3dec->p_data->p_payload_start;
......
......@@ -4,7 +4,7 @@
* decoders.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input.c,v 1.59 2000/12/19 19:08:51 massiot Exp $
* $Id: input.c,v 1.60 2000/12/20 16:04:31 massiot Exp $
*
* Authors:
*
......@@ -176,7 +176,8 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status )
*****************************************************************************/
static void RunThread( input_thread_t *p_input )
{
data_packet_t * pp_packets[INPUT_READ_ONCE];
data_packet_t * pp_packets[INPUT_READ_ONCE];
int i_error, i;
InitThread( p_input );
......@@ -195,15 +196,23 @@ static void RunThread( input_thread_t *p_input )
}
vlc_mutex_unlock( &p_input->stream.control.control_lock );
p_input->p_plugin->pf_read( p_input, pp_packets );
if( !p_input->b_error )
i_error = p_input->p_plugin->pf_read( p_input, pp_packets );
/* Demultiplex read packets. */
for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
{
int i;
p_input->p_plugin->pf_demux( p_input, pp_packets[i] );
}
for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
if( i_error )
{
if( i_error == 1 )
{
p_input->p_plugin->pf_demux( p_input, pp_packets[i] );
/* End of file */
intf_WarnMsg( 1, "End of file reached" );
/* FIXME: don't treat that as an error */
}
p_input->b_error = 1;
}
}
......
/* Communication plugin -> input */
/*****************************************************************************
* input.h: structures of the input not exported to other modules
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input.h,v 1.4 2000/12/20 16:04:31 massiot Exp $
*
* Authors:
*
* 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.
*****************************************************************************/
/*
* Communication plugin -> input
*/
/* FIXME: you've gotta move this move this, you've gotta move this move this */
#define INPUT_READ_ONCE 7 /* We live in a world dominated by Ethernet. *
* Ethernet MTU is 1500 bytes, so in a UDP *
* packet we can put : 1500/188 = 7 TS *
......@@ -22,7 +48,7 @@ typedef struct input_capabilities_s
void (* pf_end)( struct input_thread_s * );
/* Read & Demultiplex */
void (* pf_read)( struct input_thread_s *,
int (* pf_read)( struct input_thread_s *,
struct data_packet_s * pp_packets[INPUT_READ_ONCE] );
void (* pf_demux)( struct input_thread_s *,
struct data_packet_s * );
......@@ -54,6 +80,7 @@ void input_InitStream( struct input_thread_s *, size_t );
struct pgrm_descriptor_s * input_AddProgram( struct input_thread_s *,
u16, size_t );
void input_DelProgram( struct input_thread_s *, u16 );
void input_DumpStream( struct input_thread_s * );
struct es_descriptor_s * input_AddES( struct input_thread_s *,
struct pgrm_descriptor_s *, u16,
size_t );
......
......@@ -2,7 +2,7 @@
* input_programs.c: es_descriptor_t, pgrm_descriptor_t management
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_programs.c,v 1.4 2000/12/19 19:08:51 massiot Exp $
* $Id: input_programs.c,v 1.5 2000/12/20 16:04:31 massiot Exp $
*
* Authors:
*
......@@ -51,6 +51,7 @@
*****************************************************************************/
void input_InitStream( input_thread_t * p_input, size_t i_data_len )
{
p_input->stream.i_stream_id = 0;
p_input->stream.i_pgrm_number = 0;
p_input->stream.pp_programs = NULL;
......@@ -283,6 +284,44 @@ void input_DelES( input_thread_t * p_input, u16 i_id )
}
}
#ifdef STATS
/*****************************************************************************
* input_DumpStream: dumps the contents of a stream descriptor
*****************************************************************************/
void input_DumpStream( input_thread_t * p_input )
{
int i, j;
#define S p_input->stream
intf_Msg( "input info: Dumping stream ID 0x%x\n", S.i_stream_id );
if( S.b_seekable )
intf_Msg( "input info: seekable stream, position: %d/%d\n",
S.i_tell, S.i_size );
else
intf_Msg( "input info: %s\n", S.b_pace_control ? "pace controlled" :
"pace un-controlled" );
#undef S
for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
{
#define P p_input->stream.pp_programs[i]
intf_Msg( "input info: Dumping program 0x%x, version %d (%s)\n",
P->i_number, P->i_version,
P->b_is_ok ? "complete" : "partial" );
if( P->i_synchro_state == SYNCHRO_OK )
intf_Msg( "input info: synchro absolute delta : %lld (jitter : %lld)\n",
P->delta_absolute, P->delta_cr );
#undef P
for( j = 0; j < p_input->stream.pp_programs[i]->i_es_number; j++ )
{
#define ES p_input->stream.pp_programs[i]->pp_es[j]
intf_Msg( "input info: ES 0x%x, stream 0x%x, type 0x%x, %s\n",
ES->i_id, ES->i_stream_id, ES->i_type,
ES->p_decoder_fifo != NULL ? "selected" : "not selected");
#undef ES
}
}
}
#endif
/*****************************************************************************
* InitDecConfig: initializes a decoder_config_t
*****************************************************************************/
......
This diff is collapsed.
......@@ -2,7 +2,7 @@
* mpeg_system.c: TS, PS and PES management
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: mpeg_system.c,v 1.9 2000/12/19 19:08:51 massiot Exp $
* $Id: mpeg_system.c,v 1.10 2000/12/20 16:04:31 massiot Exp $
*
* Authors:
*
......@@ -748,6 +748,105 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
}
}
/*****************************************************************************
* input_ParsePS: read the PS header
*****************************************************************************/
es_descriptor_t * input_ParsePS( input_thread_t * p_input,
data_packet_t * p_data )
{
u32 i_code;
es_descriptor_t * p_es = NULL;
i_code = U32_AT( p_data->p_buffer );
if( i_code > 0x1BC ) /* ES start code */
{
u16 i_id;
int i_dummy;
/* This is a PES packet. Find out if we want it or not. */
i_id = GetID( p_data );
vlc_mutex_lock( &p_input->stream.stream_lock );
if( p_input->stream.pp_programs[0]->b_is_ok )
{
/* Look only at the selected ES. */
for( i_dummy = 0; i_dummy < INPUT_MAX_SELECTED_ES; i_dummy++ )
{
if( p_input->pp_selected_es[i_dummy] != NULL
&& p_input->pp_selected_es[i_dummy]->i_id == i_id )
{
p_es = p_input->pp_selected_es[i_dummy];
break;
}
}
}
else
{
/* Search all ES ; if not found -> AddES */
for( i_dummy = 0; i_dummy < INPUT_MAX_ES; i_dummy++ )
{
if( p_input->p_es[i_dummy].i_id != EMPTY_ID
&& p_input->p_es[i_dummy].i_id == i_id )
{
p_es = &p_input->p_es[i_dummy];
break;
}
}
if( p_es == NULL )
{
p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
i_id, 0 );
if( p_es != NULL )
{
p_es->i_stream_id = p_data->p_buffer[3];
/* Set stream type and auto-spawn. */
if( (i_id & 0xF0) == 0xE0 )
{
/* MPEG video */
p_es->i_type = MPEG2_VIDEO_ES;
#ifdef AUTO_SPAWN
input_SelectES( p_input, p_es );
#endif
}
else if( (i_id & 0xE0) == 0xC0 )
{
/* MPEG audio */
p_es->i_type = MPEG2_AUDIO_ES;
#ifdef AUTO_SPAWN
input_SelectES( p_input, p_es );
#endif
}
else if( (i_id & 0xF0FF) == 0x80BD )
{
/* AC3 audio */
p_es->i_type = AC3_AUDIO_ES;
#ifdef AUTO_SPAWN
input_SelectES( p_input, p_es );
#endif
}
else if( (i_id & 0xF0FF) == 0x20BD )
{
/* Subtitles video */
p_es->i_type = DVD_SPU_ES;
#ifdef AUTO_SPAWN
input_SelectES( p_input, p_es );
#endif
}
else
{
p_es->i_type = UNKNOWN_ES;
}
}
}
} /* stream.b_is_ok */
vlc_mutex_unlock( &p_input->stream.stream_lock );
} /* i_code > 0xBC */
return( p_es );
}
/*****************************************************************************
* input_DemuxPS: first step of demultiplexing: the PS header
*****************************************************************************/
......@@ -758,7 +857,7 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
es_descriptor_t * p_es = NULL;
i_code = U32_AT( p_data->p_buffer );
if( i_code >= 0x1B9 && i_code <= 0x1BC )
if( i_code <= 0x1BC )
{
switch( i_code )
{
......@@ -819,99 +918,9 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
}
else
{
u16 i_id;
int i_dummy;
/* This is a PES packet. Find out if we want it or not. */
i_id = GetID( p_data );
vlc_mutex_lock( &p_input->stream.stream_lock );
#if 1
for( i_dummy = 0; i_dummy < INPUT_MAX_ES; i_dummy++ )
{
if( p_input->p_es[i_dummy].i_id != EMPTY_ID
&& p_input->p_es[i_dummy].i_id == i_id )
{
p_es = &p_input->p_es[i_dummy];
break;
}
}
#else
for( i_dummy = 0; i_dummy < INPUT_MAX_SELECTED_ES; i_dummy++ )
{
if( p_input->pp_selected_es[i_dummy] != NULL
&& p_input->pp_selected_es[i_dummy]->i_id == i_id )
{
p_es = p_input->pp_selected_es[i_dummy];
break;
}
}
#endif
vlc_mutex_unlock( &p_input->stream.stream_lock );
if( p_es == NULL )
{
#if 1
vlc_mutex_lock( &p_input->stream.stream_lock );
p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
i_id, 0 );
if( p_es != NULL )
{
if( (i_id & 0xF0) == 0xE0 )
{
/* MPEG video */
p_es->i_stream_id = i_id;
p_es->i_type = MPEG2_VIDEO_ES;
#ifdef AUTO_SPAWN
input_SelectES( p_input, p_es );
#endif
}
else if( (i_id & 0xE0) == 0xC0 )
{
/* MPEG audio */
p_es->i_stream_id = i_id;
p_es->i_type = MPEG2_AUDIO_ES;
#ifdef AUTO_SPAWN
input_SelectES( p_input, p_es );
#endif
}
else if( (i_id & 0xF0FF) == 0x80BD )
{
/* AC3 audio */
p_es->i_stream_id = 0xBD;
p_es->i_type = AC3_AUDIO_ES;
#ifdef AUTO_SPAWN
input_SelectES( p_input, p_es );
#endif
}
else if( (i_id & 0xF0FF) == 0x20BD )
{
/* Subtitles video */
p_es->i_stream_id = 0xBD;
p_es->i_type = DVD_SPU_ES;
#ifdef AUTO_SPAWN
input_SelectES( p_input, p_es );
#endif
}
else
{
b_trash = 1;
}
vlc_mutex_unlock( &p_input->stream.stream_lock );
}
else
b_trash = 1;
#else
b_trash = 1;
#endif
}
p_es = input_ParsePS( p_input, p_data );
if( p_es->p_decoder_fifo != NULL && !b_trash )
if( p_es != NULL && p_es->p_decoder_fifo != NULL && !b_trash )
{
#ifdef STATS
p_es->c_packets++;
......
/*****************************************************************************
* mpeg_system.h: structures of the input used to parse MPEG-1, MPEG-2 PS
* and TS system layers
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: mpeg_system.h,v 1.2 2000/12/20 16:04:31 massiot Exp $
*
* Authors:
*
* 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.
*****************************************************************************/
/*****************************************************************************
* Constants
*****************************************************************************/
......@@ -91,5 +115,7 @@ void input_DecodePES( struct input_thread_s *, struct es_descriptor_s * );
void input_ParsePES( struct input_thread_s *, struct es_descriptor_s * );
void input_GatherPES( struct input_thread_s *, struct data_packet_s *,
struct es_descriptor_s *, boolean_t, boolean_t );
es_descriptor_t * input_ParsePS( struct input_thread_s *,
struct data_packet_s * );
void input_DemuxPS( struct input_thread_s *, struct data_packet_s * );
void input_DemuxTS( struct input_thread_s *, struct data_packet_s * );
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