input_ps.c 26.4 KB
Newer Older
1 2 3 4
/*****************************************************************************
 * input_ps.c: PS demux and packet management
 *****************************************************************************
 * Copyright (C) 1998, 1999, 2000 VideoLAN
5
 * $Id: input_ps.c,v 1.18 2001/04/27 19:29:11 massiot Exp $
6
 *
7
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
Cyril Deguet's avatar
 
Cyril Deguet committed
8
 *          Cyril Deguet <asmax@via.ecp.fr>
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

Sam Hocevar's avatar
 
Sam Hocevar committed
25 26 27
#define MODULE_NAME ps
#include "modules_inner.h"

28 29 30 31 32 33 34 35 36
/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include "defs.h"

#include <stdlib.h>
#include <string.h>
#include <errno.h>

Sam Hocevar's avatar
 
Sam Hocevar committed
37 38 39 40 41
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

42 43 44 45
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
46
#include "tests.h"
47 48 49

#include "intf_msg.h"

50 51
#include "main.h"

52 53 54 55 56 57 58 59 60 61 62
#include "stream_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"

#include "input.h"

#include "input_ps.h"
#include "mpeg_system.h"

#include "debug.h"

Sam Hocevar's avatar
 
Sam Hocevar committed
63 64
#include "modules.h"

65 66 67
/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
68
static int  PSProbe     ( probedata_t * );
69
static int  PSRead      ( struct input_thread_s *,
70 71 72
                          data_packet_t * p_packets[INPUT_READ_ONCE] );
static void PSInit      ( struct input_thread_s * );
static void PSEnd       ( struct input_thread_s * );
73 74
static void PSSeek      ( struct input_thread_s *, off_t );
static struct pes_packet_s *  NewPES    ( void * );
75 76 77 78
static struct data_packet_s * NewPacket ( void *, size_t );
static void DeletePacket( void *, struct data_packet_s * );
static void DeletePES   ( void *, struct pes_packet_s * );

Sam Hocevar's avatar
 
Sam Hocevar committed
79 80 81 82
/*****************************************************************************
 * Functions exported as capabilities. They are declared as static so that
 * we don't pollute the namespace too much.
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
83
void _M( input_getfunctions )( function_list_t * p_function_list )
Sam Hocevar's avatar
 
Sam Hocevar committed
84 85 86 87 88 89 90
{
#define input p_function_list->functions.input
    p_function_list->pf_probe = PSProbe;
    input.pf_init             = PSInit;
    input.pf_open             = input_FileOpen;
    input.pf_close            = input_FileClose;
    input.pf_end              = PSEnd;
Stéphane Borel's avatar
 
Stéphane Borel committed
91
    input.pf_set_area         = NULL;
Sam Hocevar's avatar
 
Sam Hocevar committed
92 93 94 95 96 97 98
    input.pf_read             = PSRead;
    input.pf_demux            = input_DemuxPS;
    input.pf_new_packet       = NewPacket;
    input.pf_new_pes          = NewPES;
    input.pf_delete_packet    = DeletePacket;
    input.pf_delete_pes       = DeletePES;
    input.pf_rewind           = NULL;
99
    input.pf_seek             = PSSeek;
Sam Hocevar's avatar
 
Sam Hocevar committed
100 101 102
#undef input
}

103 104 105 106 107 108 109
/*
 * Data reading functions
 */

/*****************************************************************************
 * PSProbe: verifies that the stream is a PS stream
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
110
static int PSProbe( probedata_t *p_data )
111
{
Sam Hocevar's avatar
 
Sam Hocevar committed
112 113 114 115 116 117
    input_thread_t * p_input = (input_thread_t *)p_data;

    char * psz_name = p_input->p_source;
    int i_handle;
    int i_score = 10;

Sam Hocevar's avatar
 
Sam Hocevar committed
118 119 120 121 122
    if( TestMethod( INPUT_METHOD_VAR, "ps" ) )
    {
        return( 999 );
    }

Sam Hocevar's avatar
 
Sam Hocevar committed
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
    if( ( strlen(psz_name) > 5 ) && !strncasecmp( psz_name, "file:", 5 ) )
    {
        /* If the user specified "file:" then it's probably a file */
        i_score = 100;
        psz_name += 5;
    }

    i_handle = open( psz_name, 0 );
    if( i_handle == -1 )
    {
        return( 0 );
    }
    close( i_handle );

    return( i_score );
