]> git.sesse.net Git - vlc/blob - src/input/input_ps.c
Fixed various memory leaks.
[vlc] / src / input / input_ps.c
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.9 2000/12/21 14:18:15 massiot Exp $
6  *
7  * Authors: 
8  *
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.
13  * 
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "defs.h"
28
29 #include <stdlib.h>
30 #include <netinet/in.h>
31 #include <string.h>
32 #include <errno.h>
33
34 #include "config.h"
35 #include "common.h"
36 #include "threads.h"
37 #include "mtime.h"
38
39 #include "intf_msg.h"
40
41 #include "stream_control.h"
42 #include "input_ext-intf.h"
43 #include "input_ext-dec.h"
44
45 #include "input.h"
46
47 #include "input_ps.h"
48 #include "mpeg_system.h"
49
50 #include "debug.h"
51
52 /*****************************************************************************
53  * Local prototypes
54  *****************************************************************************/
55 static int  PSProbe     ( struct input_thread_s * );
56 static int  PSRead      ( struct input_thread_s *,
57                           data_packet_t * p_packets[INPUT_READ_ONCE] );
58 static void PSInit      ( struct input_thread_s * );
59 static void PSEnd       ( struct input_thread_s * );
60 static struct data_packet_s * NewPacket ( void *, size_t );
61 static void DeletePacket( void *, struct data_packet_s * );
62 static void DeletePES   ( void *, struct pes_packet_s * );
63
64 /*
65  * Data reading functions
66  */
67
68 /*****************************************************************************
69  * PSProbe: verifies that the stream is a PS stream
70  *****************************************************************************/
71 static int PSProbe( input_thread_t * p_input )
72 {
73     /* verify that the first three bytes are 0x000001, or unscramble and
74      * re-do. */
75     return 1;
76 }
77
78 /*****************************************************************************
79  * PSInit: initializes PS structures
80  *****************************************************************************/
81 static void PSInit( input_thread_t * p_input )
82 {
83     thread_ps_data_t *  p_method;
84
85     if( (p_method =
86          (thread_ps_data_t *)malloc( sizeof(thread_ps_data_t) )) == NULL )
87     {
88         intf_ErrMsg( "Out of memory" );
89         p_input->b_error = 1;
90         return;
91     }
92
93     p_input->p_method_data = (void *)p_method;
94
95     /* Re-open the socket as a buffered FILE stream */
96     if( (p_method->stream = fdopen( p_input->i_handle, "r" )) == NULL )
97     {
98         intf_ErrMsg( "Cannot open file (%s)", strerror(errno) );
99         p_input->b_error = 1;
100         return;
101     }
102     fseek( p_method->stream, 0, SEEK_SET );
103
104     input_InitStream( p_input, 0 );
105     input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
106
107     if( p_input->stream.b_seekable )
108     {
109         /* Pre-parse the stream to gather stream_descriptor_t. */
110         p_input->stream.pp_programs[0]->b_is_ok = 0;
111         /* FIXME: don't read all stream (it can be long !) */
112         while( !p_input->b_die && !p_input->b_error )
113         {
114             int                 i_result, i;
115             data_packet_t *     pp_packets[INPUT_READ_ONCE];
116
117             i_result = PSRead( p_input, pp_packets );
118             if( i_result == 1 ) break;
119             if( i_result == -1 )
120             {
121                 p_input->b_error = 1;
122                 break;
123             }
124
125             for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
126             {
127                 /* FIXME: use i_p_config_t */
128                 input_ParsePS( p_input, pp_packets[i] );
129             }
130
131             /* File too big. */
132             if( p_input->stream.i_tell > INPUT_PREPARSE_LENGTH )
133             {
134                 break;
135             }
136         }
137         fseek( p_method->stream, 0, SEEK_SET );
138         vlc_mutex_lock( &p_input->stream.stream_lock );
139         p_input->stream.pp_programs[0]->b_is_ok = 1;
140         p_input->stream.i_tell = 0;
141 #ifdef STATS
142         input_DumpStream( p_input );
143 #endif
144         vlc_mutex_unlock( &p_input->stream.stream_lock );
145     }
146     else
147     {
148         /* The programs will be added when we read them. */
149         vlc_mutex_lock( &p_input->stream.stream_lock );
150         p_input->stream.pp_programs[0]->b_is_ok = 0;
151         vlc_mutex_unlock( &p_input->stream.stream_lock );
152     }
153 }
154
155 /*****************************************************************************
156  * PSEnd: frees unused data
157  *****************************************************************************/
158 static void PSEnd( input_thread_t * p_input )
159 {
160     free( p_input->stream.p_demux_data );
161     free( p_input->p_method_data );
162 }
163
164 /*****************************************************************************
165  * SafeRead: reads a chunk of stream and correctly detects errors
166  *****************************************************************************/
167 static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer,
168                                 size_t i_len )
169 {
170     thread_ps_data_t *  p_method;
171     int                 i_error;
172
173     p_method = (thread_ps_data_t *)p_input->p_method_data;
174     while( fread( p_buffer, i_len, 1, p_method->stream ) != 1 )
175     {
176         if( feof( p_method->stream ) )
177         {
178             return( 1 );
179         }
180
181         if( (i_error = ferror( p_method->stream )) )
182         {
183             intf_ErrMsg( "Read failed (%s)", strerror(i_error) );
184             return( -1 );
185         }
186     }
187     vlc_mutex_lock( &p_input->stream.stream_lock );
188     p_input->stream.i_tell += i_len;
189     vlc_mutex_unlock( &p_input->stream.stream_lock );
190     return( 0 );
191 }
192
193 /*****************************************************************************
194  * PSRead: reads a data packet
195  *****************************************************************************
196  * Returns -1 in case of error, 0 if everything went well, and 1 in case of
197  * EOF.
198  *****************************************************************************/
199 static int PSRead( input_thread_t * p_input,
200                    data_packet_t * pp_packets[INPUT_READ_ONCE] )
201 {
202     byte_t              p_header[6];
203     data_packet_t *     p_data;
204     size_t              i_packet_size;
205     int                 i_packet, i_error;
206     thread_ps_data_t *  p_method;
207
208     p_method = (thread_ps_data_t *)p_input->p_method_data;
209
210     memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
211     for( i_packet = 0; i_packet < INPUT_READ_ONCE; i_packet++ )
212     {
213         /* Read what we believe to be a packet header. */
214         if( (i_error = SafeRead( p_input, p_header, 6 )) )
215         {
216             return( i_error );
217         }
218
219         if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L )
220         {
221             /* This is not the startcode of a packet. Read the stream
222              * until we find one. */
223             u32         i_startcode = U32_AT(p_header);
224             int         i_dummy;
225
226             if( i_startcode )
227             {
228                 /* It is common for MPEG-1 streams to pad with zeros
229                  * (although it is forbidden by the recommendation), so
230                  * don't bother everybody in this case. */
231                 intf_WarnMsg( 1, "Garbage at input (%x)\n", i_startcode );
232             }
233
234             while( (i_startcode & 0xFFFFFF00) != 0x100L )
235             {
236                 i_startcode <<= 8;
237                 if( (i_dummy = getc( p_method->stream )) != EOF )
238                 {
239                     i_startcode |= i_dummy;
240                 }
241                 else
242                 {
243                     return( 1 );
244                 }
245             }
246             /* Packet found. */
247             *(u32 *)p_header = U32_AT(&i_startcode);
248             if( (i_error = SafeRead( p_input, p_header + 4, 2 )) )
249             {
250                 return( i_error );
251             }
252         }
253
254         if( U32_AT(p_header) != 0x1BA )
255         {
256             /* That's the case for all packets, except pack header. */
257             i_packet_size = U16_AT(&p_header[4]);
258         }
259         else
260         {
261             /* Pack header. */
262             if( (p_header[4] & 0xC0) == 0x40 )
263             {
264                 /* MPEG-2 */
265                 i_packet_size = 8;
266             }
267             else if( (p_header[4] & 0xF0) == 0x20 )
268             {
269                 /* MPEG-1 */
270                 i_packet_size = 6;
271             }
272             else
273             {
274                 intf_ErrMsg( "Unable to determine stream type" );
275                 return( -1 );
276             }
277         }
278
279         /* Fetch a packet of the appropriate size. */
280         if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL )
281         {
282             intf_ErrMsg( "Out of memory" );
283             return( -1 );
284         }
285
286         /* Copy the header we already read. */
287         memcpy( p_data->p_buffer, p_header, 6 );
288
289         /* Read the remaining of the packet. */
290         if( (i_error =
291                 SafeRead( p_input, p_data->p_buffer + 6, i_packet_size )) )
292         {
293             return( i_error );
294         }
295
296         /* In MPEG-2 pack headers we still have to read stuffing bytes. */
297         if( U32_AT(p_header) == 0x1BA )
298         {
299             if( i_packet_size == 8 && (p_data->p_buffer[13] & 0x7) != 0 )
300             {
301                 /* MPEG-2 stuffing bytes */
302                 byte_t      p_garbage[8];
303                 if( (i_error = SafeRead( p_input, p_garbage,
304                                          p_data->p_buffer[13] & 0x7)) )
305                 {
306                     return( i_error );
307                 }
308             }
309         }
310
311         /* Give the packet to the other input stages. */
312         pp_packets[i_packet] = p_data;
313     }
314
315     return( 0 );
316 }
317
318
319 /*
320  * Packet management utilities
321  */
322
323 /*****************************************************************************
324  * NewPacket: allocates a data packet
325  *****************************************************************************/
326 static struct data_packet_s * NewPacket( void * p_garbage,
327                                          size_t i_size )
328 {
329     data_packet_t * p_data;
330
331     /* Safety check */
332     if( i_size > INPUT_MAX_PACKET_SIZE )
333     {
334         intf_ErrMsg( "Packet too big (%d)", i_size );
335         return NULL;
336     }
337
338     if( (p_data = (data_packet_t *)malloc( sizeof(data_packet_t) )) == NULL )
339     {
340         intf_DbgMsg( "Out of memory" );
341         return NULL;
342     }
343
344     if( (p_data->p_buffer = (byte_t *)malloc( i_size )) == NULL )
345     {
346         intf_DbgMsg( "Out of memory" );
347         free( p_data );
348         return NULL;
349     }
350
351     p_data->p_payload_start = p_data->p_buffer;
352     p_data->p_payload_end = p_data->p_buffer + i_size;
353
354     return( p_data );
355 }
356
357 /*****************************************************************************
358  * NewPES: allocates a pes packet
359  *****************************************************************************/
360 static pes_packet_t * NewPES( void * p_garbage )
361 {
362     pes_packet_t * p_pes;
363
364     if( (p_pes = (pes_packet_t *)malloc( sizeof(pes_packet_t) )) == NULL )
365     {
366         intf_DbgMsg( "Out of memory" );
367         return NULL;
368     }
369
370     p_pes->b_messed_up = p_pes->b_data_alignment = p_pes->b_discontinuity =
371         p_pes->b_has_pts = 0;
372     p_pes->i_pes_size = 0;
373     p_pes->p_first = NULL;
374
375     return( p_pes );
376 }
377
378 /*****************************************************************************
379  * DeletePacket: deletes a data packet
380  *****************************************************************************/
381 static void DeletePacket( void * p_garbage,
382                           data_packet_t * p_data )
383 {
384     ASSERT(p_data);
385     ASSERT(p_data->p_buffer);
386     free( p_data->p_buffer );
387     free( p_data );
388 }
389
390 /*****************************************************************************
391  * DeletePES: deletes a PES packet and associated data packets
392  *****************************************************************************/
393 static void DeletePES( void * p_garbage, pes_packet_t * p_pes )
394 {
395     data_packet_t *     p_data;
396     data_packet_t *     p_next;
397
398     p_data = p_pes->p_first;
399
400     while( p_data != NULL )
401     {
402         p_next = p_data->p_next;
403         free( p_data->p_buffer );
404         free( p_data );
405         p_data = p_next;
406     }
407
408     free( p_pes );
409 }
410
411 /*****************************************************************************
412  * PSKludge: fakes a PS plugin (FIXME)
413  *****************************************************************************/
414 input_capabilities_t * PSKludge( void )
415 {
416     input_capabilities_t *  p_plugin;
417
418     p_plugin = (input_capabilities_t *)malloc( sizeof(input_capabilities_t) );
419     p_plugin->pf_init = PSInit;
420     p_plugin->pf_end = PSEnd;
421     p_plugin->pf_read = PSRead;
422     p_plugin->pf_demux = input_DemuxPS; /* FIXME: use i_p_config_t ! */
423     p_plugin->pf_new_packet = NewPacket;
424     p_plugin->pf_new_pes = NewPES;
425     p_plugin->pf_delete_packet = DeletePacket;
426     p_plugin->pf_delete_pes = DeletePES;
427     p_plugin->pf_rewind = NULL;
428     p_plugin->pf_seek = NULL;
429
430     return( p_plugin );
431 }