input_programs.c 23.3 KB
Newer Older
1
2
3
/*****************************************************************************
 * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
 *****************************************************************************
4
 * Copyright (C) 1999-2001 VideoLAN
5
 * $Id: input_programs.c,v 1.83 2002/04/25 21:52:42 sam 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
#include <stdlib.h>
Sam Hocevar's avatar
   
Sam Hocevar committed
28
#include <string.h>                                    /* memcpy(), memset() */
Sam Hocevar's avatar
   
Sam Hocevar committed
29
#include <sys/types.h>                                              /* off_t */
30

Sam Hocevar's avatar
   
Sam Hocevar committed
31
#include <videolan/vlc.h>
32
33
34
35

#include "stream_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"
36
#include "input_ext-plugins.h"
37
38
39
40
41

/*
 * NOTICE : all of these functions expect you to have taken the lock on
 * p_input->stream.lock
 */
42
43
44
45

/*****************************************************************************
 * input_InitStream: init the stream descriptor of the given input
 *****************************************************************************/
46
int input_InitStream( input_thread_t * p_input, size_t i_data_len )
47
{
48

49
    p_input->stream.i_stream_id = 0;
50
51
52
53

    /* 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;
54
55
    p_input->stream.pp_es = NULL;
    p_input->stream.pp_selected_es = NULL;
56
57
    p_input->stream.p_removed_es = NULL;
    p_input->stream.p_newly_selected_es = NULL;
58
    p_input->stream.pp_programs = NULL;
59
60
61
    p_input->stream.p_selected_program = NULL;
    p_input->stream.p_new_program = NULL;
    
62
63
    if( i_data_len )
    {
Henri Fallon's avatar
   
Henri Fallon committed
64
65
66
        if ( (p_input->stream.p_demux_data = malloc( i_data_len )) == NULL )
        {
            intf_ErrMsg( "Unable to allocate memory in input_InitStream");
67
            return 1;
Henri Fallon's avatar
   
Henri Fallon committed
68
        }
69
70
        memset( p_input->stream.p_demux_data, 0, i_data_len );
    }
71
72
73
74
    else
    {
        p_input->stream.p_demux_data = NULL;
    }
75
76

    return 0;
77
78
}

79
80
81
82
83
/*****************************************************************************
 * input_EndStream: free all stream descriptors
 *****************************************************************************/
void input_EndStream( input_thread_t * p_input )
{
84
    /* Free all programs and associated ES, and associated decoders. */
85
    while( p_input->stream.i_pgrm_number )
86
    {
87
88
        input_DelProgram( p_input, p_input->stream.pp_programs[0] );
    }
89

90
    /* Free standalone ES */
91
    while( p_input->stream.i_es_number )
92
93
94
    {
        input_DelES( p_input, p_input->stream.pp_es[0] );
    }
95

96
97
98
99
100
101
    /* Free all areas */
    while( p_input->stream.i_area_nb )
    {
        input_DelArea( p_input, p_input->stream.pp_areas[0] );
    }

102
103
104
105
106
107
    /* Free selected ES */
    if( p_input->stream.pp_selected_es != NULL )
    {
        free( p_input->stream.pp_selected_es );
    }
    
108
109
110
111
    if( p_input->stream.p_demux_data != NULL )
    {
        free( p_input->stream.p_demux_data );
    }
112
113
114
115
116
117
118
119
120
121
122
123
}

/*****************************************************************************
 * 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 )
124
        {
125
            return p_input->stream.pp_programs[i];
126
127
        }
    }
128
129

    return( NULL );
130
131
}

132
133
134
135
136
137
/*****************************************************************************
 * 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,
138
                                      u16 i_pgrm_id, size_t i_data_len )
139
{
140
141
    /* Where to add the pgrm */
    int i_pgrm_index = p_input->stream.i_pgrm_number;
142
143
144
145
146
147

    /* 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
148
149
150
    if( p_input->stream.pp_programs == NULL )
    {
        intf_ErrMsg( "Unable to realloc memory in input_AddProgram" );
Henri Fallon's avatar
   
Henri Fallon committed
151
        return( NULL );
Henri Fallon's avatar
   
Henri Fallon committed
152
153
    }
    
154
155
156
    /* 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
157
158
159
    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
160
        return( NULL );
Henri Fallon's avatar
   
Henri Fallon committed
161
162
    }
    
163
164
165
    /* 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;
166
    p_input->stream.pp_programs[i_pgrm_index]->i_version = 0;
167
168
169
170

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

171
172
    input_ClockInit( p_input->stream.pp_programs[i_pgrm_index] );

173
    p_input->stream.pp_programs[i_pgrm_index]->i_synchro_state
174
                                                = SYNCHRO_START;
175

176
177
178
179
    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
180
181
182
        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
183
            return( NULL );
Henri Fallon's avatar
   
Henri Fallon committed
184
        }
185
186
187
        memset( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data, 0,
                i_data_len );
    }
188
189
190
191
    else
    {
        p_input->stream.pp_programs[i_pgrm_index]->p_demux_data = NULL;
    }
192

193
194
195
196
197
198
199
200
    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.
 *****************************************************************************/
201
void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
202
{
203
    int i_pgrm_index;
204

205
    ASSERT( p_pgrm );
206
207

    /* Free the structures that describe the es that belongs to that program */
208
    while( p_pgrm->i_es_number )
209
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
210
        input_DelES( p_input, p_pgrm->pp_es[0] );
211
212
    }

213
214
215
216
217
218
    /* Free the demux data */
    if( p_pgrm->p_demux_data != NULL )
    {
        free( p_pgrm->p_demux_data );
    }

219
220
221
222
223
224
225
    /* 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;
    }
226
227
228

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

230
231
232
233
234
    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 *) );
235

236
    if( p_input->stream.i_pgrm_number && p_input->stream.pp_programs == NULL)
Henri Fallon's avatar
   
Henri Fallon committed
237
    {
238
239
        intf_ErrMsg( "input error: unable to realloc program list"
                     " in input_DelProgram" );
Henri Fallon's avatar
   
Henri Fallon committed
240
    }
241

242
243
244
245
    /* Free the description of this program */
    free( p_pgrm );
}

