input_programs.c 26.2 KB
Newer Older
1 2 3 4
/*****************************************************************************
 * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
 *****************************************************************************
 * Copyright (C) 1999, 2000 VideoLAN
5
 * $Id: input_programs.c,v 1.61 2001/08/09 20:16:17 jlj Exp $
6
 *
7
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * 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.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
27 28 29
#include "defs.h"

#include <stdlib.h>
Sam Hocevar's avatar
 
Sam Hocevar committed
30
#include <string.h>                                    /* memcpy(), memset() */
Sam Hocevar's avatar
 
Sam Hocevar committed
31
#include <sys/types.h>                                              /* off_t */
32 33 34 35 36 37 38 39 40 41 42 43

#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
#include "debug.h"

#include "intf_msg.h"

#include "stream_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"
44
#include "input_ext-plugins.h"
45

46 47
#include "main.h"                                     /* --noaudio --novideo */

48 49 50 51
/*
 * NOTICE : all of these functions expect you to have taken the lock on
 * p_input->stream.lock
 */
52 53 54 55

/*****************************************************************************
 * input_InitStream: init the stream descriptor of the given input
 *****************************************************************************/
56
int input_InitStream( input_thread_t * p_input, size_t i_data_len )
57
{
58 59

    p_input->stream.i_method = INPUT_METHOD_NONE;
60
    p_input->stream.i_stream_id = 0;
61 62 63 64

    /* initialized to 0 since we don't give the signal to the interface
     * before the end of input initialization */
    p_input->stream.b_changed = 0;
65 66
    p_input->stream.pp_es = NULL;
    p_input->stream.pp_selected_es = NULL;
67 68
    p_input->stream.p_removed_es = NULL;
    p_input->stream.p_newly_selected_es = NULL;
69 70 71 72
    p_input->stream.pp_programs = NULL;

    if( i_data_len )
    {
Henri Fallon's avatar
 
Henri Fallon committed
73 74 75
        if ( (p_input->stream.p_demux_data = malloc( i_data_len )) == NULL )
        {
            intf_ErrMsg( "Unable to allocate memory in input_InitStream");
76
            return 1;
Henri Fallon's avatar
 
Henri Fallon committed
77
        }
78 79
        memset( p_input->stream.p_demux_data, 0, i_data_len );
    }
80 81

    return 0;
82 83
}

84 85 86 87 88
/*****************************************************************************
 * input_EndStream: free all stream descriptors
 *****************************************************************************/
void input_EndStream( input_thread_t * p_input )
{
89
    /* Free all programs and associated ES, and associated decoders. */
90
    while( p_input->stream.i_pgrm_number )
91
    {
92 93
        input_DelProgram( p_input, p_input->stream.pp_programs[0] );
    }
94

95
    /* Free standalone ES */
96
    while( p_input->stream.i_es_number )
97 98 99
    {
        input_DelES( p_input, p_input->stream.pp_es[0] );
    }
100

101 102 103 104 105 106
    /* Free all areas */
    while( p_input->stream.i_area_nb )
    {
        input_DelArea( p_input, p_input->stream.pp_areas[0] );
    }

107 108 109 110 111 112
    /* Free selected ES */
    if( p_input->stream.pp_selected_es != NULL )
    {
        free( p_input->stream.pp_selected_es );
    }
    
113 114 115 116
    if( p_input->stream.p_demux_data != NULL )
    {
        free( p_input->stream.p_demux_data );
    }
117 118 119 120 121 122 123 124 125 126 127 128
}

/*****************************************************************************
 * input_FindProgram: returns a pointer to a program described by its ID
 *****************************************************************************/
pgrm_descriptor_t * input_FindProgram( input_thread_t * p_input, u16 i_pgrm_id )
{
    int     i;

    for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
    {
        if( p_input->stream.pp_programs[i]->i_number == i_pgrm_id )
129
        {
130
            return p_input->stream.pp_programs[i];
131 132
        }
    }
133 134

    return( NULL );
135 136
}

137 138 139 140 141 142
/*****************************************************************************
 * input_AddProgram: add and init a program descriptor
 *****************************************************************************
 * This program descriptor will be referenced in the given stream descriptor
 *****************************************************************************/
pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input,
143
                                      u16 i_pgrm_id, size_t i_data_len )
