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