Stéphane Borel's avatar
   
Stéphane Borel committed
246
247
248
249
250
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
/*****************************************************************************
 * 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;

    /* 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;
281
    p_input->stream.pp_areas[i_area_index]->i_seek = NO_SEEK;
282
    p_input->stream.pp_areas[i_area_index]->i_part_nb = 1;
Stéphane Borel's avatar
   
Stéphane Borel committed
283
284
285
286
287
    p_input->stream.pp_areas[i_area_index]->i_part= 0;

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

288
289
290
291
292
293
/*****************************************************************************
 * input_SetProgram: changes the current program
 *****************************************************************************/
int input_SetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_new_prg )
{
    int i_es_index;
Johan Bilien's avatar
   
Johan Bilien committed
294
295
296
297
298
    int i_required_audio_es;
    int i_required_spu_es;
    int i_audio_es = 0;
    int i_spu_es = 0;

Johan Bilien's avatar
   
Johan Bilien committed
299
    if ( p_input->stream.p_selected_program )
300
    {
Johan Bilien's avatar
   
Johan Bilien committed
301
302
303
        for ( i_es_index = 1 ; /* 0 should be the PMT */
                i_es_index < p_input->stream.p_selected_program->
                i_es_number ;
Johan Bilien's avatar
   
Johan Bilien committed
304
305
                i_es_index ++ )
        {
Johan Bilien's avatar
   
Johan Bilien committed
306
#define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
307
            if ( p_es->p_decoder_fifo ) /* if the ES was selected */
Johan Bilien's avatar
   
Johan Bilien committed
308
            {
Johan Bilien's avatar
   
Johan Bilien committed
309
                input_UnselectES( p_input , p_es );
Johan Bilien's avatar
   
Johan Bilien committed
310
            }
Johan Bilien's avatar
   
Johan Bilien committed
311
#undef p_es
Johan Bilien's avatar
   
Johan Bilien committed
312
        }
Johan Bilien's avatar
   
Johan Bilien committed
313
314
315
316
317
    }
    /* Get the number of the required audio stream */
    if( p_main->b_audio )
    {
        /* Default is the first one */
318
        i_required_audio_es = config_GetIntVariable( "audio-channel" );
Johan Bilien's avatar
   
Johan Bilien committed
319
        if( i_required_audio_es < 0 )
Johan Bilien's avatar
   
Johan Bilien committed
320
        {
Johan Bilien's avatar
   
Johan Bilien committed
321
            i_required_audio_es = 1;
Johan Bilien's avatar
   
Johan Bilien committed
322
        }
Johan Bilien's avatar
   
Johan Bilien committed
323
324
325
326
327
    }
    else
    {
        i_required_audio_es = 0;
    }
Johan Bilien's avatar
   
Johan Bilien committed
328

Johan Bilien's avatar
   
Johan Bilien committed
329
330
331
332
    /* Same thing for subtitles */
    if( p_main->b_video )
    {
        /* for spu, default is none */
333
        i_required_spu_es = config_GetIntVariable( "spu-channel" );
Johan Bilien's avatar
   
Johan Bilien committed
334
        if( i_required_spu_es < 0 )
Johan Bilien's avatar
   
Johan Bilien committed
335
336
337
        {
            i_required_spu_es = 0;
        }
Johan Bilien's avatar
   
Johan Bilien committed
338
339
340
341
342
343
344
345
    }
    else
    {
        i_required_spu_es = 0;
    }

    for (i_es_index = 0 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
    {
Johan Bilien's avatar
   
Johan Bilien committed
346
        switch( p_new_prg->pp_es[i_es_index]->i_cat )
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
        {
            case VIDEO_ES:
                intf_WarnMsg( 4, "Selecting ES %x",
                            p_new_prg->pp_es[i_es_index]->i_id );
                input_SelectES( p_input, p_new_prg->pp_es[i_es_index] );
                break;
            case AUDIO_ES:
                i_audio_es += 1;
                if( i_audio_es <= i_required_audio_es )
                {
                    intf_WarnMsg( 4, "Selecting ES %x",
                                p_new_prg->pp_es[i_es_index]->i_id );
                    input_SelectES( p_input, p_new_prg->pp_es[i_es_index]);
                }
                break;
            /* Not sure this one is fully specification-compliant */
            case SPU_ES :
                i_spu_es += 1;
                if( i_spu_es <= i_required_spu_es )
                {
                    intf_WarnMsg( 4, "Selecting ES %x",
                                p_new_prg->pp_es[i_es_index]->i_id );
                    input_SelectES( p_input, p_new_prg->pp_es[i_es_index] );
                }
            break;
            default :
                intf_WarnMsg( 2, "ES %x has unknown type",
                            p_new_prg->pp_es[i_es_index]->i_id );
                break;
        }
Johan Bilien's avatar
   
Johan Bilien committed
377

378
    }
Johan Bilien's avatar
   
Johan Bilien committed
379

380
381
382
383
384
385
386

    p_input->stream.p_selected_program = p_new_prg;

    return( 0 );
}


Stéphane Borel's avatar
   
Stéphane Borel committed
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
/*****************************************************************************
 * 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 );

    /* 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"
418
                     " in input_DelArea" );
Stéphane Borel's avatar
   
Stéphane Borel committed
419
420
421
422
423
424
425
    }

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


426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
/*****************************************************************************
 * 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 );
442
443
444
445
446
447
448
449
450
451
}

/*****************************************************************************
 * 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,
452
453
                               pgrm_descriptor_t * p_pgrm, u16 i_es_id,
                               size_t i_data_len )
454
{
455
    es_descriptor_t * p_es;
456

457
    p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
Henri Fallon's avatar
   
Henri Fallon committed
458
459
460
    if( p_es == NULL )
    {
        intf_ErrMsg( "Unable to allocate memory in input_AddES" );
Henri Fallon's avatar
   
Henri Fallon committed
461
        return( NULL);
Henri Fallon's avatar
   
Henri Fallon committed
462
    }
463
464
465
466
    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
467
468
469
    if( p_input->stream.pp_es == NULL )
    {
        intf_ErrMsg( "Unable to realloc memory in input_AddES" );
Henri Fallon's avatar
   
Henri Fallon committed
470
        return( NULL );
Henri Fallon's avatar
   
Henri Fallon committed
471
    }
472
    p_input->stream.pp_es[p_input->stream.i_es_number - 1] = p_es;
473

474
    /* Init its values */
475
    p_es->i_id = i_es_id;
476
    p_es->psz_desc[0] = '\0';
477
478
    p_es->p_pes = NULL;
    p_es->p_decoder_fifo = NULL;
479
    p_es->b_audio = 0;
Stéphane Borel's avatar
Stéphane Borel committed
480
    p_es->i_cat = UNKNOWN_ES;
481
    p_es->i_demux_fd = 0;
482
483

    if( i_data_len )
484
    {
485
        p_es->p_demux_data = malloc( i_data_len );
Henri Fallon's avatar
   
Henri Fallon committed
486
487
488
        if( p_es->p_demux_data == NULL )
        {
            intf_ErrMsg( "Unable to allocate memory in input_AddES" );
Henri Fallon's avatar
   
Henri Fallon committed
489
            return( NULL );
Henri Fallon's avatar
   
Henri Fallon committed
490
        }
491
492
        memset( p_es->p_demux_data, 0, i_data_len );
    }
493
494
495
496
    else
    {
        p_es->p_demux_data = NULL;
    }
497
498
499
500
501
502
503
504

    /* 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
505
506
507
        if( p_pgrm->pp_es == NULL )
        {
            intf_ErrMsg( "Unable to realloc memory in input_AddES" );
Henri Fallon's avatar
   
Henri Fallon committed
508
            return( NULL );
Henri Fallon's avatar
   
Henri Fallon committed
509
        }
510
511
        p_pgrm->pp_es[p_pgrm->i_es_number - 1] = p_es;
        p_es->p_pgrm = p_pgrm;
512
513
514
    }
    else
    {
515
        p_es->p_pgrm = NULL;
516
517
518
519
520
521
522
523
    }

    return p_es;
}

/*****************************************************************************
 * input_DelES:
 *****************************************************************************/
524
void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
525
{
526
527
    int                     i_index, i_es_index;
    pgrm_descriptor_t *     p_pgrm;
528

529
530
531
532
533
    ASSERT( p_es );
    p_pgrm = p_es->p_pgrm;

    /* Kill associated decoder, if any. */
    if( p_es->p_decoder_fifo != NULL )
534
    {
535
        input_EndDecoder( p_input, p_es );
536
537
538
539
540
541
    }

    /* Remove this ES from the description of the program if it is associated to
     * one */
    if( p_pgrm )
    {
542
        for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
543
        {
544
            if( p_pgrm->pp_es[i_index] == p_es )
545
546
            {
                p_pgrm->i_es_number--;
547
                p_pgrm->pp_es[i_index] = p_pgrm->pp_es[p_pgrm->i_es_number];
548
549
                p_pgrm->pp_es = realloc( p_pgrm->pp_es,
                                         p_pgrm->i_es_number
550
                                          * sizeof(es_descriptor_t *));
551
                if( p_pgrm->i_es_number && p_pgrm->pp_es == NULL )
Henri Fallon's avatar
   
Henri Fallon committed
552
553
554
                {
                    intf_ErrMsg( "Unable to realloc memory in input_DelES" );
                }
555
556
557
558
559
                break;
            }
        }
    }

560
561
562
563
564
    /* Free the demux data */
    if( p_es->p_demux_data != NULL )
    {
        free( p_es->p_demux_data );
    }
565

566
567
568
569
570
571
572
573
    /* 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;
    }

574
575
    /* Free the ES */
    free( p_es );
576
577
578
579
580
581
    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 *));
