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