138 139 140 141 142 143 144 145
}

/*****************************************************************************
 * PSInit: initializes PS structures
 *****************************************************************************/
static void PSInit( input_thread_t * p_input )
{
    thread_ps_data_t *  p_method;
Cyril Deguet's avatar
 
Cyril Deguet committed
146
    packet_cache_t * 	p_packet_cache;
147 148 149 150 151 152 153 154

    if( (p_method =
         (thread_ps_data_t *)malloc( sizeof(thread_ps_data_t) )) == NULL )
    {
        intf_ErrMsg( "Out of memory" );
        p_input->b_error = 1;
        return;
    }
155
    p_input->p_plugin_data = (void *)p_method;
Cyril Deguet's avatar
 
Cyril Deguet committed
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
    
    /* creates the packet cache structure */
    p_packet_cache = malloc( sizeof(packet_cache_t) );
    if ( p_packet_cache == NULL )
    {
        intf_ErrMsg( "Out of memory" );
        p_input->b_error = 1;
        return;
    }
    p_input->p_method_data = (void *)p_packet_cache;
    
    /* allocates the data cache */
    p_packet_cache->data.p_stack = malloc( DATA_CACHE_SIZE * 
        sizeof(data_packet_t*) );
    if ( p_packet_cache->data.p_stack == NULL )
    {
        intf_ErrMsg( "Out of memory" );
    	p_input->b_error = 1;
    	return;
    }
    p_packet_cache->data.l_index = 0;
    
    /* allocates the PES cache */
    p_packet_cache->pes.p_stack = malloc( PES_CACHE_SIZE * 
        sizeof(pes_packet_t*) );
    if ( p_packet_cache->pes.p_stack == NULL )
    {
        intf_ErrMsg( "Out of memory" );
        p_input->b_error = 1;
        return;
    }
    p_packet_cache->pes.l_index = 0;
    
    /* allocates the small buffer cache */
    p_packet_cache->small.p_stack = malloc( SMALL_CACHE_SIZE * 
        sizeof(packet_buffer_t) );
    if ( p_packet_cache->small.p_stack == NULL )
    {
        intf_ErrMsg( "Out of memory" );
        p_input->b_error = 1;
        return;
    }
    p_packet_cache->small.l_index = 0;
    
    /* allocates the large buffer cache */
    p_packet_cache->large.p_stack = malloc( LARGE_CACHE_SIZE * 
        sizeof(packet_buffer_t) );
    if ( p_packet_cache->large.p_stack == NULL )
    {
        intf_ErrMsg( "Out of memory" );
        p_input->b_error = 1;
        return;
    }
    p_packet_cache->large.l_index = 0;
    
211 212 213 214 215 216 217
    /* Re-open the socket as a buffered FILE stream */
    if( (p_method->stream = fdopen( p_input->i_handle, "r" )) == NULL )
    {
        intf_ErrMsg( "Cannot open file (%s)", strerror(errno) );
        p_input->b_error = 1;
        return;
    }
218
    rewind( p_method->stream );
219

220
    /* FIXME : detect if InitStream failed */
221
    input_InitStream( p_input, sizeof( stream_ps_data_t ) );
222
    input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
223 224 225

    if( p_input->stream.b_seekable )
    {
226 227 228
        stream_ps_data_t * p_demux_data =
             (stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data;

229 230
        /* Pre-parse the stream to gather stream_descriptor_t. */
        p_input->stream.pp_programs[0]->b_is_ok = 0;
231 232 233 234
        p_demux_data->i_PSM_version = EMPTY_PSM_VERSION;

        while( !p_input->b_die && !p_input->b_error
                && !p_demux_data->b_has_PSM )
235 236 237 238 239
        {
            int                 i_result, i;
            data_packet_t *     pp_packets[INPUT_READ_ONCE];

            i_result = PSRead( p_input, pp_packets );
240 241 242 243 244 245 246 247
            if( i_result == 1 )
            {
                /* EOF */
                vlc_mutex_lock( &p_input->stream.stream_lock );
                p_input->stream.pp_programs[0]->b_is_ok = 1;
                vlc_mutex_unlock( &p_input->stream.stream_lock );
                break;
            }
248 249 250 251 252 253 254 255 256 257
            if( i_result == -1 )
            {
                p_input->b_error = 1;
                break;
            }

            for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
            {
                /* FIXME: use i_p_config_t */
                input_ParsePS( p_input, pp_packets[i] );
258
                DeletePacket( p_input->p_method_data, pp_packets[i] );
259
            }
260 261

            /* File too big. */
262 263
            if( p_input->stream.p_selected_area->i_tell >
                                                    INPUT_PREPARSE_LENGTH )
264 265 266
            {
                break;
            }
267
        }
268
        rewind( p_method->stream );
269
        vlc_mutex_lock( &p_input->stream.stream_lock );
270 271

        p_input->stream.i_method = INPUT_METHOD_FILE;
272
        p_input->stream.p_selected_area->i_tell = 0;
273

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
        if( p_demux_data->b_has_PSM )
        {
            /* (The PSM decoder will care about spawning the decoders) */
            p_input->stream.pp_programs[0]->b_is_ok = 1;
        }
#ifdef AUTO_SPAWN
        else
        {
            /* (We have to do it ourselves) */
            int                 i_es;

            /* FIXME: we should do multiple passes in case an audio type
             * is not present */
            for( i_es = 0;
                 i_es < p_input->stream.pp_programs[0]->i_es_number;
                 i_es++ )
            {
#define p_es p_input->stream.pp_programs[0]->pp_es[i_es]
                switch( p_es->i_type )
                {
                    case MPEG1_VIDEO_ES:
                    case MPEG2_VIDEO_ES:
                        input_SelectES( p_input, p_es );
                        break;

                    case MPEG1_AUDIO_ES:
                    case MPEG2_AUDIO_ES:
Sam Hocevar's avatar
 
Sam Hocevar committed
301
                        if( main_GetIntVariable( INPUT_CHANNEL_VAR, 0 )
302
                                == (p_es->i_id & 0x1F) )
Sam Hocevar's avatar
 
Sam Hocevar committed
303
                        switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) )
304
                        {
Sam Hocevar's avatar
 
Sam Hocevar committed
305
                        case 0:
Sam Hocevar's avatar
 
Sam Hocevar committed
306
                            main_PutIntVariable( INPUT_AUDIO_VAR,
Sam Hocevar's avatar
 
Sam Hocevar committed
307 308
                                                 REQUESTED_MPEG );
                        case REQUESTED_MPEG:
309 310 311 312 313
                            input_SelectES( p_input, p_es );
                        }
                        break;

                    case AC3_AUDIO_ES:
Sam Hocevar's avatar
 
Sam Hocevar committed
314
                        if( main_GetIntVariable( INPUT_CHANNEL_VAR, 0 )
315
                                == ((p_es->i_id & 0xF00) >> 8) )
Sam Hocevar's avatar
 
Sam Hocevar committed
316
                        switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) )
317
                        {
Sam Hocevar's avatar
 
Sam Hocevar committed
318
                        case 0:
Sam Hocevar's avatar
 
Sam Hocevar committed
319
                            main_PutIntVariable( INPUT_AUDIO_VAR,
Sam Hocevar's avatar
 
Sam Hocevar committed
320 321
                                                 REQUESTED_AC3 );
                        case REQUESTED_AC3:
322 323
                            input_SelectES( p_input, p_es );
                        }
324
                        break;
325 326

                    case DVD_SPU_ES:
Sam Hocevar's avatar
 
Sam Hocevar committed
327
                        if( main_GetIntVariable( INPUT_SUBTITLE_VAR, -1 )
328 329 330 331
                                == ((p_es->i_id & 0x1F00) >> 8) )
                        {
                            input_SelectES( p_input, p_es );
                        }
332
                        break;
333 334 335

                    case LPCM_AUDIO_ES:
                        /* FIXME ! */
336
                        break;
337 338 339 340 341
                }
            }
                    
        }
