input_programs.c 24.9 KB
Newer Older
1
2
3
/*****************************************************************************
 * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
 *****************************************************************************
4
5
 * Copyright (C) 1999-2002 VideoLAN
 * $Id: input_programs.c,v 1.88 2002/05/17 00:58:14 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

gbazin's avatar
   
gbazin committed
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

    /* Add an entry to the list of program associated with the stream */
    p_input->stream.i_pgrm_number++;
gbazin's avatar
   
gbazin committed
145
146
147
148
    p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
                                           p_input->stream.i_pgrm_number
                                           * sizeof(pgrm_descriptor_t *) );
    if( p_input->stream.pp_programs == NULL )
Henri Fallon's avatar
   
Henri Fallon committed
149
    {
gbazin's avatar
   
gbazin committed
150
        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
    }
gbazin's avatar
   
gbazin committed
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

gbazin's avatar
   
gbazin committed
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    /* 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;
    }

    /* If the program wasn't found, do nothing */
    if( i_pgrm_index == p_input->stream.i_pgrm_number )
    {
        intf_ErrMsg( "input error: program does not belong to this input" );
        return;
    }
219
220

    /* Free the structures that describe the es that belongs to that program */
221
    while( p_pgrm->i_es_number )
222
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
223
        input_DelES( p_input, p_pgrm->pp_es[0] );
224
225
    }

226
227
228
229
230
231
    /* Free the demux data */
    if( p_pgrm->p_demux_data != NULL )
    {
        free( p_pgrm->p_demux_data );
    }

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

235
236
    p_input->stream.pp_programs[i_pgrm_index] =
        p_input->stream.pp_programs[p_input->stream.i_pgrm_number];
gbazin's avatar
   
gbazin committed
237
    if( p_input->stream.i_pgrm_number ) 
238
239
240
241
242
243
244
245
246
247
248
    {
        p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
                                               p_input->stream.i_pgrm_number
                                               * sizeof(pgrm_descriptor_t *) );
        if( p_input->stream.pp_programs == NULL )
        {
            intf_ErrMsg( "input error: unable to realloc program list"
                         " in input_DelProgram" );
        }
    }
    else
Henri Fallon's avatar
   
Henri Fallon committed
249
    {
250
        free( p_input->stream.pp_programs );
gbazin's avatar
   
gbazin committed
251
        p_input->stream.pp_programs = NULL;
Henri Fallon's avatar
   
Henri Fallon committed
252
    }
253

254
255
256
257
    /* Free the description of this program */
    free( p_pgrm );
}

Stéphane Borel's avatar
   
Stéphane Borel committed
258
259
260
261
262
263
264
265
266
267
268
269
/*****************************************************************************
 * 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++;
gbazin's avatar
   
gbazin committed
270
271
272
273
    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 )
Stéphane Borel's avatar
   
Stéphane Borel committed
274
    {
gbazin's avatar
   
gbazin committed
275
        intf_ErrMsg( "Unable to realloc memory in input_AddArea" );
Stéphane Borel's avatar
   
Stéphane Borel committed
276
277
        return( NULL );
    }
gbazin's avatar
   
gbazin committed
278

Stéphane Borel's avatar
   
Stéphane Borel committed
279
280
281
282
283
284
285
286
287
288
289
290
291
292
    /* 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;
293
    p_input->stream.pp_areas[i_area_index]->i_seek = NO_SEEK;
294
    p_input->stream.pp_areas[i_area_index]->i_part_nb = 1;
Stéphane Borel's avatar
   
Stéphane Borel committed
295
296
297
298
299
    p_input->stream.pp_areas[i_area_index]->i_part= 0;

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

300
301
302
303
304
305
/*****************************************************************************
 * 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
306
307
308
309
310
    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
311
    if ( p_input->stream.p_selected_program )
312
    {
Johan Bilien's avatar
   
Johan Bilien committed
313
314
315
        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
316
317
                i_es_index ++ )
        {
Johan Bilien's avatar
   
Johan Bilien committed
318
#define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
319
            if ( p_es->p_decoder_fifo ) /* if the ES was selected */
Johan Bilien's avatar
   
Johan Bilien committed
320
            {
Johan Bilien's avatar
   
Johan Bilien committed
321
                input_UnselectES( p_input , p_es );
Johan Bilien's avatar
   
Johan Bilien committed
322
            }
Johan Bilien's avatar
   
Johan Bilien committed
323
#undef p_es
Johan Bilien's avatar
   
Johan Bilien committed
324
        }
Johan Bilien's avatar
   
