]> git.sesse.net Git - vlc/blob - plugins/vcd/input_vcd.c
* COMPLETE CVS BREAKAGE !! The MAIN branch is going to be a playground
[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+1];
323         area[i]->i_size = p_vcd->tracks_sector[i+2] - p_vcd->tracks_sector[i+1];
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+1];
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 = 2;
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         
438         /* Change the default area */
439         p_input->stream.p_selected_area =
440                     p_input->stream.pp_areas[p_area->i_id];
441
442         /* Change the current track */
443         /* The first track is not a valid one  */
444         p_vcd->current_track = p_area->i_id + 1 ;
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
621
622     
623     vlc_mutex_lock( &p_input->stream.stream_lock );
624
625     p_input->stream.p_selected_area->i_tell =
626         p_vcd->current_sector -
627         p_input->stream.p_selected_area->i_start ;
628     
629     /* no chapter for the moment*/
630     /*if( b_eoc )
631     {
632         * We modify i_part only at end of chapter not to erase
633          * some modification from the interface *
634         p_input->stream.p_selected_area->i_part = p_vcd->i_chapter;
635     }*/
636
637     
638     b_eof = p_vcd->b_end_of_track && 
639             ( ( p_vcd->current_track + 1 ) >= p_vcd->nb_tracks );
640
641     if( b_eof )
642     {
643         vlc_mutex_unlock( &p_input->stream.stream_lock );
644         return 1;
645     }
646
647     if( p_vcd->b_end_of_track )
648     {
649         intf_WarnMsg( 4, "vcd info: new title" );
650         p_vcd->current_track++;
651         p_vcd->b_end_of_track = 0;
652         VCDSetArea( p_input, p_input->stream.pp_areas[p_vcd->current_track] );
653         vlc_mutex_unlock( &p_input->stream.stream_lock );
654         return 0;
655     }
656     
657     vlc_mutex_unlock( &p_input->stream.stream_lock );
658
659
660     return 0;
661 }
662
663 /*****************************************************************************
664  * VCDRewind : reads a stream backward
665  *****************************************************************************/
666 static int VCDRewind( input_thread_t * p_input )
667 {
668     return( -1 );
669 }
670
671
672 /****************************************************************************
673  * VCDSeek
674  ****************************************************************************/
675 static void VCDSeek( input_thread_t * p_input, off_t i_off )
676 {
677     thread_vcd_data_t *               p_vcd;
678
679     p_vcd = (thread_vcd_data_t *) p_input->p_plugin_data;
680
681     p_vcd->current_sector = p_vcd->tracks_sector[p_vcd->current_track]
682                                 + i_off;
683
684     p_input->stream.p_selected_area->i_tell = p_vcd->current_sector
685         - p_input->stream.p_selected_area->i_start;
686     
687     return ;
688 }
689
690
691
692 /*
693  * Packet management utilities
694  */
695
696
697 /*****************************************************************************
698  * NewPacket: allocates a data packet
699  *****************************************************************************/
700 static struct data_packet_s * NewPacket( void * p_packet_cache,
701                                          size_t l_size )
702
703     packet_cache_t *   p_cache;
704     data_packet_t *    p_data;
705     long               l_index;
706
707     p_cache = (packet_cache_t *)p_packet_cache;
708
709 #ifdef DEBUG
710     if ( p_cache == NULL )
711     {
712         intf_ErrMsg( "PPacket cache not initialized" );
713         return NULL;
714     }
715 #endif
716
717     /* Safety check */
718     if( l_size > INPUT_MAX_PACKET_SIZE )
719     {
720         intf_ErrMsg( "Packet too big (%d)", l_size );
721         return NULL;
722     }
723
724     vlc_mutex_lock( &p_cache->lock );
725
726     /* Checks whether the data cache is empty */
727     if( p_cache->data.l_index == 0 )
728     {
729         /* Allocates a new packet */
730         p_data = malloc( sizeof(data_packet_t) );
731         if( p_data == NULL )
732         {
733             intf_ErrMsg( "Out of memory" );
734             vlc_mutex_unlock( &p_cache->lock );
735             return NULL;
736         }
737 #ifdef TRACE_INPUT
738         intf_DbgMsg( "PS input: data packet allocated" );
739 #endif
740     }
741     else
742     {
743         /* Takes the packet out from the cache */
744         if( (p_data = p_cache->data.p_stack[ -- p_cache->data.l_index ]) 
745             == NULL )
746         {
747             intf_ErrMsg( "NULL packet in the data cache" );
748             vlc_mutex_unlock( &p_cache->lock );
749             return NULL;
750         }
751     }
752     
753     if( l_size < MAX_SMALL_SIZE )
754     {
755         /* Small buffer */  
756    
757         /* Checks whether the buffer cache is empty */
758         if( p_cache->smallbuffer.l_index == 0 )
759         {
760             /* Allocates a new packet */
761             p_data->p_buffer = malloc( l_size );
762             if( p_data->p_buffer == NULL )
763             {
764                 intf_DbgMsg( "Out of memory" );
765                 free( p_data );
766                 vlc_mutex_unlock( &p_cache->lock );
767                 return NULL;
768             }
769 #ifdef TRACE_INPUT
770             intf_DbgMsg( "PS input: small buffer allocated" );
771 #endif
772             p_data->l_size = l_size;
773         }
774         else
775         {
776             /* Takes the packet out from the cache */
777             l_index = -- p_cache->smallbuffer.l_index;    
778             if( (p_data->p_buffer = p_cache->smallbuffer.p_stack[l_index].p_data)
779                 == NULL )
780             {
781                 intf_ErrMsg( "NULL packet in the small buffer cache" );
782                 free( p_data );
783                 vlc_mutex_unlock( &p_cache->lock );
784                 return NULL;
785             }
786             /* Reallocates the packet if it is too small or too large */
787             if( p_cache->smallbuffer.p_stack[l_index].l_size < l_size ||
788                 p_cache->smallbuffer.p_stack[l_index].l_size > 2*l_size )
789             {
790                 p_data->p_buffer = realloc( p_data->p_buffer, l_size );
791                 p_data->l_size = l_size;
792             }
793             else
794             {
795                 p_data->l_size = p_cache->smallbuffer.p_stack[l_index].l_size;
796             }
797         }
798     }
799     else
800     {
801         /* Large buffer */  
802    
803         /* Checks whether the buffer cache is empty */
804         if( p_cache->largebuffer.l_index == 0 )
805         {
806             /* Allocates a new packet */
807             p_data->p_buffer = malloc( l_size );
808             if ( p_data->p_buffer == NULL )
809             {
810                 intf_ErrMsg( "Out of memory" );
811                 free( p_data );
812                 vlc_mutex_unlock( &p_cache->lock );
813                 return NULL;
814             }
815 #ifdef TRACE_INPUT
816             intf_DbgMsg( "PS input: large buffer allocated" );
817 #endif
818             p_data->l_size = l_size;
819         }
820         else
821         {
822             /* Takes the packet out from the cache */
823             l_index = -- p_cache->largebuffer.l_index;    
824             p_data->p_buffer = p_cache->largebuffer.p_stack[l_index].p_data;
825             if( p_data->p_buffer == NULL )
826             {
827                 intf_ErrMsg( "NULL packet in the small buffer cache" );
828                 free( p_data );
829                 vlc_mutex_unlock( &p_cache->lock );
830                 return NULL;
831             }
832             /* Reallocates the packet if it is too small or too large */
833             if( p_cache->largebuffer.p_stack[l_index].l_size < l_size ||
834                 p_cache->largebuffer.p_stack[l_index].l_size > 2*l_size )
835             {
836                 p_data->p_buffer = realloc( p_data->p_buffer, l_size );
837                 p_data->l_size = l_size;
838             }
839             else
840             {
841                 p_data->l_size = p_cache->largebuffer.p_stack[l_index].l_size;
842             }
843         }
844     }
845
846     vlc_mutex_unlock( &p_cache->lock );
847
848     /* Initialize data */
849     p_data->p_next = NULL;
850     p_data->b_discard_payload = 0;
851     p_data->p_payload_start = p_data->p_buffer;
852     p_data->p_payload_end = p_data->p_buffer + l_size;
853
854     return( p_data );
855
856 }
857
858
859 /*****************************************************************************
860  * NewPES: allocates a pes packet
861  *****************************************************************************/
862 static pes_packet_t * NewPES( void * p_packet_cache )
863 {
864     packet_cache_t *   p_cache;
865     pes_packet_t *     p_pes;
866
867     p_cache = (packet_cache_t *)p_packet_cache;
868
869 #ifdef DEBUG
870     if ( p_cache == NULL )
871     {
872         intf_ErrMsg( "Packet cache not initialized" );
873         return NULL;
874     }
875 #endif
876
877     vlc_mutex_lock( &p_cache->lock );
878
879     /* Checks whether the PES cache is empty */
880     if( p_cache->pes.l_index == 0 )
881     {
882         /* Allocates a new packet */
883         p_pes = malloc( sizeof(pes_packet_t) );
884         if( p_pes == NULL )
885         {
886             intf_DbgMsg( "Out of memory" );
887             vlc_mutex_unlock( &p_cache->lock );
888             return NULL;
889         }
890 #ifdef TRACE_INPUT
891         intf_DbgMsg( "PS input: PES packet allocated" );
892 #endif
893     }
894     else
895     {
896         /* Takes the packet out from the cache */
897         p_pes = p_cache->pes.p_stack[ -- p_cache->pes.l_index ];
898         if( p_pes == NULL )
899         {
900             intf_ErrMsg( "NULL packet in the data cache" );
901             vlc_mutex_unlock( &p_cache->lock );
902             return NULL;
903         }
904     }
905
906     vlc_mutex_unlock( &p_cache->lock );
907
908     p_pes->b_data_alignment = p_pes->b_discontinuity =
909         p_pes->i_pts = p_pes->i_dts = 0;
910     p_pes->i_pes_size = 0;
911     p_pes->p_first = NULL;
912
913     return( p_pes );
914     
915 }
916
917 /*****************************************************************************
918  * DeletePacket: deletes a data packet
919  *****************************************************************************/
920 static void DeletePacket( void * p_packet_cache,
921                           data_packet_t * p_data )
922 {
923     packet_cache_t *   p_cache;
924
925     p_cache = (packet_cache_t *)p_packet_cache;
926
927 #ifdef DEBUG
928     if ( p_cache == NULL )
929     {
930         intf_ErrMsg( "Packet cache not initialized" );
931         return;
932     }
933 #endif
934
935     ASSERT( p_data );
936
937     vlc_mutex_lock( &p_cache->lock );
938
939     /* Checks whether the data cache is full */
940     if ( p_cache->data.l_index < DATA_CACHE_SIZE )
941     {
942         /* Cache not full: store the packet in it */
943         p_cache->data.p_stack[ p_cache->data.l_index ++ ] = p_data;
944         /* Small buffer or large buffer? */
945         if ( p_data->l_size < MAX_SMALL_SIZE )
946         {
947             /* Checks whether the small buffer cache is full */
948             if ( p_cache->smallbuffer.l_index < SMALL_CACHE_SIZE )
949             {
950                 p_cache->smallbuffer.p_stack[
951                     p_cache->smallbuffer.l_index ].l_size = p_data->l_size;
952                 p_cache->smallbuffer.p_stack[
953                     p_cache->smallbuffer.l_index++ ].p_data = p_data->p_buffer;
954             }
955             else
956             {
957                 ASSERT( p_data->p_buffer );
958                 free( p_data->p_buffer );
959 #ifdef TRACE_INPUT
960                 intf_DbgMsg( "PS input: small buffer freed" );
961 #endif
962             }
963         }
964         else
965         {
966             /* Checks whether the large buffer cache is full */
967             if ( p_cache->largebuffer.l_index < LARGE_CACHE_SIZE )
968             {
969                 p_cache->largebuffer.p_stack[
970                     p_cache->largebuffer.l_index ].l_size = p_data->l_size;
971                 p_cache->largebuffer.p_stack[
972                     p_cache->largebuffer.l_index++ ].p_data = p_data->p_buffer;
973             }
974             else
975             {
976                 ASSERT( p_data->p_buffer );
977                 free( p_data->p_buffer );
978 #ifdef TRACE_INPUT
979                 intf_DbgMsg( "PS input: large buffer freed" );
980 #endif
981             }
982         }
983     }
984     else
985     {
986         /* Cache full: the packet must be freed */
987         free( p_data->p_buffer );
988         free( p_data );
989 #ifdef TRACE_INPUT
990         intf_DbgMsg( "PS input: data packet freed" );
991 #endif
992     }
993
994     vlc_mutex_unlock( &p_cache->lock );
995 }
996
997 /*****************************************************************************
998  * DeletePES: deletes a PES packet and associated data packets
999  *****************************************************************************/
1000 static void DeletePES( void * p_packet_cache, pes_packet_t * p_pes )
1001 {
1002     packet_cache_t *    p_cache;
1003     data_packet_t *     p_data;
1004     data_packet_t *     p_next;
1005
1006     p_cache = (packet_cache_t *)p_packet_cache;
1007
1008 #ifdef DEBUG
1009     if ( p_cache == NULL )
1010     {
1011         intf_ErrMsg( "Packet cache not initialized" );
1012         return;
1013     }
1014 #endif
1015
1016     ASSERT( p_pes);
1017
1018     p_data = p_pes->p_first;
1019
1020     while( p_data != NULL )
1021     {
1022         p_next = p_data->p_next;
1023         DeletePacket( p_cache, p_data );
1024         p_data = p_next;
1025     }
1026
1027     vlc_mutex_lock( &p_cache->lock );
1028
1029     /* Checks whether the PES cache is full */
1030     if ( p_cache->pes.l_index < PES_CACHE_SIZE )
1031     {
1032         /* Cache not full: store the packet in it */
1033         p_cache->pes.p_stack[ p_cache->pes.l_index ++ ] = p_pes;
1034     }
1035     else
1036     {
1037         /* Cache full: the packet must be freed */
1038         free( p_pes );
1039 #ifdef TRACE_INPUT
1040         intf_DbgMsg( "PS input: PES packet freed" );
1041 #endif
1042     }
1043
1044     vlc_mutex_unlock( &p_cache->lock );
1045 }