#endif
342 343 344 345 346 347 348 349 350
#ifdef STATS
        input_DumpStream( p_input );
#endif
        vlc_mutex_unlock( &p_input->stream.stream_lock );
    }
    else
    {
        /* The programs will be added when we read them. */
        vlc_mutex_lock( &p_input->stream.stream_lock );
351
        p_input->stream.i_method = INPUT_METHOD_FILE;
352 353 354
        p_input->stream.pp_programs[0]->b_is_ok = 0;
        vlc_mutex_unlock( &p_input->stream.stream_lock );
    }
355 356 357 358 359 360 361
}

/*****************************************************************************
 * PSEnd: frees unused data
 *****************************************************************************/
static void PSEnd( input_thread_t * p_input )
{
362
    free( p_input->p_plugin_data );
363 364 365
}

/*****************************************************************************
366
 * SafeRead: reads a chunk of stream and correctly detects errors
367
 *****************************************************************************/
368 369
static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer,
                                size_t i_len )
370 371
{
    thread_ps_data_t *  p_method;
372
    int                 i_error;
373

374
    p_method = (thread_ps_data_t *)p_input->p_plugin_data;
375
    while( fread( p_buffer, i_len, 1, p_method->stream ) != 1 )
376
    {
377
        if( feof( p_method->stream ) )
378
        {
379
            return( 1 );
380 381
        }

382
        if( (i_error = ferror( p_method->stream )) )
383
        {
384 385
            intf_ErrMsg( "Read failed (%s)", strerror(i_error) );
            return( -1 );
386 387
        }
    }
388
    vlc_mutex_lock( &p_input->stream.stream_lock );
389
    p_input->stream.p_selected_area->i_tell += i_len;
390 391 392
    vlc_mutex_unlock( &p_input->stream.stream_lock );
    return( 0 );
}
393