Johan Bilien committed
325
326
327
328
329
    }
    /* Get the number of the required audio stream */
    if( p_main->b_audio )
    {
        /* Default is the first one */
330
        i_required_audio_es = config_GetIntVariable( "audio-channel" );
Johan Bilien's avatar
   
Johan Bilien committed
331
        if( i_required_audio_es < 0 )
Johan Bilien's avatar
   
Johan Bilien committed
332
        {
Johan Bilien's avatar
   
Johan Bilien committed
333
            i_required_audio_es = 1;
Johan Bilien's avatar
   
Johan Bilien committed
334
        }
Johan Bilien's avatar
   
Johan Bilien committed
335
336
337
338
339
    }
    else
    {
        i_required_audio_es = 0;
    }
Johan Bilien's avatar
   
Johan Bilien committed
340

Johan Bilien's avatar
   
Johan Bilien committed
341
342
343
344
    /* Same thing for subtitles */
    if( p_main->b_video )
    {
        /* for spu, default is none */
345
        i_required_spu_es = config_GetIntVariable( "spu-channel" );
Johan Bilien's avatar
   
Johan Bilien committed
346
        if( i_required_spu_es < 0 )
Johan Bilien's avatar
   
Johan Bilien committed
347
348
349
        {
            i_required_spu_es = 0;
        }
Johan Bilien's avatar
   
Johan Bilien committed
350
351
352
353
354
355
356
357
    }
    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
358
        switch( p_new_prg->pp_es[i_es_index]->i_cat )
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
        {
            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
389

390
    }
Johan Bilien's avatar
   
Johan Bilien committed
391

392
393
394
395
396
397
398

    p_input->stream.p_selected_program = p_new_prg;

    return( 0 );
}


Stéphane Borel's avatar
   
Stéphane Borel committed
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
/*****************************************************************************
 * 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;

    /* 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;
    }

gbazin's avatar
   
gbazin committed
416
417
418
419
420
421
422
    /* If the area wasn't found, do nothing */
    if( i_area_index == p_input->stream.i_area_nb )
    {
        intf_ErrMsg( "input error: area does not belong to this input" );
        return;
    }

Stéphane Borel's avatar
   
Stéphane Borel committed
423
424
425
426
427
    /* 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];
gbazin's avatar
   
gbazin committed
428
    if( p_input->stream.i_area_nb )
429
430
431
    {
        p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
                                            p_input->stream.i_area_nb
Stéphane Borel's avatar
   
Stéphane Borel committed
432
433
                                            * sizeof(input_area_t *) );

434
435
436
437
438
439
440
        if( p_input->stream.pp_areas == NULL )
        {
            intf_ErrMsg( "input error: unable to realloc area list"
                         " in input_DelArea" );
        }
    }
    else
Stéphane Borel's avatar
   
Stéphane Borel committed
441
    {
442
        free( p_input->stream.pp_areas );
gbazin's avatar
   
gbazin committed
443
        p_input->stream.pp_areas = NULL;
Stéphane Borel's avatar
   
Stéphane Borel committed
444
445
446
447
448
449
450
    }

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


451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
/*****************************************************************************
 * 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];
        }
    }

gbazin's avatar
   
gbazin committed
466
    return NULL;
467
468
469
470
471
472
473
474
475
476
}

/*****************************************************************************
 * 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,
477
478
                               pgrm_descriptor_t * p_pgrm, u16 i_es_id,
                               size_t i_data_len )
479
{
480
    es_descriptor_t * p_es;
481

482
    p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
Henri Fallon's avatar
   
Henri Fallon committed
483
484
485
    if( p_es == NULL )
    {
        intf_ErrMsg( "Unable to allocate memory in input_AddES" );
Henri Fallon's avatar
   
Henri Fallon committed
486
        return( NULL);
Henri Fallon's avatar
   
Henri Fallon committed
487
    }
488
    p_input->stream.i_es_number++;
gbazin's avatar
   
gbazin committed
489
490
491
492
    p_input->stream.pp_es = realloc( p_input->stream.pp_es,
                                     p_input->stream.i_es_number
                                      * sizeof(es_descriptor_t *) );
    if( p_input->stream.pp_es == NULL )
493
    {
gbazin's avatar
   
gbazin committed
494
        intf_ErrMsg( "Unable to realloc memory in input_AddES" );
Henri Fallon's avatar
   
Henri Fallon committed
495
        return( NULL );
Henri Fallon's avatar
   
Henri Fallon committed
496
    }
gbazin's avatar
   
gbazin committed
497

498
    p_input->stream.pp_es[p_input->stream.i_es_number - 1] = p_es;
499

500
    /* Init its values */
501
    p_es->i_id = i_es_id;
502
    p_es->psz_desc[0] = '\0';
