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.31 2001/02/08 17:44:12 massiot 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 *****************************************************************************/
39 #include "stream_control.h"
40 #include "input_ext-intf.h"
41 #include "input_ext-dec.h"
44 #include "main.h" /* --noaudio --novideo */
47 * NOTICE : all of these functions expect you to have taken the lock on
48 * p_input->stream.lock
51 /*****************************************************************************
52 * input_InitStream: init the stream descriptor of the given input
53 *****************************************************************************/
54 int input_InitStream( input_thread_t
* p_input
, size_t i_data_len
)
56 p_input
->stream
.i_stream_id
= 0;
57 p_input
->stream
.pp_es
= NULL
;
58 p_input
->stream
.pp_selected_es
= NULL
;
59 p_input
->stream
.pp_programs
= NULL
;
63 if ( (p_input
->stream
.p_demux_data
= malloc( i_data_len
)) == NULL
)
65 intf_ErrMsg( "Unable to allocate memory in input_InitStream");
68 memset( p_input
->stream
.p_demux_data
, 0, i_data_len
);
74 /*****************************************************************************
75 * input_EndStream: free all stream descriptors
76 *****************************************************************************/
77 void input_EndStream( input_thread_t
* p_input
)
79 /* Free all programs and associated ES, and associated decoders. */
80 while( p_input
->stream
.i_pgrm_number
)
82 input_DelProgram( p_input
, p_input
->stream
.pp_programs
[0] );
85 /* Free standalone ES */
86 while( p_input
->stream
.i_es_number
)
88 input_DelES( p_input
, p_input
->stream
.pp_es
[0] );
92 /*****************************************************************************
93 * input_FindProgram: returns a pointer to a program described by its ID
94 *****************************************************************************/
95 pgrm_descriptor_t
* input_FindProgram( input_thread_t
* p_input
, u16 i_pgrm_id
)
99 for( i
= 0; i
< p_input
->stream
.i_pgrm_number
; i
++ )
101 if( p_input
->stream
.pp_programs
[i
]->i_number
== i_pgrm_id
)
103 return p_input
->stream
.pp_programs
[i
];
110 /*****************************************************************************
111 * input_AddProgram: add and init a program descriptor
112 *****************************************************************************
113 * This program descriptor will be referenced in the given stream descriptor
114 *****************************************************************************/
115 pgrm_descriptor_t
* input_AddProgram( input_thread_t
* p_input
,
116 u16 i_pgrm_id
, size_t i_data_len
)
118 /* Where to add the pgrm */
119 int i_pgrm_index
= p_input
->stream
.i_pgrm_number
;
121 intf_DbgMsg("Adding description for pgrm %d", i_pgrm_id
);
123 /* Add an entry to the list of program associated with the stream */
124 p_input
->stream
.i_pgrm_number
++;
125 p_input
->stream
.pp_programs
= realloc( p_input
->stream
.pp_programs
,
126 p_input
->stream
.i_pgrm_number
127 * sizeof(pgrm_descriptor_t
*) );
128 if( p_input
->stream
.pp_programs
== NULL
)
130 intf_ErrMsg( "Unable to realloc memory in input_AddProgram" );
134 /* Allocate the structure to store this description */
135 p_input
->stream
.pp_programs
[i_pgrm_index
] =
136 malloc( sizeof(pgrm_descriptor_t
) );
137 if( p_input
->stream
.pp_programs
[i_pgrm_index
] == NULL
)
139 intf_ErrMsg( "Unable to allocate memory in input_AddProgram" );
143 /* Init this entry */
144 p_input
->stream
.pp_programs
[i_pgrm_index
]->i_number
= i_pgrm_id
;
145 p_input
->stream
.pp_programs
[i_pgrm_index
]->b_is_ok
= 0;
146 p_input
->stream
.pp_programs
[i_pgrm_index
]->i_version
= 0;
148 p_input
->stream
.pp_programs
[i_pgrm_index
]->i_es_number
= 0;
149 p_input
->stream
.pp_programs
[i_pgrm_index
]->pp_es
= NULL
;
151 input_ClockInit( p_input
->stream
.pp_programs
[i_pgrm_index
] );
153 p_input
->stream
.pp_programs
[i_pgrm_index
]->i_synchro_state
156 p_input
->stream
.pp_programs
[i_pgrm_index
]->p_vout
157 = p_input
->p_default_vout
;
158 p_input
->stream
.pp_programs
[i_pgrm_index
]->p_aout
159 = p_input
->p_default_aout
;
163 p_input
->stream
.pp_programs
[i_pgrm_index
]->p_demux_data
=
164 malloc( i_data_len
);
165 if( p_input
->stream
.pp_programs
[i_pgrm_index
]->p_demux_data
== NULL
)
167 intf_ErrMsg( "Unable to allocate memory in input_AddProgram" );
170 memset( p_input
->stream
.pp_programs
[i_pgrm_index
]->p_demux_data
, 0,
174 return p_input
->stream
.pp_programs
[i_pgrm_index
];
177 /*****************************************************************************
178 * input_DelProgram: destroy a program descriptor
179 *****************************************************************************
180 * All ES descriptions referenced in the descriptor will be deleted.
181 *****************************************************************************/
182 void input_DelProgram( input_thread_t
* p_input
, pgrm_descriptor_t
* p_pgrm
)
188 intf_DbgMsg("Deleting description for pgrm %d", p_pgrm
->i_number
);
190 /* Free the structures that describe the es that belongs to that program */
191 while( p_pgrm
->i_es_number
)
193 input_DelES( p_input
, p_pgrm
->pp_es
[0] );
196 /* Free the demux data */
197 if( p_pgrm
->p_demux_data
!= NULL
)
199 free( p_pgrm
->p_demux_data
);
202 /* Find the program in the programs table */
203 for( i_pgrm_index
= 0; i_pgrm_index
< p_input
->stream
.i_pgrm_number
;
206 if( p_input
->stream
.pp_programs
[i_pgrm_index
] == p_pgrm
)
210 /* Remove this program from the stream's list of programs */
211 p_input
->stream
.i_pgrm_number
--;
213 p_input
->stream
.pp_programs
[i_pgrm_index
] =
214 p_input
->stream
.pp_programs
[p_input
->stream
.i_pgrm_number
];
215 p_input
->stream
.pp_programs
= realloc( p_input
->stream
.pp_programs
,
216 p_input
->stream
.i_pgrm_number
217 * sizeof(pgrm_descriptor_t
*) );
219 if( p_input
->stream
.i_pgrm_number
&& p_input
->stream
.pp_programs
== NULL
)
221 intf_ErrMsg( "input error: unable to realloc program list"
222 " in input_DelProgram" );
225 /* Free the description of this program */
229 /*****************************************************************************
230 * input_FindES: returns a pointer to an ES described by its ID
231 *****************************************************************************/
232 es_descriptor_t
* input_FindES( input_thread_t
* p_input
, u16 i_es_id
)
236 for( i
= 0; i
< p_input
->stream
.i_es_number
; i
++ )
238 if( p_input
->stream
.pp_es
[i
]->i_id
== i_es_id
)
240 return p_input
->stream
.pp_es
[i
];
247 /*****************************************************************************
249 *****************************************************************************
250 * Reserve a slot in the table of ES descriptors for the ES and add it to the
251 * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
253 *****************************************************************************/
254 es_descriptor_t
* input_AddES( input_thread_t
* p_input
,
255 pgrm_descriptor_t
* p_pgrm
, u16 i_es_id
,
258 es_descriptor_t
* p_es
;
260 intf_DbgMsg("Adding description for ES 0x%x", i_es_id
);
262 p_es
= (es_descriptor_t
*)malloc( sizeof(es_descriptor_t
) );
265 intf_ErrMsg( "Unable to allocate memory in input_AddES" );
268 p_input
->stream
.i_es_number
++;
269 p_input
->stream
.pp_es
= realloc( p_input
->stream
.pp_es
,
270 p_input
->stream
.i_es_number
271 * sizeof(es_descriptor_t
*) );
272 if( p_input
->stream
.pp_es
== NULL
)
274 intf_ErrMsg( "Unable to realloc memory in input_AddES" );
277 p_input
->stream
.pp_es
[p_input
->stream
.i_es_number
- 1] = p_es
;
279 /* Init its values */
280 p_es
->i_id
= i_es_id
;
282 p_es
->p_decoder_fifo
= NULL
;
287 p_es
->p_demux_data
= malloc( i_data_len
);
288 if( p_es
->p_demux_data
== NULL
)
290 intf_ErrMsg( "Unable to allocate memory in input_AddES" );
293 memset( p_es
->p_demux_data
, 0, i_data_len
);
297 p_es
->p_demux_data
= NULL
;
300 /* Add this ES to the program definition if one is given */
303 p_pgrm
->i_es_number
++;
304 p_pgrm
->pp_es
= realloc( p_pgrm
->pp_es
,
306 * sizeof(es_descriptor_t
*) );
307 if( p_pgrm
->pp_es
== NULL
)
309 intf_ErrMsg( "Unable to realloc memory in input_AddES" );
312 p_pgrm
->pp_es
[p_pgrm
->i_es_number
- 1] = p_es
;
313 p_es
->p_pgrm
= p_pgrm
;
323 /*****************************************************************************
325 *****************************************************************************/
326 void input_DelES( input_thread_t
* p_input
, es_descriptor_t
* p_es
)
328 int i_index
, i_es_index
;
329 pgrm_descriptor_t
* p_pgrm
;
332 p_pgrm
= p_es
->p_pgrm
;
334 /* Kill associated decoder, if any. */
335 if( p_es
->p_decoder_fifo
!= NULL
)
337 input_EndDecoder( p_input
, p_es
);
340 /* Remove this ES from the description of the program if it is associated to
344 for( i_index
= 0; i_index
< p_pgrm
->i_es_number
; i_index
++ )
346 if( p_pgrm
->pp_es
[i_index
] == p_es
)
348 p_pgrm
->i_es_number
--;
349 p_pgrm
->pp_es
[i_index
] = p_pgrm
->pp_es
[p_pgrm
->i_es_number
];
350 p_pgrm
->pp_es
= realloc( p_pgrm
->pp_es
,
352 * sizeof(es_descriptor_t
*));
353 if( p_pgrm
->i_es_number
&& p_pgrm
->pp_es
== NULL
)
355 intf_ErrMsg( "Unable to realloc memory in input_DelES" );
362 /* Free the demux data */
363 if( p_es
->p_demux_data
!= NULL
)
365 free( p_es
->p_demux_data
);
368 /* Find the ES in the ES table */
369 for( i_es_index
= 0; i_es_index
< p_input
->stream
.i_es_number
;
372 if( p_input
->stream
.pp_es
[i_es_index
] == p_es
)
378 p_input
->stream
.i_es_number
--;
379 p_input
->stream
.pp_es
[i_es_index
] =
380 p_input
->stream
.pp_es
[p_input
->stream
.i_es_number
];
381 p_input
->stream
.pp_es
= realloc( p_input
->stream
.pp_es
,
382 p_input
->stream
.i_es_number
383 * sizeof(es_descriptor_t
*));
384 if( p_input
->stream
.i_es_number
&& p_input
->stream
.pp_es
== NULL
)
386 intf_ErrMsg( "Unable to realloc memory in input_DelES" );
392 /*****************************************************************************
393 * input_DumpStream: dumps the contents of a stream descriptor
394 *****************************************************************************/
395 void input_DumpStream( input_thread_t
* p_input
)
398 #define S p_input->stream
399 intf_Msg( "input info: Dumping stream ID 0x%x", S
.i_stream_id
);
401 intf_Msg( "input info: seekable stream, position: %lld/%lld",
402 S
.i_tell
, S
.i_size
);
404 intf_Msg( "input info: %s", S
.b_pace_control
? "pace controlled" :
405 "pace un-controlled" );
407 for( i
= 0; i
< p_input
->stream
.i_pgrm_number
; i
++ )
409 #define P p_input->stream.pp_programs[i]
410 intf_Msg( "input info: Dumping program 0x%x, version %d (%s)",
411 P
->i_number
, P
->i_version
,
412 P
->b_is_ok
? "complete" : "partial" );
414 for( j
= 0; j
< p_input
->stream
.pp_programs
[i
]->i_es_number
; j
++ )
416 #define ES p_input->stream.pp_programs[i]->pp_es[j]
417 intf_Msg( "input info: ES 0x%x, stream 0x%x, type 0x%x, %s",
418 ES
->i_id
, ES
->i_stream_id
, ES
->i_type
,
419 ES
->p_decoder_fifo
!= NULL
? "selected" : "not selected");
426 /*****************************************************************************
427 * InitDecConfig: initializes a decoder_config_t
428 *****************************************************************************/
429 static int InitDecConfig( input_thread_t
* p_input
, es_descriptor_t
* p_es
,
430 decoder_config_t
* p_config
)
432 p_config
->i_id
= p_es
->i_id
;
433 p_config
->i_type
= p_es
->i_type
;
434 p_config
->p_stream_ctrl
=
435 &p_input
->stream
.control
;
438 if( (p_config
->p_decoder_fifo
=
439 (decoder_fifo_t
*)malloc( sizeof(decoder_fifo_t
) )) == NULL
)
441 intf_ErrMsg( "Out of memory" );
445 vlc_mutex_init(&p_config
->p_decoder_fifo
->data_lock
);
446 vlc_cond_init(&p_config
->p_decoder_fifo
->data_wait
);
447 p_config
->p_decoder_fifo
->i_start
= p_config
->p_decoder_fifo
->i_end
= 0;
448 p_config
->p_decoder_fifo
->b_die
= p_config
->p_decoder_fifo
->b_error
= 0;
449 p_config
->p_decoder_fifo
->p_packets_mgt
= p_input
->p_method_data
;
450 p_config
->p_decoder_fifo
->pf_delete_pes
= p_input
->pf_delete_pes
;
451 p_es
->p_decoder_fifo
= p_config
->p_decoder_fifo
;
453 p_config
->pf_init_bit_stream
= InitBitstream
;
458 /*****************************************************************************
459 * GetVdecConfig: returns a valid vdec_config_t
460 *****************************************************************************/
461 static vdec_config_t
* GetVdecConfig( input_thread_t
* p_input
,
462 es_descriptor_t
* p_es
)
464 vdec_config_t
* p_config
;
466 p_config
= (vdec_config_t
*)malloc( sizeof(vdec_config_t
) );
467 if( p_config
== NULL
)
469 intf_ErrMsg( "Unable to allocate memory in GetVdecConfig" );
472 p_config
->p_vout
= p_input
->p_default_vout
;
473 if( InitDecConfig( p_input
, p_es
, &p_config
->decoder_config
) == -1 )
482 /*****************************************************************************
483 * GetAdecConfig: returns a valid adec_config_t
484 *****************************************************************************/
485 static adec_config_t
* GetAdecConfig( input_thread_t
* p_input
,
486 es_descriptor_t
* p_es
)
488 adec_config_t
* p_config
;
490 p_config
= (adec_config_t
*)malloc( sizeof(adec_config_t
));
491 if( p_config
== NULL
)
493 intf_ErrMsg( "Unable to allocate memory in GetAdecConfig" );
496 p_config
->p_aout
= p_input
->p_default_aout
;
497 if( InitDecConfig( p_input
, p_es
, &p_config
->decoder_config
) == -1 )
506 /*****************************************************************************
507 * input_SelectES: selects an ES and spawns the associated decoder
508 *****************************************************************************/
510 vlc_thread_t
adec_CreateThread( void * );
511 vlc_thread_t
ac3dec_CreateThread( void * );
512 vlc_thread_t
vpar_CreateThread( void * );
513 vlc_thread_t
spudec_CreateThread( void * );
515 int input_SelectES( input_thread_t
* p_input
, es_descriptor_t
* p_es
)
518 decoder_capabilities_t decoder
;
521 intf_DbgMsg( "Selecting ES 0x%x", p_es
->i_id
);
524 if( p_es
->p_decoder_fifo
!= NULL
)
526 intf_ErrMsg( "ES %d is already selected", p_es
->i_id
);
530 switch( p_es
->i_type
)
534 if( p_main
->b_audio
)
536 decoder
.pf_create_thread
= adec_CreateThread
;
537 p_es
->thread_id
= input_RunDecoder( &decoder
,
538 (void *)GetAdecConfig( p_input
, p_es
) );
544 if( p_main
->b_video
)
546 decoder
.pf_create_thread
= vpar_CreateThread
;
547 p_es
->thread_id
= input_RunDecoder( &decoder
,
548 (void *)GetVdecConfig( p_input
, p_es
) );
553 if( p_main
->b_audio
)
555 decoder
.pf_create_thread
= ac3dec_CreateThread
;
556 p_es
->thread_id
= input_RunDecoder( &decoder
,
557 (void *)GetAdecConfig( p_input
, p_es
) );
562 if( p_main
->b_video
)
564 decoder
.pf_create_thread
= spudec_CreateThread
;
565 p_es
->thread_id
= input_RunDecoder( &decoder
,
566 (void *)GetVdecConfig( p_input
, p_es
) );
571 intf_ErrMsg( "Unknown stream type %d", p_es
->i_type
);
576 if( p_es
->thread_id
== 0 )
581 if( p_es
->p_decoder_fifo
!= NULL
)
583 p_input
->stream
.i_selected_es_number
++;
584 p_input
->stream
.pp_selected_es
= realloc(
585 p_input
->stream
.pp_selected_es
,
586 p_input
->stream
.i_selected_es_number
587 * sizeof(es_descriptor_t
*) );
588 if( p_input
->stream
.pp_selected_es
== NULL
)
590 intf_ErrMsg( "Unable to realloc memory in input_SelectES" );
593 p_input
->stream
.pp_selected_es
[p_input
->stream
.i_selected_es_number
- 1]