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