503
504
    p_es->p_pes = NULL;
    p_es->p_decoder_fifo = NULL;
505
    p_es->b_audio = 0;
Stéphane Borel's avatar
Stéphane Borel committed
506
    p_es->i_cat = UNKNOWN_ES;
507
    p_es->i_demux_fd = 0;
508
509

    if( i_data_len )
510
    {
511
        p_es->p_demux_data = malloc( i_data_len );
Henri Fallon's avatar
   
Henri Fallon committed
512
513
514
        if( p_es->p_demux_data == NULL )
        {
            intf_ErrMsg( "Unable to allocate memory in input_AddES" );
Henri Fallon's avatar
   
Henri Fallon committed
515
            return( NULL );
Henri Fallon's avatar
   
Henri Fallon committed
516
        }
517
518
        memset( p_es->p_demux_data, 0, i_data_len );
    }
519
520
521
522
    else
    {
        p_es->p_demux_data = NULL;
    }
523
524
525
526
527

    /* Add this ES to the program definition if one is given */
    if( p_pgrm )
    {
        p_pgrm->i_es_number++;
gbazin's avatar
   
gbazin committed
528
529
530
531
        p_pgrm->pp_es = realloc( p_pgrm->pp_es,
                                 p_pgrm->i_es_number
                                  * sizeof(es_descriptor_t *) );
        if( p_pgrm->pp_es == NULL )
Henri Fallon's avatar
   
Henri Fallon committed
532
        {
gbazin's avatar
   
gbazin committed
533
            intf_ErrMsg( "Unable to realloc memory in input_AddES" );
Henri Fallon's avatar
   
Henri Fallon committed
534
            return( NULL );
Henri Fallon's avatar
   
Henri Fallon committed
535
        }
gbazin's avatar
   
gbazin committed
536

537
538
        p_pgrm->pp_es[p_pgrm->i_es_number - 1] = p_es;
        p_es->p_pgrm = p_pgrm;
539
540
541
    }
    else
    {
542
        p_es->p_pgrm = NULL;
543
544
545
546
547
548
549
550
    }

    return p_es;
}

/*****************************************************************************
 * input_DelES:
 *****************************************************************************/
551
void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
552
{
553
554
    int                     i_index, i_es_index;
    pgrm_descriptor_t *     p_pgrm;
555

gbazin's avatar
   
gbazin committed
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
    /* 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;
    }

    /* If the ES wasn't found, do nothing */
    if( i_es_index == p_input->stream.i_es_number )
    {
        intf_ErrMsg( "input error: ES does not belong to this input" );
        return;
    }

571
572
573
574
    p_pgrm = p_es->p_pgrm;

    /* Kill associated decoder, if any. */
    if( p_es->p_decoder_fifo != NULL )
575
    {
576
        input_EndDecoder( p_input, p_es );
577
578
579
580
581
582
    }

    /* Remove this ES from the description of the program if it is associated to
     * one */
    if( p_pgrm )
    {
583
        for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
584
        {
585
            if( p_pgrm->pp_es[i_index] == p_es )
586
587
            {
                p_pgrm->i_es_number--;
588
                p_pgrm->pp_es[i_index] = p_pgrm->pp_es[p_pgrm->i_es_number];
gbazin's avatar
   
gbazin committed
589
                if( p_pgrm->i_es_number )
590
591
592
593
594
595
596
597
598
599
600
                {
                    p_pgrm->pp_es = realloc( p_pgrm->pp_es,
                                             p_pgrm->i_es_number
                                              * sizeof(es_descriptor_t *));
                    if( p_pgrm->pp_es == NULL )
                    {
                        intf_ErrMsg( "Unable to realloc memory in "
                                     "input_DelES" );
                    }
                }
                else
Henri Fallon's avatar
   
Henri Fallon committed
601
                {
602
                    free( p_pgrm->pp_es );
gbazin's avatar
   
gbazin committed
603
                    p_pgrm->pp_es = NULL;
Henri Fallon's avatar
   
Henri Fallon committed
604
                }
605
606
607
608
609
                break;
            }
        }
    }

610
611
612
613
614
    /* Free the demux data */
    if( p_es->p_demux_data != NULL )
    {
        free( p_es->p_demux_data );
    }
615

gbazin's avatar
   
gbazin committed
616
    /* Remove this ES from the stream's list of ES */
617
618
619
    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];
gbazin's avatar
   
gbazin committed
620
    if( p_input->stream.i_es_number )
621
622
623
624
625
626
627
628
629
630
    {
        p_input->stream.pp_es = realloc( p_input->stream.pp_es,
                                         p_input->stream.i_es_number
                                          * sizeof(es_descriptor_t *));
        if( p_input->stream.pp_es == NULL )
        {
            intf_ErrMsg( "Unable to realloc memory in input_DelES" );
        }
    }
    else