394
/*****************************************************************************
395
 * PSRead: reads data packets
396 397 398 399 400 401 402 403 404 405 406 407 408
 *****************************************************************************
 * Returns -1 in case of error, 0 if everything went well, and 1 in case of
 * EOF.
 *****************************************************************************/
static int PSRead( input_thread_t * p_input,
                   data_packet_t * pp_packets[INPUT_READ_ONCE] )
{
    byte_t              p_header[6];
    data_packet_t *     p_data;
    size_t              i_packet_size;
    int                 i_packet, i_error;
    thread_ps_data_t *  p_method;

409
    p_method = (thread_ps_data_t *)p_input->p_plugin_data;
410 411 412

    memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
    for( i_packet = 0; i_packet < INPUT_READ_ONCE; i_packet++ )
413
    {
414 415
        /* Read what we believe to be a packet header. */
        if( (i_error = SafeRead( p_input, p_header, 6 )) )
416
        {
417
            return( i_error );
418 419
        }

420
        if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L )
421
        {
422 423 424 425 426 427 428 429 430 431
            /* This is not the startcode of a packet. Read the stream
             * until we find one. */
            u32         i_startcode = U32_AT(p_header);
            int         i_dummy;

            if( i_startcode )
            {
                /* It is common for MPEG-1 streams to pad with zeros
                 * (although it is forbidden by the recommendation), so
                 * don't bother everybody in this case. */
Sam Hocevar's avatar
 
Sam Hocevar committed
432
                intf_WarnMsg( 1, "Garbage at input (%.8x)", i_startcode );
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
            }

            while( (i_startcode & 0xFFFFFF00) != 0x100L )
            {
                i_startcode <<= 8;
                if( (i_dummy = getc( p_method->stream )) != EOF )
                {
                    i_startcode |= i_dummy;
                }
                else
                {
                    return( 1 );
                }
            }
            /* Packet found. */
            *(u32 *)p_header = U32_AT(&i_startcode);
            if( (i_error = SafeRead( p_input, p_header + 4, 2 )) )
            {
                return( i_error );
            }
453
        }
454 455

        if( U32_AT(p_header) != 0x1BA )
456
        {
457 458
            /* That's the case for all packets, except pack header. */
            i_packet_size = U16_AT(&p_header[4]);
459 460 461
        }
        else
        {
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
            /* Pack header. */
            if( (p_header[4] & 0xC0) == 0x40 )
            {
                /* MPEG-2 */
                i_packet_size = 8;
            }
            else if( (p_header[4] & 0xF0) == 0x20 )
            {
                /* MPEG-1 */
                i_packet_size = 6;
            }
            else
            {
                intf_ErrMsg( "Unable to determine stream type" );
                return( -1 );
            }
478
        }
479

480
        /* Fetch a packet of the appropriate size. */
Cyril Deguet's avatar
 
Cyril Deguet committed
481 482
        if( (p_data = NewPacket( p_input->p_method_data, i_packet_size + 6 )) 
            == NULL )
483
        {
484 485
            intf_ErrMsg( "Out of memory" );
            return( -1 );
486 487
        }

488 489 490 491
        /* Copy the header we already read. */
        memcpy( p_data->p_buffer, p_header, 6 );

        /* Read the remaining of the packet. */
Sam Hocevar's avatar
 
Sam Hocevar committed
492
        if( i_packet_size && (i_error =
493
                SafeRead( p_input, p_data->p_buffer + 6, i_packet_size )) )
494
        {
495
            return( i_error );
496 497
        }

498 499
        /* In MPEG-2 pack headers we still have to read stuffing bytes. */
        if( U32_AT(p_header) == 0x1BA )
500
        {
501
            if( i_packet_size == 8 && (p_data->p_buffer[13] & 0x7) != 0 )
502
            {
503 504 505 506 507 508 509
                /* MPEG-2 stuffing bytes */
                byte_t      p_garbage[8];
                if( (i_error = SafeRead( p_input, p_garbage,
                                         p_data->p_buffer[13] & 0x7)) )
                {
                    return( i_error );
                }
510 511
            }
        }
512 513 514

        /* Give the packet to the other input stages. */
        pp_packets[i_packet] = p_data;
515 516
    }