144
{
145 146
    /* Where to add the pgrm */
    int i_pgrm_index = p_input->stream.i_pgrm_number;
147 148 149 150 151 152 153 154

    intf_DbgMsg("Adding description for pgrm %d", i_pgrm_id);

    /* Add an entry to the list of program associated with the stream */
    p_input->stream.i_pgrm_number++;
    p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
                                           p_input->stream.i_pgrm_number
                                            * sizeof(pgrm_descriptor_t *) );
Henri Fallon's avatar
 
Henri Fallon committed
155 156 157
    if( p_input->stream.pp_programs == NULL )
    {
        intf_ErrMsg( "Unable to realloc memory in input_AddProgram" );
Henri Fallon's avatar
 
Henri Fallon committed
158
        return( NULL );
Henri Fallon's avatar
 
Henri Fallon committed
159 160
    }
    
161 162 163
    /* Allocate the structure to store this description */
    p_input->stream.pp_programs[i_pgrm_index] =
                                        malloc( sizeof(pgrm_descriptor_t) );
Henri Fallon's avatar
 
Henri Fallon committed
164 165 166
    if( p_input->stream.pp_programs[i_pgrm_index] == NULL )
    {
        intf_ErrMsg( "Unable to allocate memory in input_AddProgram" );
Henri Fallon's avatar
 
Henri Fallon committed
167
        return( NULL );
Henri Fallon's avatar
 
Henri Fallon committed
168 169
    }
    
170 171 172
    /* Init this entry */
    p_input->stream.pp_programs[i_pgrm_index]->i_number = i_pgrm_id;
    p_input->stream.pp_programs[i_pgrm_index]->b_is_ok = 0;
173
    p_input->stream.pp_programs[i_pgrm_index]->i_version = 0;
174 175 176 177

    p_input->stream.pp_programs[i_pgrm_index]->i_es_number = 0;
    p_input->stream.pp_programs[i_pgrm_index]->pp_es = NULL;

178 179
    input_ClockInit( p_input->stream.pp_programs[i_pgrm_index] );

180
    p_input->stream.pp_programs[i_pgrm_index]->i_synchro_state
181
                                                = SYNCHRO_START;
182

183 184 185 186
    if( i_data_len )
    {
        p_input->stream.pp_programs[i_pgrm_index]->p_demux_data =
            malloc( i_data_len );
Henri Fallon's avatar
 
Henri Fallon committed
187 188 189
        if( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data == NULL )
        {
            intf_ErrMsg( "Unable to allocate memory in input_AddProgram" );
Henri Fallon's avatar
 
Henri Fallon committed
190
            return( NULL );
Henri Fallon's avatar
 
Henri Fallon committed
191
        }
192 193 194 195
        memset( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data, 0,
                i_data_len );
    }

196 197 198 199 200 201 202 203
    return p_input->stream.pp_programs[i_pgrm_index];
}

/*****************************************************************************
 * input_DelProgram: destroy a program descriptor
 *****************************************************************************
 * All ES descriptions referenced in the descriptor will be deleted.
 *****************************************************************************/
204
void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
205
{
206
    int i_pgrm_index;
207

208
    ASSERT( p_pgrm );
209

210
    intf_DbgMsg("Deleting description for pgrm %d", p_pgrm->i_number);
211 212

    /* Free the structures that describe the es that belongs to that program */
213
    while( p_pgrm->i_es_number )
214
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
215
        input_DelES( p_input, p_pgrm->pp_es[0] );
216 217
    }

218 219 220 221 222 223
    /* Free the demux data */
    if( p_pgrm->p_demux_data != NULL )
    {
        free( p_pgrm->p_demux_data );
    }

224 225 226 227 228 229 230
    /* Find the program in the programs table */
    for( i_pgrm_index = 0; i_pgrm_index < p_input->stream.i_pgrm_number;
         i_pgrm_index++ )
    {
        if( p_input->stream.pp_programs[i_pgrm_index] == p_pgrm )
            break;
    }
231 232 233

    /* Remove this program from the stream's list of programs */
    p_input->stream.i_pgrm_number--;
234

235 236 237 238 239
    p_input->stream.pp_programs[i_pgrm_index] =
        p_input->stream.pp_programs[p_input->stream.i_pgrm_number];
    p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
                                           p_input->stream.i_pgrm_number
                                            * sizeof(pgrm_descriptor_t *) );
240

