]> git.sesse.net Git - vlc/blob - src/input/input_programs.c
* fixed a bug in input_SetProgram, that made the ps file input
[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.79 2002/04/10 16:26:21 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     int i_required_audio_es;
297     int i_required_spu_es;
298     int i_audio_es = 0;
299     int i_spu_es = 0;
300
301     if ( p_input->stream.p_selected_program )
302     {
303         for ( i_es_index = 1 ; /* 0 should be the PMT */
304                 i_es_index < p_input->stream.p_selected_program->
305                 i_es_number ;
306                 i_es_index ++ )
307         {
308 #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
309             if ( p_es->p_decoder_fifo )
310             {
311                 input_UnselectES( p_input , p_es );
312             }
313 #undef p_es
314         }
315     }
316     /* Get the number of the required audio stream */
317     if( p_main->b_audio )
318     {
319         /* Default is the first one */
320         i_required_audio_es = config_GetIntVariable( "input_channel" );
321         if( i_required_audio_es < 0 )
322         {
323             i_required_audio_es = 1;
324         }
325     }
326     else
327     {
328         i_required_audio_es = 0;
329     }
330
331     /* Same thing for subtitles */
332     if( p_main->b_video )
333     {
334         /* for spu, default is none */
335         i_required_spu_es = config_GetIntVariable( "input_subtitle" );
336         if( i_required_spu_es < 0 )
337         {
338             i_required_spu_es = 0;
339         }
340     }
341     else
342     {
343         i_required_spu_es = 0;
344     }
345
346     for (i_es_index = 0 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
347     {
348         switch( p_new_prg->pp_es[i_es_index]->i_cat )
349                     {
350                        case VIDEO_ES:
351                            intf_WarnMsg( 4, "Selecting ES %x",
352                                     p_new_prg->pp_es[i_es_index]->i_id );
353                             input_SelectES( p_input,
354                                    p_new_prg->pp_es[i_es_index] );
355                             break;
356                         case 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                         /* Not sure this one is fully specification-compliant */
367                         case SPU_ES :
368                             i_spu_es += 1;
369                             if( i_spu_es <= i_required_spu_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                         default :
378                             break;
379                     }
380
381     }
382
383
384     p_input->stream.p_selected_program = p_new_prg;
385
386     return( 0 );
387 }
388
389
390 /*****************************************************************************
391  * input_DelArea: destroy a area descriptor
392  *****************************************************************************
393  * All ES descriptions referenced in the descriptor will be deleted.
394  *****************************************************************************/
395 void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
396 {
397     int i_area_index;
398
399     ASSERT( p_area );
400
401     /* Find the area in the areas table */
402     for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb;
403          i_area_index++ )
404     {
405         if( p_input->stream.pp_areas[i_area_index] == p_area )
406             break;
407     }
408
409     /* Remove this area from the stream's list of areas */
410     p_input->stream.i_area_nb--;
411
412     p_input->stream.pp_areas[i_area_index] =
413         p_input->stream.pp_areas[p_input->stream.i_area_nb];
414     p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
415                                            p_input->stream.i_area_nb
416                                             * sizeof(input_area_t *) );
417
418     if( p_input->stream.i_area_nb && p_input->stream.pp_areas == NULL)
419     {
420         intf_ErrMsg( "input error: unable to realloc area list"
421                      " in input_DelArea" );
422     }
423
424     /* Free the description of this area */
425     free( p_area );
426 }
427
428
429 /*****************************************************************************
430  * input_FindES: returns a pointer to an ES described by its ID
431  *****************************************************************************/
432 es_descriptor_t * input_FindES( input_thread_t * p_input, u16 i_es_id )
433 {
434     int     i;
435
436     for( i = 0; i < p_input->stream.i_es_number; i++ )
437     {
438         if( p_input->stream.pp_es[i]->i_id == i_es_id )
439         {
440             return p_input->stream.pp_es[i];
441         }
442     }
443
444     return( NULL );
445 }
446
447 /*****************************************************************************
448  * input_AddES:
449  *****************************************************************************
450  * Reserve a slot in the table of ES descriptors for the ES and add it to the
451  * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
452  * alone (PSI ?)
453  *****************************************************************************/
454 es_descriptor_t * input_AddES( input_thread_t * p_input,
455                                pgrm_descriptor_t * p_pgrm, u16 i_es_id,
456                                size_t i_data_len )
457 {
458     es_descriptor_t * p_es;
459
460     p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
461     if( p_es == NULL )
462     {
463         intf_ErrMsg( "Unable to allocate memory in input_AddES" );
464         return( NULL);
465     }
466     p_input->stream.i_es_number++;
467     p_input->stream.pp_es = realloc( p_input->stream.pp_es,
468                                      p_input->stream.i_es_number
469                                       * sizeof(es_descriptor_t *) );
470     if( p_input->stream.pp_es == NULL )
471     {
472         intf_ErrMsg( "Unable to realloc memory in input_AddES" );
473         return( NULL );
474     }
475     p_input->stream.pp_es[p_input->stream.i_es_number - 1] = p_es;
476
477     /* Init its values */
478     p_es->i_id = i_es_id;
479     p_es->psz_desc[0] = '\0';
480     p_es->p_pes = NULL;
481     p_es->p_decoder_fifo = NULL;
482     p_es->b_audio = 0;
483     p_es->i_cat = UNKNOWN_ES;
484 #ifdef HAVE_SATELLITE
485     p_es->i_dmx_fd = 0;
486 #endif
487
488     if( i_data_len )
489     {
490         p_es->p_demux_data = malloc( i_data_len );
491         if( p_es->p_demux_data == NULL )
492         {
493             intf_ErrMsg( "Unable to allocate memory in input_AddES" );
494             return( NULL );
495         }
496         memset( p_es->p_demux_data, 0, i_data_len );
497     }
498     else
499     {
500         p_es->p_demux_data = NULL;
501     }
502
503     /* Add this ES to the program definition if one is given */
504     if( p_pgrm )
505     {
506         p_pgrm->i_es_number++;
507         p_pgrm->pp_es = realloc( p_pgrm->pp_es,
508                                  p_pgrm->i_es_number
509                                   * sizeof(es_descriptor_t *) );
510         if( p_pgrm->pp_es == NULL )
511         {
512             intf_ErrMsg( "Unable to realloc memory in input_AddES" );
513             return( NULL );
514         }
515         p_pgrm->pp_es[p_pgrm->i_es_number - 1] = p_es;
516         p_es->p_pgrm = p_pgrm;
517     }
518     else
519     {
520         p_es->p_pgrm = NULL;
521     }
522
523     return p_es;
524 }
525
526 /*****************************************************************************
527  * input_DelES:
528  *****************************************************************************/
529 void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
530 {
531     int                     i_index, i_es_index;
532     pgrm_descriptor_t *     p_pgrm;
533
534     ASSERT( p_es );
535     p_pgrm = p_es->p_pgrm;
536
537     /* Kill associated decoder, if any. */
538     if( p_es->p_decoder_fifo != NULL )
539     {
540         input_EndDecoder( p_input, p_es );
541     }
542
543     /* Remove this ES from the description of the program if it is associated to
544      * one */
545     if( p_pgrm )
546     {
547         for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
548         {
549             if( p_pgrm->pp_es[i_index] == p_es )
550             {
551                 p_pgrm->i_es_number--;
552                 p_pgrm->pp_es[i_index] = p_pgrm->pp_es[p_pgrm->i_es_number];
553                 p_pgrm->pp_es = realloc( p_pgrm->pp_es,
554                                          p_pgrm->i_es_number
555                                           * sizeof(es_descriptor_t *));
556                 if( p_pgrm->i_es_number && p_pgrm->pp_es == NULL )
557                 {
558                     intf_ErrMsg( "Unable to realloc memory in input_DelES" );
559                 }
560                 break;
561             }
562         }
563     }
564
565     /* Free the demux data */
566     if( p_es->p_demux_data != NULL )
567     {
568         free( p_es->p_demux_data );
569     }
570
571     /* Find the ES in the ES table */
572     for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
573          i_es_index++ )
574     {
575         if( p_input->stream.pp_es[i_es_index] == p_es )
576             break;
577     }
578
579     /* Free the ES */
580     free( p_es );
581     p_input->stream.i_es_number--;
582     p_input->stream.pp_es[i_es_index] =
583                     p_input->stream.pp_es[p_input->stream.i_es_number];
584     p_input->stream.pp_es = realloc( p_input->stream.pp_es,
585                                      p_input->stream.i_es_number
586                                       * sizeof(es_descriptor_t *));
587     if( p_input->stream.i_es_number && p_input->stream.pp_es == NULL )
588     {
589         intf_ErrMsg( "Unable to realloc memory in input_DelES" );
590     }
591     
592 }
593
594 /*****************************************************************************
595  * input_SelectES: selects an ES and spawns the associated decoder
596  *****************************************************************************
597  * Remember we are still supposed to have stream_lock when entering this
598  * function ?
599  *****************************************************************************/
600 int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
601 {
602     if( p_es == NULL )
603     {
604         intf_ErrMsg( "input error: nothing to do in input_SelectES" );
605         return -1;
606     }
607
608     intf_WarnMsg( 4, "input: selecting ES 0x%x", p_es->i_id );
609
610     if( p_es->p_decoder_fifo != NULL )
611     {
612         intf_ErrMsg( "ES 0x%x is already selected", p_es->i_id );
613         return( -1 );
614     }
615
616     p_es->thread_id = 0;
617
618     switch( p_es->i_type )
619     {
620     case AC3_AUDIO_ES:
621     case MPEG1_AUDIO_ES:
622     case MPEG2_AUDIO_ES:
623     case LPCM_AUDIO_ES:
624         if( p_main->b_audio )
625         {
626             /* Release the lock, not to block the input thread during
627              * the creation of the thread. */
628             vlc_mutex_unlock( &p_input->stream.stream_lock );
629             p_es->thread_id = input_RunDecoder( p_input, p_es );
630             vlc_mutex_lock( &p_input->stream.stream_lock );
631         }
632         break;
633
634     case MPEG1_VIDEO_ES:
635     case MPEG2_VIDEO_ES:
636     case DVD_SPU_ES:
637         if( p_main->b_video )
638         {
639             /* Release the lock, not to block the input thread during
640              * the creation of the thread. */
641             vlc_mutex_unlock( &p_input->stream.stream_lock );
642             p_es->thread_id = input_RunDecoder( p_input, p_es );
643             vlc_mutex_lock( &p_input->stream.stream_lock );
644         }
645         break;
646
647     default:
648         intf_ErrMsg( "Unknown stream type 0x%x", p_es->i_type );
649         return( -1 );
650         break;
651     }
652
653     if( p_es->thread_id == 0 )
654     {
655         return( -1 );
656     }
657
658     return( 0 );
659 }
660
661 /*****************************************************************************
662  * input_UnselectES: removes an ES from the list of selected ES
663  *****************************************************************************/
664 int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
665 {
666
667     int     i_index = 0;
668
669     if( p_es == NULL )
670     {
671         intf_ErrMsg( "Nothing to do in input_UnselectES" );
672         return -1;
673     }
674
675     intf_WarnMsg( 4, "input: unselecting ES 0x%x", p_es->i_id );
676
677     if( p_es->p_decoder_fifo == NULL )
678     {
679         intf_ErrMsg( "ES 0x%x is not selected", p_es->i_id );
680         return( -1 );
681     }
682
683     input_EndDecoder( p_input, p_es );
684     p_es->p_pes = NULL;
685
686     if( ( p_es->p_decoder_fifo == NULL ) &&
687         ( p_input->stream.i_selected_es_number > 0 ) )
688     {
689         p_input->stream.i_selected_es_number--;
690
691         while( ( i_index < p_input->stream.i_selected_es_number ) &&
692                ( p_input->stream.pp_selected_es[i_index] != p_es ) )
693         {
694             i_index++;
695         }
696
697         p_input->stream.pp_selected_es[i_index] = 
698           p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number];
699
700         p_input->stream.pp_selected_es = realloc(
701                                            p_input->stream.pp_selected_es,
702                                            p_input->stream.i_selected_es_number
703                                             * sizeof(es_descriptor_t *) );
704
705         if( p_input->stream.pp_selected_es == NULL )
706         {
707             intf_WarnMsg( 4, "input: no more selected ES in input_UnselectES" );
708             return( 1 );
709         }
710     }
711
712     return( 0 );
713 }