]> git.sesse.net Git - vlc/blob - plugins/mpeg/input_ps.c
Fixed a bug in System End Code handling. Contact me in case of problem.
[vlc] / plugins / mpeg / 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.33 2001/08/10 16:38:09 massiot Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Cyril Deguet <asmax@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 #define MODULE_NAME ps
26 #include "modules_inner.h"
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #include "defs.h"
32
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <errno.h>
37
38 #ifdef STRNCASECMP_IN_STRINGS_H
39 #   include <strings.h>
40 #endif
41
42 #include <sys/types.h>
43 #include <sys/stat.h>
44
45 #ifdef HAVE_UNISTD_H
46 #   include <unistd.h>
47 #elif defined( _MSC_VER ) && defined( _WIN32 )
48 #   include <io.h>
49 #endif
50
51 #include <fcntl.h>
52
53 #include "config.h"
54 #include "common.h"
55 #include "threads.h"
56 #include "mtime.h"
57 #include "tests.h"
58
59 #include "intf_msg.h"
60
61 #include "main.h"
62
63 #include "stream_control.h"
64 #include "input_ext-intf.h"
65 #include "input_ext-dec.h"
66 #include "input_ext-plugins.h"
67
68 #include "input_ps.h"
69
70 #include "debug.h"
71
72 #include "modules.h"
73 #include "modules_export.h"
74
75 /*****************************************************************************
76  * fseeko: fseeko replacement for BSDI.
77  *****************************************************************************/
78 #ifdef __bsdi__
79 int    __sfseek __P(( FILE *, fpos_t, int ));
80 fpos_t __sftell __P(( FILE * ));
81
82 static __inline__ off_t fseeko( FILE *p_file, off_t i_offset, int i_pos )
83 {
84     return __sfseek( p_file, i_offset, i_pos );
85 }
86 #endif
87
88 /*****************************************************************************
89  * Local prototypes
90  *****************************************************************************/
91 static int  PSProbe     ( probedata_t * );
92 static int  PSRead      ( struct input_thread_s *,
93                           data_packet_t * p_packets[INPUT_READ_ONCE] );
94 static void PSInit      ( struct input_thread_s * );
95 static void PSEnd       ( struct input_thread_s * );
96 static void PSSeek      ( struct input_thread_s *, off_t );
97 static struct pes_packet_s *  NewPES    ( void * );
98 static struct data_packet_s * NewPacket ( void *, size_t );
99 static void DeletePacket( void *, struct data_packet_s * );
100 static void DeletePES   ( void *, struct pes_packet_s * );
101
102 /*****************************************************************************
103  * Functions exported as capabilities. They are declared as static so that
104  * we don't pollute the namespace too much.
105  *****************************************************************************/
106 void _M( input_getfunctions )( function_list_t * p_function_list )
107 {
108 #define input p_function_list->functions.input
109     p_function_list->pf_probe = PSProbe;
110     input.pf_init             = PSInit;
111     input.pf_open             = NULL; /* Set in PSInit */
112     input.pf_close            = NULL;
113     input.pf_end              = PSEnd;
114     input.pf_init_bit_stream  = InitBitstream;
115     input.pf_set_area         = NULL;
116     input.pf_read             = PSRead;
117     input.pf_demux            = input_DemuxPS;
118     input.pf_new_packet       = NewPacket;
119     input.pf_new_pes          = NewPES;
120     input.pf_delete_packet    = DeletePacket;
121     input.pf_delete_pes       = DeletePES;
122     input.pf_rewind           = NULL;
123     input.pf_seek             = PSSeek;
124 #undef input
125 }
126
127 /*
128  * Data reading functions
129  */
130
131 /*****************************************************************************
132  * PSProbe: verifies that the stream is a PS stream
133  *****************************************************************************/
134 static int PSProbe( probedata_t *p_data )
135 {
136     input_thread_t * p_input = (input_thread_t *)p_data;
137
138     char * psz_name = p_input->p_source;
139     int i_handle;
140     int i_score = 10;
141
142     if( TestMethod( INPUT_METHOD_VAR, "ps" ) )
143     {
144         return( 999 );
145     }
146
147     if( ( strlen(psz_name) > 5 ) && !strncasecmp( psz_name, "file:", 5 ) )
148     {
149         /* If the user specified "file:" then it's probably a file */
150         i_score = 100;
151         psz_name += 5;
152     }
153
154     i_handle = open( psz_name, 0 );
155     if( i_handle == -1 )
156     {
157         return( 0 );
158     }
159     close( i_handle );
160
161     return( i_score );
162 }
163
164 /*****************************************************************************
165  * PSInit: initializes PS structures
166  *****************************************************************************/
167 static void PSInit( input_thread_t * p_input )
168 {
169     thread_ps_data_t *  p_method;
170     packet_cache_t *    p_packet_cache;
171
172     p_method = (thread_ps_data_t *)malloc( sizeof(thread_ps_data_t) );
173     if( p_method == NULL )
174     {
175         intf_ErrMsg( "Out of memory" );
176         p_input->b_error = 1;
177         return;
178     }
179     p_input->p_plugin_data = (void *)p_method;
180     
181     /* creates the packet cache structure */
182     p_packet_cache = malloc( sizeof(packet_cache_t) );
183     if ( p_packet_cache == NULL )
184     {
185         intf_ErrMsg( "Out of memory" );
186         p_input->b_error = 1;
187         return;
188     }
189     p_input->p_method_data = (void *)p_packet_cache;
190
191     /* Set callback */
192     p_input->pf_open  = p_input->pf_file_open;
193     p_input->pf_close = p_input->pf_file_close;
194
195     /* Initialize packet cache mutex */
196     vlc_mutex_init( &p_packet_cache->lock );
197     
198     /* allocates the data cache */
199     p_packet_cache->data.p_stack = malloc( DATA_CACHE_SIZE * 
200         sizeof(data_packet_t*) );
201     if ( p_packet_cache->data.p_stack == NULL )
202     {
203         intf_ErrMsg( "Out of memory" );
204         p_input->b_error = 1;
205         return;
206     }
207     p_packet_cache->data.l_index = 0;
208     
209     /* allocates the PES cache */
210     p_packet_cache->pes.p_stack = malloc( PES_CACHE_SIZE * 
211         sizeof(pes_packet_t*) );
212     if ( p_packet_cache->pes.p_stack == NULL )
213     {
214         intf_ErrMsg( "Out of memory" );
215         p_input->b_error = 1;
216         return;
217     }
218     p_packet_cache->pes.l_index = 0;
219     
220     /* allocates the small buffer cache */
221     p_packet_cache->smallbuffer.p_stack = malloc( SMALL_CACHE_SIZE * 
222         sizeof(packet_buffer_t) );
223     if ( p_packet_cache->smallbuffer.p_stack == NULL )
224     {
225         intf_ErrMsg( "Out of memory" );
226         p_input->b_error = 1;
227         return;
228     }
229     p_packet_cache->smallbuffer.l_index = 0;
230     
231     /* allocates the large buffer cache */
232     p_packet_cache->largebuffer.p_stack = malloc( LARGE_CACHE_SIZE * 
233         sizeof(packet_buffer_t) );
234     if ( p_packet_cache->largebuffer.p_stack == NULL )
235     {
236         intf_ErrMsg( "Out of memory" );
237         p_input->b_error = 1;
238         return;
239     }
240     p_packet_cache->largebuffer.l_index = 0;
241     
242     /* Re-open the socket as a buffered FILE stream */
243     p_method->stream = fdopen( p_input->i_handle, "r" );
244
245     if( p_method->stream == NULL )
246     {
247         intf_ErrMsg( "Cannot open file (%s)", strerror(errno) );
248         p_input->b_error = 1;
249         return;
250     }
251     rewind( p_method->stream );
252
253     /* FIXME : detect if InitStream failed */
254     input_InitStream( p_input, sizeof( stream_ps_data_t ) );
255     input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
256
257     if( p_input->stream.b_seekable )
258     {
259         stream_ps_data_t * p_demux_data =
260              (stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data;
261
262         /* Pre-parse the stream to gather stream_descriptor_t. */
263         p_input->stream.pp_programs[0]->b_is_ok = 0;
264         p_demux_data->i_PSM_version = EMPTY_PSM_VERSION;
265
266         while( !p_input->b_die && !p_input->b_error
267                 && !p_demux_data->b_has_PSM )
268         {
269             int                 i_result, i;
270             data_packet_t *     pp_packets[INPUT_READ_ONCE];
271
272             i_result = PSRead( p_input, pp_packets );
273             if( i_result == 1 )
274             {
275                 /* EOF */
276                 vlc_mutex_lock( &p_input->stream.stream_lock );
277                 p_input->stream.pp_programs[0]->b_is_ok = 1;
278                 vlc_mutex_unlock( &p_input->stream.stream_lock );
279                 break;
280             }
281             if( i_result == -1 )
282             {
283                 p_input->b_error = 1;
284                 break;
285             }
286
287             for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
288             {
289                 /* FIXME: use i_p_config_t */
290                 input_ParsePS( p_input, pp_packets[i] );
291                 DeletePacket( p_input->p_method_data, pp_packets[i] );
292             }
293
294             /* File too big. */
295             if( p_input->stream.p_selected_area->i_tell >
296                                                     INPUT_PREPARSE_LENGTH )
297             {
298                 break;
299             }
300         }
301         rewind( p_method->stream );
302         vlc_mutex_lock( &p_input->stream.stream_lock );
303
304         p_input->stream.i_method = INPUT_METHOD_FILE;
305         p_input->stream.p_selected_area->i_tell = 0;
306
307         if( p_demux_data->b_has_PSM )
308         {
309             /* (The PSM decoder will care about spawning the decoders) */
310             p_input->stream.pp_programs[0]->b_is_ok = 1;
311         }
312 #ifdef AUTO_SPAWN
313         else
314         {
315             /* (We have to do it ourselves) */
316             int                 i_es;
317
318             /* FIXME: we should do multiple passes in case an audio type
319              * is not present */
320             for( i_es = 0;
321                  i_es < p_input->stream.pp_programs[0]->i_es_number;
322                  i_es++ )
323             {
324 #define p_es p_input->stream.pp_programs[0]->pp_es[i_es]
325                 switch( p_es->i_type )
326                 {
327                     case MPEG1_VIDEO_ES:
328                     case MPEG2_VIDEO_ES:
329                         input_SelectES( p_input, p_es );
330                         break;
331
332                     case MPEG1_AUDIO_ES:
333                     case MPEG2_AUDIO_ES:
334                         if( main_GetIntVariable( INPUT_CHANNEL_VAR, 0 )
335                                 == (p_es->i_id & 0x1F) )
336                         switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) )
337                         {
338                         case 0:
339                             main_PutIntVariable( INPUT_AUDIO_VAR,
340                                                  REQUESTED_MPEG );
341                         case REQUESTED_MPEG:
342                             input_SelectES( p_input, p_es );
343                         }
344                         break;
345
346                     case AC3_AUDIO_ES:
347                         if( main_GetIntVariable( INPUT_CHANNEL_VAR, 0 )
348                                 == ((p_es->i_id & 0xF00) >> 8) )
349                         switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) )
350                         {
351                         case 0:
352                             main_PutIntVariable( INPUT_AUDIO_VAR,
353                                                  REQUESTED_AC3 );
354                         case REQUESTED_AC3:
355                             input_SelectES( p_input, p_es );
356                         }
357                         break;
358
359                     case DVD_SPU_ES:
360                         if( main_GetIntVariable( INPUT_SUBTITLE_VAR, -1 )
361                                 == ((p_es->i_id & 0x1F00) >> 8) )
362                         {
363                             input_SelectES( p_input, p_es );
364                         }
365                         break;
366
367                     case LPCM_AUDIO_ES:
368                         if( main_GetIntVariable( INPUT_CHANNEL_VAR, 0 )
369                                 == ((p_es->i_id & 0x1F00) >> 8) )
370                         switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) )
371                         {
372                         case 0:
373                             main_PutIntVariable( INPUT_AUDIO_VAR,
374                                                  REQUESTED_LPCM );
375                         case REQUESTED_LPCM:
376                             input_SelectES( p_input, p_es );
377                         }
378                         break;
379                 }
380             }
381                     
382         }
383 #endif
384 #ifdef STATS
385         input_DumpStream( p_input );
386 #endif
387         vlc_mutex_unlock( &p_input->stream.stream_lock );
388     }
389     else
390     {
391         /* The programs will be added when we read them. */
392         vlc_mutex_lock( &p_input->stream.stream_lock );
393         p_input->stream.i_method = INPUT_METHOD_FILE;
394         p_input->stream.pp_programs[0]->b_is_ok = 0;
395         vlc_mutex_unlock( &p_input->stream.stream_lock );
396     }
397 }
398
399 /*****************************************************************************
400  * PSEnd: frees unused data
401  *****************************************************************************/
402 static void PSEnd( input_thread_t * p_input )
403 {
404 #define p_packet_cache ((packet_cache_t *)p_input->p_method_data)
405
406     vlc_mutex_destroy( &p_packet_cache->lock );
407
408     if( p_packet_cache->data.p_stack )
409         free( p_packet_cache->data.p_stack );
410     if( p_packet_cache->pes.p_stack )
411         free( p_packet_cache->pes.p_stack );
412     if( p_packet_cache->smallbuffer.p_stack )
413         free( p_packet_cache->smallbuffer.p_stack );
414     if( p_packet_cache->largebuffer.p_stack )
415         free( p_packet_cache->largebuffer.p_stack );
416
417 #undef p_packet_cache
418
419     free( p_input->p_method_data );
420     free( p_input->p_plugin_data );
421 }
422
423 /*****************************************************************************
424  * SafeRead: reads a chunk of stream and correctly detects errors
425  *****************************************************************************/
426 static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer,
427                                 size_t i_len )
428 {
429     thread_ps_data_t *  p_method;
430     int                 i_error;
431
432     p_method = (thread_ps_data_t *)p_input->p_plugin_data;
433     while( fread( p_buffer, i_len, 1, p_method->stream ) != 1 )
434     {
435         if( feof( p_method->stream ) )
436         {
437             return( 1 );
438         }
439
440         if( (i_error = ferror( p_method->stream )) )
441         {
442             intf_ErrMsg( "Read failed (%s)", strerror(i_error) );
443             return( -1 );
444         }
445     }
446     vlc_mutex_lock( &p_input->stream.stream_lock );
447     p_input->stream.p_selected_area->i_tell += i_len;
448     vlc_mutex_unlock( &p_input->stream.stream_lock );
449     return( 0 );
450 }
451
452 /*****************************************************************************
453  * PSRead: reads data packets
454  *****************************************************************************
455  * Returns -1 in case of error, 0 if everything went well, and 1 in case of
456  * EOF.
457  *****************************************************************************/
458 static int PSRead( input_thread_t * p_input,
459                    data_packet_t * pp_packets[INPUT_READ_ONCE] )
460 {
461     byte_t              p_header[6];
462     data_packet_t *     p_data;
463     size_t              i_packet_size;
464     int                 i_packet, i_error;
465     thread_ps_data_t *  p_method;
466
467     p_method = (thread_ps_data_t *)p_input->p_plugin_data;
468
469     memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
470     for( i_packet = 0; i_packet < INPUT_READ_ONCE; i_packet++ )
471     {
472         /* Read what we believe to be a packet header. */
473         if( (i_error = SafeRead( p_input, p_header, 4 )) )
474         {
475             return( i_error );
476         }
477
478         if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L )
479         {
480             /* This is not the startcode of a packet. Read the stream
481              * until we find one. */
482             u32         i_startcode = U32_AT(p_header);
483             int         i_dummy;
484
485             if( i_startcode )
486             {
487                 /* It is common for MPEG-1 streams to pad with zeros
488                  * (although it is forbidden by the recommendation), so
489                  * don't bother everybody in this case. */
490                 intf_WarnMsg( 3, "Garbage at input (%.8x)", i_startcode );
491             }
492
493             while( (i_startcode & 0xFFFFFF00) != 0x100L )
494             {
495                 i_startcode <<= 8;
496                 if( (i_dummy = getc( p_method->stream )) != EOF )
497                 {
498                     i_startcode |= i_dummy;
499                 }
500                 else
501                 {
502                     return( 1 );
503                 }
504             }
505             /* Packet found. */
506             *(u32 *)p_header = U32_AT(&i_startcode);
507         }
508
509         /* 0x1B9 == SYSTEM_END_CODE, it is only 4 bytes long. */
510         if( U32_AT(p_header) != 0x1B9 )
511         {
512             /* The packet is at least 6 bytes long. */
513             if( (i_error = SafeRead( p_input, p_header + 4, 2 )) )
514             {
515                 return( i_error );
516             }
517
518             if( U32_AT(p_header) != 0x1BA )
519             {
520                 /* That's the case for all packets, except pack header. */
521                 i_packet_size = U16_AT(&p_header[4]);
522             }
523             else
524             {
525                 /* Pack header. */
526                 if( (p_header[4] & 0xC0) == 0x40 )
527                 {
528                     /* MPEG-2 */
529                     i_packet_size = 8;
530                 }
531                 else if( (p_header[4] & 0xF0) == 0x20 )
532                 {
533                     /* MPEG-1 */
534                     i_packet_size = 6;
535                 }
536                 else
537                 {
538                     intf_ErrMsg( "Unable to determine stream type" );
539                     return( -1 );
540                 }
541             }
542         }
543         else
544         {
545             /* System End Code */
546             i_packet_size = -2;
547         }
548
549         /* Fetch a packet of the appropriate size. */
550         p_data = NewPacket( p_input->p_method_data, i_packet_size + 6 );
551         if( p_data == NULL )
552         {
553             intf_ErrMsg( "Out of memory" );
554             return( -1 );
555         }
556
557         if( U32_AT(p_header) != 0x1B9 )
558         {
559             /* Copy the header we already read. */
560             memcpy( p_data->p_buffer, p_header, 6 );
561
562             /* Read the remaining of the packet. */
563             if( i_packet_size && (i_error =
564                     SafeRead( p_input, p_data->p_buffer + 6, i_packet_size )) )
565             {
566                 return( i_error );
567             }
568
569             /* In MPEG-2 pack headers we still have to read stuffing bytes. */
570             if( U32_AT(p_header) == 0x1BA )
571             {
572                 if( i_packet_size == 8 && (p_data->p_buffer[13] & 0x7) != 0 )
573                 {
574                     /* MPEG-2 stuffing bytes */
575                     byte_t      p_garbage[8];
576                     if( (i_error = SafeRead( p_input, p_garbage,
577                                              p_data->p_buffer[13] & 0x7)) )
578                     {
579                         return( i_error );
580                     }
581                 }
582             }
583         }
584         else
585         {
586             /* Copy the small header. */
587             memcpy( p_data->p_buffer, p_header, 4 );
588         }
589
590         /* Give the packet to the other input stages. */
591         pp_packets[i_packet] = p_data;
592     }
593
594     return( 0 );
595 }
596
597 /*****************************************************************************
598  * PSSeek: changes the stream position indicator
599  *****************************************************************************/
600 static void PSSeek( input_thread_t * p_input, off_t i_position )
601 {
602     thread_ps_data_t *  p_method;
603
604     p_method = (thread_ps_data_t *)p_input->p_plugin_data;
605
606     /* A little bourrin but should work for a while --Meuuh */
607 #ifndef WIN32
608     fseeko( p_method->stream, i_position, SEEK_SET );
609 #else
610     fseek( p_method->stream, (long)i_position, SEEK_SET );
611 #endif
612
613     p_input->stream.p_selected_area->i_tell = i_position;
614 }
615
616 /*
617  * Packet management utilities
618  */
619
620
621 /*****************************************************************************
622  * NewPacket: allocates a data packet
623  *****************************************************************************/
624 static struct data_packet_s * NewPacket( void * p_packet_cache,
625                                          size_t l_size )
626
627     packet_cache_t *   p_cache;
628     data_packet_t *    p_data;
629     long               l_index;
630
631     p_cache = (packet_cache_t *)p_packet_cache;
632
633 #ifdef DEBUG
634     if ( p_cache == NULL )
635     {
636         intf_ErrMsg( "PPacket cache not initialized" );
637         return NULL;
638     }
639 #endif
640
641     /* Safety check */
642     if( l_size > INPUT_MAX_PACKET_SIZE )
643     {
644         intf_ErrMsg( "Packet too big (%d)", l_size );
645         return NULL;
646     }
647
648     vlc_mutex_lock( &p_cache->lock );
649
650     /* Checks whether the data cache is empty */
651     if( p_cache->data.l_index == 0 )
652     {
653         /* Allocates a new packet */
654         p_data = malloc( sizeof(data_packet_t) );
655         if( p_data == NULL )
656         {
657             intf_ErrMsg( "Out of memory" );
658             vlc_mutex_unlock( &p_cache->lock );
659             return NULL;
660         }
661 #ifdef TRACE_INPUT
662         intf_DbgMsg( "PS input: data packet allocated" );
663 #endif
664     }
665     else
666     {
667         /* Takes the packet out from the cache */
668         if( (p_data = p_cache->data.p_stack[ -- p_cache->data.l_index ]) 
669             == NULL )
670         {
671             intf_ErrMsg( "NULL packet in the data cache" );
672             vlc_mutex_unlock( &p_cache->lock );
673             return NULL;
674         }
675     }
676     
677     if( l_size < MAX_SMALL_SIZE )
678     {
679         /* Small buffer */  
680    
681         /* Checks whether the buffer cache is empty */
682         if( p_cache->smallbuffer.l_index == 0 )
683         {
684             /* Allocates a new packet */
685             p_data->p_buffer = malloc( l_size );
686             if( p_data->p_buffer == NULL )
687             {
688                 intf_DbgMsg( "Out of memory" );
689                 free( p_data );
690                 vlc_mutex_unlock( &p_cache->lock );
691                 return NULL;
692             }
693 #ifdef TRACE_INPUT
694             intf_DbgMsg( "PS input: small buffer allocated" );
695 #endif
696             p_data->l_size = l_size;
697         }
698         else
699         {
700             /* Takes the packet out from the cache */
701             l_index = -- p_cache->smallbuffer.l_index;    
702             if( (p_data->p_buffer = p_cache->smallbuffer.p_stack[l_index].p_data)
703                 == NULL )
704             {
705                 intf_ErrMsg( "NULL packet in the small buffer cache" );
706                 free( p_data );
707                 vlc_mutex_unlock( &p_cache->lock );
708                 return NULL;
709             }
710             /* Reallocates the packet if it is too small or too large */
711             if( p_cache->smallbuffer.p_stack[l_index].l_size < l_size ||
712                 p_cache->smallbuffer.p_stack[l_index].l_size > 2*l_size )
713             {
714                 p_data->p_buffer = realloc( p_data->p_buffer, l_size );
715                 p_data->l_size = l_size;
716             }
717             else
718             {
719                 p_data->l_size = p_cache->smallbuffer.p_stack[l_index].l_size;
720             }
721         }
722     }
723     else
724     {
725         /* Large buffer */  
726    
727         /* Checks whether the buffer cache is empty */
728         if( p_cache->largebuffer.l_index == 0 )
729         {
730             /* Allocates a new packet */
731             p_data->p_buffer = malloc( l_size );
732             if ( p_data->p_buffer == NULL )
733             {
734                 intf_ErrMsg( "Out of memory" );
735                 free( p_data );
736                 vlc_mutex_unlock( &p_cache->lock );
737                 return NULL;
738             }
739 #ifdef TRACE_INPUT
740             intf_DbgMsg( "PS input: large buffer allocated" );
741 #endif
742             p_data->l_size = l_size;
743         }
744         else
745         {
746             /* Takes the packet out from the cache */
747             l_index = -- p_cache->largebuffer.l_index;    
748             p_data->p_buffer = p_cache->largebuffer.p_stack[l_index].p_data;
749             if( p_data->p_buffer == NULL )
750             {
751                 intf_ErrMsg( "NULL packet in the small buffer cache" );
752                 free( p_data );
753                 vlc_mutex_unlock( &p_cache->lock );
754                 return NULL;
755             }
756             /* Reallocates the packet if it is too small or too large */
757             if( p_cache->largebuffer.p_stack[l_index].l_size < l_size ||
758                 p_cache->largebuffer.p_stack[l_index].l_size > 2*l_size )
759             {
760                 p_data->p_buffer = realloc( p_data->p_buffer, l_size );
761                 p_data->l_size = l_size;
762             }
763             else
764             {
765                 p_data->l_size = p_cache->largebuffer.p_stack[l_index].l_size;
766             }
767         }
768     }
769
770     vlc_mutex_unlock( &p_cache->lock );
771
772     /* Initialize data */
773     p_data->p_next = NULL;
774     p_data->b_discard_payload = 0;
775     p_data->p_payload_start = p_data->p_buffer;
776     p_data->p_payload_end = p_data->p_buffer + l_size;
777
778     return( p_data );
779
780 }
781
782
783 /*****************************************************************************
784  * NewPES: allocates a pes packet
785  *****************************************************************************/
786 static pes_packet_t * NewPES( void * p_packet_cache )
787 {
788     packet_cache_t *   p_cache;
789     pes_packet_t *     p_pes;
790
791     p_cache = (packet_cache_t *)p_packet_cache;
792
793 #ifdef DEBUG
794     if ( p_cache == NULL )
795     {
796         intf_ErrMsg( "Packet cache not initialized" );
797         return NULL;
798     }
799 #endif
800
801     vlc_mutex_lock( &p_cache->lock );   
802
803     /* Checks whether the PES cache is empty */
804     if( p_cache->pes.l_index == 0 )
805     {
806         /* Allocates a new packet */
807         p_pes = malloc( sizeof(pes_packet_t) );
808         if( p_pes == NULL )
809         {
810             intf_DbgMsg( "Out of memory" );
811             vlc_mutex_unlock( &p_cache->lock ); 
812             return NULL;
813         }
814 #ifdef TRACE_INPUT
815         intf_DbgMsg( "PS input: PES packet allocated" );
816 #endif
817     }
818     else
819     {
820         /* Takes the packet out from the cache */
821         p_pes = p_cache->pes.p_stack[ -- p_cache->pes.l_index ];
822         if( p_pes == NULL )
823         {
824             intf_ErrMsg( "NULL packet in the data cache" );
825             vlc_mutex_unlock( &p_cache->lock );
826             return NULL;
827         }
828     }
829
830     vlc_mutex_unlock( &p_cache->lock );
831
832     p_pes->b_data_alignment = p_pes->b_discontinuity =
833         p_pes->i_pts = p_pes->i_dts = 0;
834     p_pes->i_pes_size = 0;
835     p_pes->p_first = NULL;
836
837     return( p_pes );
838     
839 }
840
841 /*****************************************************************************
842  * DeletePacket: deletes a data packet
843  *****************************************************************************/
844 static void DeletePacket( void * p_packet_cache,
845                           data_packet_t * p_data )
846 {
847     packet_cache_t *   p_cache;
848
849     p_cache = (packet_cache_t *)p_packet_cache;
850
851 #ifdef DEBUG
852     if ( p_cache == NULL )
853     {
854         intf_ErrMsg( "Packet cache not initialized" );
855         return;
856     }
857 #endif
858
859     ASSERT( p_data );
860
861     vlc_mutex_lock( &p_cache->lock );
862
863     /* Checks whether the data cache is full */
864     if ( p_cache->data.l_index < DATA_CACHE_SIZE )
865     {
866         /* Cache not full: store the packet in it */
867         p_cache->data.p_stack[ p_cache->data.l_index ++ ] = p_data;
868         /* Small buffer or large buffer? */
869         if ( p_data->l_size < MAX_SMALL_SIZE )
870         {
871             /* Checks whether the small buffer cache is full */
872             if ( p_cache->smallbuffer.l_index < SMALL_CACHE_SIZE )
873             {
874                 p_cache->smallbuffer.p_stack[
875                     p_cache->smallbuffer.l_index ].l_size = p_data->l_size;
876                 p_cache->smallbuffer.p_stack[
877                     p_cache->smallbuffer.l_index++ ].p_data = p_data->p_buffer;
878             }
879             else
880             {
881                 ASSERT( p_data->p_buffer );
882                 free( p_data->p_buffer );
883 #ifdef TRACE_INPUT
884                 intf_DbgMsg( "PS input: small buffer freed" );
885 #endif
886             }
887         }
888         else
889         {
890             /* Checks whether the large buffer cache is full */
891             if ( p_cache->largebuffer.l_index < LARGE_CACHE_SIZE )
892             {
893                 p_cache->largebuffer.p_stack[
894                     p_cache->largebuffer.l_index ].l_size = p_data->l_size;
895                 p_cache->largebuffer.p_stack[
896                     p_cache->largebuffer.l_index++ ].p_data = p_data->p_buffer;
897             }
898             else
899             {
900                 ASSERT( p_data->p_buffer );
901                 free( p_data->p_buffer );
902 #ifdef TRACE_INPUT
903                 intf_DbgMsg( "PS input: large buffer freed" );
904 #endif
905             }
906         }
907     }
908     else
909     {
910         /* Cache full: the packet must be freed */
911         free( p_data->p_buffer );
912         free( p_data );
913 #ifdef TRACE_INPUT
914         intf_DbgMsg( "PS input: data packet freed" );
915 #endif
916     }
917
918     vlc_mutex_unlock( &p_cache->lock );
919 }
920
921 /*****************************************************************************
922  * DeletePES: deletes a PES packet and associated data packets
923  *****************************************************************************/
924 static void DeletePES( void * p_packet_cache, pes_packet_t * p_pes )
925 {
926     packet_cache_t *    p_cache;
927     data_packet_t *     p_data;
928     data_packet_t *     p_next;
929
930     p_cache = (packet_cache_t *)p_packet_cache;
931
932 #ifdef DEBUG
933     if ( p_cache == NULL )
934     {
935         intf_ErrMsg( "Packet cache not initialized" );
936         return;
937     }
938 #endif
939
940     ASSERT( p_pes);
941
942     p_data = p_pes->p_first;
943
944     while( p_data != NULL )
945     {
946         p_next = p_data->p_next;
947         DeletePacket( p_cache, p_data );
948         p_data = p_next;
949     }
950
951     vlc_mutex_lock( &p_cache->lock );
952
953     /* Checks whether the PES cache is full */
954     if ( p_cache->pes.l_index < PES_CACHE_SIZE )
955     {
956         /* Cache not full: store the packet in it */
957         p_cache->pes.p_stack[ p_cache->pes.l_index ++ ] = p_pes;
958     }
959     else
960     {
961         /* Cache full: the packet must be freed */
962         free( p_pes );
963 #ifdef TRACE_INPUT
964         intf_DbgMsg( "PS input: PES packet freed" );
965 #endif
966     }
967
968     vlc_mutex_unlock( &p_cache->lock );
969 }
970