241
    if( p_input->stream.i_pgrm_number && p_input->stream.pp_programs == NULL)
Henri Fallon's avatar
 
Henri Fallon committed
242
    {
243 244
        intf_ErrMsg( "input error: unable to realloc program list"
                     " in input_DelProgram" );
Henri Fallon's avatar
 
Henri Fallon committed
245
    }
246

247 248 249 250
    /* Free the description of this program */
    free( p_pgrm );
}

Stéphane Borel's avatar
 
Stéphane Borel committed
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
/*****************************************************************************
 * input_AddArea: add and init an area descriptor
 *****************************************************************************
 * This area descriptor will be referenced in the given stream descriptor
 *****************************************************************************/
input_area_t * input_AddArea( input_thread_t * p_input )
{
    /* Where to add the pgrm */
    int i_area_index = p_input->stream.i_area_nb;

    intf_DbgMsg("Adding description for area %d", i_area_index );

    /* Add an entry to the list of program associated with the stream */
    p_input->stream.i_area_nb++;
    p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
                                        p_input->stream.i_area_nb
                                            * sizeof(input_area_t *) );
    if( p_input->stream.pp_areas == NULL )
    {
        intf_ErrMsg( "Unable to realloc memory in input_AddArea" );
        return( NULL );
    }
    
    /* Allocate the structure to store this description */
    p_input->stream.pp_areas[i_area_index] =
                                        malloc( sizeof(input_area_t) );
    if( p_input->stream.pp_areas[i_area_index] == NULL )
    {
        intf_ErrMsg( "Unable to allocate memory in input_AddArea" );
        return( NULL );
    }
    
    /* Init this entry */
    p_input->stream.pp_areas[i_area_index]->i_id = 0;
    p_input->stream.pp_areas[i_area_index]->i_start = 0;
    p_input->stream.pp_areas[i_area_index]->i_size = 0;
    p_input->stream.pp_areas[i_area_index]->i_tell = 0;
288
    p_input->stream.pp_areas[i_area_index]->i_seek = NO_SEEK;
289
    p_input->stream.pp_areas[i_area_index]->i_part_nb = 1;
Stéphane Borel's avatar
 
Stéphane Borel committed
290
    p_input->stream.pp_areas[i_area_index]->i_part= 0;
291 292
    p_input->stream.pp_areas[i_area_index]->i_angle_nb = 1;
    p_input->stream.pp_areas[i_area_index]->i_angle = 0;
Stéphane Borel's avatar
 
Stéphane Borel committed
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307

    return p_input->stream.pp_areas[i_area_index];
}

/*****************************************************************************
 * input_DelArea: destroy a area descriptor
 *****************************************************************************
 * All ES descriptions referenced in the descriptor will be deleted.
 *****************************************************************************/
void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
{
    int i_area_index;

    ASSERT( p_area );

308
    intf_DbgMsg("Deleting description for area %d", p_area->i_id );
Stéphane Borel's avatar
 
Stéphane Borel committed
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329

    /* Find the area in the areas table */
    for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb;
         i_area_index++ )
    {
        if( p_input->stream.pp_areas[i_area_index] == p_area )
            break;
    }

    /* Remove this area from the stream's list of areas */
    p_input->stream.i_area_nb--;

    p_input->stream.pp_areas[i_area_index] =
        p_input->stream.pp_areas[p_input->stream.i_area_nb];
    p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
                                           p_input->stream.i_area_nb
                                            * sizeof(input_area_t *) );

    if( p_input->stream.i_area_nb && p_input->stream.pp_areas == NULL)
    {
        intf_ErrMsg( "input error: unable to realloc area list"
330
                     " in input_DelArea" );
Stéphane Borel's avatar
 
Stéphane Borel committed
331 332 333 334 335 336 337
    }

    /* Free the description of this area */
    free( p_area );
}


338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
/*****************************************************************************
 * input_FindES: returns a pointer to an ES described by its ID
 *****************************************************************************/
es_descriptor_t * input_FindES( input_thread_t * p_input, u16 i_es_id )
{
    int     i;

    for( i = 0; i < p_input->stream.i_es_number; i++ )
    {
        if( p_input->stream.pp_es[i]->i_id == i_es_id )
        {
            return p_input->stream.pp_es[i];
        }
    }

    return( NULL );
354 355 356 357 358 359 360 361 362 363
}

