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