]> git.sesse.net Git - vlc/blob - plugins/vcd/input_vcd.c
fixed a segfault in vcd input (thank you Sam)
[vlc] / plugins / vcd / input_vcd.c
1 /****************************************************************************
2  * input_vcd.c: VideoCD raw reading plugin.
3  *****************************************************************************
4  * Copyright (C) 1998-2001 VideoLAN
5  *
6  * Author: Johan Bilien <jobi@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 #define MODULE_NAME vcd
24 #include "modules_inner.h"
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include "defs.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33
34 #ifdef HAVE_UNISTD_H
35 #   include <unistd.h>
36 #endif
37
38 #include <fcntl.h>
39 #include <sys/types.h>
40 #include <string.h>
41 #include <errno.h>
42
43 #ifdef STRNCASECMP_IN_STRINGS_H
44 #   include <strings.h>
45 #endif
46
47 #if defined( WIN32 )
48 #   include <io.h>                                                 /* read() */
49 #else
50 #   include <sys/uio.h>                                      /* struct iovec */
51 #endif
52
53 #include "common.h"
54 #include "intf_msg.h"
55 #include "threads.h"
56 #include "mtime.h"
57 #include "tests.h"
58
59 #if defined( WIN32 )
60 #   include "input_iovec.h"
61 #endif
62
63 #include "stream_control.h"
64 #include "input_ext-intf.h"
65 #include "input_ext-dec.h"
66 #include "input_ext-plugins.h"
67
68 #include "debug.h"
69
70 #include "modules.h"
71 #include "modules_export.h"
72
73 #include "../mpeg_system/input_ps.h"
74 #include "input_vcd.h"
75 #include "linux_cdrom_tools.h"
76
77 /* how many blocks VCDRead will read in each loop */
78 #define VCD_BLOCKS_ONCE 64
79 #define VCD_DATA_ONCE  (2 * VCD_BLOCKS_ONCE)
80 #define BUFFER_SIZE VCD_DATA_SIZE
81
82
83
84 /*****************************************************************************
85  * Local prototypes
86  *****************************************************************************/
87 /* called from outside */
88 static int  VCDProbe        ( probedata_t *p_data );
89 static void VCDInit         ( struct input_thread_s * );
90 static int  VCDRead         ( struct input_thread_s *, data_packet_t ** );
91 static int  VCDSetArea      ( struct input_thread_s *, struct input_area_s * ); 
92 static int  VCDSetProgram   ( struct input_thread_s *, pgrm_descriptor_t * ); 
93 static void VCDOpen         ( struct input_thread_s *);
94 static void VCDClose         ( struct input_thread_s *);
95 static void VCDEnd          ( struct input_thread_s *);
96 static void VCDSeek         ( struct input_thread_s *, off_t );
97 static int  VCDRewind       ( struct input_thread_s * );
98 static struct data_packet_s * NewPacket( void *, size_t );
99 static pes_packet_t *         NewPES   ( void * );
100 static void DeletePacket     ( void *, data_packet_t * );
101 static void DeletePES       ( void *, pes_packet_t *);
102
103
104
105 /*****************************************************************************
106  * Functions exported as capabilities. They are declared as static so that
107  * we don't pollute the namespace too much.
108  *****************************************************************************/
109 void _M( input_getfunctions )( function_list_t * p_function_list )
110 {
111 #define input p_function_list->functions.input
112     p_function_list->pf_probe = VCDProbe;
113     input.pf_init             = VCDInit;
114     input.pf_open             = VCDOpen;
115     input.pf_close            = VCDClose;
116     input.pf_end              = VCDEnd;
117     input.pf_init_bit_stream  = InitBitstream;
118     input.pf_read             = VCDRead;
119     input.pf_set_area         = VCDSetArea;
120     input.pf_set_program      = VCDSetProgram;
121     input.pf_demux            = input_DemuxPS;
122     input.pf_new_packet       = NewPacket;
123     input.pf_new_pes          = NewPES;
124     input.pf_delete_packet    = DeletePacket;
125     input.pf_delete_pes       = DeletePES;
126     input.pf_rewind           = VCDRewind;
127     input.pf_seek             = VCDSeek;
128 #undef input
129 }
130
131 /*
132  * Data reading functions
133  */
134
135 /*****************************************************************************
136  * VCDProbe: verifies that the stream is a PS stream
137  *****************************************************************************/
138 static int VCDProbe( probedata_t *p_data )
139 {
140     
141     input_thread_t * p_input = (input_thread_t *)p_data;
142
143     char * psz_name = p_input->p_source;
144     int i_score = 5;
145
146     if( TestMethod( INPUT_METHOD_VAR, "vcd" ) )
147     {
148         return( 999 );
149     }
150
151     if( ( strlen(psz_name) > 4 ) && !strncasecmp( psz_name, "vcd:", 4 ) )
152     {
153         /* If the user specified "vcd:" then it's probably a VCD */
154         i_score = 100;
155         psz_name += 4;
156     }
157     return( i_score );
158 }
159
160 /*****************************************************************************
161  * VCDOpen: open vcd
162  *****************************************************************************/
163 static void VCDOpen( struct input_thread_s *p_input )
164 {
165     int vcdhandle;
166
167     vlc_mutex_lock( &p_input->stream.stream_lock );
168
169     /* If we are here we can control the pace... */
170     p_input->stream.b_pace_control = 1;
171
172     p_input->stream.b_seekable = 1;
173     p_input->stream.p_selected_area->i_size = 0;
174
175     p_input->stream.p_selected_area->i_tell = 0;
176
177     vlc_mutex_unlock( &p_input->stream.stream_lock );
178     
179     
180     /* XXX: put this shit in an access plugin */
181     if( strlen( p_input->p_source ) > 4
182          && !strncasecmp( p_input->p_source, "vcd:", 4 ) )
183     {
184         vcdhandle = open( p_input->p_source + 4, O_RDONLY | O_NONBLOCK );
185     }
186     else
187     {
188         vcdhandle = open( p_input->p_source + 4, O_RDONLY | O_NONBLOCK );
189     }
190
191     if( vcdhandle == -1 )
192     {
193         p_input->b_error = 1;
194         return;
195     }
196
197     p_input->i_handle = (int) vcdhandle;
198 }
199
200 /*****************************************************************************
201  * VCDClose: close vcd
202  *****************************************************************************/
203 static void VCDClose( struct input_thread_s *p_input )
204 {
205     close( p_input->i_handle );
206 }
207
208 /*****************************************************************************
209  * VCDInit: initializes VCD structures
210  *****************************************************************************/
211 static void VCDInit( input_thread_t * p_input )
212 {
213     thread_vcd_data_t *  p_vcd;
214     int                  i_title;
215     int                  i_chapter;
216     int                  i;
217     input_area_t *       p_area;
218     es_descriptor_t *    p_es;
219     packet_cache_t *     p_packet_cache;
220     
221     p_vcd = malloc( sizeof(thread_vcd_data_t) );
222         
223     if( p_vcd == NULL )
224     {
225         intf_ErrMsg( "vcd error: out of memory" );
226         p_input->b_error = 1;
227         return;
228     }
229
230     
231     
232     p_input->p_plugin_data = (void *)p_vcd;
233     p_input->p_method_data = NULL;
234
235     p_vcd->vcdhandle = p_input->i_handle;
236     p_vcd->b_end_of_track = 0;
237
238     /* we read the Table Of Content information */
239     if ( read_toc(p_vcd) == -1 )
240     {
241         intf_ErrMsg("An error occured when reading vcd's TOC");
242     }
243     
244     p_input->i_read_once = VCD_DATA_ONCE;
245     
246     p_packet_cache = malloc( sizeof(packet_cache_t) );
247     
248     if ( p_packet_cache == NULL )
249     {
250         intf_ErrMsg( "vcd error: out of memory" );
251         p_input->b_error = 1;
252         return;
253     }
254     
255     p_input->p_method_data = (void *)p_packet_cache;
256      /* Initialize packet cache mutex */
257     vlc_mutex_init( &p_packet_cache->lock );
258     
259     /* allocates the data cache */
260     p_packet_cache->data.p_stack = malloc( DATA_CACHE_SIZE * 
261         sizeof(data_packet_t*) );
262     if ( p_packet_cache->data.p_stack == NULL )
263     {
264         intf_ErrMsg( "Out of memory" );
265         p_input->b_error = 1;
266         return;
267     }
268     p_packet_cache->data.l_index = 0;
269     
270     /* allocates the PES cache */
271     p_packet_cache->pes.p_stack = malloc( PES_CACHE_SIZE * 
272         sizeof(pes_packet_t*) );
273     if ( p_packet_cache->pes.p_stack == NULL )
274     {
275         intf_ErrMsg( "Out of memory" );
276         p_input->b_error = 1;
277         return;
278     }
279     p_packet_cache->pes.l_index = 0;
280     
281     /* allocates the small buffer cache */
282     p_packet_cache->smallbuffer.p_stack = malloc( SMALL_CACHE_SIZE * 
283         sizeof(packet_buffer_t) );
284     if ( p_packet_cache->smallbuffer.p_stack == NULL )
285     {
286         intf_ErrMsg( "Out of memory" );
287         p_input->b_error = 1;
288         return;
289     }
290     p_packet_cache->smallbuffer.l_index = 0;
291     
292     /* allocates the large buffer cache */
293     p_packet_cache->largebuffer.p_stack = malloc( LARGE_CACHE_SIZE * 
294         sizeof(packet_buffer_t) );
295     if ( p_packet_cache->largebuffer.p_stack == NULL )
296     {
297         intf_ErrMsg( "Out of memory" );
298         p_input->b_error = 1;
299         return;
300     }
301     p_packet_cache->largebuffer.l_index = 0;
302
303     /* Set stream and area data */
304     vlc_mutex_lock( &p_input->stream.stream_lock );
305
306     /* Initialize ES structures */
307     input_InitStream( p_input, sizeof( stream_ps_data_t ) );
308
309     /* disc input method */
310     p_input->stream.i_method = INPUT_METHOD_VCD;
311
312
313 #define area p_input->stream.pp_areas
314     for( i = 1 ; i <= p_vcd->nb_tracks - 1 ; i++ )
315     {
316         input_AddArea( p_input );
317
318         /* Titles are Program Chains */
319         area[i]->i_id = i;
320
321         /* Absolute start offset and size */
322         area[i]->i_start = p_vcd->tracks_sector[i];
323         area[i]->i_size = p_vcd->tracks_sector[i+1] - p_vcd->tracks_sector[i];
324
325         /* Number of chapters */
326         area[i]->i_part_nb = 0;   // will be the entry points
327         area[i]->i_part = 1;
328
329         /* Number of angles */
330         area[i]->i_angle_nb = 1; // no angle support in VCDs
331         area[i]->i_angle = 1;
332
333         area[i]->i_plugin_data = p_vcd->tracks_sector[i];
334     }   
335 #undef area
336
337     /* Get requested title - if none try the first title */
338     i_title = main_GetIntVariable( INPUT_TITLE_VAR, 1 );
339     if( i_title <= 0)
340     {
341         i_title = 1;
342     }
343     
344     // p_vcd->current_track = i_title-1 ;
345     
346     /* Get requested chapter - if none defaults to first one */
347     i_chapter = main_GetIntVariable( INPUT_CHAPTER_VAR, 1 );
348     if( i_chapter <= 0 )
349     {
350         i_chapter = 1;
351     }
352
353     
354     p_input->stream.pp_areas[i_title]->i_part = i_chapter;
355
356     p_area = p_input->stream.pp_areas[i_title];
357
358     VCDSetArea( p_input, p_area );
359
360     /* Set program information. */
361
362     input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
363     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
364
365     /* No PSM to read in disc mode, we already have all information */
366     p_input->stream.p_selected_program->b_is_ok = 1;
367
368     p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xe0, 0 );
369     p_es->i_stream_id = 0xe0;
370     p_es->i_type = MPEG1_VIDEO_ES;
371     p_es->i_cat = VIDEO_ES;
372     
373     if( p_main->b_video )
374     {
375         input_SelectES( p_input, p_es );
376     }
377     
378     p_es = input_AddES( p_input,
379                 p_input->stream.p_selected_program, 0xc0, 0 );
380     p_es->i_stream_id = 0xc0;
381     p_es->i_type = MPEG1_AUDIO_ES;
382     p_es->b_audio = 1;
383     p_es->i_cat = AUDIO_ES;
384      
385     if( p_main->b_audio )
386     {
387         input_SelectES( p_input, p_es );
388     }
389     
390     vlc_mutex_unlock( &p_input->stream.stream_lock );
391
392     
393     return;
394 }
395
396
397 /*****************************************************************************
398  * VCDEnd: frees unused data
399  *****************************************************************************/
400 static void VCDEnd( input_thread_t * p_input )
401 {
402     thread_vcd_data_t *     p_vcd;
403
404     p_vcd = (thread_vcd_data_t*)p_input->p_plugin_data;
405
406     free( p_vcd );
407
408 }
409
410 /*****************************************************************************
411  * VCDSetProgram: Does nothing since a VCD is mono_program
412  *****************************************************************************/
413 static int VCDSetProgram( input_thread_t * p_input, 
414             pgrm_descriptor_t * p_program)
415 {
416     return 0;
417 }
418
419
420 /*****************************************************************************
421  * VCDSetArea: initialize input data for title x, chapter y.
422  * It should be called for each user navigation request.
423  ****************************************************************************/
424 static int VCDSetArea( input_thread_t * p_input, input_area_t * p_area )
425 {
426     thread_vcd_data_t *     p_vcd;
427     
428     p_vcd = (thread_vcd_data_t*)p_input->p_plugin_data;
429     
430     /* we can't use the interface slider until initilization is complete */
431     p_input->stream.b_seekable = 0;
432     
433     if ( p_area != p_input->stream.p_selected_area ) 
434     {
435         /* Reset the Chapter position of the old title */
436         p_input->stream.p_selected_area->i_part = 0;
437         p_input->stream.p_selected_area->i_tell = 0;
438         
439         /* Change the default area */
440         p_input->stream.p_selected_area = p_area;
441
442         /* Change the current track */
443         /* The first track is not a valid one  */
444         p_vcd->current_track = p_area->i_id ;
445         p_vcd->current_sector = p_vcd->tracks_sector[p_vcd->current_track] ;
446     }
447     /* warn interface that something has changed */
448     p_input->stream.b_seekable = 1;
449     p_input->stream.b_changed = 1;
450     return 0 ;
451     
452 }
453
454
455
456 /*****************************************************************************
457  * VCDRead: reads from the VCD into PES packets.
458  *****************************************************************************
459  * Returns -1 in case of error, 0 if everything went well, and 1 in case of
460  * EOF.
461  *****************************************************************************/
462 static int VCDRead( input_thread_t * p_input,
463                     data_packet_t ** pp_packets )
464 {
465     thread_vcd_data_t *     p_vcd;
466     data_packet_t *         p_data;
467     int                     i_packet_size;
468     int                     i_index;
469     int                     i_packet;   
470     boolean_t               b_eof;
471     byte_t *                p_buffer;
472     boolean_t                  b_no_packet;
473     /* boolean_t               b_eoc; No chapters yet */
474     
475     p_vcd = (thread_vcd_data_t *)p_input->p_plugin_data;
476    
477
478     p_buffer = malloc ( VCD_DATA_SIZE );
479
480     if ( p_buffer == NULL )
481     {
482         intf_ErrMsg("Could not malloc the read buffer");
483         return -1;
484     }
485
486     
487     i_packet = 0;
488     b_no_packet = 0;
489
490     while( i_packet < VCD_DATA_ONCE ) 
491     {
492         i_index = 0;
493         
494         if ( VCD_sector_read( p_vcd, p_buffer ) == -1 )
495         {
496               return -1;
497         }
498         
499         while (i_index < BUFFER_SIZE - 6) 
500         {
501             
502             if( (U32_AT(p_buffer + i_index) & 0xFFFFFF00) != 0x100L )
503             {
504                 /* This is not the startcode of a packet. Read the stream
505                  * until we find one. */
506     
507                 if( !U32_AT( p_buffer + i_index ) )
508                 {
509                     /* It is common for MPEG-1 streams to pad with zeros
510                      * (although it is forbidden by the recommendation), so
511                      * don't bother everybody in this case. */
512                     intf_WarnMsg( 3, "Garbage at input" );
513                 }
514     
515                 while( ( (U32_AT(p_buffer + i_index) & 0xFFFFFF00) != 0x100L )
516                        && ( i_index < BUFFER_SIZE - 4 ) )
517                 {
518                     i_index ++;
519                 }
520     
521                 if ( i_index == BUFFER_SIZE - 4 )
522                 {
523                     b_no_packet = 1;
524                 }
525                 /* Packet found. */
526             }
527             
528             if (b_no_packet)
529             {
530                 b_no_packet = 0;
531                 intf_WarnMsg(3, "No packet found on sector %d\n", 
532                             p_vcd->current_sector -1 );
533                 break; /* go to the next sector */
534             }
535             
536 #ifdef DEBUG
537             intf_DbgMsg("packet start code : %X\n", 
538                         U32_AT(p_buffer + i_index));
539 #endif
540             /* 0x1B9 == SYSTEM_END_CODE, it is only 4 bytes long. */
541             if( U32_AT(p_buffer + i_index) != 0x1B9 )
542             {
543                 /* The packet is at least 6 bytes long. */
544     
545                 if( U32_AT(p_buffer + i_index) != 0x1BA )
546                 {
547                     /* That's the case for all packets, except pack header. */
548                     i_packet_size = U16_AT((p_buffer + ( i_index + 4 )));
549                 }
550                 else
551                 {
552                     /* Pack header. */
553                     if( ( *( p_buffer + ( i_index + 4 ) ) & 0xC0) == 0x40 )
554                     {
555                         /* MPEG-2 */
556                         i_packet_size = 8;
557                     }
558                     else if( (*(p_buffer + ( i_index + 4 ) ) & 0xF0) == 0x20 )
559                     {
560                         /* MPEG-1 */
561                         i_packet_size = 6;
562                     }
563                     else
564                     {
565                         intf_ErrMsg( "Unable to determine stream type" );
566                         return( -1 );
567                     }
568                 }
569             }
570             else
571             {
572                 /* System End Code */
573                 i_packet_size = -2;
574             }
575 #ifdef DEBUG
576             intf_DbgMsg("i_index : %d\n", i_index);
577             intf_DbgMsg("i_packet_size : %d\n", i_packet_size);
578 #endif
579             if ( i_index + i_packet_size > BUFFER_SIZE )
580             {
581                 intf_ErrMsg( "Too long packet");
582                 continue;
583             }
584             
585             /* Fetch a packet of the appropriate size. */
586             
587             p_data = NewPacket( p_input->p_method_data, i_packet_size + 6 );
588             
589             if( p_data == NULL )
590             {
591                 intf_ErrMsg( "Out of memory" );
592                 return( -1 );
593             }
594     
595             if( U32_AT(p_buffer) != 0x1B9 )
596             {
597                 p_main->fast_memcpy( p_data->p_buffer, p_buffer + i_index,
598                                      6 + i_packet_size );
599                 i_index += ( 6 + i_packet_size );
600     
601             }
602             else
603             {
604                 /* Copy the small header. */
605                 memcpy( p_data->p_buffer, p_buffer + i_index, 4 );
606                 i_index += 4;
607             }
608     
609             /* Give the packet to the other input stages. */
610             pp_packets[i_packet] = p_data;
611             i_packet ++;
612         }
613         
614         if ( p_vcd->b_end_of_track )
615             break;
616     }
617
618
619     
620     vlc_mutex_lock( &p_input->stream.stream_lock );
621
622     p_input->stream.p_selected_area->i_tell =
623         p_vcd->current_sector -
624         p_input->stream.p_selected_area->i_start ;
625     
626     /* no chapter for the moment*/
627     /*if( b_eoc )
628     {
629         * We modify i_part only at end of chapter not to erase
630          * some modification from the interface *
631         p_input->stream.p_selected_area->i_part = p_vcd->i_chapter;
632     }*/
633
634     
635     b_eof = p_vcd->b_end_of_track; 
636         /*FIXME&& ( ( p_vcd->current_track ) >= p_vcd->nb_tracks - 1);*/
637
638     if( b_eof )
639     {
640         vlc_mutex_unlock( &p_input->stream.stream_lock );
641         return 1;
642     }
643
644     if( p_vcd->b_end_of_track )
645     {
646         intf_WarnMsg( 4, "vcd info: new title" );
647         p_vcd->b_end_of_track = 0;
648         VCDSetArea( p_input, p_input->stream.pp_areas[
649                      p_input->stream.p_selected_area->i_id + 1] );
650         vlc_mutex_unlock( &p_input->stream.stream_lock );
651         return 0;
652     }
653     
654     vlc_mutex_unlock( &p_input->stream.stream_lock );
655
656
657     return 0;
658 }
659
660 /*****************************************************************************
661  * VCDRewind : reads a stream backward
662  *****************************************************************************/
663 static int VCDRewind( input_thread_t * p_input )
664 {
665     return( -1 );
666 }
667
668
669 /****************************************************************************
670  * VCDSeek
671  ****************************************************************************/
672 static void VCDSeek( input_thread_t * p_input, off_t i_off )
673 {
674     thread_vcd_data_t *               p_vcd;
675
676     p_vcd = (thread_vcd_data_t *) p_input->p_plugin_data;
677
678     p_vcd->current_sector = p_vcd->tracks_sector[p_vcd->current_track]
679                                 + i_off;
680
681     p_input->stream.p_selected_area->i_tell = p_vcd->current_sector
682         - p_input->stream.p_selected_area->i_start;
683     
684     return ;
685 }
686
687
688
689 /*
690  * Packet management utilities
691  */
692
693
694 /*****************************************************************************
695  * NewPacket: allocates a data packet
696  *****************************************************************************/
697 static struct data_packet_s * NewPacket( void * p_packet_cache,
698                                          size_t l_size )
699
700     packet_cache_t *   p_cache;
701     data_packet_t *    p_data;
702     long               l_index;
703
704     p_cache = (packet_cache_t *)p_packet_cache;
705
706 #ifdef DEBUG
707     if ( p_cache == NULL )
708     {
709         intf_ErrMsg( "PPacket cache not initialized" );
710         return NULL;
711     }
712 #endif
713
714     /* Safety check */
715     if( l_size > INPUT_MAX_PACKET_SIZE )
716     {
717         intf_ErrMsg( "Packet too big (%d)", l_size );
718         return NULL;
719     }
720
721     vlc_mutex_lock( &p_cache->lock );
722
723     /* Checks whether the data cache is empty */
724     if( p_cache->data.l_index == 0 )
725     {
726         /* Allocates a new packet */
727         p_data = malloc( sizeof(data_packet_t) );
728         if( p_data == NULL )
729         {
730             intf_ErrMsg( "Out of memory" );
731             vlc_mutex_unlock( &p_cache->lock );
732             return NULL;
733         }
734 #ifdef TRACE_INPUT
735         intf_DbgMsg( "PS input: data packet allocated" );
736 #endif
737     }
738     else
739     {
740         /* Takes the packet out from the cache */
741         if( (p_data = p_cache->data.p_stack[ -- p_cache->data.l_index ]) 
742             == NULL )
743         {
744             intf_ErrMsg( "NULL packet in the data cache" );
745             vlc_mutex_unlock( &p_cache->lock );
746             return NULL;
747         }
748     }
749     
750     if( l_size < MAX_SMALL_SIZE )
751     {
752         /* Small buffer */  
753    
754         /* Checks whether the buffer cache is empty */
755         if( p_cache->smallbuffer.l_index == 0 )
756         {
757             /* Allocates a new packet */
758             p_data->p_buffer = malloc( l_size );
759             if( p_data->p_buffer == NULL )
760             {
761                 intf_DbgMsg( "Out of memory" );
762                 free( p_data );
763                 vlc_mutex_unlock( &p_cache->lock );
764                 return NULL;
765             }
766 #ifdef TRACE_INPUT
767             intf_DbgMsg( "PS input: small buffer allocated" );
768 #endif
769             p_data->l_size = l_size;
770         }
771         else
772         {
773             /* Takes the packet out from the cache */
774             l_index = -- p_cache->smallbuffer.l_index;    
775             if( (p_data->p_buffer = p_cache->smallbuffer.p_stack[l_index].p_data)
776                 == NULL )
777             {
778                 intf_ErrMsg( "NULL packet in the small buffer cache" );
779                 free( p_data );
780                 vlc_mutex_unlock( &p_cache->lock );
781                 return NULL;
782             }
783             /* Reallocates the packet if it is too small or too large */
784             if( p_cache->smallbuffer.p_stack[l_index].l_size < l_size ||
785                 p_cache->smallbuffer.p_stack[l_index].l_size > 2*l_size )
786             {
787                 p_data->p_buffer = realloc( p_data->p_buffer, l_size );
788                 p_data->l_size = l_size;
789             }
790             else
791             {
792                 p_data->l_size = p_cache->smallbuffer.p_stack[l_index].l_size;
793             }
794         }
795     }
796     else
797     {
798         /* Large buffer */  
799    
800         /* Checks whether the buffer cache is empty */
801         if( p_cache->largebuffer.l_index == 0 )
802         {
803             /* Allocates a new packet */
804             p_data->p_buffer = malloc( l_size );
805             if ( p_data->p_buffer == NULL )
806             {
807                 intf_ErrMsg( "Out of memory" );
808                 free( p_data );
809                 vlc_mutex_unlock( &p_cache->lock );
810                 return NULL;
811             }
812 #ifdef TRACE_INPUT
813             intf_DbgMsg( "PS input: large buffer allocated" );
814 #endif
815             p_data->l_size = l_size;
816         }
817         else
818         {
819             /* Takes the packet out from the cache */
820             l_index = -- p_cache->largebuffer.l_index;    
821             p_data->p_buffer = p_cache->largebuffer.p_stack[l_index].p_data;
822             if( p_data->p_buffer == NULL )
823             {
824                 intf_ErrMsg( "NULL packet in the small buffer cache" );
825                 free( p_data );
826                 vlc_mutex_unlock( &p_cache->lock );
827                 return NULL;
828             }
829             /* Reallocates the packet if it is too small or too large */
830             if( p_cache->largebuffer.p_stack[l_index].l_size < l_size ||
831                 p_cache->largebuffer.p_stack[l_index].l_size > 2*l_size )
832             {
833                 p_data->p_buffer = realloc( p_data->p_buffer, l_size );
834                 p_data->l_size = l_size;
835             }
836             else
837             {
838                 p_data->l_size = p_cache->largebuffer.p_stack[l_index].l_size;
839             }
840         }
841     }
842
843     vlc_mutex_unlock( &p_cache->lock );
844
845     /* Initialize data */
846     p_data->p_next = NULL;
847     p_data->b_discard_payload = 0;
848     p_data->p_payload_start = p_data->p_buffer;
849     p_data->p_payload_end = p_data->p_buffer + l_size;
850
851     return( p_data );
852
853 }
854
855
856 /*****************************************************************************
857  * NewPES: allocates a pes packet
858  *****************************************************************************/
859 static pes_packet_t * NewPES( void * p_packet_cache )
860 {
861     packet_cache_t *   p_cache;
862     pes_packet_t *     p_pes;
863
864     p_cache = (packet_cache_t *)p_packet_cache;
865
866 #ifdef DEBUG
867     if ( p_cache == NULL )
868     {
869         intf_ErrMsg( "Packet cache not initialized" );
870         return NULL;
871     }
872 #endif
873
874     vlc_mutex_lock( &p_cache->lock );
875
876     /* Checks whether the PES cache is empty */
877     if( p_cache->pes.l_index == 0 )
878     {
879         /* Allocates a new packet */
880         p_pes = malloc( sizeof(pes_packet_t) );
881         if( p_pes == NULL )
882         {
883             intf_DbgMsg( "Out of memory" );
884             vlc_mutex_unlock( &p_cache->lock );
885             return NULL;
886         }
887 #ifdef TRACE_INPUT
888         intf_DbgMsg( "PS input: PES packet allocated" );
889 #endif
890     }
891     else
892     {
893         /* Takes the packet out from the cache */
894         p_pes = p_cache->pes.p_stack[ -- p_cache->pes.l_index ];
895         if( p_pes == NULL )
896         {
897             intf_ErrMsg( "NULL packet in the data cache" );
898             vlc_mutex_unlock( &p_cache->lock );
899             return NULL;
900         }
901     }
902
903     vlc_mutex_unlock( &p_cache->lock );
904
905     p_pes->b_data_alignment = p_pes->b_discontinuity =
906         p_pes->i_pts = p_pes->i_dts = 0;
907     p_pes->i_pes_size = 0;
908     p_pes->p_first = NULL;
909
910     return( p_pes );
911     
912 }
913
914 /*****************************************************************************
915  * DeletePacket: deletes a data packet
916  *****************************************************************************/
917 static void DeletePacket( void * p_packet_cache,
918                           data_packet_t * p_data )
919 {
920     packet_cache_t *   p_cache;
921
922     p_cache = (packet_cache_t *)p_packet_cache;
923
924 #ifdef DEBUG
925     if ( p_cache == NULL )
926     {
927         intf_ErrMsg( "Packet cache not initialized" );
928         return;
929     }
930 #endif
931
932     ASSERT( p_data );
933
934     vlc_mutex_lock( &p_cache->lock );
935
936     /* Checks whether the data cache is full */
937     if ( p_cache->data.l_index < DATA_CACHE_SIZE )
938     {
939         /* Cache not full: store the packet in it */
940         p_cache->data.p_stack[ p_cache->data.l_index ++ ] = p_data;
941         /* Small buffer or large buffer? */
942         if ( p_data->l_size < MAX_SMALL_SIZE )
943         {
944             /* Checks whether the small buffer cache is full */
945             if ( p_cache->smallbuffer.l_index < SMALL_CACHE_SIZE )
946             {
947                 p_cache->smallbuffer.p_stack[
948                     p_cache->smallbuffer.l_index ].l_size = p_data->l_size;
949                 p_cache->smallbuffer.p_stack[
950                     p_cache->smallbuffer.l_index++ ].p_data = p_data->p_buffer;
951             }
952             else
953             {
954                 ASSERT( p_data->p_buffer );
955                 free( p_data->p_buffer );
956 #ifdef TRACE_INPUT
957                 intf_DbgMsg( "PS input: small buffer freed" );
958 #endif
959             }
960         }
961         else
962         {
963             /* Checks whether the large buffer cache is full */
964             if ( p_cache->largebuffer.l_index < LARGE_CACHE_SIZE )
965             {
966                 p_cache->largebuffer.p_stack[
967                     p_cache->largebuffer.l_index ].l_size = p_data->l_size;
968                 p_cache->largebuffer.p_stack[
969                     p_cache->largebuffer.l_index++ ].p_data = p_data->p_buffer;
970             }
971             else
972             {
973                 ASSERT( p_data->p_buffer );
974                 free( p_data->p_buffer );
975 #ifdef TRACE_INPUT
976                 intf_DbgMsg( "PS input: large buffer freed" );
977 #endif
978             }
979         }
980     }
981     else
982     {
983         /* Cache full: the packet must be freed */
984         free( p_data->p_buffer );
985         free( p_data );
986 #ifdef TRACE_INPUT
987         intf_DbgMsg( "PS input: data packet freed" );
988 #endif
989     }
990
991     vlc_mutex_unlock( &p_cache->lock );
992 }
993
994 /*****************************************************************************
995  * DeletePES: deletes a PES packet and associated data packets
996  *****************************************************************************/
997 static void DeletePES( void * p_packet_cache, pes_packet_t * p_pes )
998 {
999     packet_cache_t *    p_cache;
1000     data_packet_t *     p_data;
1001     data_packet_t *     p_next;
1002
1003     p_cache = (packet_cache_t *)p_packet_cache;
1004
1005 #ifdef DEBUG
1006     if ( p_cache == NULL )
1007     {
1008         intf_ErrMsg( "Packet cache not initialized" );
1009         return;
1010     }
1011 #endif
1012
1013     ASSERT( p_pes);
1014
1015     p_data = p_pes->p_first;
1016
1017     while( p_data != NULL )
1018     {
1019         p_next = p_data->p_next;
1020         DeletePacket( p_cache, p_data );
1021         p_data = p_next;
1022     }
1023
1024     vlc_mutex_lock( &p_cache->lock );
1025
1026     /* Checks whether the PES cache is full */
1027     if ( p_cache->pes.l_index < PES_CACHE_SIZE )
1028     {
1029         /* Cache not full: store the packet in it */
1030         p_cache->pes.p_stack[ p_cache->pes.l_index ++ ] = p_pes;
1031     }
1032     else
1033     {
1034         /* Cache full: the packet must be freed */
1035         free( p_pes );
1036 #ifdef TRACE_INPUT
1037         intf_DbgMsg( "PS input: PES packet freed" );
1038 #endif
1039     }
1040
1041     vlc_mutex_unlock( &p_cache->lock );
1042 }