/*****************************************************************************
 * input_AddES:
 *****************************************************************************
 * Reserve a slot in the table of ES descriptors for the ES and add it to the
 * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
 * alone (PSI ?)
 *****************************************************************************/
es_descriptor_t * input_AddES( input_thread_t * p_input,
364 365
                               pgrm_descriptor_t * p_pgrm, u16 i_es_id,
                               size_t i_data_len )
366
{
367
    es_descriptor_t * p_es;
368

369
    intf_DbgMsg("Adding description for ES 0x%x", i_es_id);
370

371
    p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
Henri Fallon's avatar
 
Henri Fallon committed
372 373 374
    if( p_es == NULL )
    {
        intf_ErrMsg( "Unable to allocate memory in input_AddES" );
Henri Fallon's avatar
 
Henri Fallon committed
375
        return( NULL);
Henri Fallon's avatar
 
Henri Fallon committed
376
    }
377 378 379 380
    p_input->stream.i_es_number++;
    p_input->stream.pp_es = realloc( p_input->stream.pp_es,
                                     p_input->stream.i_es_number
                                      * sizeof(es_descriptor_t *) );
Henri Fallon's avatar
 
Henri Fallon committed
381 382 383
    if( p_input->stream.pp_es == NULL )
    {
        intf_ErrMsg( "Unable to realloc memory in input_AddES" );
Henri Fallon's avatar
 
Henri Fallon committed
384
        return( NULL );
Henri Fallon's avatar
 
Henri Fallon committed
385
    }
386
    p_input->stream.pp_es[p_input->stream.i_es_number - 1] = p_es;
387

388
    /* Init its values */
389
    p_es->i_id = i_es_id;
390
    p_es->psz_desc[0] = '\0';
391 392
    p_es->p_pes = NULL;
    p_es->p_decoder_fifo = NULL;
393
    p_es->b_audio = 0;
Stéphane Borel's avatar
Stéphane Borel committed
394
    p_es->i_cat = UNKNOWN_ES;
395 396

    if( i_data_len )
397
    {
398
        p_es->p_demux_data = malloc( i_data_len );
Henri Fallon's avatar
 
Henri Fallon committed
399 400 401
        if( p_es->p_demux_data == NULL )
        {
            intf_ErrMsg( "Unable to allocate memory in input_AddES" );
Henri Fallon's avatar
 
Henri Fallon committed
402
            return( NULL );
Henri Fallon's avatar
 
Henri Fallon committed
403
        }
404 405
        memset( p_es->p_demux_data, 0, i_data_len );
    }
406 407 408 409
    else
    {
        p_es->p_demux_data = NULL;
    }
410 411 412 413 414 415 416 417

    /* Add this ES to the program definition if one is given */
    if( p_pgrm )
    {
        p_pgrm->i_es_number++;
        p_pgrm->pp_es = realloc( p_pgrm->pp_es,
                                 p_pgrm->i_es_number
                                  * sizeof(es_descriptor_t *) );
Henri Fallon's avatar
 
Henri Fallon committed
418 419 420
        if( p_pgrm->pp_es == NULL )
        {
            intf_ErrMsg( "Unable to realloc memory in input_AddES" );
Henri Fallon's avatar
 
Henri Fallon committed
421
            return( NULL );
Henri Fallon's avatar
 
Henri Fallon committed
422
        }
423 424
        p_pgrm->pp_es[p_pgrm->i_es_number - 1] = p_es;
        p_es->p_pgrm = p_pgrm;
425 426 427
    }
    else
    {
428
        p_es->p_pgrm = NULL;
429 430 431 432 433 434 435 436
    }

    return p_es;
}

/*****************************************************************************
 * input_DelES:
 *****************************************************************************/
