From 79b461542e823c923581e073ea60cc21c790ba70 Mon Sep 17 00:00:00 2001 From: Henri Fallon Date: Wed, 14 Feb 2001 15:58:29 +0000 Subject: [PATCH] Begining of TS Input Done : - fixed netlist - embryo : support TS video trough file ( kludgy ... ) Next : - Write DecodePSI and DemuxPSI, wich will clean the kludges off Then : - Write NetworkOpen ( shouldn't be difficult ) Eventually : - Deal with lost/corrupt packets --- include/input_netlist.h | 5 ++- plugins/dvd/input_dvd.c | 6 +-- plugins/mpeg/input_ts.c | 91 +++++++++++++++++++++++++++++++++++++-- plugins/mpeg/input_ts.h | 35 +++++++++++++++ src/input/input_netlist.c | 80 ++++++++++++++++++++++------------ src/input/mpeg_system.c | 54 +++++++++++++++++------ 6 files changed, 222 insertions(+), 49 deletions(-) create mode 100644 plugins/mpeg/input_ts.h diff --git a/include/input_netlist.h b/include/input_netlist.h index 301d5e1c25..105af6088d 100644 --- a/include/input_netlist.h +++ b/include/input_netlist.h @@ -36,8 +36,9 @@ int input_NetlistInit( struct input_thread_s *, int i_nb_data, int i_nb_pes, size_t i_buffer_size, int i_read_once ); -struct iovec * input_NetlistGetiovec( void *, struct data_packet_s** ); -void input_NetlistMviovec( void *, size_t ); + +struct iovec * input_NetlistGetiovec( void * p_method_data ); +void input_NetlistMviovec( void * , size_t, struct data_packet_s **); struct data_packet_s * input_NetlistNewPacket( void *, size_t ); struct pes_packet_s * input_NetlistNewPES( void * ); void input_NetlistDeletePacket( void *, struct data_packet_s * ); diff --git a/plugins/dvd/input_dvd.c b/plugins/dvd/input_dvd.c index 0aee39d9db..4bd1ba0c96 100644 --- a/plugins/dvd/input_dvd.c +++ b/plugins/dvd/input_dvd.c @@ -10,7 +10,7 @@ * -dvd_udf to find files ***************************************************************************** * Copyright (C) 1998-2001 VideoLAN - * $Id: input_dvd.c,v 1.10 2001/02/14 04:11:01 stef Exp $ + * $Id: input_dvd.c,v 1.11 2001/02/14 15:58:29 henri Exp $ * * Author: Stéphane Borel * @@ -475,7 +475,7 @@ static int DVDRead( input_thread_t * p_input, p_netlist = ( netlist_t * ) p_input->p_method_data; /* Get an iovec pointer */ - if( ( p_vec = input_NetlistGetiovec( p_netlist, &p_data ) ) == NULL ) + if( ( p_vec = input_NetlistGetiovec( p_netlist ) ) == NULL ) { intf_ErrMsg( "DVD: read error" ); return -1; @@ -498,7 +498,7 @@ static int DVDRead( input_thread_t * p_input, #endif /* Update netlist indexes */ - input_NetlistMviovec( p_netlist, p_method->i_read_once ); + input_NetlistMviovec( p_netlist, p_method->i_read_once, &p_data ); i_packet = 0; /* Read headers to compute payload length */ diff --git a/plugins/mpeg/input_ts.c b/plugins/mpeg/input_ts.c index 26aa41c690..7168161781 100644 --- a/plugins/mpeg/input_ts.c +++ b/plugins/mpeg/input_ts.c @@ -2,7 +2,7 @@ * input_ts.c: TS demux and netlist management ***************************************************************************** * Copyright (C) 1998, 1999, 2000 VideoLAN - * $Id: input_ts.c,v 1.1 2001/02/08 04:43:27 sam Exp $ + * $Id: input_ts.c,v 1.2 2001/02/14 15:58:29 henri Exp $ * * Authors: * @@ -29,6 +29,8 @@ #include #include #include +#include + #include "config.h" #include "common.h" @@ -44,6 +46,7 @@ #include "input_ext-dec.h" #include "input.h" +#include "input_ts.h" #include "mpeg_system.h" #include "input_netlist.h" @@ -91,7 +94,7 @@ static int TSProbe( probedata_t * p_data ) } /* verify that the first byte is 0x47 */ - return 1; + return 0; } /***************************************************************************** @@ -100,6 +103,58 @@ static int TSProbe( probedata_t * p_data ) static void TSInit( input_thread_t * p_input ) { /* Initialize netlist and TS structures */ + thread_ts_data_t * p_method; + pgrm_ts_data_t * p_pgrm_demux; + es_descriptor_t * kludge1; + + /* Initialise structure */ + p_method = malloc( sizeof( thread_ts_data_t ) ); + if( p_method == NULL ) + { + intf_ErrMsg( "Out of memory" ); + p_input->b_error = 1; + return; + } + + p_input->p_plugin_data = (void *)p_method; + p_input->p_method_data = NULL; + + + /* XXX : For the time being, only file, after, i'll do the network */ + + /* Initialize netlist */ + if( input_NetlistInit( p_input, NB_DATA, NB_PES, TS_PACKET_SIZE, + INPUT_READ_ONCE ) ) + { + intf_ErrMsg( "Could not initialize netlist" ); + return; + } + + /* Initialize the stream */ + input_InitStream( p_input, sizeof( stream_ts_data_t ) ); + + /* FIXME : PSIDemux and PSIDecode */ + /* Add audio and video programs */ + /* p_input->stream.pp_programs[0] = */ + input_AddProgram( p_input, 0, sizeof( pgrm_ts_data_t ) ); + p_pgrm_demux = + (pgrm_ts_data_t *)p_input->stream.pp_programs[0]->p_demux_data; + p_pgrm_demux->i_pcr_pid = 0x78; + + kludge1 = input_AddES( p_input, p_input->stream.pp_programs[0], + 0x78, sizeof( es_ts_data_t ) ); + + // kludge + kludge1->i_type = MPEG2_VIDEO_ES; + + input_SelectES( p_input, kludge1 ); + + vlc_mutex_lock( &(p_input->stream.stream_lock) ); + p_input->stream.pp_programs[0]->b_is_ok = 1; + vlc_mutex_unlock( &(p_input->stream.stream_lock) ); + +//debug +intf_ErrMsg("End of TSINIT"); } /***************************************************************************** @@ -119,6 +174,34 @@ static void TSEnd( input_thread_t * p_input ) static int TSRead( input_thread_t * p_input, data_packet_t * pp_packets[INPUT_READ_ONCE] ) { - return -1; -} + unsigned int i_read, i_loop; + struct iovec * p_iovec; + + memset( pp_packets, 0, INPUT_READ_ONCE*sizeof(data_packet_t *) ); + + p_iovec = input_NetlistGetiovec( p_input->p_method_data ); + + if ( p_iovec == NULL ) + { + return( -1 ); /* empty netlist */ + } + i_read = readv( p_input->i_handle, p_iovec, INPUT_READ_ONCE ); + + if( i_read == -1 ) + { + intf_ErrMsg( "Could not readv" ); + return( -1 ); + } + + input_NetlistMviovec( p_input->p_method_data, + (int)(i_read/TS_PACKET_SIZE) , pp_packets ); + + /* check correct TS header */ + for( i_loop=0; i_loop < (int)(i_read/TS_PACKET_SIZE); i_loop++ ) + { + if( pp_packets[i_loop]->p_buffer[0] != 0x47 ) + intf_ErrMsg( "Bad TS Packet (starcode != 0x47)." ); + } + return 0; +} diff --git a/plugins/mpeg/input_ts.h b/plugins/mpeg/input_ts.h new file mode 100644 index 0000000000..f45d22902d --- /dev/null +++ b/plugins/mpeg/input_ts.h @@ -0,0 +1,35 @@ +/***************************************************************************** + * input.h: structures of the input not exported to other modules + ***************************************************************************** + * Copyright (C) 1999, 2000 VideoLAN + * $Id: input_ts.h,v 1.1 2001/02/14 15:58:29 henri 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. + *****************************************************************************/ + + +// #define NB_DATA 16384 +// #define NB_PES 8192 +#define NB_DATA 17000 +#define NB_PES 9000 + + +typedef struct thread_ts_data_s { + + // FILE * stream; + +} thread_ts_data_t; diff --git a/src/input/input_netlist.c b/src/input/input_netlist.c index b3593dc112..884377f2c0 100644 --- a/src/input/input_netlist.c +++ b/src/input/input_netlist.c @@ -2,7 +2,7 @@ * input_netlist.c: netlist management ***************************************************************************** * Copyright (C) 1998, 1999, 2000 VideoLAN - * $Id: input_netlist.c,v 1.30 2001/02/08 17:44:12 massiot Exp $ + * $Id: input_netlist.c,v 1.31 2001/02/14 15:58:29 henri Exp $ * * Authors: Henri Fallon * @@ -41,8 +41,8 @@ #include "input_ext-intf.h" #include "input_ext-dec.h" -#include "input_netlist.h" #include "input.h" +#include "input_netlist.h" /***************************************************************************** * Local prototypes @@ -67,6 +67,8 @@ int input_NetlistInit( input_thread_t * p_input, int i_nb_data, int i_nb_pes, p_netlist = (netlist_t *) p_input->p_method_data; + p_netlist->i_read_once = i_read_once; + /* allocate the buffers */ p_netlist->p_buffers = (byte_t *) malloc(i_buffer_size* i_nb_data ); @@ -107,7 +109,7 @@ int input_NetlistInit( input_thread_t * p_input, int i_nb_data, int i_nb_pes, } p_netlist->p_free_iovec = ( struct iovec * ) - malloc( (i_nb_data + INPUT_READ_ONCE) * sizeof(struct iovec) ); + malloc( (i_nb_data + p_netlist->i_read_once) * sizeof(struct iovec) ); if ( p_netlist->p_free_iovec == NULL ) { intf_ErrMsg ("Unable to malloc in netlist initialization (6)"); @@ -121,6 +123,9 @@ int input_NetlistInit( input_thread_t * p_input, int i_nb_data, int i_nb_pes, p_netlist->pp_free_data[i_loop]->p_buffer = p_netlist->p_buffers + i_loop * i_buffer_size; + + p_netlist->pp_free_data[i_loop]->p_payload_start = + p_netlist->pp_free_data[i_loop]->p_buffer; p_netlist->pp_free_data[i_loop]->p_payload_end = p_netlist->pp_free_data[i_loop]->p_buffer + i_buffer_size; @@ -140,7 +145,7 @@ int input_NetlistInit( input_thread_t * p_input, int i_nb_data, int i_nb_pes, p_netlist->p_free_iovec[i_loop].iov_len = i_buffer_size; } - + /* vlc_mutex_init */ vlc_mutex_init (&p_netlist->lock); @@ -155,16 +160,17 @@ int input_NetlistInit( input_thread_t * p_input, int i_nb_data, int i_nb_pes, p_netlist->i_nb_pes = i_nb_pes; p_netlist->i_buffer_size = i_buffer_size; - p_netlist->i_read_once = i_read_once; - return (0); /* Everything went all right */ } /***************************************************************************** * input_NetlistGetiovec: returns an iovec pointer for a readv() operation + ***************************************************************************** + * We return an iovec vector, so that readv can read many packets at a time, + * and we set pp_data to direct to the fifo pointer, which will allow us + * to get the corresponding data_packet. *****************************************************************************/ -struct iovec * input_NetlistGetiovec( void * p_method_data, - struct data_packet_s ** pp_data ) +struct iovec * input_NetlistGetiovec( void * p_method_data ) { netlist_t * p_netlist; @@ -191,22 +197,11 @@ struct iovec * input_NetlistGetiovec( void * p_method_data, p_netlist->p_free_iovec, (p_netlist->i_read_once- (p_netlist->i_nb_data-p_netlist->i_data_start)) - * sizeof(struct iovec*) + * sizeof(struct iovec) ); } - /* Gives a pointer to the data_packet struct associated with io_vec */ - *pp_data = p_netlist->pp_free_data[p_netlist->i_data_start]; - - /* Initialize payload start and end */ - p_netlist->pp_free_data[p_netlist->i_data_start]->p_payload_start - = p_netlist->pp_free_data[p_netlist->i_data_start]->p_buffer; - - p_netlist->pp_free_data[p_netlist->i_data_start]->p_payload_end - = p_netlist->pp_free_data[p_netlist->i_data_start]->p_payload_start - + p_netlist->i_buffer_size; - return &p_netlist->p_free_iovec[p_netlist->i_data_start]; } @@ -214,16 +209,34 @@ struct iovec * input_NetlistGetiovec( void * p_method_data, /***************************************************************************** * input_NetlistMviovec: move the iovec pointer after a readv() operation *****************************************************************************/ -void input_NetlistMviovec( void * p_method_data, size_t i_nb_iovec ) +void input_NetlistMviovec( void * p_method_data, size_t i_nb_iovec, + struct data_packet_s * pp_packets[INPUT_READ_ONCE] ) { netlist_t * p_netlist; + unsigned int i_loop = 0; + unsigned int i_current; /* cast */ p_netlist = (netlist_t *) p_method_data; /* lock */ vlc_mutex_lock ( &p_netlist->lock ); - + + i_current = p_netlist->i_data_start; + + + /* Fills a table of pointers to packets associated with the io_vec's */ +while (i_loop < i_nb_iovec ) + { + if( i_current >= p_netlist->i_nb_data ) + i_current-=p_netlist->i_nb_data; + + pp_packets[i_loop] = p_netlist->pp_free_data[i_current]; + + i_loop ++; + i_current ++; + } + p_netlist->i_data_start += i_nb_iovec; p_netlist->i_data_start %= p_netlist->i_nb_data; @@ -333,13 +346,18 @@ void input_NetlistDeletePacket( void * p_method_data, data_packet_t * p_data ) /* lock */ vlc_mutex_lock ( &p_netlist->lock ); - /* Delete data_packet */ + + /* Delete data_packet */ p_netlist->i_data_end ++; p_netlist->i_data_end %= p_netlist->i_nb_data; + p_netlist->pp_free_data[p_netlist->i_data_end] = p_data; - p_netlist->p_free_iovec[p_netlist->i_data_end].iov_base = p_data->p_buffer; - + + /* re initialize for next time */ + p_data->p_payload_start = p_data->p_buffer; + p_data->p_next = NULL; + /* unlock */ vlc_mutex_unlock (&p_netlist->lock); } @@ -350,7 +368,7 @@ void input_NetlistDeletePacket( void * p_method_data, data_packet_t * p_data ) void input_NetlistDeletePES( void * p_method_data, pes_packet_t * p_pes ) { netlist_t * p_netlist; - data_packet_t * p_current_packet; + data_packet_t * p_current_packet,* p_next_packet; /* cast */ p_netlist = (netlist_t *)p_method_data; @@ -366,12 +384,18 @@ void input_NetlistDeletePES( void * p_method_data, pes_packet_t * p_pes ) p_netlist->i_data_end ++; p_netlist->i_data_end %= p_netlist->i_nb_data; - p_netlist->pp_free_data[p_netlist->i_data_end] = p_current_packet; + + /* re initialize*/ + p_current_packet->p_payload_start = p_current_packet->p_buffer; + p_netlist->pp_free_data[p_netlist->i_data_end] = p_current_packet; + p_netlist->p_free_iovec[p_netlist->i_data_end].iov_base = p_current_packet->p_buffer; - p_current_packet = p_current_packet->p_next; + p_next_packet = p_current_packet->p_next; + p_current_packet->p_next = NULL; + p_current_packet = p_next_packet; } /* delete our current PES packet */ diff --git a/src/input/mpeg_system.c b/src/input/mpeg_system.c index 49dae60cae..099f74c9db 100644 --- a/src/input/mpeg_system.c +++ b/src/input/mpeg_system.c @@ -2,7 +2,7 @@ * mpeg_system.c: TS, PS and PES management ***************************************************************************** * Copyright (C) 1998, 1999, 2000 VideoLAN - * $Id: mpeg_system.c,v 1.35 2001/02/12 07:52:40 sam Exp $ + * $Id: mpeg_system.c,v 1.36 2001/02/14 15:58:29 henri Exp $ * * Authors: Christophe Massiot * Michel Lespinasse @@ -448,7 +448,7 @@ void input_GatherPES( input_thread_t * p_input, data_packet_t * p_data, } p_pes->i_rate = p_input->stream.control.i_rate; p_pes->p_first = p_data; - + /* If the PES header fits in the first data packet, we can * already set p_gather->i_pes_real_size. */ if( p_data->p_payload_end - p_data->p_payload_start @@ -456,11 +456,12 @@ void input_GatherPES( input_thread_t * p_input, data_packet_t * p_data, { p_es->i_pes_real_size = U16_AT(p_data->p_payload_start + 4) + 6; + } else - { + { p_es->i_pes_real_size = 0; - } + } } else { @@ -864,7 +865,7 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data ) } } - + /* * TS Demultiplexing */ @@ -884,7 +885,7 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data ) es_ts_data_t * p_es_demux = NULL; pgrm_ts_data_t * p_pgrm_demux = NULL; -#define p (p_data->p_buffer) + #define p (p_data->p_buffer) //intf_DbgMsg("input debug: TS-demultiplexing packet %p, pid %d", // p_ts_packet, U16_AT(&p[1]) & 0x1fff); @@ -897,8 +898,22 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data ) /* Find out the elementary stream. */ vlc_mutex_lock( &p_input->stream.stream_lock ); - p_es = input_FindES( p_input, i_pid ); +// kludge +if ( i_pid == 0x78 ) +{ + p_es = input_FindES( p_input, 0x78 ); + p_es->i_type = MPEG2_VIDEO_ES; + if( p_es->p_pes == NULL ) + intf_ErrMsg("Got p_es . p_es->p_pes == null ? %d",p_es->p_pes == NULL); +} +else +{ + p_es = NULL; + b_trash = 1; +} + + vlc_mutex_lock( &p_input->stream.control.control_lock ); if( p_es == NULL || p_es->p_decoder_fifo == NULL || (p_es->b_audio && p_input->stream.control.b_mute) ) @@ -909,6 +924,15 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data ) vlc_mutex_unlock( &p_input->stream.control.control_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock ); +// kludge + if (p_es != NULL ) + { + + p_es_demux = (es_ts_data_t *)p_es->p_demux_data; + p_pgrm_demux = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data; + + p_pgrm_demux->i_pcr_pid = 0x78; + if( (p_es->p_decoder_fifo != NULL) || (p_pgrm_demux->i_pcr_pid == i_pid) ) { #ifdef STATS @@ -916,6 +940,7 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data ) #endif /* Extract adaptation field information if any */ + if( !b_adaptation ) { /* We don't have any adaptation_field, so payload starts @@ -973,6 +998,7 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data ) /* If this is a PCR_PID, and this TS packet contains a * PCR, we pass it along to the PCR decoder. */ + if( (p_pgrm_demux->i_pcr_pid == i_pid) && (p[5] & 0x10) ) { /* There should be a PCR field in the packet, check @@ -993,13 +1019,12 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data ) } /* valid TS adaptation field ? */ } /* length > 0 */ } /* has adaptation field */ - /* Check the continuity of the stream. */ i_dummy = ((p[3] & 0x0f) - p_es_demux->i_continuity_counter) & 0x0f; if( i_dummy == 1 ) { /* Everything is ok, just increase our counter */ - p_es_demux->i_continuity_counter++; + (p_es_demux->i_continuity_counter)++; } else { @@ -1046,10 +1071,13 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data ) } /* continuity */ } /* if selected or PCR */ + } + /* Trash the packet if it has no payload or if it isn't selected */ if( b_trash ) { - p_input->pf_delete_packet( p_input, p_data ); + + p_input->pf_delete_packet( p_input->p_method_data, p_data ); #ifdef STATS p_input->c_packets_trashed++; #endif @@ -1058,6 +1086,8 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data ) { if( p_es_demux->b_psi ) { +//debug +//printf("DemuxTS : Was a PSI\n"); /* The payload contains PSI tables */ #if 0 /* FIXME ! write the PSI decoder :p */ @@ -1068,10 +1098,10 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data ) else { /* The payload carries a PES stream */ - if( b_unit_start ) - input_GatherPES( p_input, p_data, p_es, b_unit_start, b_lost ); + input_GatherPES( p_input, p_data, p_es, b_unit_start, b_lost ); } } #undef p + }