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