437
void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
438
{
439 440
    int                     i_index, i_es_index;
    pgrm_descriptor_t *     p_pgrm;
441

442 443 444 445 446
    ASSERT( p_es );
    p_pgrm = p_es->p_pgrm;

    /* Kill associated decoder, if any. */
    if( p_es->p_decoder_fifo != NULL )
447
    {
448
        input_EndDecoder( p_input, p_es );
449 450 451 452 453 454
    }

    /* Remove this ES from the description of the program if it is associated to
     * one */
    if( p_pgrm )
    {
455
        for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
456
        {
457
            if( p_pgrm->pp_es[i_index] == p_es )
458 459
            {
                p_pgrm->i_es_number--;
460
                p_pgrm->pp_es[i_index] = p_pgrm->pp_es[p_pgrm->i_es_number];
461 462
                p_pgrm->pp_es = realloc( p_pgrm->pp_es,
                                         p_pgrm->i_es_number
463
                                          * sizeof(es_descriptor_t *));
464
                if( p_pgrm->i_es_number && p_pgrm->pp_es == NULL )
Henri Fallon's avatar
 
Henri Fallon committed
465 466 467
                {
                    intf_ErrMsg( "Unable to realloc memory in input_DelES" );
                }
468 469 470 471 472
                break;
            }
        }
    }

473 474 475 476 477
    /* Free the demux data */
    if( p_es->p_demux_data != NULL )
    {
        free( p_es->p_demux_data );
    }
478

479 480 481 482 483 484 485 486
    /* Find the ES in the ES table */
    for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
         i_es_index++ )
    {
        if( p_input->stream.pp_es[i_es_index] == p_es )
            break;
    }

487 488
    /* Free the ES */
    free( p_es );
489 490 491 492 493 494
    p_input->stream.i_es_number--;
    p_input->stream.pp_es[i_es_index] =
                    p_input->stream.pp_es[p_input->stream.i_es_number];
    p_input->stream.pp_es = realloc( p_input->stream.pp_es,
                                     p_input->stream.i_es_number
                                      * sizeof(es_descriptor_t *));
495
    if( p_input->stream.i_es_number && p_input->stream.pp_es == NULL )
Henri Fallon's avatar
 
Henri Fallon committed
496 497 498 499
    {
        intf_ErrMsg( "Unable to realloc memory in input_DelES" );
    }
    
500 501 502 503 504 505 506 507
}

/*****************************************************************************
 * InitDecConfig: initializes a decoder_config_t
 *****************************************************************************/
static int InitDecConfig( input_thread_t * p_input, es_descriptor_t * p_es,
                          decoder_config_t * p_config )
{
508
    p_config->i_id = p_es->i_id;
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
    p_config->i_type = p_es->i_type;
    p_config->p_stream_ctrl =
        &p_input->stream.control;

    /* Decoder FIFO */
    if( (p_config->p_decoder_fifo =
            (decoder_fifo_t *)malloc( sizeof(decoder_fifo_t) )) == NULL )
    {
        intf_ErrMsg( "Out of memory" );
        return( -1 );
    }

    vlc_mutex_init(&p_config->p_decoder_fifo->data_lock);
    vlc_cond_init(&p_config->p_decoder_fifo->data_wait);
    p_config->p_decoder_fifo->i_start = p_config->p_decoder_fifo->i_end = 0;
524
    p_config->p_decoder_fifo->b_die = p_config->p_decoder_fifo->b_error = 0;
525
    p_config->p_decoder_fifo->p_packets_mgt = p_input->p_method_data;
Sam Hocevar's avatar
 
Sam Hocevar committed
526
    p_config->p_decoder_fifo->pf_delete_pes = p_input->pf_delete_pes;
527 528
    p_es->p_decoder_fifo = p_config->p_decoder_fifo;

529
    p_config->pf_init_bit_stream = p_input->pf_init_bit_stream;
530

531
    p_input->stream.i_selected_es_number++;
532

533 534 535 536 537 538 539 540 541 542 543 544
    p_input->stream.pp_selected_es = realloc(
                                       p_input->stream.pp_selected_es,
                                       p_input->stream.i_selected_es_number
                                        * sizeof(es_descriptor_t *) );
    if( p_input->stream.pp_selected_es == NULL )
    {
        intf_ErrMsg( "Unable to realloc memory in input_SelectES" );
        return(-1);
    }
    p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number - 1]
            = p_es;

545 546 547 548 549 550 551 552 553 554 555
    return( 0 );
}

/*****************************************************************************
 * GetVdecConfig: returns a valid vdec_config_t
 *****************************************************************************/
