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