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