1 /*****************************************************************************
2 * input_es.c: Elementary Stream demux and packet management
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: input_es.c,v 1.5 2001/12/13 17:58:16 jobi 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 #define MODULE_NAME mpeg_es
25 #include "modules_inner.h"
27 /*****************************************************************************
29 *****************************************************************************/
36 #include <sys/types.h>
46 # include <io.h> /* read() */
48 # include <sys/uio.h> /* struct iovec */
58 # include "input_iovec.h"
61 #include "stream_control.h"
62 #include "input_ext-intf.h"
63 #include "input_ext-dec.h"
64 #include "input_ext-plugins.h"
71 #include "modules_export.h"
73 /*****************************************************************************
75 *****************************************************************************/
76 static int ESProbe ( probedata_t * );
77 static int ESRead ( struct input_thread_s *,
78 data_packet_t * p_packets[INPUT_READ_ONCE] );
79 static void ESInit ( struct input_thread_s * );
80 static void ESEnd ( struct input_thread_s * );
81 static void ESSeek ( struct input_thread_s *, off_t );
82 static int ESSetProgram ( struct input_thread_s *, pgrm_descriptor_t * );
83 static void ESDemux ( struct input_thread_s *,
84 struct data_packet_s * );
85 static void ESNextDataPacket( struct bit_stream_s * );
86 static void ESInitBitstream( struct bit_stream_s *, struct decoder_fifo_s *,
87 void (* pf_bitstream_callback)( struct bit_stream_s *,
91 /*****************************************************************************
92 * Declare a buffer manager
93 *****************************************************************************/
94 #define FLAGS BUFFERS_UNIQUE_SIZE
96 DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO );
97 DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
98 DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
99 DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
100 DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 150 );
101 DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
102 DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150, 150 );
103 DECLARE_BUFFERS_TOIO( FLAGS, ES_PACKET_SIZE );
105 /*****************************************************************************
106 * Functions exported as capabilities. They are declared as static so that
107 * we don't pollute the namespace too much.
108 *****************************************************************************/
109 void _M( input_getfunctions )( function_list_t * p_function_list )
111 #define input p_function_list->functions.input
112 p_function_list->pf_probe = ESProbe;
113 input.pf_init = ESInit;
114 input.pf_open = NULL;
115 input.pf_close = NULL;
116 input.pf_end = ESEnd;
117 input.pf_init_bit_stream = ESInitBitstream;
118 input.pf_set_area = NULL;
119 input.pf_set_program = ESSetProgram;
120 input.pf_read = ESRead;
121 input.pf_demux = ESDemux;
122 input.pf_new_packet = input_NewPacket;
123 input.pf_new_pes = input_NewPES;
124 input.pf_delete_packet = input_DeletePacket;
125 input.pf_delete_pes = input_DeletePES;
126 input.pf_rewind = NULL;
127 input.pf_seek = ESSeek;
132 * Data reading functions
135 /*****************************************************************************
136 * ESProbe: verifies that the stream is a ES stream
137 *****************************************************************************/
138 static int ESProbe( probedata_t *p_data )
142 if( TestMethod( INPUT_METHOD_VAR, "es" ) )
150 /*****************************************************************************
151 * ESInit: initializes ES structures
152 *****************************************************************************/
153 static void ESInit( input_thread_t * p_input )
155 es_descriptor_t * p_es;
157 p_input->p_method_data = NULL;
159 if( (p_input->p_method_data = input_BuffersInit()) == NULL )
161 p_input->b_error = 1;
165 /* FIXME : detect if InitStream failed */
166 input_InitStream( p_input, 0 );
167 input_AddProgram( p_input, 0, 0 );
168 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
169 vlc_mutex_lock( &p_input->stream.stream_lock );
170 p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xE0, 0 );
171 p_es->i_stream_id = 0xE0;
172 p_es->i_type = MPEG1_VIDEO_ES;
173 p_es->i_cat = VIDEO_ES;
174 input_SelectES( p_input, p_es );
175 p_input->stream.p_selected_area->i_tell = 0;
176 p_input->stream.p_selected_program->b_is_ok = 1;
177 vlc_mutex_unlock( &p_input->stream.stream_lock );
180 /*****************************************************************************
181 * ESEnd: frees unused data
182 *****************************************************************************/
183 static void ESEnd( input_thread_t * p_input )
185 input_BuffersEnd( p_input->p_method_data );
188 /*****************************************************************************
189 * ESRead: reads data packets
190 *****************************************************************************
191 * Returns -1 in case of error, 0 if everything went well, and 1 in case of
193 *****************************************************************************/
194 static int ESRead( input_thread_t * p_input,
195 data_packet_t * pp_packets[INPUT_READ_ONCE] )
198 struct iovec p_iovec[INPUT_READ_ONCE];
199 data_packet_t * p_data;
202 p_data = input_BuffersToIO( p_input->p_method_data, p_iovec,
205 if ( p_data == NULL )
207 return( -1 ); /* empty netlist */
210 memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
212 i_read = readv( p_input->i_handle, p_iovec, INPUT_READ_ONCE );
215 intf_ErrMsg( "input error: ES readv error" );
219 for( i_loop=0; i_loop * ES_PACKET_SIZE < i_read; i_loop++ )
221 pp_packets[i_loop] = p_data;
222 p_data = p_data->p_next;
223 pp_packets[i_loop]->p_next = NULL;
225 for( ; i_loop < INPUT_READ_ONCE ; i_loop++ )
227 data_packet_t * p_next = p_data->p_next;
228 input_DeletePacket( p_input->p_method_data, p_data );
230 pp_packets[i_loop] = NULL;
234 if( i_read == 0 && p_input->stream.b_seekable )
239 p_input->stream.p_selected_area->i_tell += i_read;
244 /*****************************************************************************
245 * ESSeek: changes the stream position indicator
246 *****************************************************************************/
247 static void ESSeek( input_thread_t * p_input, off_t i_position )
249 lseek( p_input->i_handle, i_position, SEEK_SET );
251 p_input->stream.p_selected_area->i_tell = i_position;
255 /*****************************************************************************
256 * ESSetProgram: Does nothing
257 *****************************************************************************/
258 static int ESSetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
263 /*****************************************************************************
264 * ESDemux: fakes a demultiplexer
265 *****************************************************************************/
266 static void ESDemux( input_thread_t * p_input, data_packet_t * p_data )
268 pes_packet_t * p_pes = p_input->pf_new_pes( p_input->p_method_data );
269 decoder_fifo_t * p_fifo =
270 p_input->stream.p_selected_program->pp_es[0]->p_decoder_fifo;
274 intf_ErrMsg("Out of memory");
275 p_input->b_error = 1;
279 p_pes->i_rate = p_input->stream.control.i_rate;
280 p_pes->p_first = p_pes->p_last = p_data;
281 p_pes->i_nb_data = 1;
283 if( (p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT)
284 | (input_ClockManageControl( p_input,
285 p_input->stream.p_selected_program,
286 (mtime_t)0 ) == PAUSE_S) )
288 intf_WarnMsg( 2, "synchro reinit" );
289 p_pes->i_pts = mdate() + DEFAULT_PTS_DELAY;
290 p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
293 input_DecodePES( p_fifo, p_pes );
295 vlc_mutex_lock( &p_fifo->data_lock );
296 if( ( (DECODER_FIFO_END( *p_fifo ) - DECODER_FIFO_START( *p_fifo ))
297 & FIFO_SIZE ) >= MAX_PACKETS_IN_FIFO )
299 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
301 vlc_mutex_unlock( &p_fifo->data_lock );
304 /*****************************************************************************
305 * ESNextDataPacket: signals the input thread if there isn't enough packets
307 *****************************************************************************/
308 static void ESNextDataPacket( bit_stream_t * p_bit_stream )
310 decoder_fifo_t * p_fifo = p_bit_stream->p_decoder_fifo;
313 /* We are looking for the next data packet that contains real data,
314 * and not just a PES header */
317 /* We were reading the last data packet of this PES packet... It's
318 * time to jump to the next PES packet */
319 if( p_bit_stream->p_data->p_next == NULL )
321 /* We are going to read/write the start and end indexes of the
322 * decoder fifo and to use the fifo's conditional variable,
323 * that's why we need to take the lock before. */
324 vlc_mutex_lock( &p_fifo->data_lock );
326 /* Free the previous PES packet. */
327 p_fifo->pf_delete_pes( p_fifo->p_packets_mgt,
328 DECODER_FIFO_START( *p_fifo ) );
329 DECODER_FIFO_INCSTART( *p_fifo );
331 if( DECODER_FIFO_ISEMPTY( *p_fifo ) )
333 /* Signal the input thread we're waiting. */
334 vlc_cond_signal( &p_fifo->data_wait );
336 /* Wait for the input to tell us when we receive a packet. */
337 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
340 /* The next byte could be found in the next PES packet */
341 p_bit_stream->p_data = DECODER_FIFO_START( *p_fifo )->p_first;
343 vlc_mutex_unlock( &p_fifo->data_lock );
349 /* Perhaps the next data packet of the current PES packet contains
350 * real data (ie its payload's size is greater than 0). */
351 p_bit_stream->p_data = p_bit_stream->p_data->p_next;
355 } while ( p_bit_stream->p_data->p_payload_start
356 == p_bit_stream->p_data->p_payload_end );
358 /* We've found a data packet which contains interesting data... */
359 p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
360 p_bit_stream->p_end = p_bit_stream->p_data->p_payload_end;
362 /* Call back the decoder. */
363 if( p_bit_stream->pf_bitstream_callback != NULL )
365 p_bit_stream->pf_bitstream_callback( p_bit_stream, b_new_pes );
369 /*****************************************************************************
370 * ESInitBitstream: changes pf_next_data_packet
371 *****************************************************************************/
372 static void ESInitBitstream( bit_stream_t * p_bit_stream,
373 decoder_fifo_t * p_decoder_fifo,
374 void (* pf_bitstream_callback)( struct bit_stream_s *,
376 void * p_callback_arg )
378 InitBitstream( p_bit_stream, p_decoder_fifo, pf_bitstream_callback,
380 p_bit_stream->pf_next_data_packet = ESNextDataPacket;