517
    return( 0 );
518 519
}

520 521 522 523 524 525 526 527 528 529
/*****************************************************************************
 * PSSeek: changes the stream position indicator
 *****************************************************************************/
static void PSSeek( input_thread_t * p_input, off_t i_position )
{
    thread_ps_data_t *  p_method;

    p_method = (thread_ps_data_t *)p_input->p_plugin_data;

    /* A little bourrin but should work for a while --Meuuh */
530
    fseeko( p_method->stream, i_position, SEEK_SET );
531

532
    p_input->stream.p_selected_area->i_tell = i_position;
533
}
534 535 536 537 538

/*
 * Packet management utilities
 */

Cyril Deguet's avatar
 
Cyril Deguet committed
539

540 541 542
/*****************************************************************************
 * NewPacket: allocates a data packet
 *****************************************************************************/
Cyril Deguet's avatar
 
Cyril Deguet committed
543 544 545 546 547 548 549
static struct data_packet_s * NewPacket( void * p_packet_cache,
                                         size_t l_size )
{ 
    packet_cache_t *   p_cache;
    data_packet_t *    p_data;
    long               l_index;

550
#ifdef DEBUG
Cyril Deguet's avatar
 
Cyril Deguet committed
551
    if ( (p_cache = (packet_cache_t *)p_packet_cache) == NULL )
552
    {
Cyril Deguet's avatar
 
Cyril Deguet committed
553
        intf_ErrMsg( "PPacket cache not initialized" );
554 555
        return NULL;
    }
556 557
#endif

Cyril Deguet's avatar
 
Cyril Deguet committed
558 559
    /* Safety check */
    if( l_size > INPUT_MAX_PACKET_SIZE )
560
    {
Cyril Deguet's avatar
 
Cyril Deguet committed
561
        intf_ErrMsg( "Packet too big (%d)", l_size );
Cyril Deguet's avatar
 
Cyril Deguet committed
562
        return NULL;
Cyril Deguet's avatar
 
Cyril Deguet committed
563
    }
Cyril Deguet's avatar
 
Cyril Deguet committed
564

Cyril Deguet's avatar
 
Cyril Deguet committed
565 566
    /* Checks whether the data cache is empty */
    if( p_cache->data.l_index == 0 )
Cyril Deguet's avatar
 
Cyril Deguet committed
567
    {
Cyril Deguet's avatar
 
Cyril Deguet committed
568 569 570
        /* Allocates a new packet */
        if ( (p_data = malloc( sizeof(data_packet_t) )) == NULL )
        {
571
            intf_ErrMsg( "Out of memory" );
Cyril Deguet's avatar
 
Cyril Deguet committed
572 573
            return NULL;
        }
574 575 576
#ifdef TRACE_INPUT
        intf_DbgMsg( "PS input: data packet allocated" );
#endif
Cyril Deguet's avatar
 
Cyril Deguet committed
577 578 579 580 581 582 583
    }
    else
    {
        /* Takes the packet out from the cache */
        if( (p_data = p_cache->data.p_stack[ -- p_cache->data.l_index ]) 
            == NULL )
        {
584
            intf_ErrMsg( "NULL packet in the data cache" );
Cyril Deguet's avatar
 
Cyril Deguet committed
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
            return NULL;
        }
    }
    
    if( l_size < MAX_SMALL_SIZE )
    {
        /* Small buffer */  
   
        /* Checks whether the buffer cache is empty */
        if( p_cache->small.l_index == 0 )
        {
    	    /* Allocates a new packet */
            if ( (p_data->p_buffer = malloc( l_size )) == NULL )
            {
                intf_DbgMsg( "Out of memory" );
                free( p_data );
                return NULL;
            }
603 604 605
#ifdef TRACE_INPUT
            intf_DbgMsg( "PS input: small buffer allocated" );
#endif
Cyril Deguet's avatar
 
Cyril Deguet committed
606 607 608 609 610 611 612 613 614
            p_data->l_size = l_size;
        }
        else
        {
            /* Takes the packet out from the cache */
            l_index = -- p_cache->small.l_index;    
            if( (p_data->p_buffer = p_cache->small.p_stack[l_index].p_data)
                == NULL )
            {
615
                intf_ErrMsg( "NULL packet in the small buffer cache" );
Cyril Deguet's avatar
 
Cyril Deguet committed
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
                free( p_data );
                return NULL;
            }
	        /* Reallocates the packet if it is too small or too large */
            if( p_cache->small.p_stack[l_index].l_size < l_size ||
                p_cache->small.p_stack[l_index].l_size > 2*l_size )
            {
                p_data->p_buffer = realloc( p_data->p_buffer, l_size );
                p_data->l_size = l_size;
            }
            else
            {
                p_data->l_size = p_cache->small.p_stack[l_index].l_size;
            }
        }
    }
    else
    {
        /* Large buffer */  
   
        /* Checks whether the buffer cache is empty */
        if( p_cache->large.l_index == 0 )
        {
    	    /* Allocates a new packet */
            if ( (p_data->p_buffer = malloc( l_size )) == NULL )
            {
642
                intf_ErrMsg( "Out of memory" );
Cyril Deguet's avatar
 
Cyril Deguet committed
643 644 645
                free( p_data );
                return NULL;
            }
646 647 648
#ifdef TRACE_INPUT
            intf_DbgMsg( "PS input: large buffer allocated" );
#endif
Cyril Deguet's avatar
 
Cyril Deguet committed
649 650 651 652 653 654 655 656 657
            p_data->l_size = l_size;
        }
        else
        {
            /* Takes the packet out from the cache */
            l_index = -- p_cache->large.l_index;    
            if( (p_data->p_buffer = p_cache->large.p_stack[l_index].p_data)
                == NULL )
            {
658
                intf_ErrMsg( "NULL packet in the small buffer cache" );
Cyril Deguet's avatar
 
Cyril Deguet committed
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
                free( p_data );
                return NULL;
            }
	        /* Reallocates the packet if it is too small or too large */
            if( p_cache->large.p_stack[l_index].l_size < l_size ||
                p_cache->large.p_stack[l_index].l_size > 2*l_size )
            {
                p_data->p_buffer = realloc( p_data->p_buffer, l_size );
                p_data->l_size = l_size;
            }
            else
            {
                p_data->l_size = p_cache->large.p_stack[l_index].l_size;
            }
	    }
674 675
    }

676 677 678
    /* Initialize data */
    p_data->p_next = NULL;
    p_data->b_discard_payload = 0;
679
    p_data->p_payload_start = p_data->p_buffer;
Cyril Deguet's avatar
 
Cyril Deguet committed
680
    p_data->p_payload_end = p_data->p_buffer + l_size;
681 682

    return( p_data );
Cyril Deguet's avatar
 
Cyril Deguet committed
683
	
684 685
}

