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