96c2cdf0ecb4a4b0e4d1bfc0d67ded138966305d
[vlc.git] / src / input / input_programs.c
1 /*****************************************************************************
2  * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
3  *****************************************************************************
4  * Copyright (C) 1999-2002 VideoLAN
5  * $Id: input_programs.c,v 1.101 2003/01/31 11:23:37 massiot 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
30 #include <vlc/vlc.h>
31
32 #include "stream_control.h"
33 #include "input_ext-intf.h"
34 #include "input_ext-dec.h"
35 #include "input_ext-plugins.h"
36
37 /*
38  * NOTICE : all of these functions expect you to have taken the lock on
39  * p_input->stream.lock
40  */
41
42 /*****************************************************************************
43  * input_InitStream: init the stream descriptor of the given input
44  *****************************************************************************/
45 int input_InitStream( input_thread_t * p_input, size_t i_data_len )
46 {
47
48     p_input->stream.i_stream_id = 0;
49
50     /* initialized to 0 since we don't give the signal to the interface
51      * before the end of input initialization */
52     p_input->stream.b_changed = 0;
53     p_input->stream.pp_es = NULL;
54     p_input->stream.pp_selected_es = NULL;
55     p_input->stream.p_removed_es = NULL;
56     p_input->stream.p_newly_selected_es = NULL;
57     p_input->stream.pp_programs = NULL;
58     p_input->stream.p_selected_program = NULL;
59     p_input->stream.p_new_program = NULL;
60
61     if( i_data_len )
62     {
63         if ( (p_input->stream.p_demux_data = malloc( i_data_len )) == NULL )
64         {
65             msg_Err( p_input, "out of memory" );
66             return 1;
67         }
68         memset( p_input->stream.p_demux_data, 0, i_data_len );
69     }
70     else
71     {
72         p_input->stream.p_demux_data = NULL;
73     }
74
75     return 0;
76 }
77
78 /*****************************************************************************
79  * input_EndStream: free all stream descriptors
80  *****************************************************************************/
81 void input_EndStream( input_thread_t * p_input )
82 {
83     /* Free all programs and associated ES, and associated decoders. */
84     while( p_input->stream.i_pgrm_number )
85     {
86         input_DelProgram( p_input, p_input->stream.pp_programs[0] );
87     }
88
89     /* Free standalone ES */
90     while( p_input->stream.i_es_number )
91     {
92         input_DelES( p_input, p_input->stream.pp_es[0] );
93     }
94
95     /* Free all areas */
96     while( p_input->stream.i_area_nb )
97     {
98         input_DelArea( p_input, p_input->stream.pp_areas[0] );
99     }
100
101     /* Free selected ES */
102     if( p_input->stream.pp_selected_es != NULL )
103     {
104         free( p_input->stream.pp_selected_es );
105     }
106
107     if( p_input->stream.p_demux_data != NULL )
108     {
109         free( p_input->stream.p_demux_data );
110     }
111 }
112
113 /*****************************************************************************
114  * input_FindProgram: returns a pointer to a program described by its ID
115  *****************************************************************************/
116 pgrm_descriptor_t * input_FindProgram( input_thread_t * p_input,
117                                        uint16_t i_pgrm_id )
118 {
119     unsigned 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     pgrm_descriptor_t * p_pgrm = malloc( sizeof(pgrm_descriptor_t) );
142
143     if( p_pgrm == NULL )
144     {
145         msg_Err( p_input, "out of memory" );
146         return NULL;
147     }
148
149     /* Init this entry */
150     p_pgrm->i_number = i_pgrm_id;
151     p_pgrm->b_is_ok = 0;
152     p_pgrm->i_version = 0;
153
154     p_pgrm->i_es_number = 0;
155     p_pgrm->pp_es = NULL;
156
157     input_ClockInit( p_pgrm );
158
159     p_pgrm->i_synchro_state = SYNCHRO_START;
160
161     if( i_data_len )
162     {
163         p_pgrm->p_demux_data = malloc( i_data_len );
164         if( p_pgrm->p_demux_data == NULL )
165         {
166             msg_Err( p_input, "out of memory" );
167             return NULL;
168         }
169         memset( p_pgrm->p_demux_data, 0, i_data_len );
170     }
171     else
172     {
173         p_pgrm->p_demux_data = NULL;
174     }
175
176     /* Add an entry to the list of program associated with the stream */
177     INSERT_ELEM( p_input->stream.pp_programs,
178                  p_input->stream.i_pgrm_number,
179                  p_input->stream.i_pgrm_number,
180                  p_pgrm );
181
182     return p_pgrm;
183 }
184
185 /*****************************************************************************
186  * input_DelProgram: destroy a program descriptor
187  *****************************************************************************
188  * All ES descriptions referenced in the descriptor will be deleted.
189  *****************************************************************************/
190 void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
191 {
192     unsigned int i_pgrm_index;
193
194     /* Find the program in the programs table */
195     for( i_pgrm_index = 0; i_pgrm_index < p_input->stream.i_pgrm_number;
196          i_pgrm_index++ )
197     {
198         if( p_input->stream.pp_programs[i_pgrm_index] == p_pgrm )
199             break;
200     }
201
202     /* If the program wasn't found, do nothing */
203     if( i_pgrm_index == p_input->stream.i_pgrm_number )
204     {
205         msg_Err( p_input, "program does not belong to this input" );
206         return;
207     }
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     /* Remove this program from the stream's list of programs */
222     REMOVE_ELEM( p_input->stream.pp_programs,
223                  p_input->stream.i_pgrm_number,
224                  i_pgrm_index );
225
226     /* Free the description of this program */
227     free( p_pgrm );
228 }
229
230 /*****************************************************************************
231  * input_AddArea: add and init an area descriptor
232  *****************************************************************************
233  * This area descriptor will be referenced in the given stream descriptor
234  *****************************************************************************/
235 input_area_t * input_AddArea( input_thread_t * p_input )
236 {
237     /* Where to add the pgrm */
238     input_area_t * p_area = malloc( sizeof(input_area_t) );
239
240     if( p_area == NULL )
241     {
242         msg_Err( p_input, "out of memory" );
243         return NULL;
244     }
245
246     /* Init this entry */
247     p_area->i_id = 0;
248     p_area->i_start = 0;
249     p_area->i_size = 0;
250     p_area->i_tell = 0;
251     p_area->i_seek = NO_SEEK;
252     p_area->i_part_nb = 1;
253     p_area->i_part= 0;
254
255     /* Add an entry to the list of program associated with the stream */
256     INSERT_ELEM( p_input->stream.pp_areas,
257                  p_input->stream.i_area_nb,
258                  p_input->stream.i_area_nb,
259                  p_area );
260
261     return p_area;
262 }
263
264 /*****************************************************************************
265  * input_SetProgram: changes the current program
266  *****************************************************************************/
267 int input_SetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_new_prg )
268 {
269     unsigned int i_es_index;
270     int i_required_audio_es;
271     int i_required_spu_es;
272     int i_audio_es = 0;
273     int i_spu_es = 0;
274
275     if ( p_input->stream.p_selected_program )
276     {
277         for ( i_es_index = 1 ; /* 0 should be the PMT */
278                 i_es_index < p_input->stream.p_selected_program->
279                 i_es_number ;
280                 i_es_index ++ )
281         {
282 #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
283             if ( p_es->p_decoder_fifo ) /* if the ES was selected */
284             {
285                 input_UnselectES( p_input , p_es );
286             }
287 #undef p_es
288         }
289     }
290     /* Get the number of the required audio stream */
291     if( config_GetInt( p_input, "audio" ) )
292     {
293         /* Default is the first one */
294         i_required_audio_es = config_GetInt( p_input, "audio-channel" );
295         if( i_required_audio_es < 0 )
296         {
297             i_required_audio_es = 1;
298         }
299     }
300     else
301     {
302         i_required_audio_es = 0;
303     }
304
305     /* Same thing for subtitles */
306     if( config_GetInt( p_input, "video" ) )
307     {
308         /* for spu, default is none */
309         i_required_spu_es = config_GetInt( p_input, "spu-channel" );
310         if( i_required_spu_es < 0 )
311         {
312             i_required_spu_es = 0;
313         }
314     }
315     else
316     {
317         i_required_spu_es = 0;
318     }
319
320     for( i_es_index = 0 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
321     {
322         switch( p_new_prg->pp_es[i_es_index]->i_cat )
323         {
324             case VIDEO_ES:
325                 msg_Dbg( p_input, "selecting ES %x",
326                          p_new_prg->pp_es[i_es_index]->i_id );
327                 input_SelectES( p_input, p_new_prg->pp_es[i_es_index] );
328                 break;
329             case AUDIO_ES:
330                 i_audio_es += 1;
331                 if( i_audio_es <= i_required_audio_es )
332                 {
333                     msg_Dbg( p_input, "selecting ES %x",
334                              p_new_prg->pp_es[i_es_index]->i_id );
335                     input_SelectES( p_input, p_new_prg->pp_es[i_es_index]);
336                 }
337                 break;
338             /* Not sure this one is fully specification-compliant */
339             case SPU_ES :
340                 i_spu_es += 1;
341                 if( i_spu_es <= i_required_spu_es )
342                 {
343                     msg_Dbg( p_input, "selecting ES %x",
344                              p_new_prg->pp_es[i_es_index]->i_id );
345                     input_SelectES( p_input, p_new_prg->pp_es[i_es_index] );
346                 }
347             break;
348             default :
349                 msg_Dbg( p_input, "ES %x has unknown type",
350                          p_new_prg->pp_es[i_es_index]->i_id );
351                 break;
352         }
353
354     }
355
356
357     p_input->stream.p_selected_program = p_new_prg;
358
359     return( 0 );
360 }
361
362
363 /*****************************************************************************
364  * input_DelArea: destroy a area descriptor
365  *****************************************************************************
366  * All ES descriptions referenced in the descriptor will be deleted.
367  *****************************************************************************/
368 void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
369 {
370     unsigned int i_area_index;
371
372     /* Find the area in the areas table */
373     for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb;
374          i_area_index++ )
375     {
376         if( p_input->stream.pp_areas[i_area_index] == p_area )
377             break;
378     }
379
380     /* If the area wasn't found, do nothing */
381     if( i_area_index == p_input->stream.i_area_nb )
382     {
383         msg_Err( p_input, "area does not belong to this input" );
384         return;
385     }
386
387     /* Remove this area from the stream's list of areas */
388     REMOVE_ELEM( p_input->stream.pp_areas,
389                  p_input->stream.i_area_nb,
390                  i_area_index );
391
392     /* Free the description of this area */
393     free( p_area );
394 }
395
396
397 /*****************************************************************************
398  * input_FindES: returns a pointer to an ES described by its ID
399  *****************************************************************************/
400 es_descriptor_t * input_FindES( input_thread_t * p_input, uint16_t i_es_id )
401 {
402     unsigned int i;
403
404     for( i = 0; i < p_input->stream.i_es_number; i++ )
405     {
406         if( p_input->stream.pp_es[i]->i_id == i_es_id )
407         {
408             return p_input->stream.pp_es[i];
409         }
410     }
411
412     return NULL;
413 }
414
415 /*****************************************************************************
416  * input_AddES:
417  *****************************************************************************
418  * Reserve a slot in the table of ES descriptors for the ES and add it to the
419  * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
420  * alone (PSI ?)
421  *****************************************************************************/
422 es_descriptor_t * input_AddES( input_thread_t * p_input,
423                                pgrm_descriptor_t * p_pgrm, u16 i_es_id,
424                                size_t i_data_len )
425 {
426     es_descriptor_t * p_es;
427
428     p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
429     if( p_es == NULL )
430     {
431         msg_Err( p_input, "out of memory" );
432         return( NULL);
433     }
434
435     INSERT_ELEM( p_input->stream.pp_es,
436                  p_input->stream.i_es_number,
437                  p_input->stream.i_es_number,
438                  p_es );
439
440     /* Init its values */
441     p_es->i_id = i_es_id;
442     p_es->psz_desc[0] = '\0';
443     p_es->p_pes = NULL;
444     p_es->p_decoder_fifo = NULL;
445     p_es->i_cat = UNKNOWN_ES;
446     p_es->i_demux_fd = 0;
447     p_es->c_packets = 0;
448     p_es->c_invalid_packets = 0;
449
450     if( i_data_len )
451     {
452         p_es->p_demux_data = malloc( i_data_len );
453         if( p_es->p_demux_data == NULL )
454         {
455             msg_Err( p_input, "out of memory" );
456             return( NULL );
457         }
458         memset( p_es->p_demux_data, 0, i_data_len );
459     }
460     else
461     {
462         p_es->p_demux_data = NULL;
463     }
464     p_es->p_waveformatex     = NULL;
465     p_es->p_bitmapinfoheader = NULL;
466
467     /* Add this ES to the program definition if one is given */
468     if( p_pgrm )
469     {
470         INSERT_ELEM( p_pgrm->pp_es,
471                      p_pgrm->i_es_number,
472                      p_pgrm->i_es_number,
473                      p_es );
474         p_es->p_pgrm = p_pgrm;
475     }
476     else
477     {
478         p_es->p_pgrm = NULL;
479     }
480
481     return p_es;
482 }
483
484 /*****************************************************************************
485  * input_DelES:
486  *****************************************************************************/
487 void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
488 {
489     unsigned int            i_index, i_es_index;
490     pgrm_descriptor_t *     p_pgrm;
491
492     /* Find the ES in the ES table */
493     for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
494          i_es_index++ )
495     {
496         if( p_input->stream.pp_es[i_es_index] == p_es )
497             break;
498     }
499
500     /* If the ES wasn't found, do nothing */
501     if( i_es_index == p_input->stream.i_es_number )
502     {
503         msg_Err( p_input, "ES does not belong to this input" );
504         return;
505     }
506
507     p_pgrm = p_es->p_pgrm;
508
509     /* Kill associated decoder, if any. */
510     if( p_es->p_decoder_fifo != NULL )
511     {
512         input_EndDecoder( p_input, p_es );
513     }
514
515     /* Remove this ES from the description of the program if it is associated to
516      * one */
517     if( p_pgrm )
518     {
519         for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
520         {
521             if( p_pgrm->pp_es[i_index] == p_es )
522             {
523                 REMOVE_ELEM( p_pgrm->pp_es,
524                              p_pgrm->i_es_number,
525                              i_index );
526                 break;
527             }
528         }
529     }
530
531     /* Free the demux data */
532     if( p_es->p_demux_data != NULL )
533     {
534         free( p_es->p_demux_data );
535     }
536     if( p_es->p_waveformatex )
537     {
538         free( p_es->p_waveformatex );
539     }
540     if( p_es->p_bitmapinfoheader )
541     {
542         free( p_es->p_bitmapinfoheader );
543     }
544
545     /* Find the ES in the ES table */
546     for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
547          i_es_index++ )
548     {
549         if( p_input->stream.pp_es[i_es_index] == p_es )
550             break;
551     }
552
553     /* Remove this ES from the stream's list of ES */
554     REMOVE_ELEM( p_input->stream.pp_es,
555                  p_input->stream.i_es_number,
556                  i_es_index );
557
558     /* Free the ES */
559     free( p_es );
560 }
561
562 /*****************************************************************************
563  * input_SelectES: selects an ES and spawns the associated decoder
564  *****************************************************************************
565  * Remember we are still supposed to have stream_lock when entering this
566  * function ?
567  *****************************************************************************/
568 int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
569 {
570     if( p_es == NULL )
571     {
572         msg_Err( p_input, "nothing to do in input_SelectES" );
573         return -1;
574     }
575
576     if( ((p_es->i_cat == VIDEO_ES) || (p_es->i_cat == SPU_ES))
577         && !config_GetInt( p_input, "video" ) )
578     {
579         msg_Dbg( p_input,
580                  "video is disabled, not selecting ES 0x%x", p_es->i_id );
581         return -1;
582     }
583
584     if( (p_es->i_cat == AUDIO_ES) && !config_GetInt( p_input, "audio" ) )
585     {
586         msg_Dbg( p_input,
587                  "audio is disabled, not selecting ES 0x%x", p_es->i_id );
588         return -1;
589     }
590
591     msg_Dbg( p_input, "selecting ES 0x%x", p_es->i_id );
592
593     if( p_es->p_decoder_fifo != NULL )
594     {
595         msg_Err( p_input, "ES 0x%x is already selected", p_es->i_id );
596         return -1;
597     }
598
599     /* Release the lock, not to block the input thread during
600      * the creation of the thread. */
601     vlc_mutex_unlock( &p_input->stream.stream_lock );
602     p_es->p_decoder_fifo = input_RunDecoder( p_input, p_es );
603     vlc_mutex_lock( &p_input->stream.stream_lock );
604
605     if( p_es->p_decoder_fifo == NULL )
606     {
607         return -1;
608     }
609
610     return 0;
611 }
612
613 /*****************************************************************************
614  * input_UnselectES: removes an ES from the list of selected ES
615  *****************************************************************************/
616 int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
617 {
618
619     unsigned int i_index = 0;
620
621     if( p_es == NULL )
622     {
623         msg_Err( p_input, "nothing to do in input_UnselectES" );
624         return -1;
625     }
626
627     msg_Dbg( p_input, "unselecting ES 0x%x", p_es->i_id );
628
629     if( p_es->p_decoder_fifo == NULL )
630     {
631         msg_Err( p_input, "ES 0x%x is not selected", p_es->i_id );
632         return( -1 );
633     }
634
635     input_EndDecoder( p_input, p_es );
636     p_es->p_pes = NULL;
637
638     if( ( p_es->p_decoder_fifo == NULL ) &&
639         ( p_input->stream.i_selected_es_number > 0 ) )
640     {
641         while( ( i_index < p_input->stream.i_selected_es_number - 1 ) &&
642                ( p_input->stream.pp_selected_es[i_index] != p_es ) )
643         {
644             i_index++;
645         }
646
647         /* XXX: no need to memmove, we have unsorted data */
648         REMOVE_ELEM( p_input->stream.pp_selected_es,
649                      p_input->stream.i_selected_es_number,
650                      i_index );
651
652         if( p_input->stream.i_selected_es_number == 0 )
653         {
654             msg_Dbg( p_input, "no more selected ES" );
655             return 1;
656         }
657     }
658
659     return 0;
660 }