Cyril Deguet's avatar
 
Cyril Deguet committed
686

687 688 689
/*****************************************************************************
 * NewPES: allocates a pes packet
 *****************************************************************************/
Cyril Deguet's avatar
 
Cyril Deguet committed
690
static pes_packet_t * NewPES( void * p_packet_cache )
691
{
Cyril Deguet's avatar
 
Cyril Deguet committed
692 693
    packet_cache_t *   p_cache;
    pes_packet_t *     p_pes;
694

695
#ifdef DEBUG
Cyril Deguet's avatar
 
Cyril Deguet committed
696
    if ( (p_cache = (packet_cache_t *)p_packet_cache) == NULL )
697
    {
Cyril Deguet's avatar
 
Cyril Deguet committed
698
        intf_ErrMsg( "Packet cache not initialized" );
699 700
        return NULL;
    }
701 702
#endif

Cyril Deguet's avatar
 
Cyril Deguet committed
703 704 705 706 707 708 709 710 711
    /* Checks whether the PES cache is empty */
    if( p_cache->pes.l_index == 0 )
    {
        /* Allocates a new packet */
        if ( (p_pes = malloc( sizeof(pes_packet_t) )) == NULL )
        {
            intf_DbgMsg( "Out of memory" );
            return NULL;
        }
712 713 714
#ifdef TRACE_INPUT
        intf_DbgMsg( "PS input: PES packet allocated" );
#endif
Cyril Deguet's avatar
 
Cyril Deguet committed
715 716 717 718 719 720 721
    }
    else
    {
        /* Takes the packet out from the cache */
        if( (p_pes = p_cache->pes.p_stack[ -- p_cache->pes.l_index ]) 
            == NULL )
        {
722
            intf_ErrMsg( "NULL packet in the data cache" );
Cyril Deguet's avatar
 
Cyril Deguet committed
723 724 725 726
            return NULL;
        }
    }
	
727
    p_pes->b_data_alignment = p_pes->b_discontinuity =
728
        p_pes->i_pts = p_pes->i_dts = 0;
729 730 731 732
    p_pes->i_pes_size = 0;
    p_pes->p_first = NULL;

    return( p_pes );
Cyril Deguet's avatar
 
Cyril Deguet committed
733
    
734 735
}