582
    if( p_input->stream.i_es_number && p_input->stream.pp_es == NULL )
Henri Fallon's avatar
   
Henri Fallon committed
583
584
585
586
    {
        intf_ErrMsg( "Unable to realloc memory in input_DelES" );
    }
    
587
588
589
590
}

/*****************************************************************************
 * input_SelectES: selects an ES and spawns the associated decoder
591
592
593
 *****************************************************************************
 * Remember we are still supposed to have stream_lock when entering this
 * function ?
594
595
596
 *****************************************************************************/
int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
{
597
598
    if( p_es == NULL )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
599
        intf_ErrMsg( "input error: nothing to do in input_SelectES" );
600
601
602
        return -1;
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
603
    intf_WarnMsg( 4, "input: selecting ES 0x%x", p_es->i_id );
604
605
606

    if( p_es->p_decoder_fifo != NULL )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
607
        intf_ErrMsg( "ES 0x%x is already selected", p_es->i_id );
608
609
610
        return( -1 );
    }

gbazin's avatar
   
gbazin committed
611
612
    p_es->thread_id = 0;

613
614
    switch( p_es->i_type )
    {
Henri Fallon's avatar
   
Henri Fallon committed
615
    case AC3_AUDIO_ES:
616
617
    case MPEG1_AUDIO_ES:
    case MPEG2_AUDIO_ES:
618
619
    case MPEG4_VIDEO_ES:
    case MSMPEG4_VIDEO_ES:
Henri Fallon's avatar
   
Henri Fallon committed
620
    case LPCM_AUDIO_ES:
621
622
        if( p_main->b_audio )
        {
623
624
625
            /* Release the lock, not to block the input thread during
             * the creation of the thread. */
            vlc_mutex_unlock( &p_input->stream.stream_lock );
Sam Hocevar's avatar
   
Sam Hocevar committed
626
            p_es->thread_id = input_RunDecoder( p_input, p_es );
627
            vlc_mutex_lock( &p_input->stream.stream_lock );
628
        }
629
630
631
632
        break;

    case MPEG1_VIDEO_ES:
    case MPEG2_VIDEO_ES:
633
    case DVD_SPU_ES:
634
635
        if( p_main->b_video )
        {
636
637
638
            /* Release the lock, not to block the input thread during
             * the creation of the thread. */
            vlc_mutex_unlock( &p_input->stream.stream_lock );
Sam Hocevar's avatar
   
Sam Hocevar committed
639
            p_es->thread_id = input_RunDecoder( p_input, p_es );
640
            vlc_mutex_lock( &p_input->stream.stream_lock );
641
        }
642
643
        break;

644
    default:
Sam Hocevar's avatar
   
Sam Hocevar committed
645
        intf_ErrMsg( "Unknown stream type 0x%x", p_es->i_type );
646
647
648
649
        return( -1 );
        break;
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
650
651
652
653
654
    if( p_es->thread_id == 0 )
    {
        return( -1 );
    }

655
    return( 0 );
656
}
657
658

