1 /*****************************************************************************
2 * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
3 * FIXME : check the return value of realloc() and malloc() !
4 *****************************************************************************
5 * Copyright (C) 1999, 2000 VideoLAN
6 * $Id: input_programs.c,v 1.12 2000/12/21 14:18:15 massiot Exp $
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
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 void input_InitStream( input_thread_t * p_input, size_t i_data_len )
57 p_input->stream.i_stream_id = 0;
58 p_input->stream.i_pgrm_number = 0;
59 p_input->stream.pp_programs = NULL;
63 p_input->stream.p_demux_data = malloc( i_data_len );
64 memset( p_input->stream.p_demux_data, 0, i_data_len );
68 /*****************************************************************************
69 * input_EndStream: free all stream descriptors
70 *****************************************************************************/
71 void input_EndStream( input_thread_t * p_input )
75 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
77 for( j = 0; j < p_input->stream.pp_programs[i]->i_es_number; j++ )
79 if( p_input->stream.pp_programs[i]->pp_es[j]->p_demux_data != NULL )
81 free( p_input->stream.pp_programs[i]->pp_es[j]->p_demux_data );
83 free( p_input->stream.pp_programs[i]->pp_es[j] );
86 if( p_input->stream.pp_programs[i]->p_demux_data != NULL )
88 free( p_input->stream.pp_programs[i]->p_demux_data );
90 free( p_input->stream.pp_programs[i] );
94 /*****************************************************************************
95 * input_AddProgram: add and init a program descriptor
96 *****************************************************************************
97 * This program descriptor will be referenced in the given stream descriptor
98 *****************************************************************************/
99 pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input,
100 u16 i_pgrm_id, size_t i_data_len )
102 /* Where to add the pgrm */
103 int i_pgrm_index = p_input->stream.i_pgrm_number;
105 intf_DbgMsg("Adding description for pgrm %d", i_pgrm_id);
107 /* Add an entry to the list of program associated with the stream */
108 p_input->stream.i_pgrm_number++;
109 p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
110 p_input->stream.i_pgrm_number
111 * sizeof(pgrm_descriptor_t *) );
113 /* Allocate the structure to store this description */
114 p_input->stream.pp_programs[i_pgrm_index] =
115 malloc( sizeof(pgrm_descriptor_t) );
117 /* Init this entry */
118 p_input->stream.pp_programs[i_pgrm_index]->i_number = i_pgrm_id;
119 p_input->stream.pp_programs[i_pgrm_index]->b_is_ok = 0;
120 p_input->stream.pp_programs[i_pgrm_index]->i_version = 0;
122 p_input->stream.pp_programs[i_pgrm_index]->i_es_number = 0;
123 p_input->stream.pp_programs[i_pgrm_index]->pp_es = NULL;
125 p_input->stream.pp_programs[i_pgrm_index]->delta_cr = 0;
126 p_input->stream.pp_programs[i_pgrm_index]->delta_absolute = 0;
127 p_input->stream.pp_programs[i_pgrm_index]->last_cr = 0;
128 p_input->stream.pp_programs[i_pgrm_index]->c_average_count = 0;
129 p_input->stream.pp_programs[i_pgrm_index]->i_synchro_state
130 = SYNCHRO_NOT_STARTED;
131 p_input->stream.pp_programs[i_pgrm_index]->b_discontinuity = 0;
133 p_input->stream.pp_programs[i_pgrm_index]->p_vout
134 = p_input->p_default_vout;
135 p_input->stream.pp_programs[i_pgrm_index]->p_aout
136 = p_input->p_default_aout;
140 p_input->stream.pp_programs[i_pgrm_index]->p_demux_data =
141 malloc( i_data_len );
142 memset( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data, 0,
146 return p_input->stream.pp_programs[i_pgrm_index];
149 /*****************************************************************************
150 * input_DelProgram: destroy a program descriptor
151 *****************************************************************************
152 * All ES descriptions referenced in the descriptor will be deleted.
153 *****************************************************************************/
154 void input_DelProgram( input_thread_t * p_input, u16 i_pgrm_id )
156 int i_index, i_pgrm_index = -1;
157 pgrm_descriptor_t * p_pgrm = NULL;
159 intf_DbgMsg("Deleting description for pgrm %d", i_pgrm_id);
161 /* Find where this program is described */
162 for( i_index = 0; i_index < p_input->stream.i_pgrm_number; i_index++ )
164 if( p_input->stream.pp_programs[i_index]->i_number == i_pgrm_id )
166 i_pgrm_index = i_index;
167 p_pgrm = p_input->stream.pp_programs[ i_pgrm_index ];
172 /* Make sure that the pgrm exists */
173 ASSERT(i_pgrm_index >= 0);
176 /* Free the structures that describe the es that belongs to that program */
177 for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
179 input_DelES( p_input, p_pgrm->pp_es[i_index]->i_id );
182 /* Free the table of es descriptors */
183 free( p_pgrm->pp_es );
185 /* Free the demux data */
186 if( p_pgrm->p_demux_data != NULL )
188 free( p_pgrm->p_demux_data );
191 /* Free the description of this stream */
194 /* Remove this program from the stream's list of programs */
195 p_input->stream.i_pgrm_number--;
196 p_input->stream.pp_programs[i_pgrm_index] =
197 p_input->stream.pp_programs[p_input->stream.i_pgrm_number];
198 p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
199 p_input->stream.i_pgrm_number
200 * sizeof(pgrm_descriptor_t *) );
203 /*****************************************************************************
205 *****************************************************************************
206 * Reserve a slot in the table of ES descriptors for the ES and add it to the
207 * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
209 *****************************************************************************/
210 es_descriptor_t * input_AddES( input_thread_t * p_input,
211 pgrm_descriptor_t * p_pgrm, u16 i_es_id,
214 es_descriptor_t * p_es;
216 intf_DbgMsg("Adding description for ES %d", i_es_id);
218 p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
219 p_input->i_es_number++;
220 p_input->pp_es = realloc( p_input->pp_es, p_input->i_es_number
221 * sizeof(es_descriptor_t *) );
222 p_input->pp_es[p_input->i_es_number - 1] = p_es;
223 p_es->i_id = i_es_id;
225 /* Init its values */
226 p_es->b_discontinuity = 0;
228 p_es->p_decoder_fifo = NULL;
232 p_es->p_demux_data = malloc( i_data_len );
233 memset( p_es->p_demux_data, 0, i_data_len );
236 /* Add this ES to the program definition if one is given */
239 p_pgrm->i_es_number++;
240 p_pgrm->pp_es = realloc( p_pgrm->pp_es,
242 * sizeof(es_descriptor_t *) );
243 p_pgrm->pp_es[p_pgrm->i_es_number - 1] = p_es;
244 p_es->p_pgrm = p_pgrm;
254 /*****************************************************************************
256 *****************************************************************************/
257 void input_DelES( input_thread_t * p_input, u16 i_id )
260 pgrm_descriptor_t * p_pgrm = NULL;
261 es_descriptor_t * p_es = NULL;
263 /* Look for the description of the ES */
264 for( i_es = 0; i_es < p_input->i_es_number; i_es++ )
266 if( p_input->pp_es[i_es]->i_id == i_id )
268 p_es = p_input->pp_es[i_es];
269 p_pgrm = p_input->pp_es[i_es]->p_pgrm;
276 /* Remove this ES from the description of the program if it is associated to
280 for( i_index = 0; ; i_index++ )
282 if( p_pgrm->pp_es[i_index]->i_id == i_id )
284 p_pgrm->i_es_number--;
285 p_pgrm->pp_es[i_index] = p_pgrm->pp_es[p_pgrm->i_es_number];
286 p_pgrm->pp_es = realloc( p_pgrm->pp_es,
288 * sizeof(es_descriptor_t *));
294 /* Free the demux data */
295 if( p_es->p_demux_data != NULL )
297 free( p_es->p_demux_data );
302 p_input->i_es_number--;
303 p_input->pp_es[i_es] = p_input->pp_es[p_input->i_es_number];
304 p_input->pp_es = realloc( p_input->pp_es, p_input->i_es_number
305 * sizeof(es_descriptor_t *));
309 /*****************************************************************************
310 * input_DumpStream: dumps the contents of a stream descriptor
311 *****************************************************************************/
312 void input_DumpStream( input_thread_t * p_input )
315 #define S p_input->stream
316 intf_Msg( "input info: Dumping stream ID 0x%x\n", S.i_stream_id );
318 intf_Msg( "input info: seekable stream, position: %d/%d\n",
319 S.i_tell, S.i_size );
321 intf_Msg( "input info: %s\n", S.b_pace_control ? "pace controlled" :
322 "pace un-controlled" );
324 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
326 #define P p_input->stream.pp_programs[i]
327 intf_Msg( "input info: Dumping program 0x%x, version %d (%s)\n",
328 P->i_number, P->i_version,
329 P->b_is_ok ? "complete" : "partial" );
330 if( P->i_synchro_state == SYNCHRO_OK )
331 intf_Msg( "input info: synchro absolute delta : %lld (jitter : %lld)\n",
332 P->delta_absolute, P->delta_cr );
334 for( j = 0; j < p_input->stream.pp_programs[i]->i_es_number; j++ )
336 #define ES p_input->stream.pp_programs[i]->pp_es[j]
337 intf_Msg( "input info: ES 0x%x, stream 0x%x, type 0x%x, %s\n",
338 ES->i_id, ES->i_stream_id, ES->i_type,
339 ES->p_decoder_fifo != NULL ? "selected" : "not selected");
346 /*****************************************************************************
347 * InitDecConfig: initializes a decoder_config_t
348 *****************************************************************************/
349 static int InitDecConfig( input_thread_t * p_input, es_descriptor_t * p_es,
350 decoder_config_t * p_config )
352 p_config->i_stream_id = p_es->i_stream_id;
353 p_config->i_type = p_es->i_type;
354 p_config->p_stream_ctrl =
355 &p_input->stream.control;
358 if( (p_config->p_decoder_fifo =
359 (decoder_fifo_t *)malloc( sizeof(decoder_fifo_t) )) == NULL )
361 intf_ErrMsg( "Out of memory" );
365 vlc_mutex_init(&p_config->p_decoder_fifo->data_lock);
366 vlc_cond_init(&p_config->p_decoder_fifo->data_wait);
367 p_config->p_decoder_fifo->i_start = p_config->p_decoder_fifo->i_end = 0;
368 p_config->p_decoder_fifo->b_die = p_config->p_decoder_fifo->b_error = 0;
369 p_config->p_decoder_fifo->p_packets_mgt = p_input->p_method_data;
370 p_config->p_decoder_fifo->pf_delete_pes =
371 p_input->p_plugin->pf_delete_pes;
372 p_es->p_decoder_fifo = p_config->p_decoder_fifo;
374 p_config->pf_init_bit_stream = InitBitstream;
379 /*****************************************************************************
380 * GetVdecConfig: returns a valid vdec_config_t
381 *****************************************************************************/
382 static vdec_config_t * GetVdecConfig( input_thread_t * p_input,
383 es_descriptor_t * p_es )
385 vdec_config_t * p_config;
387 p_config = (vdec_config_t *)malloc( sizeof(vdec_config_t) );
388 p_config->p_vout = p_input->p_default_vout;
389 if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 )
398 /*****************************************************************************
399 * GetAdecConfig: returns a valid adec_config_t
400 *****************************************************************************/
401 static adec_config_t * GetAdecConfig( input_thread_t * p_input,
402 es_descriptor_t * p_es )
404 adec_config_t * p_config;
406 p_config = (adec_config_t *)malloc( sizeof(adec_config_t) );
407 p_config->p_aout = p_input->p_default_aout;
408 if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 )
417 /*****************************************************************************
418 * input_SelectES: selects an ES and spawns the associated decoder
419 *****************************************************************************/
420 int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
425 intf_DbgMsg( "Selecting ES %d", p_es->i_id );
428 if( p_es->p_decoder_fifo != NULL )
430 intf_ErrMsg( "ES %d is already selected", p_es->i_id );
434 switch( p_es->i_type )
438 if( p_main->b_audio )
440 p_es->thread_id = adec_CreateThread( GetAdecConfig( p_input,
447 if( p_main->b_video )
449 p_es->thread_id = vpar_CreateThread( GetVdecConfig( p_input,
455 if( p_main->b_audio )
457 p_es->thread_id = ac3dec_CreateThread( GetAdecConfig( p_input,
463 if( p_main->b_video )
465 p_es->thread_id = spudec_CreateThread( GetVdecConfig( p_input,
471 intf_ErrMsg( "Unknown stream type %d", p_es->i_type );
476 if( p_es->p_decoder_fifo != NULL )
478 p_input->i_selected_es_number++;
479 p_input->pp_selected_es = realloc( p_input->pp_selected_es,
480 p_input->i_selected_es_number
481 * sizeof(es_descriptor_t *) );
482 p_input->pp_selected_es[p_input->i_selected_es_number - 1] = p_es;