736 737 738
/*****************************************************************************
 * DeletePacket: deletes a data packet
 *****************************************************************************/
Cyril Deguet's avatar
 
Cyril Deguet committed
739
static void DeletePacket( void * p_packet_cache,
740 741
                          data_packet_t * p_data )
{
Cyril Deguet's avatar
 
Cyril Deguet committed
742
    packet_cache_t *   p_cache;
743 744

#ifdef DEBUG
Cyril Deguet's avatar
 
Cyril Deguet committed
745 746 747 748 749
    if ( (p_cache = (packet_cache_t *)p_packet_cache) == NULL )
    {
        intf_ErrMsg( "Packet cache not initialized" );
        return;
    }
750
#endif
Cyril Deguet's avatar
 
Cyril Deguet committed
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773

	ASSERT( p_data );

    /* Checks whether the data cache is full */
    if ( p_cache->data.l_index < DATA_CACHE_SIZE )
    {
        /* Cache not full: store the packet in it */
        p_cache->data.p_stack[ p_cache->data.l_index ++ ] = p_data;
        /* Small buffer or large buffer? */
        if ( p_data->l_size < MAX_SMALL_SIZE )
        {
            /* Checks whether the small buffer cache is full */
            if ( p_cache->small.l_index < SMALL_CACHE_SIZE )
            {
                p_cache->small.p_stack[ p_cache->small.l_index ].l_size = 
                    p_data->l_size;
                p_cache->small.p_stack[ p_cache->small.l_index ++ ].p_data = 
                    p_data->p_buffer;
            }
            else
            {
                ASSERT( p_data->p_buffer );
                free( p_data->p_buffer );
774 775 776
#ifdef TRACE_INPUT
                intf_DbgMsg( "PS input: small buffer freed" );
#endif
Cyril Deguet's avatar
 
Cyril Deguet committed
777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792
            }
        }
    	else
        {
            /* Checks whether the large buffer cache is full */
            if ( p_cache->large.l_index < LARGE_CACHE_SIZE )
            {
                p_cache->large.p_stack[ p_cache->large.l_index ].l_size = 
                    p_data->l_size;
                p_cache->large.p_stack[ p_cache->large.l_index ++ ].p_data = 
                    p_data->p_buffer;
            }
            else
            {
                ASSERT( p_data->p_buffer );
                free( p_data->p_buffer );
793 794 795
#ifdef TRACE_INPUT
                intf_DbgMsg( "PS input: large buffer freed" );
#endif
Cyril Deguet's avatar
 
Cyril Deguet committed
796 797 798 799 800 801 802 803
            }
        }
    }
    else
    {
        /* Cache full: the packet must be freed */
        free( p_data->p_buffer );
    	free( p_data );
804 805 806
#ifdef TRACE_INPUT
        intf_DbgMsg( "PS input: data packet freed" );
#endif
Cyril Deguet's avatar
 
Cyril Deguet committed
807 808
    }

809 810 811 812 813
}