Henri Fallon's avatar
   
Henri Fallon committed
631
    {
632
        free( p_input->stream.pp_es );
gbazin's avatar
   
gbazin committed
633
        p_input->stream.pp_es = NULL;
Henri Fallon's avatar
   
Henri Fallon committed
634
635
    }
    
gbazin's avatar
   
gbazin committed
636
637
    /* Free the ES */
    free( p_es );
638
639
640
641
}

/*****************************************************************************
 * input_SelectES: selects an ES and spawns the associated decoder
642
643
644
 *****************************************************************************
 * Remember we are still supposed to have stream_lock when entering this
 * function ?
645
646
647
 *****************************************************************************/
int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
{
648
649
    if( p_es == NULL )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
650
        intf_ErrMsg( "input error: nothing to do in input_SelectES" );
651
652
653
        return -1;
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
654
    intf_WarnMsg( 4, "input: selecting ES 0x%x", p_es->i_id );
655
656
657

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

gbazin's avatar
   
gbazin committed
662
663
    p_es->thread_id = 0;

664
665
    switch( p_es->i_type )
    {
Henri Fallon's avatar
   
Henri Fallon committed
666
    case AC3_AUDIO_ES:
667
668
    case MPEG1_AUDIO_ES:
    case MPEG2_AUDIO_ES:
Henri Fallon's avatar
   
Henri Fallon committed
669
    case LPCM_AUDIO_ES:
670
671
        if( p_main->b_audio )
        {
672
673
674
            /* 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
675
            p_es->thread_id = input_RunDecoder( p_input, p_es );
676
            vlc_mutex_lock( &p_input->stream.stream_lock );
677
        }
678
679
680
681
        break;

    case MPEG1_VIDEO_ES:
    case MPEG2_VIDEO_ES:
682
    case MPEG4_VIDEO_ES:
683
684
685
    case MSMPEG4v1_VIDEO_ES:
    case MSMPEG4v2_VIDEO_ES:
    case MSMPEG4v3_VIDEO_ES:
686
    case DVD_SPU_ES:
687
688
        if( p_main->b_video )
        {
689
690
691
            /* 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
692
            p_es->thread_id = input_RunDecoder( p_input, p_es );
693
            vlc_mutex_lock( &p_input->stream.stream_lock );
694
        }
695
696
        break;

697
    default:
Sam Hocevar's avatar
   
Sam Hocevar committed
698
        intf_ErrMsg( "Unknown stream type 0x%x", p_es->i_type );
699
700
701
702
        return( -1 );
        break;
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
703
704
705
706
707
    if( p_es->thread_id == 0 )
    {
        return( -1 );
    }

708
    return( 0 );
709
}
710
711

/*****************************************************************************
712
 * input_UnselectES: removes an ES from the list of selected ES
713
 *****************************************************************************/
714
int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
715
716
717
718
{

    int     i_index = 0;

719
720
721
722
723
724
    if( p_es == NULL )
    {
        intf_ErrMsg( "Nothing to do in input_UnselectES" );
        return -1;
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
725
    intf_WarnMsg( 4, "input: unselecting ES 0x%x", p_es->i_id );
726
727
728

    if( p_es->p_decoder_fifo == NULL )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
729
        intf_ErrMsg( "ES 0x%x is not selected", p_es->i_id );
730
731
732
733
        return( -1 );
    }

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

736
737
    if( ( p_es->p_decoder_fifo == NULL ) &&
        ( p_input->stream.i_selected_es_number > 0 ) )
738
739
740
741
742
743
744
745
746
747
748
749
    {
        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];

gbazin's avatar
   
gbazin committed
750
        if( p_input->stream.i_selected_es_number )
751
752
        {
            p_input->stream.pp_selected_es = realloc(
753
754
                                           p_input->stream.pp_selected_es,
                                           p_input->stream.i_selected_es_number
755
756
757
758
759
760
761
762
                                           * sizeof(es_descriptor_t *) );
            if( p_input->stream.pp_selected_es == NULL )
            {
                intf_ErrMsg( "Unable to realloc memory in input_UnselectES" );
                return( -1 );
            }
        }
        else
763
        {
764
            free( p_input->stream.pp_selected_es );   
gbazin's avatar
   
gbazin committed
765
            p_input->stream.pp_selected_es = NULL;
766
            intf_WarnMsg( 4, "input: no more selected ES in input_UnselectES" );            return( 1 );
767
768
        }
    }
769

770
771
    return( 0 );
}