static vdec_config_t * GetVdecConfig( input_thread_t * p_input,
                                      es_descriptor_t * p_es )
{
    vdec_config_t *     p_config;

Henri Fallon's avatar
 
Henri Fallon committed
556 557
    p_config = (vdec_config_t *)malloc( sizeof(vdec_config_t) );
    if( p_config == NULL )
Henri Fallon's avatar
 
Henri Fallon committed
558 559
    {
        intf_ErrMsg( "Unable to allocate memory in GetVdecConfig" );
Henri Fallon's avatar
 
Henri Fallon committed
560
        return( NULL );
Henri Fallon's avatar
 
Henri Fallon committed
561
    }
562 563 564
    if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 )
    {
        free( p_config );
Henri Fallon's avatar
 
Henri Fallon committed
565
        return( NULL );
566 567 568 569 570 571 572 573 574 575 576 577 578
    }

    return( p_config );
}

/*****************************************************************************
 * GetAdecConfig: returns a valid adec_config_t
 *****************************************************************************/
static adec_config_t * GetAdecConfig( input_thread_t * p_input,
                                      es_descriptor_t * p_es )
{
    adec_config_t *     p_config;

Henri Fallon's avatar
 
Henri Fallon committed
579 580
    p_config = (adec_config_t *)malloc( sizeof(adec_config_t));
    if( p_config == NULL )
Henri Fallon's avatar
 
Henri Fallon committed
581 582
    {
        intf_ErrMsg( "Unable to allocate memory in GetAdecConfig" );
Henri Fallon's avatar
 
Henri Fallon committed
583
        return( NULL );
Henri Fallon's avatar
 
Henri Fallon committed
584
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
585

586 587 588
    if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 )
    {
        free( p_config );
Henri Fallon's avatar
 
Henri Fallon committed
589
        return( NULL );
590 591 592 593 594 595 596
    }

    return( p_config );
}

/*****************************************************************************
 * input_SelectES: selects an ES and spawns the associated decoder
597 598 599
 *****************************************************************************
 * Remember we are still supposed to have stream_lock when entering this
 * function ?
600
 *****************************************************************************/
601 602 603
/* FIXME */
vlc_thread_t adec_CreateThread( void * );
vlc_thread_t ac3dec_CreateThread( void * );
604 605
vlc_thread_t ac3spdif_CreateThread( void * );
vlc_thread_t spdif_CreateThread( void * );
606 607
vlc_thread_t vpar_CreateThread( void * );
vlc_thread_t spudec_CreateThread( void * );
608
vlc_thread_t lpcmdec_CreateThread( void * );
609

610 611
int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
{
612 613
    /* FIXME ! */
    decoder_capabilities_t  decoder;
614
    void *                  p_config;
615

616 617 618 619 620 621
    if( p_es == NULL )
    {
        intf_ErrMsg( "Nothing to do in input_SelectES" );
        return -1;
    }

622
#ifdef TRACE_INPUT
623
    intf_DbgMsg( "Selecting ES 0x%x", p_es->i_id );
624 625 626 627
#endif

    if( p_es->p_decoder_fifo != NULL )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
628
        intf_ErrMsg( "ES 0x%x is already selected", p_es->i_id );
629 630 631 632 633 634 635
        return( -1 );
    }

    switch( p_es->i_type )
    {
    case MPEG1_AUDIO_ES:
    case MPEG2_AUDIO_ES:
636 637
        if( p_main->b_audio )
        {
638
            decoder.pf_create_thread = adec_CreateThread;
639
            p_config = (void *)GetAdecConfig( p_input, p_es );
640
            p_main->b_ac3 = 0;
641 642 643 644 645 646

            /* Release the lock, not to block the input thread during
             * the creation of the thread. */
            vlc_mutex_unlock( &p_input->stream.stream_lock );
            p_es->thread_id = input_RunDecoder( &decoder, p_config );
            vlc_mutex_lock( &p_input->stream.stream_lock );
647
        }
648 649 650 651
        break;

    case MPEG1_VIDEO_ES:
    case MPEG2_VIDEO_ES:
652 653
        if( p_main->b_video )
        {
654
            decoder.pf_create_thread = vpar_CreateThread;
655 656 657 658 659 660 661
            p_config = (void *)GetVdecConfig( p_input, p_es );

            /* Release the lock, not to block the input thread during
             * the creation of the thread. */
            vlc_mutex_unlock( &p_input->stream.stream_lock );
            p_es->thread_id = input_RunDecoder( &decoder, p_config );
            vlc_mutex_lock( &p_input->stream.stream_lock );
662
        }
663 664
        break;

665
    case AC3_AUDIO_ES:
666 667
        if( p_main->b_audio )
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
668
            if( main_GetIntVariable( AOUT_SPDIF_VAR, 0 ) )
669
            {
Sam Hocevar's avatar
 
Sam Hocevar committed
670
                decoder.pf_create_thread = spdif_CreateThread;
671 672 673
            }
            else
            {
Sam Hocevar's avatar
 
Sam Hocevar committed
674
                decoder.pf_create_thread = ac3dec_CreateThread;
675 676
            }

677
            p_config = (void *)GetAdecConfig( p_input, p_es );
678
            p_main->b_ac3 = 1;
679 680 681 682 683 684

            /* Release the lock, not to block the input thread during
             * the creation of the thread. */
            vlc_mutex_unlock( &p_input->stream.stream_lock );
            p_es->thread_id = input_RunDecoder( &decoder, p_config );
            vlc_mutex_lock( &p_input->stream.stream_lock );
685
        }