/*****************************************************************************
 * DeletePES: deletes a PES packet and associated data packets
 *****************************************************************************/
Cyril Deguet's avatar
 
Cyril Deguet committed
814
static void DeletePES( void * p_packet_cache, pes_packet_t * p_pes )
815
{
Cyril Deguet's avatar
 
Cyril Deguet committed
816
    packet_cache_t *    p_cache;
817 818 819
    data_packet_t *     p_data;
    data_packet_t *     p_next;

820
#ifdef DEBUG
Cyril Deguet's avatar
 
Cyril Deguet committed
821 822 823 824 825
    if ( (p_cache = (packet_cache_t *)p_packet_cache) == NULL )
    {
        intf_ErrMsg( "Packet cache not initialized" );
        return;
    }
826
#endif
Cyril Deguet's avatar
 
Cyril Deguet committed
827 828 829

    ASSERT( p_pes);

830 831 832 833 834
    p_data = p_pes->p_first;

    while( p_data != NULL )
    {
        p_next = p_data->p_next;
Cyril Deguet's avatar
 
Cyril Deguet committed
835
        DeletePacket( p_cache, p_data );
836 837 838
        p_data = p_next;
    }

Cyril Deguet's avatar
 
Cyril Deguet committed
839 840 841 842 843 844 845 846 847 848
    /* Checks whether the PES cache is full */
    if ( p_cache->pes.l_index < PES_CACHE_SIZE )
    {
    	/* Cache not full: store the packet in it */
        p_cache->pes.p_stack[ p_cache->pes.l_index ++ ] = p_pes;
    }
    else
    {
        /* Cache full: the packet must be freed */
        free( p_pes );
849 850 851
#ifdef TRACE_INPUT
        intf_DbgMsg( "PS input: PES packet freed" );
#endif
Cyril Deguet's avatar
 
Cyril Deguet committed
852
    }
853 854
}