1 /*****************************************************************************
2 * input_es.c: Elementary Stream demux and packet management
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: input_es.c,v 1.12 2002/01/21 23:57:46 massiot Exp $
7 * Author: Christophe Massiot <massiot@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <videolan/vlc.h>
33 #include <sys/types.h>
43 # include <io.h> /* read() */
45 # include <sys/uio.h> /* struct iovec */
49 # include "input_iovec.h"
52 #include "stream_control.h"
53 #include "input_ext-intf.h"
54 #include "input_ext-dec.h"
55 #include "input_ext-plugins.h"
61 /*****************************************************************************
63 *****************************************************************************/
64 static int ESProbe ( probedata_t * );
65 static int ESRead ( struct input_thread_s *, data_packet_t ** );
66 static void ESInit ( struct input_thread_s * );
67 static void ESEnd ( struct input_thread_s * );
68 static void ESSeek ( struct input_thread_s *, off_t );
69 static int ESSetProgram ( struct input_thread_s *, pgrm_descriptor_t * );
70 static void ESDemux ( struct input_thread_s *,
71 struct data_packet_s * );
73 /*****************************************************************************
74 * Declare a buffer manager
75 *****************************************************************************/
76 #define FLAGS BUFFERS_UNIQUE_SIZE
78 DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO );
79 DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
80 DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
81 DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
82 DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 150 );
83 DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
84 DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150 );
85 DECLARE_BUFFERS_TOIO( FLAGS, ES_PACKET_SIZE );
87 /*****************************************************************************
88 * Functions exported as capabilities. They are declared as static so that
89 * we don't pollute the namespace too much.
90 *****************************************************************************/
91 void _M( input_getfunctions )( function_list_t * p_function_list )
93 #define input p_function_list->functions.input
94 p_function_list->pf_probe = ESProbe;
95 input.pf_init = ESInit;
97 input.pf_close = NULL;
99 input.pf_set_area = NULL;
100 input.pf_set_program = ESSetProgram;
101 input.pf_read = ESRead;
102 input.pf_demux = ESDemux;
103 input.pf_new_packet = input_NewPacket;
104 input.pf_new_pes = input_NewPES;
105 input.pf_delete_packet = input_DeletePacket;
106 input.pf_delete_pes = input_DeletePES;
107 input.pf_rewind = NULL;
108 input.pf_seek = ESSeek;
113 * Data reading functions
116 /*****************************************************************************
117 * ESProbe: verifies that the stream is a ES stream
118 *****************************************************************************/
119 static int ESProbe( probedata_t *p_data )
126 /*****************************************************************************
127 * ESInit: initializes ES structures
128 *****************************************************************************/
129 static void ESInit( input_thread_t * p_input )
131 es_descriptor_t * p_es;
133 p_input->p_method_data = NULL;
135 if( (p_input->p_method_data = input_BuffersInit()) == NULL )
137 p_input->b_error = 1;
141 /* FIXME : detect if InitStream failed */
142 input_InitStream( p_input, 0 );
143 input_AddProgram( p_input, 0, 0 );
144 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
145 vlc_mutex_lock( &p_input->stream.stream_lock );
146 p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xE0, 0 );
147 p_es->i_stream_id = 0xE0;
148 p_es->i_type = MPEG1_VIDEO_ES;
149 p_es->i_cat = VIDEO_ES;
150 input_SelectES( p_input, p_es );
151 p_input->stream.p_selected_area->i_tell = 0;
152 p_input->stream.p_selected_program->b_is_ok = 1;
153 vlc_mutex_unlock( &p_input->stream.stream_lock );
156 /*****************************************************************************
157 * ESEnd: frees unused data
158 *****************************************************************************/
159 static void ESEnd( input_thread_t * p_input )
161 input_BuffersEnd( p_input->p_method_data );
164 /*****************************************************************************
165 * ESRead: reads data packets
166 *****************************************************************************
167 * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
169 *****************************************************************************/
170 static int ESRead( input_thread_t * p_input,
171 data_packet_t ** pp_data )
174 struct iovec p_iovec[ES_READ_ONCE];
175 data_packet_t * p_data;
178 *pp_data = p_data = input_BuffersToIO( p_input->p_method_data, p_iovec,
181 if ( p_data == NULL )
186 i_read = readv( p_input->i_handle, p_iovec, ES_READ_ONCE );
189 intf_ErrMsg( "input error: ES readv error" );
190 p_input->pf_delete_packet( p_input->p_method_data, p_data );
193 p_input->stream.p_selected_area->i_tell += i_read;
194 i_read /= ES_PACKET_SIZE;
196 if( i_read != ES_READ_ONCE )
198 /* We got fewer packets than wanted. Give remaining packets
199 * back to the buffer allocator. */
202 for( i_loop = 0; i_loop < i_read; i_loop++ )
204 pp_data = &(*pp_data)->p_next;
207 p_input->pf_delete_packet( p_input->p_method_data, *pp_data );
214 /*****************************************************************************
215 * ESSeek: changes the stream position indicator
216 *****************************************************************************/
217 static void ESSeek( input_thread_t * p_input, off_t i_position )
219 lseek( p_input->i_handle, i_position, SEEK_SET );
221 p_input->stream.p_selected_area->i_tell = i_position;
225 /*****************************************************************************
226 * ESSetProgram: Does nothing
227 *****************************************************************************/
228 static int ESSetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
233 /*****************************************************************************
234 * ESDemux: fakes a demultiplexer
235 *****************************************************************************/
236 static void ESDemux( input_thread_t * p_input, data_packet_t * p_data )
238 pes_packet_t * p_pes = p_input->pf_new_pes( p_input->p_method_data );
239 decoder_fifo_t * p_fifo =
240 p_input->stream.p_selected_program->pp_es[0]->p_decoder_fifo;
244 intf_ErrMsg("Out of memory");
245 p_input->b_error = 1;
249 p_pes->i_rate = p_input->stream.control.i_rate;
250 p_pes->p_first = p_pes->p_last = p_data;
251 p_pes->i_nb_data = 1;
253 vlc_mutex_lock( &p_input->stream.stream_lock );
254 if( p_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
256 /* Wait for the decoder. */
257 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
259 vlc_mutex_unlock( &p_input->stream.stream_lock );
261 if( (p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT)
262 | (input_ClockManageControl( p_input,
263 p_input->stream.p_selected_program,
264 (mtime_t)0 ) == PAUSE_S) )
266 intf_WarnMsg( 2, "synchro reinit" );
267 p_pes->i_pts = mdate() + DEFAULT_PTS_DELAY;
268 p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
271 input_DecodePES( p_fifo, p_pes );