12c6efcbdf96911d3e70a30ad11714406c827e0d
[vlc.git] / 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.54 2001/05/01 04:18:18 sam 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.pp_programs = NULL;
68
69     if( i_data_len )
70     {
71         if ( (p_input->stream.p_demux_data = malloc( i_data_len )) == NULL )
72         {
73             intf_ErrMsg( "Unable to allocate memory in input_InitStream");
74             return 1;
75         }
76         memset( p_input->stream.p_demux_data, 0, i_data_len );
77     }
78
79     return 0;
80 }
81
82 /*****************************************************************************
83  * input_EndStream: free all stream descriptors
84  *****************************************************************************/
85 void input_EndStream( input_thread_t * p_input )
86 {
87     /* Free all programs and associated ES, and associated decoders. */
88     while( p_input->stream.i_pgrm_number )
89     {
90         input_DelProgram( p_input, p_input->stream.pp_programs[0] );
91     }
92
93     /* Free standalone ES */
94     while( p_input->stream.i_es_number )
95     {
96         input_DelES( p_input, p_input->stream.pp_es[0] );
97     }
98
99     /* Free all areas */
100     while( p_input->stream.i_area_nb )
101     {
102         input_DelArea( p_input, p_input->stream.pp_areas[0] );
103     }
104
105     if( p_input->stream.p_demux_data != NULL )
106     {
107         free( p_input->stream.p_demux_data );
108     }
109 }
110
111 /*****************************************************************************
112  * input_FindProgram: returns a pointer to a program described by its ID
113  *****************************************************************************/
114 pgrm_descriptor_t * input_FindProgram( input_thread_t * p_input, u16 i_pgrm_id )
115 {
116     int     i;
117
118     for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
119     {
120         if( p_input->stream.pp_programs[i]->i_number == i_pgrm_id )
121         {
122             return p_input->stream.pp_programs[i];
123         }
124     }
125
126     return( NULL );
127 }
128
129 /*****************************************************************************
130  * input_AddProgram: add and init a program descriptor
131  *****************************************************************************
132  * This program descriptor will be referenced in the given stream descriptor
133  *****************************************************************************/
134 pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input,
135                                       u16 i_pgrm_id, size_t i_data_len )
136 {
137     /* Where to add the pgrm */
138     int i_pgrm_index = p_input->stream.i_pgrm_number;
139
140     intf_DbgMsg("Adding description for pgrm %d", i_pgrm_id);
141
142     /* Add an entry to the list of program associated with the stream */
143     p_input->stream.i_pgrm_number++;
144     p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
145                                            p_input->stream.i_pgrm_number
146                                             * sizeof(pgrm_descriptor_t *) );
147     if( p_input->stream.pp_programs == NULL )
148     {
149         intf_ErrMsg( "Unable to realloc memory in input_AddProgram" );
150         return( NULL );
151     }
152     
153     /* Allocate the structure to store this description */
154     p_input->stream.pp_programs[i_pgrm_index] =
155                                         malloc( sizeof(pgrm_descriptor_t) );
156     if( p_input->stream.pp_programs[i_pgrm_index] == NULL )
157     {
158         intf_ErrMsg( "Unable to allocate memory in input_AddProgram" );
159         return( NULL );
160     }
161     
162     /* Init this entry */
163     p_input->stream.pp_programs[i_pgrm_index]->i_number = i_pgrm_id;
164     p_input->stream.pp_programs[i_pgrm_index]->b_is_ok = 0;
165     p_input->stream.pp_programs[i_pgrm_index]->i_version = 0;
166
167     p_input->stream.pp_programs[i_pgrm_index]->i_es_number = 0;
168     p_input->stream.pp_programs[i_pgrm_index]->pp_es = NULL;
169
170     input_ClockInit( p_input->stream.pp_programs[i_pgrm_index] );
171
172     p_input->stream.pp_programs[i_pgrm_index]->i_synchro_state
173                                                 = SYNCHRO_START;
174
175     p_input->stream.pp_programs[i_pgrm_index]->p_vout
176                                             = p_input->p_default_vout;
177
178     if( i_data_len )
179     {
180         p_input->stream.pp_programs[i_pgrm_index]->p_demux_data =
181             malloc( i_data_len );
182         if( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data == NULL )
183         {
184             intf_ErrMsg( "Unable to allocate memory in input_AddProgram" );
185             return( NULL );
186         }
187         memset( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data, 0,
188                 i_data_len );
189     }
190
191     return p_input->stream.pp_programs[i_pgrm_index];
192 }
193
194 /*****************************************************************************
195  * input_DelProgram: destroy a program descriptor
196  *****************************************************************************
197  * All ES descriptions referenced in the descriptor will be deleted.
198  *****************************************************************************/
199 void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
200 {
201     int i_pgrm_index;
202
203     ASSERT( p_pgrm );
204
205     intf_DbgMsg("Deleting description for pgrm %d", p_pgrm->i_number);
206
207     /* Free the structures that describe the es that belongs to that program */
208     while( p_pgrm->i_es_number )
209     {
210         input_DelES( p_input, p_pgrm->pp_es[0] );
211     }
212
213     /* Free the demux data */
214     if( p_pgrm->p_demux_data != NULL )
215     {
216         free( p_pgrm->p_demux_data );
217     }
218
219     /* Find the program in the programs table */
220     for( i_pgrm_index = 0; i_pgrm_index < p_input->stream.i_pgrm_number;
221          i_pgrm_index++ )
222     {
223         if( p_input->stream.pp_programs[i_pgrm_index] == p_pgrm )
224             break;
225     }
226
227     /* Remove this program from the stream's list of programs */
228     p_input->stream.i_pgrm_number--;
229
230     p_input->stream.pp_programs[i_pgrm_index] =
231         p_input->stream.pp_programs[p_input->stream.i_pgrm_number];
232     p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
233                                            p_input->stream.i_pgrm_number
234                                             * sizeof(pgrm_descriptor_t *) );
235
236     if( p_input->stream.i_pgrm_number && p_input->stream.pp_programs == NULL)
237     {
238         intf_ErrMsg( "input error: unable to realloc program list"
239                      " in input_DelProgram" );
240     }
241
242     /* Free the description of this program */
243     free( p_pgrm );
244 }
245
246 /*****************************************************************************
247  * input_AddArea: add and init an area descriptor
248  *****************************************************************************
249  * This area descriptor will be referenced in the given stream descriptor
250  *****************************************************************************/
251 input_area_t * input_AddArea( input_thread_t * p_input )
252 {
253     /* Where to add the pgrm */
254     int i_area_index = p_input->stream.i_area_nb;
255
256     intf_DbgMsg("Adding description for area %d", i_area_index );
257
258     /* Add an entry to the list of program associated with the stream */
259     p_input->stream.i_area_nb++;
260     p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
261                                         p_input->stream.i_area_nb
262                                             * sizeof(input_area_t *) );
263     if( p_input->stream.pp_areas == NULL )
264     {
265         intf_ErrMsg( "Unable to realloc memory in input_AddArea" );
266         return( NULL );
267     }
268     
269     /* Allocate the structure to store this description */
270     p_input->stream.pp_areas[i_area_index] =
271                                         malloc( sizeof(input_area_t) );
272     if( p_input->stream.pp_areas[i_area_index] == NULL )
273     {
274         intf_ErrMsg( "Unable to allocate memory in input_AddArea" );
275         return( NULL );
276     }
277     
278     /* Init this entry */
279     p_input->stream.pp_areas[i_area_index]->i_id = 0;
280     p_input->stream.pp_areas[i_area_index]->i_start = 0;
281     p_input->stream.pp_areas[i_area_index]->i_size = 0;
282     p_input->stream.pp_areas[i_area_index]->i_tell = 0;
283     p_input->stream.pp_areas[i_area_index]->i_seek = NO_SEEK;
284     p_input->stream.pp_areas[i_area_index]->i_part_nb = 1;
285     p_input->stream.pp_areas[i_area_index]->i_part= 0;
286     p_input->stream.pp_areas[i_area_index]->i_angle_nb = 1;
287     p_input->stream.pp_areas[i_area_index]->i_angle = 0;
288
289     return p_input->stream.pp_areas[i_area_index];
290 }
291
292 /*****************************************************************************
293  * input_DelArea: destroy a area descriptor
294  *****************************************************************************
295  * All ES descriptions referenced in the descriptor will be deleted.
296  *****************************************************************************/
297 void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
298 {
299     int i_area_index;
300
301     ASSERT( p_area );
302
303     intf_DbgMsg("Deleting description for area %d", p_area->i_id );
304
305     /* Find the area in the areas table */
306     for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb;
307          i_area_index++ )
308     {
309         if( p_input->stream.pp_areas[i_area_index] == p_area )
310             break;
311     }
312
313     /* Remove this area from the stream's list of areas */
314     p_input->stream.i_area_nb--;
315
316     p_input->stream.pp_areas[i_area_index] =
317         p_input->stream.pp_areas[p_input->stream.i_area_nb];
318     p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
319                                            p_input->stream.i_area_nb
320                                             * sizeof(input_area_t *) );
321
322     if( p_input->stream.i_area_nb && p_input->stream.pp_areas == NULL)
323     {
324         intf_ErrMsg( "input error: unable to realloc area list"
325                      " in input_DelArea" );
326     }
327
328     /* Free the description of this area */
329     free( p_area );
330 }
331
332
333 /*****************************************************************************
334  * input_FindES: returns a pointer to an ES described by its ID
335  *****************************************************************************/
336 es_descriptor_t * input_FindES( input_thread_t * p_input, u16 i_es_id )
337 {
338     int     i;
339
340     for( i = 0; i < p_input->stream.i_es_number; i++ )
341     {
342         if( p_input->stream.pp_es[i]->i_id == i_es_id )
343         {
344             return p_input->stream.pp_es[i];
345         }
346     }
347
348     return( NULL );
349 }
350
351 /*****************************************************************************
352  * input_AddES:
353  *****************************************************************************
354  * Reserve a slot in the table of ES descriptors for the ES and add it to the
355  * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
356  * alone (PSI ?)
357  *****************************************************************************/
358 es_descriptor_t * input_AddES( input_thread_t * p_input,
359                                pgrm_descriptor_t * p_pgrm, u16 i_es_id,
360                                size_t i_data_len )
361 {
362     es_descriptor_t * p_es;
363
364     intf_DbgMsg("Adding description for ES 0x%x", i_es_id);
365
366     p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
367     if( p_es == NULL )
368     {
369         intf_ErrMsg( "Unable to allocate memory in input_AddES" );
370         return( NULL);
371     }
372     p_input->stream.i_es_number++;
373     p_input->stream.pp_es = realloc( p_input->stream.pp_es,
374                                      p_input->stream.i_es_number
375                                       * sizeof(es_descriptor_t *) );
376     if( p_input->stream.pp_es == NULL )
377     {
378         intf_ErrMsg( "Unable to realloc memory in input_AddES" );
379         return( NULL );
380     }
381     p_input->stream.pp_es[p_input->stream.i_es_number - 1] = p_es;
382
383     /* Init its values */
384     p_es->i_id = i_es_id;
385     p_es->psz_desc[0] = '\0';
386     p_es->p_pes = NULL;
387     p_es->p_decoder_fifo = NULL;
388     p_es->b_audio = 0;
389     p_es->i_cat = UNKNOWN_ES;
390
391     if( i_data_len )
392     {
393         p_es->p_demux_data = malloc( i_data_len );
394         if( p_es->p_demux_data == NULL )
395         {
396             intf_ErrMsg( "Unable to allocate memory in input_AddES" );
397             return( NULL );
398         }
399         memset( p_es->p_demux_data, 0, i_data_len );
400     }
401     else
402     {
403         p_es->p_demux_data = NULL;
404     }
405
406     /* Add this ES to the program definition if one is given */
407     if( p_pgrm )
408     {
409         p_pgrm->i_es_number++;
410         p_pgrm->pp_es = realloc( p_pgrm->pp_es,
411                                  p_pgrm->i_es_number
412                                   * sizeof(es_descriptor_t *) );
413         if( p_pgrm->pp_es == NULL )
414         {
415             intf_ErrMsg( "Unable to realloc memory in input_AddES" );
416             return( NULL );
417         }
418         p_pgrm->pp_es[p_pgrm->i_es_number - 1] = p_es;
419         p_es->p_pgrm = p_pgrm;
420     }
421     else
422     {
423         p_es->p_pgrm = NULL;
424     }
425
426     return p_es;
427 }
428
429 /*****************************************************************************
430  * input_DelES:
431  *****************************************************************************/
432 void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
433 {
434     int                     i_index, i_es_index;
435     pgrm_descriptor_t *     p_pgrm;
436
437     ASSERT( p_es );
438     p_pgrm = p_es->p_pgrm;
439
440     /* Kill associated decoder, if any. */
441     if( p_es->p_decoder_fifo != NULL )
442     {
443         input_EndDecoder( p_input, p_es );
444     }
445
446     /* Remove this ES from the description of the program if it is associated to
447      * one */
448     if( p_pgrm )
449     {
450         for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
451         {
452             if( p_pgrm->pp_es[i_index] == p_es )
453             {
454                 p_pgrm->i_es_number--;
455                 p_pgrm->pp_es[i_index] = p_pgrm->pp_es[p_pgrm->i_es_number];
456                 p_pgrm->pp_es = realloc( p_pgrm->pp_es,
457                                          p_pgrm->i_es_number
458                                           * sizeof(es_descriptor_t *));
459                 if( p_pgrm->i_es_number && p_pgrm->pp_es == NULL )
460                 {
461                     intf_ErrMsg( "Unable to realloc memory in input_DelES" );
462                 }
463                 break;
464             }
465         }
466     }
467
468     /* Free the demux data */
469     if( p_es->p_demux_data != NULL )
470     {
471         free( p_es->p_demux_data );
472     }
473
474     /* Find the ES in the ES table */
475     for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
476          i_es_index++ )
477     {
478         if( p_input->stream.pp_es[i_es_index] == p_es )
479             break;
480     }
481
482     /* Free the ES */
483     free( p_es );
484     p_input->stream.i_es_number--;
485     p_input->stream.pp_es[i_es_index] =
486                     p_input->stream.pp_es[p_input->stream.i_es_number];
487     p_input->stream.pp_es = realloc( p_input->stream.pp_es,
488                                      p_input->stream.i_es_number
489                                       * sizeof(es_descriptor_t *));
490     if( p_input->stream.i_es_number && p_input->stream.pp_es == NULL )
491     {
492         intf_ErrMsg( "Unable to realloc memory in input_DelES" );
493     }
494     
495 }
496
497 /*****************************************************************************
498  * InitDecConfig: initializes a decoder_config_t
499  *****************************************************************************/
500 static int InitDecConfig( input_thread_t * p_input, es_descriptor_t * p_es,
501                           decoder_config_t * p_config )
502 {
503     p_config->i_id = p_es->i_id;
504     p_config->i_type = p_es->i_type;
505     p_config->p_stream_ctrl =
506         &p_input->stream.control;
507
508     /* Decoder FIFO */
509     if( (p_config->p_decoder_fifo =
510             (decoder_fifo_t *)malloc( sizeof(decoder_fifo_t) )) == NULL )
511     {
512         intf_ErrMsg( "Out of memory" );
513         return( -1 );
514     }
515
516     vlc_mutex_init(&p_config->p_decoder_fifo->data_lock);
517     vlc_cond_init(&p_config->p_decoder_fifo->data_wait);
518     p_config->p_decoder_fifo->i_start = p_config->p_decoder_fifo->i_end = 0;
519     p_config->p_decoder_fifo->b_die = p_config->p_decoder_fifo->b_error = 0;
520     p_config->p_decoder_fifo->p_packets_mgt = p_input->p_method_data;
521     p_config->p_decoder_fifo->pf_delete_pes = p_input->pf_delete_pes;
522     p_es->p_decoder_fifo = p_config->p_decoder_fifo;
523
524     p_config->pf_init_bit_stream = InitBitstream;
525
526     p_input->stream.i_selected_es_number++;
527
528     p_input->stream.pp_selected_es = realloc(
529                                        p_input->stream.pp_selected_es,
530                                        p_input->stream.i_selected_es_number
531                                         * sizeof(es_descriptor_t *) );
532     if( p_input->stream.pp_selected_es == NULL )
533     {
534         intf_ErrMsg( "Unable to realloc memory in input_SelectES" );
535         return(-1);
536     }
537     p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number - 1]
538             = p_es;
539
540     return( 0 );
541 }
542
543 /*****************************************************************************
544  * GetVdecConfig: returns a valid vdec_config_t
545  *****************************************************************************/
546 static vdec_config_t * GetVdecConfig( input_thread_t * p_input,
547                                       es_descriptor_t * p_es )
548 {
549     vdec_config_t *     p_config;
550
551     p_config = (vdec_config_t *)malloc( sizeof(vdec_config_t) );
552     if( p_config == NULL )
553     {
554         intf_ErrMsg( "Unable to allocate memory in GetVdecConfig" );
555         return( NULL );
556     }
557     p_config->p_vout = p_input->p_default_vout;
558     if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 )
559     {
560         free( p_config );
561         return( NULL );
562     }
563
564     return( p_config );
565 }
566
567 /*****************************************************************************
568  * GetAdecConfig: returns a valid adec_config_t
569  *****************************************************************************/
570 static adec_config_t * GetAdecConfig( input_thread_t * p_input,
571                                       es_descriptor_t * p_es )
572 {
573     adec_config_t *     p_config;
574
575     p_config = (adec_config_t *)malloc( sizeof(adec_config_t));
576     if( p_config == NULL )
577     {
578         intf_ErrMsg( "Unable to allocate memory in GetAdecConfig" );
579         return( NULL );
580     }
581
582     if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 )
583     {
584         free( p_config );
585         return( NULL );
586     }
587
588     return( p_config );
589 }
590
591 /*****************************************************************************
592  * input_SelectES: selects an ES and spawns the associated decoder
593  *****************************************************************************
594  * Remember we are still supposed to have stream_lock when entering this
595  * function ?
596  *****************************************************************************/
597 /* FIXME */
598 vlc_thread_t adec_CreateThread( void * );
599 vlc_thread_t ac3dec_CreateThread( void * );
600 vlc_thread_t ac3spdif_CreateThread( void * );
601 vlc_thread_t spdif_CreateThread( void * );
602 vlc_thread_t vpar_CreateThread( void * );
603 vlc_thread_t spudec_CreateThread( void * );
604
605 int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
606 {
607     /* FIXME ! */
608     decoder_capabilities_t  decoder;
609     void *                  p_config;
610
611     if( p_es == NULL )
612     {
613         intf_ErrMsg( "Nothing to do in input_SelectES" );
614         return -1;
615     }
616
617 #ifdef TRACE_INPUT
618     intf_DbgMsg( "Selecting ES 0x%x", p_es->i_id );
619 #endif
620
621     if( p_es->p_decoder_fifo != NULL )
622     {
623         intf_ErrMsg( "ES 0x%x is already selected", p_es->i_id );
624         return( -1 );
625     }
626
627     switch( p_es->i_type )
628     {
629     case MPEG1_AUDIO_ES:
630     case MPEG2_AUDIO_ES:
631         if( p_main->b_audio )
632         {
633             decoder.pf_create_thread = adec_CreateThread;
634             p_config = (void *)GetAdecConfig( p_input, p_es );
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
673             /* Release the lock, not to block the input thread during
674              * the creation of the thread. */
675             vlc_mutex_unlock( &p_input->stream.stream_lock );
676             p_es->thread_id = input_RunDecoder( &decoder, p_config );
677             vlc_mutex_lock( &p_input->stream.stream_lock );
678         }
679         break;
680 #if 0
681     case LPCM_AUDIO_ES:
682         if( p_main->b_audio )
683         {
684             if( p_main->b_spdif )
685             {
686                 decoder.pf_create_thread = spdif_CreateThread;
687             }
688             else
689             {
690                 intf_ErrMsg( "input error: LPCM audio not handled yet" );
691                 break;
692             }
693
694             p_config = (void *)GetAdecConfig( p_input, p_es );
695
696             /* Release the lock, not to block the input thread during
697              * the creation of the thread. */
698             vlc_mutex_unlock( &p_input->stream.stream_lock );
699             p_es->thread_id = input_RunDecoder( &decoder, p_config );
700             vlc_mutex_lock( &p_input->stream.stream_lock );
701         }
702         break;
703 #endif
704     case DVD_SPU_ES:
705         if( p_main->b_video )
706         {
707             decoder.pf_create_thread = spudec_CreateThread;
708             p_config = (void *)GetVdecConfig( p_input, p_es );
709
710             /* Release the lock, not to block the input thread during
711              * the creation of the thread. */
712             vlc_mutex_unlock( &p_input->stream.stream_lock );
713             p_es->thread_id = input_RunDecoder( &decoder, p_config );
714             vlc_mutex_lock( &p_input->stream.stream_lock );
715         }
716         break;
717
718     default:
719         intf_ErrMsg( "Unknown stream type 0x%x", p_es->i_type );
720         return( -1 );
721         break;
722     }
723
724     if( p_es->thread_id == 0 )
725     {
726         return( -1 );
727     }
728
729     return( 0 );
730 }
731
732 /*****************************************************************************
733  * input_UnselectES: removes an ES from the list of selected ES
734  *****************************************************************************/
735 int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
736 {
737
738     int     i_index = 0;
739
740     if( p_es == NULL )
741     {
742         intf_ErrMsg( "Nothing to do in input_UnselectES" );
743         return -1;
744     }
745
746 #ifdef TRACE_INPUT
747     intf_DbgMsg( "Unselecting ES 0x%x", p_es->i_id );
748 #endif
749
750     if( p_es->p_decoder_fifo == NULL )
751     {
752         intf_ErrMsg( "ES 0x%x is not selected", p_es->i_id );
753         return( -1 );
754     }
755
756     input_EndDecoder( p_input, p_es );
757
758     if( ( p_es->p_decoder_fifo == NULL ) &&
759         ( p_input->stream.i_selected_es_number > 0 ) )
760     {
761         p_input->stream.i_selected_es_number--;
762
763         while( ( i_index < p_input->stream.i_selected_es_number ) &&
764                ( p_input->stream.pp_selected_es[i_index] != p_es ) )
765         {
766             i_index++;
767         }
768
769         p_input->stream.pp_selected_es[i_index] = 
770           p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number];
771
772         p_input->stream.pp_selected_es = realloc(
773                                            p_input->stream.pp_selected_es,
774                                            p_input->stream.i_selected_es_number
775                                             * sizeof(es_descriptor_t *) );
776
777         if( p_input->stream.pp_selected_es == NULL )
778         {
779 #ifdef TRACE_INPUT
780             intf_DbgMsg( "No more selected ES in input_UnselectES" );
781 #endif
782             return( 1 );
783         }
784     }
785
786     return( 0 );
787 }