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