1 /*****************************************************************************
2 * input_ps.c: PS demux and packet management
3 *****************************************************************************
4 * Copyright (C) 1998, 1999, 2000 VideoLAN
5 * $Id: input_ps.c,v 1.6 2001/02/16 09:25:03 sam Exp $
7 * Authors: 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 *****************************************************************************/
33 #include <sys/types.h>
48 #include "stream_control.h"
49 #include "input_ext-intf.h"
50 #include "input_ext-dec.h"
55 #include "mpeg_system.h"
61 /*****************************************************************************
63 *****************************************************************************/
64 static int PSProbe ( probedata_t * );
65 static int PSRead ( struct input_thread_s *,
66 data_packet_t * p_packets[INPUT_READ_ONCE] );
67 static void PSInit ( struct input_thread_s * );
68 static void PSEnd ( struct input_thread_s * );
69 static void PSSeek ( struct input_thread_s *, off_t );
70 static struct pes_packet_s * NewPES ( void * );
71 static struct data_packet_s * NewPacket ( void *, size_t );
72 static void DeletePacket( void *, struct data_packet_s * );
73 static void DeletePES ( void *, struct pes_packet_s * );
75 /*****************************************************************************
76 * Functions exported as capabilities. They are declared as static so that
77 * we don't pollute the namespace too much.
78 *****************************************************************************/
79 void input_getfunctions( function_list_t * p_function_list )
81 #define input p_function_list->functions.input
82 p_function_list->pf_probe = PSProbe;
83 input.pf_init = PSInit;
84 input.pf_open = input_FileOpen;
85 input.pf_close = input_FileClose;
87 input.pf_read = PSRead;
88 input.pf_demux = input_DemuxPS;
89 input.pf_new_packet = NewPacket;
90 input.pf_new_pes = NewPES;
91 input.pf_delete_packet = DeletePacket;
92 input.pf_delete_pes = DeletePES;
93 input.pf_rewind = NULL;
94 input.pf_seek = PSSeek;
99 * Data reading functions
102 /*****************************************************************************
103 * PSProbe: verifies that the stream is a PS stream
104 *****************************************************************************/
105 static int PSProbe( probedata_t *p_data )
107 input_thread_t * p_input = (input_thread_t *)p_data;
109 char * psz_name = p_input->p_source;
113 if( TestMethod( INPUT_METHOD_VAR, "ps" ) )
118 if( ( strlen(psz_name) > 5 ) && !strncasecmp( psz_name, "file:", 5 ) )
120 /* If the user specified "file:" then it's probably a file */
125 i_handle = open( psz_name, 0 );
135 /*****************************************************************************
136 * PSInit: initializes PS structures
137 *****************************************************************************/
138 static void PSInit( input_thread_t * p_input )
140 thread_ps_data_t * p_method;
143 (thread_ps_data_t *)malloc( sizeof(thread_ps_data_t) )) == NULL )
145 intf_ErrMsg( "Out of memory" );
146 p_input->b_error = 1;
150 p_input->p_plugin_data = (void *)p_method;
151 p_input->p_method_data = NULL;
153 /* Re-open the socket as a buffered FILE stream */
154 if( (p_method->stream = fdopen( p_input->i_handle, "r" )) == NULL )
156 intf_ErrMsg( "Cannot open file (%s)", strerror(errno) );
157 p_input->b_error = 1;
160 rewind( p_method->stream );
162 /* FIXME : detect if InitStream failed */
163 input_InitStream( p_input, sizeof( stream_ps_data_t ) );
164 input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
166 if( p_input->stream.b_seekable )
168 stream_ps_data_t * p_demux_data =
169 (stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data;
171 /* Pre-parse the stream to gather stream_descriptor_t. */
172 p_input->stream.pp_programs[0]->b_is_ok = 0;
173 p_demux_data->i_PSM_version = EMPTY_PSM_VERSION;
175 while( !p_input->b_die && !p_input->b_error
176 && !p_demux_data->b_has_PSM )
179 data_packet_t * pp_packets[INPUT_READ_ONCE];
181 i_result = PSRead( p_input, pp_packets );
185 vlc_mutex_lock( &p_input->stream.stream_lock );
186 p_input->stream.pp_programs[0]->b_is_ok = 1;
187 vlc_mutex_unlock( &p_input->stream.stream_lock );
192 p_input->b_error = 1;
196 for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
198 /* FIXME: use i_p_config_t */
199 input_ParsePS( p_input, pp_packets[i] );
200 DeletePacket( p_input->p_method_data, pp_packets[i] );
204 if( p_input->stream.i_tell > INPUT_PREPARSE_LENGTH )
209 rewind( p_method->stream );
210 vlc_mutex_lock( &p_input->stream.stream_lock );
211 p_input->stream.i_tell = 0;
212 if( p_demux_data->b_has_PSM )
214 /* (The PSM decoder will care about spawning the decoders) */
215 p_input->stream.pp_programs[0]->b_is_ok = 1;
220 /* (We have to do it ourselves) */
223 /* FIXME: we should do multiple passes in case an audio type
226 i_es < p_input->stream.pp_programs[0]->i_es_number;
229 #define p_es p_input->stream.pp_programs[0]->pp_es[i_es]
230 switch( p_es->i_type )
234 input_SelectES( p_input, p_es );
239 if( main_GetIntVariable( INPUT_CHANNEL_VAR, 0 )
240 == (p_es->i_id & 0x1F) )
241 switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) )
244 main_PutIntVariable( INPUT_AUDIO_VAR,
247 input_SelectES( p_input, p_es );
252 if( main_GetIntVariable( INPUT_CHANNEL_VAR, 0 )
253 == ((p_es->i_id & 0xF00) >> 8) )
254 switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) )
257 main_PutIntVariable( INPUT_AUDIO_VAR,
260 input_SelectES( p_input, p_es );
265 if( main_GetIntVariable( INPUT_SUBTITLE_VAR, -1 )
266 == ((p_es->i_id & 0x1F00) >> 8) )
268 input_SelectES( p_input, p_es );
281 input_DumpStream( p_input );
283 vlc_mutex_unlock( &p_input->stream.stream_lock );
287 /* The programs will be added when we read them. */
288 vlc_mutex_lock( &p_input->stream.stream_lock );
289 p_input->stream.pp_programs[0]->b_is_ok = 0;
290 vlc_mutex_unlock( &p_input->stream.stream_lock );
294 /*****************************************************************************
295 * PSEnd: frees unused data
296 *****************************************************************************/
297 static void PSEnd( input_thread_t * p_input )
299 free( p_input->stream.p_demux_data );
300 free( p_input->p_plugin_data );
303 /*****************************************************************************
304 * SafeRead: reads a chunk of stream and correctly detects errors
305 *****************************************************************************/
306 static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer,
309 thread_ps_data_t * p_method;
312 p_method = (thread_ps_data_t *)p_input->p_plugin_data;
313 while( fread( p_buffer, i_len, 1, p_method->stream ) != 1 )
315 if( feof( p_method->stream ) )
320 if( (i_error = ferror( p_method->stream )) )
322 intf_ErrMsg( "Read failed (%s)", strerror(i_error) );
326 vlc_mutex_lock( &p_input->stream.stream_lock );
327 p_input->stream.i_tell += i_len;
328 vlc_mutex_unlock( &p_input->stream.stream_lock );
332 /*****************************************************************************
333 * PSRead: reads data packets
334 *****************************************************************************
335 * Returns -1 in case of error, 0 if everything went well, and 1 in case of
337 *****************************************************************************/
338 static int PSRead( input_thread_t * p_input,
339 data_packet_t * pp_packets[INPUT_READ_ONCE] )
342 data_packet_t * p_data;
343 size_t i_packet_size;
344 int i_packet, i_error;
345 thread_ps_data_t * p_method;
347 p_method = (thread_ps_data_t *)p_input->p_plugin_data;
349 memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
350 for( i_packet = 0; i_packet < INPUT_READ_ONCE; i_packet++ )
352 /* Read what we believe to be a packet header. */
353 if( (i_error = SafeRead( p_input, p_header, 6 )) )
358 if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L )
360 /* This is not the startcode of a packet. Read the stream
361 * until we find one. */
362 u32 i_startcode = U32_AT(p_header);
367 /* It is common for MPEG-1 streams to pad with zeros
368 * (although it is forbidden by the recommendation), so
369 * don't bother everybody in this case. */
370 intf_WarnMsg( 1, "Garbage at input (%x)", i_startcode );
373 while( (i_startcode & 0xFFFFFF00) != 0x100L )
376 if( (i_dummy = getc( p_method->stream )) != EOF )
378 i_startcode |= i_dummy;
386 *(u32 *)p_header = U32_AT(&i_startcode);
387 if( (i_error = SafeRead( p_input, p_header + 4, 2 )) )
393 if( U32_AT(p_header) != 0x1BA )
395 /* That's the case for all packets, except pack header. */
396 i_packet_size = U16_AT(&p_header[4]);
401 if( (p_header[4] & 0xC0) == 0x40 )
406 else if( (p_header[4] & 0xF0) == 0x20 )
413 intf_ErrMsg( "Unable to determine stream type" );
418 /* Fetch a packet of the appropriate size. */
419 if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL )
421 intf_ErrMsg( "Out of memory" );
425 /* Copy the header we already read. */
426 memcpy( p_data->p_buffer, p_header, 6 );
428 /* Read the remaining of the packet. */
429 if( i_packet_size && (i_error =
430 SafeRead( p_input, p_data->p_buffer + 6, i_packet_size )) )
435 /* In MPEG-2 pack headers we still have to read stuffing bytes. */
436 if( U32_AT(p_header) == 0x1BA )
438 if( i_packet_size == 8 && (p_data->p_buffer[13] & 0x7) != 0 )
440 /* MPEG-2 stuffing bytes */
442 if( (i_error = SafeRead( p_input, p_garbage,
443 p_data->p_buffer[13] & 0x7)) )
450 /* Give the packet to the other input stages. */
451 pp_packets[i_packet] = p_data;
457 /*****************************************************************************
458 * PSSeek: changes the stream position indicator
459 *****************************************************************************/
460 static void PSSeek( input_thread_t * p_input, off_t i_position )
462 thread_ps_data_t * p_method;
464 p_method = (thread_ps_data_t *)p_input->p_plugin_data;
466 /* A little bourrin but should work for a while --Meuuh */
467 fseeko( p_method->stream, i_position, SEEK_SET );
469 p_input->stream.i_tell = i_position;
473 * Packet management utilities
476 /*****************************************************************************
477 * NewPacket: allocates a data packet
478 *****************************************************************************/
479 static struct data_packet_s * NewPacket( void * p_garbage,
482 data_packet_t * p_data;
485 if( i_size > INPUT_MAX_PACKET_SIZE )
487 intf_ErrMsg( "Packet too big (%d)", i_size );
491 if( (p_data = (data_packet_t *)malloc( sizeof(data_packet_t) )) == NULL )
493 intf_DbgMsg( "Out of memory" );
497 if( (p_data->p_buffer = (byte_t *)malloc( i_size )) == NULL )
499 intf_DbgMsg( "Out of memory" );
504 /* Initialize data */
505 p_data->p_next = NULL;
506 p_data->b_discard_payload = 0;
508 p_data->p_payload_start = p_data->p_buffer;
509 p_data->p_payload_end = p_data->p_buffer + i_size;
514 /*****************************************************************************
515 * NewPES: allocates a pes packet
516 *****************************************************************************/
517 static pes_packet_t * NewPES( void * p_garbage )
519 pes_packet_t * p_pes;
521 if( (p_pes = (pes_packet_t *)malloc( sizeof(pes_packet_t) )) == NULL )
523 intf_DbgMsg( "Out of memory" );
527 p_pes->b_data_alignment = p_pes->b_discontinuity =
528 p_pes->i_pts = p_pes->i_dts = 0;
529 p_pes->i_pes_size = 0;
530 p_pes->p_first = NULL;
535 /*****************************************************************************
536 * DeletePacket: deletes a data packet
537 *****************************************************************************/
538 static void DeletePacket( void * p_garbage,
539 data_packet_t * p_data )
542 ASSERT(p_data->p_buffer);
543 free( p_data->p_buffer );
547 /*****************************************************************************
548 * DeletePES: deletes a PES packet and associated data packets
549 *****************************************************************************/
550 static void DeletePES( void * p_garbage, pes_packet_t * p_pes )
552 data_packet_t * p_data;
553 data_packet_t * p_next;
555 p_data = p_pes->p_first;
557 while( p_data != NULL )
559 p_next = p_data->p_next;
560 free( p_data->p_buffer );