/*****************************************************************************
659
 * input_UnselectES: removes an ES from the list of selected ES
660
 *****************************************************************************/
661
int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
662
663
664
665
{

    int     i_index = 0;

666
667
668
669
670
671
    if( p_es == NULL )
    {
        intf_ErrMsg( "Nothing to do in input_UnselectES" );
        return -1;
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
672
    intf_WarnMsg( 4, "input: unselecting ES 0x%x", p_es->i_id );
673
674
675

    if( p_es->p_decoder_fifo == NULL )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
676
        intf_ErrMsg( "ES 0x%x is not selected", p_es->i_id );
677
678
679
680
        return( -1 );
    }

    input_EndDecoder( p_input, p_es );
Johan Bilien's avatar
   
Johan Bilien committed
681
    p_es->p_pes = NULL;
682

683
684
    if( ( p_es->p_decoder_fifo == NULL ) &&
        ( p_input->stream.i_selected_es_number > 0 ) )
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
    {
        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 *) );
701

702
703
        if( p_input->stream.pp_selected_es == NULL )
        {
Sam Hocevar's avatar
   
Sam Hocevar committed
704
            intf_WarnMsg( 4, "input: no more selected ES in input_UnselectES" );
705
            return( 1 );
706
707
        }
    }
708

709
710
    return( 0 );
}