686
        break;
687 688 689
    case LPCM_AUDIO_ES:
        if( p_main->b_audio )
        {
690
            decoder.pf_create_thread = lpcmdec_CreateThread;
691
            p_config = (void *)GetAdecConfig( p_input, p_es );
692
            p_main->b_ac3 = 0;
693

694 695 696 697 698 699 700
            /* Release the lock, not to block the input thread during
             * the creation of the thread. */
            vlc_mutex_unlock( &p_input->stream.stream_lock );
            p_es->thread_id = input_RunDecoder( &decoder, p_config );
            vlc_mutex_lock( &p_input->stream.stream_lock );
        }
        break;
701
    case DVD_SPU_ES:
702 703
        if( p_main->b_video )
        {
704
            decoder.pf_create_thread = spudec_CreateThread;
705 706 707 708 709 710 711
            p_config = (void *)GetVdecConfig( p_input, p_es );

            /* Release the lock, not to block the input thread during
             * the creation of the thread. */
            vlc_mutex_unlock( &p_input->stream.stream_lock );
            p_es->thread_id = input_RunDecoder( &decoder, p_config );
            vlc_mutex_lock( &p_input->stream.stream_lock );
712
        }
713 714
        break;

715
    default:
Sam Hocevar's avatar
 
Sam Hocevar committed
716
        intf_ErrMsg( "Unknown stream type 0x%x", p_es->i_type );
717 718 719 720
        return( -1 );
        break;
    }

Sam Hocevar's avatar
 
Sam Hocevar committed
721 722 723 724 725
    if( p_es->thread_id == 0 )
    {
        return( -1 );
    }

726
    return( 0 );
727
}
728 729

/*****************************************************************************
730
 * input_UnselectES: removes an ES from the list of selected ES
731
 *****************************************************************************/
732
int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
733 734 735 736
{

    int     i_index = 0;

737 738 739 740 741 742
    if( p_es == NULL )
    {
        intf_ErrMsg( "Nothing to do in input_UnselectES" );
        return -1;
    }

743
#ifdef TRACE_INPUT
744
    intf_DbgMsg( "Unselecting ES 0x%x", p_es->i_id );
745 746 747 748
#endif

    if( p_es->p_decoder_fifo == NULL )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
749
        intf_ErrMsg( "ES 0x%x is not selected", p_es->i_id );
750 751 752 753 754
        return( -1 );
    }

    input_EndDecoder( p_input, p_es );

755 756
    if( ( p_es->p_decoder_fifo == NULL ) &&
        ( p_input->stream.i_selected_es_number > 0 ) )
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
    {
        p_input->stream.i_selected_es_number--;

        while( ( i_index < p_input->stream.i_selected_es_number ) &&
               ( p_input->stream.pp_selected_es[i_index] != p_es ) )
        {
            i_index++;
        }

        p_input->stream.pp_selected_es[i_index] = 
          p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number];

        p_input->stream.pp_selected_es = realloc(
                                           p_input->stream.pp_selected_es,
                                           p_input->stream.i_selected_es_number
                                            * sizeof(es_descriptor_t *) );
773

774 775
        if( p_input->stream.pp_selected_es == NULL )
        {
776
#ifdef TRACE_INPUT
Stéphane Borel's avatar
Stéphane Borel committed
777 778
            intf_DbgMsg( "No more selected ES in input_UnselectES" );
#endif
779
            return( 1 );
780 781
        }
    }
782

783 784
    return( 0 );
}