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