]> git.sesse.net Git - vlc/blob - src/input/input_programs.c
b4df05a0abfa816cc9b7efa7e57132c614fde217
[vlc] / src / input / input_programs.c
1 /*****************************************************************************
2  * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  * $Id: input_programs.c,v 1.58 2001/06/12 18:16:49 stef Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "defs.h"
28
29 #include <stdlib.h>
30 #include <string.h>                                    /* memcpy(), memset() */
31 #include <sys/types.h>                                              /* off_t */
32
33 #include "config.h"
34 #include "common.h"
35 #include "threads.h"
36 #include "mtime.h"
37 #include "debug.h"
38
39 #include "intf_msg.h"
40
41 #include "stream_control.h"
42 #include "input_ext-intf.h"
43 #include "input_ext-dec.h"
44 #include "input.h"
45
46 #include "main.h"                                     /* --noaudio --novideo */
47
48 /*
49  * NOTICE : all of these functions expect you to have taken the lock on
50  * p_input->stream.lock
51  */
52
53 /*****************************************************************************
54  * input_InitStream: init the stream descriptor of the given input
55  *****************************************************************************/
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     /* initialized to 0 since we don't give the signal to the interface
63      * before the end of input initialization */
64     p_input->stream.b_changed = 0;
65     p_input->stream.pp_es = NULL;
66     p_input->stream.pp_selected_es = NULL;
67     p_input->stream.p_removed_es = NULL;
68     p_input->stream.p_newly_selected_es = NULL;
69     p_input->stream.pp_programs = NULL;
70
71     if( i_data_len )
72     {
73         if ( (p_input->stream.p_demux_data = malloc( i_data_len )) == NULL )
74         {
75             intf_ErrMsg( "Unable to allocate memory in input_InitStream");
76             return 1;
77         }
78         memset( p_input->stream.p_demux_data, 0, i_data_len );
79     }
80
81     return 0;
82 }
83
84 /*****************************************************************************
85  * input_EndStream: free all stream descriptors
86  *****************************************************************************/
87 void input_EndStream( input_thread_t * p_input )
88 {
89     /* Free all programs and associated ES, and associated decoders. */
90     while( p_input->stream.i_pgrm_number )
91     {
92         input_DelProgram( p_input, p_input->stream.pp_programs[0] );
93     }
94
95     /* Free standalone ES */
96     while( p_input->stream.i_es_number )
97     {
98         input_DelES( p_input, p_input->stream.pp_es[0] );
99     }
100
101     /* Free all areas */
102     while( p_input->stream.i_area_nb )
103     {
104         input_DelArea( p_input, p_input->stream.pp_areas[0] );
105     }
106
107     if( p_input->stream.p_demux_data != NULL )
108     {
109         free( p_input->stream.p_demux_data );
110     }
111 }
112
113 /*****************************************************************************
114  * input_FindProgram: returns a pointer to a program described by its ID
115  *****************************************************************************/
116 pgrm_descriptor_t * input_FindProgram( input_thread_t * p_input, u16 i_pgrm_id )
117 {
118     int     i;
119
120     for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
121     {
122         if( p_input->stream.pp_programs[i]->i_number == i_pgrm_id )
123         {
124             return p_input->stream.pp_programs[i];
125         }
126     }
127
128     return( NULL );
129 }
130
131 /*****************************************************************************
132  * input_AddProgram: add and init a program descriptor
133  *****************************************************************************
134  * This program descriptor will be referenced in the given stream descriptor
135  *****************************************************************************/
136 pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input,
137                                       u16 i_pgrm_id, size_t i_data_len )
138 {
139     /* Where to add the pgrm */
140     int i_pgrm_index = p_input->stream.i_pgrm_number;
141
142     intf_DbgMsg("Adding description for pgrm %d", i_pgrm_id);
143
144     /* Add an entry to the list of program associated with the stream */
145     p_input->stream.i_pgrm_number++;
146     p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
147                                            p_input->stream.i_pgrm_number
148                                             * sizeof(pgrm_descriptor_t *) );
149     if( p_input->stream.pp_programs == NULL )
150     {
151         intf_ErrMsg( "Unable to realloc memory in input_AddProgram" );
152         return( NULL );
153     }
154     
155     /* Allocate the structure to store this description */
156     p_input->stream.pp_programs[i_pgrm_index] =
157                                         malloc( sizeof(pgrm_descriptor_t) );
158     if( p_input->stream.pp_programs[i_pgrm_index] == NULL )
159     {
160         intf_ErrMsg( "Unable to allocate memory in input_AddProgram" );
161         return( NULL );
162     }
163     
164     /* Init this entry */
165     p_input->stream.pp_programs[i_pgrm_index]->i_number = i_pgrm_id;
166     p_input->stream.pp_programs[i_pgrm_index]->b_is_ok = 0;
167     p_input->stream.pp_programs[i_pgrm_index]->i_version = 0;
168
169     p_input->stream.pp_programs[i_pgrm_index]->i_es_number = 0;
170     p_input->stream.pp_programs[i_pgrm_index]->pp_es = NULL;
171
172     input_ClockInit( p_input->stream.pp_programs[i_pgrm_index] );
173
174     p_input->stream.pp_programs[i_pgrm_index]->i_synchro_state
175                                                 = SYNCHRO_START;
176
177     if( i_data_len )
178     {
179         p_input->stream.pp_programs[i_pgrm_index]->p_demux_data =
180             malloc( i_data_len );
181         if( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data == NULL )
182         {
183             intf_ErrMsg( "Unable to allocate memory in input_AddProgram" );
184             return( NULL );
185         }
186         memset( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data, 0,
187                 i_data_len );
188     }
189
190     return p_input->stream.pp_programs[i_pgrm_index];
191 }
192
193 /*****************************************************************************
194  * input_DelProgram: destroy a program descriptor
195  *****************************************************************************
196  * All ES descriptions referenced in the descriptor will be deleted.
197  *****************************************************************************/
198 void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
199 {
200     int i_pgrm_index;
201
202     ASSERT( p_pgrm );
203
204     intf_DbgMsg("Deleting description for pgrm %d", p_pgrm->i_number);
205
206     /* Free the structures that describe the es that belongs to that program */
207     while( p_pgrm->i_es_number )
208     {
209         input_DelES( p_input, p_pgrm->pp_es[0] );
210     }
211
212     /* Free the demux data */
213     if( p_pgrm->p_demux_data != NULL )
214     {
215         free( p_pgrm->p_demux_data );
216     }
217
218     /* Find the program in the programs table */
219     for( i_pgrm_index = 0; i_pgrm_index < p_input->stream.i_pgrm_number;
220          i_pgrm_index++ )
221     {
222         if( p_input->stream.pp_programs[i_pgrm_index] == p_pgrm )
223             break;
224     }
225
226     /* Remove this program from the stream's list of programs */
227     p_input->stream.i_pgrm_number--;
228
229     p_input->stream.pp_programs[i_pgrm_index] =
230         p_input->stream.pp_programs[p_input->stream.i_pgrm_number];
231     p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
232                                            p_input->stream.i_pgrm_number
233                                             * sizeof(pgrm_descriptor_t *) );
234
235     if( p_input->stream.i_pgrm_number && p_input->stream.pp_programs == NULL)
236     {
237         intf_ErrMsg( "input error: unable to realloc program list"
238                      " in input_DelProgram" );
239     }
240
241     /* Free the description of this program */
242     free( p_pgrm );
243 }
244
245 /*****************************************************************************
246  * input_AddArea: add and init an area descriptor
247  *****************************************************************************
248  * This area descriptor will be referenced in the given stream descriptor
249  *****************************************************************************/
250 input_area_t * input_AddArea( input_thread_t * p_input )
251 {
252     /* Where to add the pgrm */
253     int i_area_index = p_input->stream.i_area_nb;
254
255     intf_DbgMsg("Adding description for area %d", i_area_index );
256
257     /* Add an entry to the list of program associated with the stream */
258     p_input->stream.i_area_nb++;
259     p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
260                                         p_input->stream.i_area_nb
261                                             * sizeof(input_area_t *) );
262     if( p_input->stream.pp_areas == NULL )
263     {
264         intf_ErrMsg( "Unable to realloc memory in input_AddArea" );
265         return( NULL );
266     }
267     
268     /* Allocate the structure to store this description */
269     p_input->stream.pp_areas[i_area_index] =
270                                         malloc( sizeof(input_area_t) );
271     if( p_input->stream.pp_areas[i_area_index] == NULL )
272     {
273         intf_ErrMsg( "Unable to allocate memory in input_AddArea" );
274         return( NULL );
275     }
276     
277     /* Init this entry */
278     p_input->stream.pp_areas[i_area_index]->i_id = 0;
279     p_input->stream.pp_areas[i_area_index]->i_start = 0;
280     p_input->stream.pp_areas[i_area_index]->i_size = 0;
281     p_input->stream.pp_areas[i_area_index]->i_tell = 0;
282     p_input->stream.pp_areas[i_area_index]->i_seek = NO_SEEK;
283     p_input->stream.pp_areas[i_area_index]->i_part_nb = 1;
284     p_input->stream.pp_areas[i_area_index]->i_part= 0;
285     p_input->stream.pp_areas[i_area_index]->i_angle_nb = 1;
286     p_input->stream.pp_areas[i_area_index]->i_angle = 0;
287
288     return p_input->stream.pp_areas[i_area_index];
289 }
290
291 /*****************************************************************************
292  * input_DelArea: destroy a area descriptor
293  *****************************************************************************
294  * All ES descriptions referenced in the descriptor will be deleted.
295  *****************************************************************************/
296 void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
297 {
298     int i_area_index;
299
300     ASSERT( p_area );
301
302     intf_DbgMsg("Deleting description for area %d", p_area->i_id );
303
304     /* Find the area in the areas table */
305     for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb;
306          i_area_index++ )
307     {
308         if( p_input->stream.pp_areas[i_area_index] == p_area )
309             break;
310     }
311
312     /* Remove this area from the stream's list of areas */
313     p_input->stream.i_area_nb--;
314
315     p_input->stream.pp_areas[i_area_index] =
316         p_input->stream.pp_areas[p_input->stream.i_area_nb];
317     p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
318                                            p_input->stream.i_area_nb
319                                             * sizeof(input_area_t *) );
320
321     if( p_input->stream.i_area_nb && p_input->stream.pp_areas == NULL)
322     {
323         intf_ErrMsg( "input error: unable to realloc area list"
324                      " in input_DelArea" );
325     }
326
327     /* Free the description of this area */
328     free( p_area );
329 }
330
331
332 /*****************************************************************************
333  * input_FindES: returns a pointer to an ES described by its ID
334  *****************************************************************************/
335 es_descriptor_t * input_FindES( input_thread_t * p_input, u16 i_es_id )
336 {
337     int     i;
338
339     for( i = 0; i < p_input->stream.i_es_number; i++ )
340     {
341         if( p_input->stream.pp_es[i]->i_id == i_es_id )
342         {
343             return p_input->stream.pp_es[i];
344         }
345     }
346
347     return( NULL );
348 }
349
350 /*****************************************************************************
351  * input_AddES:
352  *****************************************************************************
353  * Reserve a slot in the table of ES descriptors for the ES and add it to the
354  * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
355  * alone (PSI ?)
356  *****************************************************************************/
357 es_descriptor_t * input_AddES( input_thread_t * p_input,
358                                pgrm_descriptor_t * p_pgrm, u16 i_es_id,
359                                size_t i_data_len )
360 {
361     es_descriptor_t * p_es;
362
363     intf_DbgMsg("Adding description for ES 0x%x", i_es_id);
364
365     p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
366     if( p_es == NULL )
367     {
368         intf_ErrMsg( "Unable to allocate memory in input_AddES" );
369         return( NULL);
370     }
371     p_input->stream.i_es_number++;
372     p_input->stream.pp_es = realloc( p_input->stream.pp_es,
373                                      p_input->stream.i_es_number
374                                       * sizeof(es_descriptor_t *) );
375     if( p_input->stream.pp_es == NULL )
376     {
377         intf_ErrMsg( "Unable to realloc memory in input_AddES" );
378         return( NULL );
379     }
380     p_input->stream.pp_es[p_input->stream.i_es_number - 1] = p_es;
381
382     /* Init its values */
383     p_es->i_id = i_es_id;
384     p_es->psz_desc[0] = '\0';
385     p_es->p_pes = NULL;
386     p_es->p_decoder_fifo = NULL;
387     p_es->b_audio = 0;
388     p_es->i_cat = UNKNOWN_ES;
389
390     if( i_data_len )
391     {
392         p_es->p_demux_data = malloc( i_data_len );
393         if( p_es->p_demux_data == NULL )
394         {
395             intf_ErrMsg( "Unable to allocate memory in input_AddES" );
396             return( NULL );
397         }
398         memset( p_es->p_demux_data, 0, i_data_len );
399     }
400     else
401     {
402         p_es->p_demux_data = NULL;
403     }
404
405     /* Add this ES to the program definition if one is given */
406     if( p_pgrm )
407     {
408         p_pgrm->i_es_number++;
409         p_pgrm->pp_es = realloc( p_pgrm->pp_es,
410                                  p_pgrm->i_es_number
411                                   * sizeof(es_descriptor_t *) );
412         if( p_pgrm->pp_es == NULL )
413         {
414             intf_ErrMsg( "Unable to realloc memory in input_AddES" );
415             return( NULL );
416         }
417         p_pgrm->pp_es[p_pgrm->i_es_number - 1] = p_es;
418         p_es->p_pgrm = p_pgrm;
419     }
420     else
421     {
422         p_es->p_pgrm = NULL;
423     }
424
425     return p_es;
426 }
427
428 /*****************************************************************************
429  * input_DelES:
430  *****************************************************************************/
431 void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
432 {
433     int                     i_index, i_es_index;
434     pgrm_descriptor_t *     p_pgrm;
435
436     ASSERT( p_es );
437     p_pgrm = p_es->p_pgrm;
438
439     /* Kill associated decoder, if any. */
440     if( p_es->p_decoder_fifo != NULL )
441     {
442         input_EndDecoder( p_input, p_es );
443     }
444
445     /* Remove this ES from the description of the program if it is associated to
446      * one */
447     if( p_pgrm )
448     {
449         for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
450         {
451             if( p_pgrm->pp_es[i_index] == p_es )
452             {
453                 p_pgrm->i_es_number--;
454                 p_pgrm->pp_es[i_index] = p_pgrm->pp_es[p_pgrm->i_es_number];
455                 p_pgrm->pp_es = realloc( p_pgrm->pp_es,
456                                          p_pgrm->i_es_number
457                                           * sizeof(es_descriptor_t *));
458                 if( p_pgrm->i_es_number && p_pgrm->pp_es == NULL )
459                 {
460                     intf_ErrMsg( "Unable to realloc memory in input_DelES" );
461                 }
462                 break;
463             }
464         }
465     }
466
467     /* Free the demux data */
468     if( p_es->p_demux_data != NULL )
469     {
470         free( p_es->p_demux_data );
471     }
472
473     /* Find the ES in the ES table */
474     for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
475          i_es_index++ )
476     {
477         if( p_input->stream.pp_es[i_es_index] == p_es )
478             break;
479     }
480
481     /* Free the ES */
482     free( p_es );
483     p_input->stream.i_es_number--;
484     p_input->stream.pp_es[i_es_index] =
485                     p_input->stream.pp_es[p_input->stream.i_es_number];
486     p_input->stream.pp_es = realloc( p_input->stream.pp_es,
487                                      p_input->stream.i_es_number
488                                       * sizeof(es_descriptor_t *));
489     if( p_input->stream.i_es_number && p_input->stream.pp_es == NULL )
490     {
491         intf_ErrMsg( "Unable to realloc memory in input_DelES" );
492     }
493     
494 }
495
496 /*****************************************************************************
497  * InitDecConfig: initializes a decoder_config_t
498  *****************************************************************************/
499 static int InitDecConfig( input_thread_t * p_input, es_descriptor_t * p_es,
500                           decoder_config_t * p_config )
501 {
502     p_config->i_id = p_es->i_id;
503     p_config->i_type = p_es->i_type;
504     p_config->p_stream_ctrl =
505         &p_input->stream.control;
506
507     /* Decoder FIFO */
508     if( (p_config->p_decoder_fifo =
509             (decoder_fifo_t *)malloc( sizeof(decoder_fifo_t) )) == NULL )
510     {
511         intf_ErrMsg( "Out of memory" );
512         return( -1 );
513     }
514
515     vlc_mutex_init(&p_config->p_decoder_fifo->data_lock);
516     vlc_cond_init(&p_config->p_decoder_fifo->data_wait);
517     p_config->p_decoder_fifo->i_start = p_config->p_decoder_fifo->i_end = 0;
518     p_config->p_decoder_fifo->b_die = p_config->p_decoder_fifo->b_error = 0;
519     p_config->p_decoder_fifo->p_packets_mgt = p_input->p_method_data;
520     p_config->p_decoder_fifo->pf_delete_pes = p_input->pf_delete_pes;
521     p_es->p_decoder_fifo = p_config->p_decoder_fifo;
522
523     p_config->pf_init_bit_stream = InitBitstream;
524
525     p_input->stream.i_selected_es_number++;
526
527     p_input->stream.pp_selected_es = realloc(
528                                        p_input->stream.pp_selected_es,
529                                        p_input->stream.i_selected_es_number
530                                         * sizeof(es_descriptor_t *) );
531     if( p_input->stream.pp_selected_es == NULL )
532     {
533         intf_ErrMsg( "Unable to realloc memory in input_SelectES" );
534         return(-1);
535     }
536     p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number - 1]
537             = p_es;
538
539     return( 0 );
540 }
541
542 /*****************************************************************************
543  * GetVdecConfig: returns a valid vdec_config_t
544  *****************************************************************************/
545 static vdec_config_t * GetVdecConfig( input_thread_t * p_input,
546                                       es_descriptor_t * p_es )
547 {
548     vdec_config_t *     p_config;
549
550     p_config = (vdec_config_t *)malloc( sizeof(vdec_config_t) );
551     if( p_config == NULL )
552     {
553         intf_ErrMsg( "Unable to allocate memory in GetVdecConfig" );
554         return( NULL );
555     }
556     if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 )
557     {
558         free( p_config );
559         return( NULL );
560     }
561
562     return( p_config );
563 }
564
565 /*****************************************************************************
566  * GetAdecConfig: returns a valid adec_config_t
567  *****************************************************************************/
568 static adec_config_t * GetAdecConfig( input_thread_t * p_input,
569                                       es_descriptor_t * p_es )
570 {
571     adec_config_t *     p_config;
572
573     p_config = (adec_config_t *)malloc( sizeof(adec_config_t));
574     if( p_config == NULL )
575     {
576         intf_ErrMsg( "Unable to allocate memory in GetAdecConfig" );
577         return( NULL );
578     }
579
580     if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 )
581     {
582         free( p_config );
583         return( NULL );
584     }
585
586     return( p_config );
587 }
588
589 /*****************************************************************************
590  * input_SelectES: selects an ES and spawns the associated decoder
591  *****************************************************************************
592  * Remember we are still supposed to have stream_lock when entering this
593  * function ?
594  *****************************************************************************/
595 /* FIXME */
596 vlc_thread_t adec_CreateThread( void * );
597 vlc_thread_t ac3dec_CreateThread( void * );
598 vlc_thread_t ac3spdif_CreateThread( void * );
599 vlc_thread_t spdif_CreateThread( void * );
600 vlc_thread_t vpar_CreateThread( void * );
601 vlc_thread_t spudec_CreateThread( void * );
602 vlc_thread_t lpcmdec_CreateThread( void * );
603
604 int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
605 {
606     /* FIXME ! */
607     decoder_capabilities_t  decoder;
608     void *                  p_config;
609
610     if( p_es == NULL )
611     {
612         intf_ErrMsg( "Nothing to do in input_SelectES" );
613         return -1;
614     }
615
616 #ifdef TRACE_INPUT
617     intf_DbgMsg( "Selecting ES 0x%x", p_es->i_id );
618 #endif
619
620     if( p_es->p_decoder_fifo != NULL )
621     {
622         intf_ErrMsg( "ES 0x%x is already selected", p_es->i_id );
623         return( -1 );
624     }
625
626     switch( p_es->i_type )
627     {
628     case MPEG1_AUDIO_ES:
629     case MPEG2_AUDIO_ES:
630         if( p_main->b_audio )
631         {
632             decoder.pf_create_thread = adec_CreateThread;
633             p_config = (void *)GetAdecConfig( p_input, p_es );
634             p_main->b_ac3 = 0;
635
636             /* Release the lock, not to block the input thread during
637              * the creation of the thread. */
638             vlc_mutex_unlock( &p_input->stream.stream_lock );
639             p_es->thread_id = input_RunDecoder( &decoder, p_config );
640             vlc_mutex_lock( &p_input->stream.stream_lock );
641         }
642         break;
643
644     case MPEG1_VIDEO_ES:
645     case MPEG2_VIDEO_ES:
646         if( p_main->b_video )
647         {
648             decoder.pf_create_thread = vpar_CreateThread;
649             p_config = (void *)GetVdecConfig( p_input, p_es );
650
651             /* Release the lock, not to block the input thread during
652              * the creation of the thread. */
653             vlc_mutex_unlock( &p_input->stream.stream_lock );
654             p_es->thread_id = input_RunDecoder( &decoder, p_config );
655             vlc_mutex_lock( &p_input->stream.stream_lock );
656         }
657         break;
658
659     case AC3_AUDIO_ES:
660         if( p_main->b_audio )
661         {
662             if( main_GetIntVariable( AOUT_SPDIF_VAR, 0 ) )
663             {
664                 decoder.pf_create_thread = spdif_CreateThread;
665             }
666             else
667             {
668                 decoder.pf_create_thread = ac3dec_CreateThread;
669             }
670
671             p_config = (void *)GetAdecConfig( p_input, p_es );
672             p_main->b_ac3 = 1;
673
674             /* Release the lock, not to block the input thread during
675              * the creation of the thread. */
676             vlc_mutex_unlock( &p_input->stream.stream_lock );
677             p_es->thread_id = input_RunDecoder( &decoder, p_config );
678             vlc_mutex_lock( &p_input->stream.stream_lock );
679         }
680         break;
681     case LPCM_AUDIO_ES:
682         if( p_main->b_audio )
683         {
684             decoder.pf_create_thread = lpcmdec_CreateThread;
685             p_config = (void *)GetAdecConfig( p_input, p_es );
686             p_main->b_ac3 = 0;
687
688             /* Release the lock, not to block the input thread during
689              * the creation of the thread. */
690             vlc_mutex_unlock( &p_input->stream.stream_lock );
691             p_es->thread_id = input_RunDecoder( &decoder, p_config );
692             vlc_mutex_lock( &p_input->stream.stream_lock );
693         }
694         break;
695     case DVD_SPU_ES:
696         if( p_main->b_video )
697         {
698             decoder.pf_create_thread = spudec_CreateThread;
699             p_config = (void *)GetVdecConfig( p_input, p_es );
700
701             /* Release the lock, not to block the input thread during
702              * the creation of the thread. */
703             vlc_mutex_unlock( &p_input->stream.stream_lock );
704             p_es->thread_id = input_RunDecoder( &decoder, p_config );
705             vlc_mutex_lock( &p_input->stream.stream_lock );
706         }
707         break;
708
709     default:
710         intf_ErrMsg( "Unknown stream type 0x%x", p_es->i_type );
711         return( -1 );
712         break;
713     }
714
715     if( p_es->thread_id == 0 )
716     {
717         return( -1 );
718     }
719
720     return( 0 );
721 }
722
723 /*****************************************************************************
724  * input_UnselectES: removes an ES from the list of selected ES
725  *****************************************************************************/
726 int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
727 {
728
729     int     i_index = 0;
730
731     if( p_es == NULL )
732     {
733         intf_ErrMsg( "Nothing to do in input_UnselectES" );
734         return -1;
735     }
736
737 #ifdef TRACE_INPUT
738     intf_DbgMsg( "Unselecting ES 0x%x", p_es->i_id );
739 #endif
740
741     if( p_es->p_decoder_fifo == NULL )
742     {
743         intf_ErrMsg( "ES 0x%x is not selected", p_es->i_id );
744         return( -1 );
745     }
746
747     input_EndDecoder( p_input, p_es );
748
749     if( ( p_es->p_decoder_fifo == NULL ) &&
750         ( p_input->stream.i_selected_es_number > 0 ) )
751     {
752         p_input->stream.i_selected_es_number--;
753
754         while( ( i_index < p_input->stream.i_selected_es_number ) &&
755                ( p_input->stream.pp_selected_es[i_index] != p_es ) )
756         {
757             i_index++;
758         }
759
760         p_input->stream.pp_selected_es[i_index] = 
761           p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number];
762
763         p_input->stream.pp_selected_es = realloc(
764                                            p_input->stream.pp_selected_es,
765                                            p_input->stream.i_selected_es_number
766                                             * sizeof(es_descriptor_t *) );
767
768         if( p_input->stream.pp_selected_es == NULL )
769         {
770 #ifdef TRACE_INPUT
771             intf_DbgMsg( "No more selected ES in input_UnselectES" );
772 #endif
773             return( 1 );
774         }
775     }
776
777     return( 0 );
778 }