1 /*****************************************************************************
2 * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
5 * $Id: input_programs.c,v 1.50 2001/04/22 00:08:26 stef Exp $
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
30 #include <string.h> /* memcpy(), memset() */
40 #include "stream_control.h"
41 #include "input_ext-intf.h"
42 #include "input_ext-dec.h"
45 #include "main.h" /* --noaudio --novideo */
48 * NOTICE : all of these functions expect you to have taken the lock on
49 * p_input->stream.lock
52 /*****************************************************************************
53 * input_InitStream: init the stream descriptor of the given input
54 *****************************************************************************/
55 int input_InitStream( input_thread_t * p_input, size_t i_data_len )
58 p_input->stream.i_method = INPUT_METHOD_NONE;
59 p_input->stream.i_stream_id = 0;
61 /* initialized to 0 since we don't give the signal to the interface
62 * before the end of input initialization */
63 p_input->stream.b_changed = 0;
64 p_input->stream.pp_es = NULL;
65 p_input->stream.pp_selected_es = NULL;
66 p_input->stream.pp_programs = NULL;
70 if ( (p_input->stream.p_demux_data = malloc( i_data_len )) == NULL )
72 intf_ErrMsg( "Unable to allocate memory in input_InitStream");
75 memset( p_input->stream.p_demux_data, 0, i_data_len );
81 /*****************************************************************************
82 * input_EndStream: free all stream descriptors
83 *****************************************************************************/
84 void input_EndStream( input_thread_t * p_input )
86 /* Free all programs and associated ES, and associated decoders. */
87 while( p_input->stream.i_pgrm_number )
89 input_DelProgram( p_input, p_input->stream.pp_programs[0] );
92 /* Free standalone ES */
93 while( p_input->stream.i_es_number )
95 input_DelES( p_input, p_input->stream.pp_es[0] );
99 while( p_input->stream.i_area_nb )
101 input_DelArea( p_input, p_input->stream.pp_areas[0] );
104 if( p_input->stream.p_demux_data != NULL )
106 free( p_input->stream.p_demux_data );
110 /*****************************************************************************
111 * input_FindProgram: returns a pointer to a program described by its ID
112 *****************************************************************************/
113 pgrm_descriptor_t * input_FindProgram( input_thread_t * p_input, u16 i_pgrm_id )
117 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
119 if( p_input->stream.pp_programs[i]->i_number == i_pgrm_id )
121 return p_input->stream.pp_programs[i];
128 /*****************************************************************************
129 * input_AddProgram: add and init a program descriptor
130 *****************************************************************************
131 * This program descriptor will be referenced in the given stream descriptor
132 *****************************************************************************/
133 pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input,
134 u16 i_pgrm_id, size_t i_data_len )
136 /* Where to add the pgrm */
137 int i_pgrm_index = p_input->stream.i_pgrm_number;
139 intf_DbgMsg("Adding description for pgrm %d", i_pgrm_id);
141 /* Add an entry to the list of program associated with the stream */
142 p_input->stream.i_pgrm_number++;
143 p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
144 p_input->stream.i_pgrm_number
145 * sizeof(pgrm_descriptor_t *) );
146 if( p_input->stream.pp_programs == NULL )
148 intf_ErrMsg( "Unable to realloc memory in input_AddProgram" );
152 /* Allocate the structure to store this description */
153 p_input->stream.pp_programs[i_pgrm_index] =
154 malloc( sizeof(pgrm_descriptor_t) );
155 if( p_input->stream.pp_programs[i_pgrm_index] == NULL )
157 intf_ErrMsg( "Unable to allocate memory in input_AddProgram" );
161 /* Init this entry */
162 p_input->stream.pp_programs[i_pgrm_index]->i_number = i_pgrm_id;
163 p_input->stream.pp_programs[i_pgrm_index]->b_is_ok = 0;
164 p_input->stream.pp_programs[i_pgrm_index]->i_version = 0;
166 p_input->stream.pp_programs[i_pgrm_index]->i_es_number = 0;
167 p_input->stream.pp_programs[i_pgrm_index]->pp_es = NULL;
169 input_ClockInit( p_input->stream.pp_programs[i_pgrm_index] );
171 p_input->stream.pp_programs[i_pgrm_index]->i_synchro_state
174 p_input->stream.pp_programs[i_pgrm_index]->p_vout
175 = p_input->p_default_vout;
176 p_input->stream.pp_programs[i_pgrm_index]->p_aout
177 = p_input->p_default_aout;
181 p_input->stream.pp_programs[i_pgrm_index]->p_demux_data =
182 malloc( i_data_len );
183 if( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data == NULL )
185 intf_ErrMsg( "Unable to allocate memory in input_AddProgram" );
188 memset( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data, 0,
192 return p_input->stream.pp_programs[i_pgrm_index];
195 /*****************************************************************************
196 * input_DelProgram: destroy a program descriptor
197 *****************************************************************************
198 * All ES descriptions referenced in the descriptor will be deleted.
199 *****************************************************************************/
200 void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
206 intf_DbgMsg("Deleting description for pgrm %d", p_pgrm->i_number);
208 /* Free the structures that describe the es that belongs to that program */
209 while( p_pgrm->i_es_number )
211 input_DelES( p_input, p_pgrm->pp_es[0] );
214 /* Free the demux data */
215 if( p_pgrm->p_demux_data != NULL )
217 free( p_pgrm->p_demux_data );
220 /* Find the program in the programs table */
221 for( i_pgrm_index = 0; i_pgrm_index < p_input->stream.i_pgrm_number;
224 if( p_input->stream.pp_programs[i_pgrm_index] == p_pgrm )
228 /* Remove this program from the stream's list of programs */
229 p_input->stream.i_pgrm_number--;
231 p_input->stream.pp_programs[i_pgrm_index] =
232 p_input->stream.pp_programs[p_input->stream.i_pgrm_number];
233 p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
234 p_input->stream.i_pgrm_number
235 * sizeof(pgrm_descriptor_t *) );
237 if( p_input->stream.i_pgrm_number && p_input->stream.pp_programs == NULL)
239 intf_ErrMsg( "input error: unable to realloc program list"
240 " in input_DelProgram" );
243 /* Free the description of this program */
247 /*****************************************************************************
248 * input_AddArea: add and init an area descriptor
249 *****************************************************************************
250 * This area descriptor will be referenced in the given stream descriptor
251 *****************************************************************************/
252 input_area_t * input_AddArea( input_thread_t * p_input )
254 /* Where to add the pgrm */
255 int i_area_index = p_input->stream.i_area_nb;
257 intf_DbgMsg("Adding description for area %d", i_area_index );
259 /* Add an entry to the list of program associated with the stream */
260 p_input->stream.i_area_nb++;
261 p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
262 p_input->stream.i_area_nb
263 * sizeof(input_area_t *) );
264 if( p_input->stream.pp_areas == NULL )
266 intf_ErrMsg( "Unable to realloc memory in input_AddArea" );
270 /* Allocate the structure to store this description */
271 p_input->stream.pp_areas[i_area_index] =
272 malloc( sizeof(input_area_t) );
273 if( p_input->stream.pp_areas[i_area_index] == NULL )
275 intf_ErrMsg( "Unable to allocate memory in input_AddArea" );
279 /* Init this entry */
280 p_input->stream.pp_areas[i_area_index]->i_id = 0;
281 p_input->stream.pp_areas[i_area_index]->i_start = 0;
282 p_input->stream.pp_areas[i_area_index]->i_size = 0;
283 p_input->stream.pp_areas[i_area_index]->i_tell = 0;
284 p_input->stream.pp_areas[i_area_index]->i_seek = NO_SEEK;
285 p_input->stream.pp_areas[i_area_index]->i_part_nb = 1;
286 p_input->stream.pp_areas[i_area_index]->i_part= 0;
287 p_input->stream.pp_areas[i_area_index]->i_angle_nb = 1;
288 p_input->stream.pp_areas[i_area_index]->i_angle = 0;
290 return p_input->stream.pp_areas[i_area_index];
293 /*****************************************************************************
294 * input_DelArea: destroy a area descriptor
295 *****************************************************************************
296 * All ES descriptions referenced in the descriptor will be deleted.
297 *****************************************************************************/
298 void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
304 intf_DbgMsg("Deleting description for area %d", p_area->i_id );
306 /* Find the area in the areas table */
307 for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb;
310 if( p_input->stream.pp_areas[i_area_index] == p_area )
314 /* Remove this area from the stream's list of areas */
315 p_input->stream.i_area_nb--;
317 p_input->stream.pp_areas[i_area_index] =
318 p_input->stream.pp_areas[p_input->stream.i_area_nb];
319 p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
320 p_input->stream.i_area_nb
321 * sizeof(input_area_t *) );
323 if( p_input->stream.i_area_nb && p_input->stream.pp_areas == NULL)
325 intf_ErrMsg( "input error: unable to realloc area list"
326 " in input_DelArea" );
329 /* Free the description of this area */
334 /*****************************************************************************
335 * input_FindES: returns a pointer to an ES described by its ID
336 *****************************************************************************/
337 es_descriptor_t * input_FindES( input_thread_t * p_input, u16 i_es_id )
341 for( i = 0; i < p_input->stream.i_es_number; i++ )
343 if( p_input->stream.pp_es[i]->i_id == i_es_id )
345 return p_input->stream.pp_es[i];
352 /*****************************************************************************
354 *****************************************************************************
355 * Reserve a slot in the table of ES descriptors for the ES and add it to the
356 * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
358 *****************************************************************************/
359 es_descriptor_t * input_AddES( input_thread_t * p_input,
360 pgrm_descriptor_t * p_pgrm, u16 i_es_id,
363 es_descriptor_t * p_es;
365 intf_DbgMsg("Adding description for ES 0x%x", i_es_id);
367 p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
370 intf_ErrMsg( "Unable to allocate memory in input_AddES" );
373 p_input->stream.i_es_number++;
374 p_input->stream.pp_es = realloc( p_input->stream.pp_es,
375 p_input->stream.i_es_number
376 * sizeof(es_descriptor_t *) );
377 if( p_input->stream.pp_es == NULL )
379 intf_ErrMsg( "Unable to realloc memory in input_AddES" );
382 p_input->stream.pp_es[p_input->stream.i_es_number - 1] = p_es;
384 /* Init its values */
385 p_es->i_id = i_es_id;
386 p_es->psz_desc[0] = '\0';
388 p_es->p_decoder_fifo = NULL;
390 p_es->i_cat = UNKNOWN_ES;
394 p_es->p_demux_data = malloc( i_data_len );
395 if( p_es->p_demux_data == NULL )
397 intf_ErrMsg( "Unable to allocate memory in input_AddES" );
400 memset( p_es->p_demux_data, 0, i_data_len );
404 p_es->p_demux_data = NULL;
407 /* Add this ES to the program definition if one is given */
410 p_pgrm->i_es_number++;
411 p_pgrm->pp_es = realloc( p_pgrm->pp_es,
413 * sizeof(es_descriptor_t *) );
414 if( p_pgrm->pp_es == NULL )
416 intf_ErrMsg( "Unable to realloc memory in input_AddES" );
419 p_pgrm->pp_es[p_pgrm->i_es_number - 1] = p_es;
420 p_es->p_pgrm = p_pgrm;
430 /*****************************************************************************
432 *****************************************************************************/
433 void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
435 int i_index, i_es_index;
436 pgrm_descriptor_t * p_pgrm;
439 p_pgrm = p_es->p_pgrm;
441 /* Kill associated decoder, if any. */
442 if( p_es->p_decoder_fifo != NULL )
444 input_EndDecoder( p_input, p_es );
447 /* Remove this ES from the description of the program if it is associated to
451 for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
453 if( p_pgrm->pp_es[i_index] == p_es )
455 p_pgrm->i_es_number--;
456 p_pgrm->pp_es[i_index] = p_pgrm->pp_es[p_pgrm->i_es_number];
457 p_pgrm->pp_es = realloc( p_pgrm->pp_es,
459 * sizeof(es_descriptor_t *));
460 if( p_pgrm->i_es_number && p_pgrm->pp_es == NULL )
462 intf_ErrMsg( "Unable to realloc memory in input_DelES" );
469 /* Free the demux data */
470 if( p_es->p_demux_data != NULL )
472 free( p_es->p_demux_data );
475 /* Find the ES in the ES table */
476 for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
479 if( p_input->stream.pp_es[i_es_index] == p_es )
485 p_input->stream.i_es_number--;
486 p_input->stream.pp_es[i_es_index] =
487 p_input->stream.pp_es[p_input->stream.i_es_number];
488 p_input->stream.pp_es = realloc( p_input->stream.pp_es,
489 p_input->stream.i_es_number
490 * sizeof(es_descriptor_t *));
491 if( p_input->stream.i_es_number && p_input->stream.pp_es == NULL )
493 intf_ErrMsg( "Unable to realloc memory in input_DelES" );
498 /*****************************************************************************
499 * InitDecConfig: initializes a decoder_config_t
500 *****************************************************************************/
501 static int InitDecConfig( input_thread_t * p_input, es_descriptor_t * p_es,
502 decoder_config_t * p_config )
504 p_config->i_id = p_es->i_id;
505 p_config->i_type = p_es->i_type;
506 p_config->p_stream_ctrl =
507 &p_input->stream.control;
510 if( (p_config->p_decoder_fifo =
511 (decoder_fifo_t *)malloc( sizeof(decoder_fifo_t) )) == NULL )
513 intf_ErrMsg( "Out of memory" );
517 vlc_mutex_init(&p_config->p_decoder_fifo->data_lock);
518 vlc_cond_init(&p_config->p_decoder_fifo->data_wait);
519 p_config->p_decoder_fifo->i_start = p_config->p_decoder_fifo->i_end = 0;
520 p_config->p_decoder_fifo->b_die = p_config->p_decoder_fifo->b_error = 0;
521 p_config->p_decoder_fifo->p_packets_mgt = p_input->p_method_data;
522 p_config->p_decoder_fifo->pf_delete_pes = p_input->pf_delete_pes;
523 p_es->p_decoder_fifo = p_config->p_decoder_fifo;
525 p_config->pf_init_bit_stream = InitBitstream;
527 p_input->stream.i_selected_es_number++;
529 p_input->stream.pp_selected_es = realloc(
530 p_input->stream.pp_selected_es,
531 p_input->stream.i_selected_es_number
532 * sizeof(es_descriptor_t *) );
533 if( p_input->stream.pp_selected_es == NULL )
535 intf_ErrMsg( "Unable to realloc memory in input_SelectES" );
538 p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number - 1]
544 /*****************************************************************************
545 * GetVdecConfig: returns a valid vdec_config_t
546 *****************************************************************************/
547 static vdec_config_t * GetVdecConfig( input_thread_t * p_input,
548 es_descriptor_t * p_es )
550 vdec_config_t * p_config;
552 p_config = (vdec_config_t *)malloc( sizeof(vdec_config_t) );
553 if( p_config == NULL )
555 intf_ErrMsg( "Unable to allocate memory in GetVdecConfig" );
558 p_config->p_vout = p_input->p_default_vout;
559 if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 )
568 /*****************************************************************************
569 * GetAdecConfig: returns a valid adec_config_t
570 *****************************************************************************/
571 static adec_config_t * GetAdecConfig( input_thread_t * p_input,
572 es_descriptor_t * p_es )
574 adec_config_t * p_config;
576 p_config = (adec_config_t *)malloc( sizeof(adec_config_t));
577 if( p_config == NULL )
579 intf_ErrMsg( "Unable to allocate memory in GetAdecConfig" );
582 p_config->p_aout = p_input->p_default_aout;
583 if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 )
592 /*****************************************************************************
593 * input_SelectES: selects an ES and spawns the associated decoder
594 *****************************************************************************
595 * Remember we are still supposed to have stream_lock when entering this
597 *****************************************************************************/
599 vlc_thread_t adec_CreateThread( void * );
600 vlc_thread_t ac3dec_CreateThread( void * );
601 vlc_thread_t vpar_CreateThread( void * );
602 vlc_thread_t spudec_CreateThread( void * );
604 int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
607 decoder_capabilities_t decoder;
612 intf_ErrMsg( "Nothing to do in input_SelectES" );
617 intf_DbgMsg( "Selecting ES 0x%x", p_es->i_id );
620 if( p_es->p_decoder_fifo != NULL )
622 intf_ErrMsg( "ES 0x%x is already selected", p_es->i_id );
626 switch( p_es->i_type )
630 if( p_main->b_audio )
632 decoder.pf_create_thread = adec_CreateThread;
633 p_config = (void *)GetAdecConfig( p_input, p_es );
635 /* Release the lock, not to block the input thread during
636 * the creation of the thread. */
637 vlc_mutex_unlock( &p_input->stream.stream_lock );
638 p_es->thread_id = input_RunDecoder( &decoder, p_config );
639 vlc_mutex_lock( &p_input->stream.stream_lock );
645 if( p_main->b_video )
647 decoder.pf_create_thread = vpar_CreateThread;
648 p_config = (void *)GetVdecConfig( p_input, p_es );
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( &decoder, p_config );
654 vlc_mutex_lock( &p_input->stream.stream_lock );
659 if( p_main->b_audio )
661 decoder.pf_create_thread = ac3dec_CreateThread;
662 p_config = (void *)GetAdecConfig( p_input, p_es );
664 /* Release the lock, not to block the input thread during
665 * the creation of the thread. */
666 vlc_mutex_unlock( &p_input->stream.stream_lock );
667 p_es->thread_id = input_RunDecoder( &decoder, p_config );
668 vlc_mutex_lock( &p_input->stream.stream_lock );
673 if( p_main->b_video )
675 decoder.pf_create_thread = spudec_CreateThread;
676 p_config = (void *)GetVdecConfig( p_input, p_es );
678 /* Release the lock, not to block the input thread during
679 * the creation of the thread. */
680 vlc_mutex_unlock( &p_input->stream.stream_lock );
681 p_es->thread_id = input_RunDecoder( &decoder, p_config );
682 vlc_mutex_lock( &p_input->stream.stream_lock );
687 intf_ErrMsg( "Unknown stream type 0x%x", p_es->i_type );
692 if( p_es->thread_id == 0 )
700 /*****************************************************************************
701 * input_UnselectES: removes an ES from the list of selected ES
702 *****************************************************************************/
703 int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
710 intf_ErrMsg( "Nothing to do in input_UnselectES" );
715 intf_DbgMsg( "Unselecting ES 0x%x", p_es->i_id );
718 if( p_es->p_decoder_fifo == NULL )
720 intf_ErrMsg( "ES 0x%x is not selected", p_es->i_id );
724 input_EndDecoder( p_input, p_es );
726 if( ( p_es->p_decoder_fifo == NULL ) &&
727 ( p_input->stream.i_selected_es_number > 0 ) )
729 p_input->stream.i_selected_es_number--;
731 while( ( i_index < p_input->stream.i_selected_es_number ) &&
732 ( p_input->stream.pp_selected_es[i_index] != p_es ) )
737 p_input->stream.pp_selected_es[i_index] =
738 p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number];
740 p_input->stream.pp_selected_es = realloc(
741 p_input->stream.pp_selected_es,
742 p_input->stream.i_selected_es_number
743 * sizeof(es_descriptor_t *) );
745 if( p_input->stream.pp_selected_es == NULL )
748 intf_DbgMsg( "No more selected ES in input_UnselectES" );