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