- check size to avoid realloc(0)
[vlc.git] / src / input / input_programs.c
1 /*****************************************************************************
2  * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: input_programs.c,v 1.86 2002/05/15 15:46:34 asmax 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 <stdlib.h>
28 #include <string.h>                                    /* memcpy(), memset() */
29 #include <sys/types.h>                                              /* off_t */
30
31 #include <videolan/vlc.h>
32
33 #include "stream_control.h"
34 #include "input_ext-intf.h"
35 #include "input_ext-dec.h"
36 #include "input_ext-plugins.h"
37
38 /*
39  * NOTICE : all of these functions expect you to have taken the lock on
40  * p_input->stream.lock
41  */
42
43 /*****************************************************************************
44  * input_InitStream: init the stream descriptor of the given input
45  *****************************************************************************/
46 int input_InitStream( input_thread_t * p_input, size_t i_data_len )
47 {
48
49     p_input->stream.i_stream_id = 0;
50
51     /* initialized to 0 since we don't give the signal to the interface
52      * before the end of input initialization */
53     p_input->stream.b_changed = 0;
54     p_input->stream.pp_es = NULL;
55     p_input->stream.pp_selected_es = NULL;
56     p_input->stream.p_removed_es = NULL;
57     p_input->stream.p_newly_selected_es = NULL;
58     p_input->stream.pp_programs = NULL;
59     p_input->stream.p_selected_program = NULL;
60     p_input->stream.p_new_program = 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     else
72     {
73         p_input->stream.p_demux_data = NULL;
74     }
75
76     return 0;
77 }
78
79 /*****************************************************************************
80  * input_EndStream: free all stream descriptors
81  *****************************************************************************/
82 void input_EndStream( input_thread_t * p_input )
83 {
84     /* Free all programs and associated ES, and associated decoders. */
85     while( p_input->stream.i_pgrm_number )
86     {
87         input_DelProgram( p_input, p_input->stream.pp_programs[0] );
88     }
89
90     /* Free standalone ES */
91     while( p_input->stream.i_es_number )
92     {
93         input_DelES( p_input, p_input->stream.pp_es[0] );
94     }
95
96     /* Free all areas */
97     while( p_input->stream.i_area_nb )
98     {
99         input_DelArea( p_input, p_input->stream.pp_areas[0] );
100     }
101
102     /* Free selected ES */
103     if( p_input->stream.pp_selected_es != NULL )
104     {
105         free( p_input->stream.pp_selected_es );
106     }
107     
108     if( p_input->stream.p_demux_data != NULL )
109     {
110         free( p_input->stream.p_demux_data );
111     }
112 }
113
114 /*****************************************************************************
115  * input_FindProgram: returns a pointer to a program described by its ID
116  *****************************************************************************/
117 pgrm_descriptor_t * input_FindProgram( input_thread_t * p_input, u16 i_pgrm_id )
118 {
119     int     i;
120
121     for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
122     {
123         if( p_input->stream.pp_programs[i]->i_number == i_pgrm_id )
124         {
125             return p_input->stream.pp_programs[i];
126         }
127     }
128
129     return( NULL );
130 }
131
132 /*****************************************************************************
133  * input_AddProgram: add and init a program descriptor
134  *****************************************************************************
135  * This program descriptor will be referenced in the given stream descriptor
136  *****************************************************************************/
137 pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input,
138                                       u16 i_pgrm_id, size_t i_data_len )
139 {
140     /* Where to add the pgrm */
141     int i_pgrm_index = p_input->stream.i_pgrm_number;
142
143     /* Add an entry to the list of program associated with the stream */
144     p_input->stream.i_pgrm_number++;
145     if( p_input->stream.i_pgrm_number > 0 )
146     {
147         p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
148                                                p_input->stream.i_pgrm_number
149                                                * sizeof(pgrm_descriptor_t *) );
150         if( p_input->stream.pp_programs == NULL )
151         {
152             intf_ErrMsg( "Unable to realloc memory in input_AddProgram" );
153             return( NULL );
154         }
155     }
156     else {
157         intf_ErrMsg( "realloc(0) (p_input->stream.i_pgrm_number corrupted ?)");
158         return( NULL );
159     }
160         
161     /* Allocate the structure to store this description */
162     p_input->stream.pp_programs[i_pgrm_index] =
163                                         malloc( sizeof(pgrm_descriptor_t) );
164     if( p_input->stream.pp_programs[i_pgrm_index] == NULL )
165     {
166         intf_ErrMsg( "Unable to allocate memory in input_AddProgram" );
167         return( NULL );
168     }
169     
170     /* Init this entry */
171     p_input->stream.pp_programs[i_pgrm_index]->i_number = i_pgrm_id;
172     p_input->stream.pp_programs[i_pgrm_index]->b_is_ok = 0;
173     p_input->stream.pp_programs[i_pgrm_index]->i_version = 0;
174
175     p_input->stream.pp_programs[i_pgrm_index]->i_es_number = 0;
176     p_input->stream.pp_programs[i_pgrm_index]->pp_es = NULL;
177
178     input_ClockInit( p_input->stream.pp_programs[i_pgrm_index] );
179
180     p_input->stream.pp_programs[i_pgrm_index]->i_synchro_state
181                                                 = SYNCHRO_START;
182
183     if( i_data_len )
184     {
185         p_input->stream.pp_programs[i_pgrm_index]->p_demux_data =
186             malloc( i_data_len );
187         if( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data == NULL )
188         {
189             intf_ErrMsg( "Unable to allocate memory in input_AddProgram" );
190             return( NULL );
191         }
192         memset( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data, 0,
193                 i_data_len );
194     }
195     else
196     {
197         p_input->stream.pp_programs[i_pgrm_index]->p_demux_data = NULL;
198     }
199
200     return p_input->stream.pp_programs[i_pgrm_index];
201 }
202
203 /*****************************************************************************
204  * input_DelProgram: destroy a program descriptor
205  *****************************************************************************
206  * All ES descriptions referenced in the descriptor will be deleted.
207  *****************************************************************************/
208 void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
209 {
210     int i_pgrm_index;
211
212     ASSERT( p_pgrm );
213
214     /* Free the structures that describe the es that belongs to that program */
215     while( p_pgrm->i_es_number )
216     {
217         input_DelES( p_input, p_pgrm->pp_es[0] );
218     }
219
220     /* Free the demux data */
221     if( p_pgrm->p_demux_data != NULL )
222     {
223         free( p_pgrm->p_demux_data );
224     }
225
226     /* Find the program in the programs table */
227     for( i_pgrm_index = 0; i_pgrm_index < p_input->stream.i_pgrm_number;
228          i_pgrm_index++ )
229     {
230         if( p_input->stream.pp_programs[i_pgrm_index] == p_pgrm )
231             break;
232     }
233
234     /* Remove this program from the stream's list of programs */
235     p_input->stream.i_pgrm_number--;
236
237     p_input->stream.pp_programs[i_pgrm_index] =
238         p_input->stream.pp_programs[p_input->stream.i_pgrm_number];
239     if( p_input->stream.i_pgrm_number > 0 ) 
240     {
241         p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
242                                                p_input->stream.i_pgrm_number
243                                                * sizeof(pgrm_descriptor_t *) );
244         if( p_input->stream.pp_programs == NULL )
245         {
246             intf_ErrMsg( "input error: unable to realloc program list"
247                          " in input_DelProgram" );
248         }
249
250     }
251     else
252     {
253         free( p_input->stream.pp_programs );
254     }
255
256     /* Free the description of this program */
257     free( p_pgrm );
258 }
259
260 /*****************************************************************************
261  * input_AddArea: add and init an area descriptor
262  *****************************************************************************
263  * This area descriptor will be referenced in the given stream descriptor
264  *****************************************************************************/
265 input_area_t * input_AddArea( input_thread_t * p_input )
266 {
267     /* Where to add the pgrm */
268     int i_area_index = p_input->stream.i_area_nb;
269
270     /* Add an entry to the list of program associated with the stream */
271     p_input->stream.i_area_nb++;
272     if( p_input->stream.i_area_nb > 0 )
273     {
274         p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
275                                             p_input->stream.i_area_nb
276                                             * sizeof(input_area_t *) );
277         if( p_input->stream.pp_areas == NULL )
278         {
279             intf_ErrMsg( "Unable to realloc memory in input_AddArea" );
280             return( NULL );
281         }
282     }
283     else
284     {
285         intf_ErrMsg( "realloc(0) (p_input->stream.i_area_nb corrupted ?)");
286         return( NULL );
287     }
288     
289     /* Allocate the structure to store this description */
290     p_input->stream.pp_areas[i_area_index] =
291                                         malloc( sizeof(input_area_t) );
292     if( p_input->stream.pp_areas[i_area_index] == NULL )
293     {
294         intf_ErrMsg( "Unable to allocate memory in input_AddArea" );
295         return( NULL );
296     }
297     
298     /* Init this entry */
299     p_input->stream.pp_areas[i_area_index]->i_id = 0;
300     p_input->stream.pp_areas[i_area_index]->i_start = 0;
301     p_input->stream.pp_areas[i_area_index]->i_size = 0;
302     p_input->stream.pp_areas[i_area_index]->i_tell = 0;
303     p_input->stream.pp_areas[i_area_index]->i_seek = NO_SEEK;
304     p_input->stream.pp_areas[i_area_index]->i_part_nb = 1;
305     p_input->stream.pp_areas[i_area_index]->i_part= 0;
306
307     return p_input->stream.pp_areas[i_area_index];
308 }
309
310 /*****************************************************************************
311  * input_SetProgram: changes the current program
312  *****************************************************************************/
313 int input_SetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_new_prg )
314 {
315     int i_es_index;
316     int i_required_audio_es;
317     int i_required_spu_es;
318     int i_audio_es = 0;
319     int i_spu_es = 0;
320
321     if ( p_input->stream.p_selected_program )
322     {
323         for ( i_es_index = 1 ; /* 0 should be the PMT */
324                 i_es_index < p_input->stream.p_selected_program->
325                 i_es_number ;
326                 i_es_index ++ )
327         {
328 #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
329             if ( p_es->p_decoder_fifo ) /* if the ES was selected */
330             {
331                 input_UnselectES( p_input , p_es );
332             }
333 #undef p_es
334         }
335     }
336     /* Get the number of the required audio stream */
337     if( p_main->b_audio )
338     {
339         /* Default is the first one */
340         i_required_audio_es = config_GetIntVariable( "audio-channel" );
341         if( i_required_audio_es < 0 )
342         {
343             i_required_audio_es = 1;
344         }
345     }
346     else
347     {
348         i_required_audio_es = 0;
349     }
350
351     /* Same thing for subtitles */
352     if( p_main->b_video )
353     {
354         /* for spu, default is none */
355         i_required_spu_es = config_GetIntVariable( "spu-channel" );
356         if( i_required_spu_es < 0 )
357         {
358             i_required_spu_es = 0;
359         }
360     }
361     else
362     {
363         i_required_spu_es = 0;
364     }
365
366     for (i_es_index = 0 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
367     {
368         switch( p_new_prg->pp_es[i_es_index]->i_cat )
369         {
370             case VIDEO_ES:
371                 intf_WarnMsg( 4, "Selecting ES %x",
372                             p_new_prg->pp_es[i_es_index]->i_id );
373                 input_SelectES( p_input, p_new_prg->pp_es[i_es_index] );
374                 break;
375             case AUDIO_ES:
376                 i_audio_es += 1;
377                 if( i_audio_es <= i_required_audio_es )
378                 {
379                     intf_WarnMsg( 4, "Selecting ES %x",
380                                 p_new_prg->pp_es[i_es_index]->i_id );
381                     input_SelectES( p_input, p_new_prg->pp_es[i_es_index]);
382                 }
383                 break;
384             /* Not sure this one is fully specification-compliant */
385             case SPU_ES :
386                 i_spu_es += 1;
387                 if( i_spu_es <= i_required_spu_es )
388                 {
389                     intf_WarnMsg( 4, "Selecting ES %x",
390                                 p_new_prg->pp_es[i_es_index]->i_id );
391                     input_SelectES( p_input, p_new_prg->pp_es[i_es_index] );
392                 }
393             break;
394             default :
395                 intf_WarnMsg( 2, "ES %x has unknown type",
396                             p_new_prg->pp_es[i_es_index]->i_id );
397                 break;
398         }
399
400     }
401
402
403     p_input->stream.p_selected_program = p_new_prg;
404
405     return( 0 );
406 }
407
408
409 /*****************************************************************************
410  * input_DelArea: destroy a area descriptor
411  *****************************************************************************
412  * All ES descriptions referenced in the descriptor will be deleted.
413  *****************************************************************************/
414 void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
415 {
416     int i_area_index;
417
418     ASSERT( p_area );
419
420     /* Find the area in the areas table */
421     for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb;
422          i_area_index++ )
423     {
424         if( p_input->stream.pp_areas[i_area_index] == p_area )
425             break;
426     }
427
428     /* Remove this area from the stream's list of areas */
429     p_input->stream.i_area_nb--;
430
431     p_input->stream.pp_areas[i_area_index] =
432         p_input->stream.pp_areas[p_input->stream.i_area_nb];
433     if( p_input->stream.i_area_nb > 0 )
434     {
435         p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
436                                             p_input->stream.i_area_nb
437                                             * sizeof(input_area_t *) );
438
439         if( p_input->stream.pp_areas == NULL )
440         {
441             intf_ErrMsg( "input error: unable to realloc area list"
442                          " in input_DelArea" );
443         }
444     }
445     else
446     {
447         free( p_input->stream.pp_areas );
448     }
449
450     /* Free the description of this area */
451     free( p_area );
452 }
453
454
455 /*****************************************************************************
456  * input_FindES: returns a pointer to an ES described by its ID
457  *****************************************************************************/
458 es_descriptor_t * input_FindES( input_thread_t * p_input, u16 i_es_id )
459 {
460     int     i;
461
462     for( i = 0; i < p_input->stream.i_es_number; i++ )
463     {
464         if( p_input->stream.pp_es[i]->i_id == i_es_id )
465         {
466             return p_input->stream.pp_es[i];
467         }
468     }
469
470     return( NULL );
471 }
472
473 /*****************************************************************************
474  * input_AddES:
475  *****************************************************************************
476  * Reserve a slot in the table of ES descriptors for the ES and add it to the
477  * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
478  * alone (PSI ?)
479  *****************************************************************************/
480 es_descriptor_t * input_AddES( input_thread_t * p_input,
481                                pgrm_descriptor_t * p_pgrm, u16 i_es_id,
482                                size_t i_data_len )
483 {
484     es_descriptor_t * p_es;
485
486     p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
487     if( p_es == NULL )
488     {
489         intf_ErrMsg( "Unable to allocate memory in input_AddES" );
490         return( NULL);
491     }
492     p_input->stream.i_es_number++;
493     if( p_input->stream.i_es_number > 0 )
494     {
495         p_input->stream.pp_es = realloc( p_input->stream.pp_es,
496                                          p_input->stream.i_es_number
497                                           * sizeof(es_descriptor_t *) );
498         if( p_input->stream.pp_es == NULL )
499         {
500             intf_ErrMsg( "Unable to realloc memory in input_AddES" );
501             return( NULL );
502         }
503     }
504     else
505     {
506         intf_ErrMsg( "realloc(0) (p_input->stream.pp_es_number corrupted ?)");
507         return( NULL );
508     }
509     p_input->stream.pp_es[p_input->stream.i_es_number - 1] = p_es;
510
511     /* Init its values */
512     p_es->i_id = i_es_id;
513     p_es->psz_desc[0] = '\0';
514     p_es->p_pes = NULL;
515     p_es->p_decoder_fifo = NULL;
516     p_es->b_audio = 0;
517     p_es->i_cat = UNKNOWN_ES;
518     p_es->i_demux_fd = 0;
519
520     if( i_data_len )
521     {
522         p_es->p_demux_data = malloc( i_data_len );
523         if( p_es->p_demux_data == NULL )
524         {
525             intf_ErrMsg( "Unable to allocate memory in input_AddES" );
526             return( NULL );
527         }
528         memset( p_es->p_demux_data, 0, i_data_len );
529     }
530     else
531     {
532         p_es->p_demux_data = NULL;
533     }
534
535     /* Add this ES to the program definition if one is given */
536     if( p_pgrm )
537     {
538         p_pgrm->i_es_number++;
539         if( p_pgrm->i_es_number > 0 )
540         {
541             p_pgrm->pp_es = realloc( p_pgrm->pp_es,
542                                      p_pgrm->i_es_number
543                                       * sizeof(es_descriptor_t *) );
544             if( p_pgrm->pp_es == NULL )
545             {
546                 intf_ErrMsg( "Unable to realloc memory in input_AddES" );
547                 return( NULL );
548             }
549         }
550         else
551         {
552             intf_ErrMsg( "realloc(0) (p_pgrm->i_es_number corrupted ?)");
553             return( NULL );
554         }
555         p_pgrm->pp_es[p_pgrm->i_es_number - 1] = p_es;
556         p_es->p_pgrm = p_pgrm;
557     }
558     else
559     {
560         p_es->p_pgrm = NULL;
561     }
562
563     return p_es;
564 }
565
566 /*****************************************************************************
567  * input_DelES:
568  *****************************************************************************/
569 void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
570 {
571     int                     i_index, i_es_index;
572     pgrm_descriptor_t *     p_pgrm;
573
574     ASSERT( p_es );
575     p_pgrm = p_es->p_pgrm;
576
577     /* Kill associated decoder, if any. */
578     if( p_es->p_decoder_fifo != NULL )
579     {
580         input_EndDecoder( p_input, p_es );
581     }
582
583     /* Remove this ES from the description of the program if it is associated to
584      * one */
585     if( p_pgrm )
586     {
587         for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
588         {
589             if( p_pgrm->pp_es[i_index] == p_es )
590             {
591                 p_pgrm->i_es_number--;
592                 p_pgrm->pp_es[i_index] = p_pgrm->pp_es[p_pgrm->i_es_number];
593                 if( p_pgrm->i_es_number > 0 )
594                 {
595                     p_pgrm->pp_es = realloc( p_pgrm->pp_es,
596                                              p_pgrm->i_es_number
597                                               * sizeof(es_descriptor_t *));
598                     if( p_pgrm->pp_es == NULL )
599                     {
600                         intf_ErrMsg( "Unable to realloc memory in "
601                                      "input_DelES" );
602                     }
603                 }
604                 else
605                 {
606                     free( p_pgrm->pp_es );
607                 }
608                 break;
609             }
610         }
611     }
612
613     /* Free the demux data */
614     if( p_es->p_demux_data != NULL )
615     {
616         free( p_es->p_demux_data );
617     }
618
619     /* Find the ES in the ES table */
620     for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
621          i_es_index++ )
622     {
623         if( p_input->stream.pp_es[i_es_index] == p_es )
624             break;
625     }
626
627     /* Free the ES */
628     free( p_es );
629     p_input->stream.i_es_number--;
630     p_input->stream.pp_es[i_es_index] =
631                     p_input->stream.pp_es[p_input->stream.i_es_number];
632     if( p_input->stream.i_es_number > 0 )
633     {
634         p_input->stream.pp_es = realloc( p_input->stream.pp_es,
635                                          p_input->stream.i_es_number
636                                           * sizeof(es_descriptor_t *));
637         if( p_input->stream.pp_es == NULL )
638         {
639             intf_ErrMsg( "Unable to realloc memory in input_DelES" );
640         }
641     }
642     else
643     {
644         free( p_input->stream.pp_es );
645     }
646     
647 }
648
649 /*****************************************************************************
650  * input_SelectES: selects an ES and spawns the associated decoder
651  *****************************************************************************
652  * Remember we are still supposed to have stream_lock when entering this
653  * function ?
654  *****************************************************************************/
655 int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
656 {
657     if( p_es == NULL )
658     {
659         intf_ErrMsg( "input error: nothing to do in input_SelectES" );
660         return -1;
661     }
662
663     intf_WarnMsg( 4, "input: selecting ES 0x%x", p_es->i_id );
664
665     if( p_es->p_decoder_fifo != NULL )
666     {
667         intf_ErrMsg( "ES 0x%x is already selected", p_es->i_id );
668         return( -1 );
669     }
670
671     p_es->thread_id = 0;
672
673     switch( p_es->i_type )
674     {
675     case AC3_AUDIO_ES:
676     case MPEG1_AUDIO_ES:
677     case MPEG2_AUDIO_ES:
678     case LPCM_AUDIO_ES:
679         if( p_main->b_audio )
680         {
681             /* Release the lock, not to block the input thread during
682              * the creation of the thread. */
683             vlc_mutex_unlock( &p_input->stream.stream_lock );
684             p_es->thread_id = input_RunDecoder( p_input, p_es );
685             vlc_mutex_lock( &p_input->stream.stream_lock );
686         }
687         break;
688
689     case MPEG1_VIDEO_ES:
690     case MPEG2_VIDEO_ES:
691     case MPEG4_VIDEO_ES:
692     case MSMPEG4v1_VIDEO_ES:
693     case MSMPEG4v2_VIDEO_ES:
694     case MSMPEG4v3_VIDEO_ES:
695     case DVD_SPU_ES:
696         if( p_main->b_video )
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( p_input, p_es );
702             vlc_mutex_lock( &p_input->stream.stream_lock );
703         }
704         break;
705
706     default:
707         intf_ErrMsg( "Unknown stream type 0x%x", p_es->i_type );
708         return( -1 );
709         break;
710     }
711
712     if( p_es->thread_id == 0 )
713     {
714         return( -1 );
715     }
716
717     return( 0 );
718 }
719
720 /*****************************************************************************
721  * input_UnselectES: removes an ES from the list of selected ES
722  *****************************************************************************/
723 int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
724 {
725
726     int     i_index = 0;
727
728     if( p_es == NULL )
729     {
730         intf_ErrMsg( "Nothing to do in input_UnselectES" );
731         return -1;
732     }
733
734     intf_WarnMsg( 4, "input: unselecting ES 0x%x", p_es->i_id );
735
736     if( p_es->p_decoder_fifo == NULL )
737     {
738         intf_ErrMsg( "ES 0x%x is not selected", p_es->i_id );
739         return( -1 );
740     }
741
742     input_EndDecoder( p_input, p_es );
743     p_es->p_pes = NULL;
744
745     if( ( p_es->p_decoder_fifo == NULL ) &&
746         ( p_input->stream.i_selected_es_number > 0 ) )
747     {
748         p_input->stream.i_selected_es_number--;
749
750         while( ( i_index < p_input->stream.i_selected_es_number ) &&
751                ( p_input->stream.pp_selected_es[i_index] != p_es ) )
752         {
753             i_index++;
754         }
755
756         p_input->stream.pp_selected_es[i_index] = 
757           p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number];
758
759         if( p_input->stream.i_selected_es_number > 0 )
760         {
761             p_input->stream.pp_selected_es = realloc(
762                                            p_input->stream.pp_selected_es,
763                                            p_input->stream.i_selected_es_number
764                                            * sizeof(es_descriptor_t *) );
765             if( p_input->stream.pp_selected_es == NULL )
766             {
767                 intf_ErrMsg( "Unable to realloc memory in input_UnselectES" );
768                 return( -1 );
769             }
770         }
771         else
772         {
773             free( p_input->stream.pp_selected_es );   
774             intf_WarnMsg( 4, "input: no more selected ES in input_UnselectES" );            return( 1 );
775         }
776     }
777
778     return( 0 );
779 }