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