1 /*****************************************************************************
2 * input_dec.c: Functions for the management of decoders
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: input_dec.c,v 1.36 2002/05/20 22:39:36 sam 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 *****************************************************************************/
28 #include <string.h> /* memcpy(), memset() */
29 #include <sys/types.h> /* off_t */
31 #include <videolan/vlc.h>
33 #include "stream_control.h"
34 #include "input_ext-dec.h"
35 #include "input_ext-intf.h"
36 #include "input_ext-plugins.h"
38 static decoder_config_t
* CreateDecoderConfig( input_thread_t
* p_input
,
39 es_descriptor_t
* p_es
);
40 static void DeleteDecoderConfig( decoder_config_t
* p_config
);
42 /*****************************************************************************
43 * input_RunDecoder: spawns a new decoder thread
44 *****************************************************************************/
45 vlc_thread_t
input_RunDecoder( input_thread_t
* p_input
,
46 es_descriptor_t
* p_es
)
48 vlc_thread_t thread_id
;
49 char * psz_plugin
= NULL
;
51 if( p_es
->i_type
== MPEG1_AUDIO_ES
|| p_es
->i_type
== MPEG2_AUDIO_ES
)
53 psz_plugin
= config_GetPszVariable( "mpeg-adec" );
55 if( p_es
->i_type
== AC3_AUDIO_ES
)
57 psz_plugin
= config_GetPszVariable( "ac3-adec" );
60 /* Get a suitable module */
61 p_es
->p_module
= module_Need( MODULE_CAPABILITY_DECODER
, psz_plugin
,
62 (void *)&p_es
->i_type
);
63 if( psz_plugin
) free( psz_plugin
);
64 if( p_es
->p_module
== NULL
)
66 intf_ErrMsg( "input error: no suitable decoder module for type 0x%x",
71 /* Create the decoder configuration structure */
72 p_es
->p_config
= CreateDecoderConfig( p_input
, p_es
);
74 if( p_es
->p_config
== NULL
)
76 intf_ErrMsg( "input error: could not create decoder config" );
77 module_Unneed( p_es
->p_module
);
81 /* Spawn the decoder thread */
82 if ( vlc_thread_create( &thread_id
, "decoder",
83 (vlc_thread_func_t
)p_es
->p_module
->
84 p_functions
->dec
.functions
.dec
.pf_run
,
85 (void *)p_es
->p_config
) )
87 intf_ErrMsg( "input error: can't spawn decoder thread \"%s\"",
88 p_es
->p_module
->psz_name
);
89 free( p_es
->p_config
);
90 module_Unneed( p_es
->p_module
);
94 p_input
->stream
.b_changed
= 1;
100 /*****************************************************************************
101 * input_EndDecoder: kills a decoder thread and waits until it's finished
102 *****************************************************************************/
103 void input_EndDecoder( input_thread_t
* p_input
, es_descriptor_t
* p_es
)
107 p_es
->p_decoder_fifo
->b_die
= 1;
109 /* Make sure the thread leaves the NextDataPacket() function by
110 * sending it a few null packets. */
111 for( i_dummy
= 0; i_dummy
< PADDING_PACKET_NUMBER
; i_dummy
++ )
113 input_NullPacket( p_input
, p_es
);
116 if( p_es
->p_pes
!= NULL
)
118 input_DecodePES( p_es
->p_decoder_fifo
, p_es
->p_pes
);
121 /* Waiting for the thread to exit */
122 /* I thought that unlocking was better since thread join can be long
123 * but it actually creates late pictures and freezes --stef */
124 // vlc_mutex_unlock( &p_input->stream.stream_lock );
125 vlc_thread_join( p_es
->thread_id
);
126 // vlc_mutex_lock( &p_input->stream.stream_lock );
128 /* Delete decoder configuration */
129 DeleteDecoderConfig( p_es
->p_config
);
132 module_Unneed( p_es
->p_module
);
134 /* Tell the input there is no more decoder */
135 p_es
->p_decoder_fifo
= NULL
;
137 p_input
->stream
.b_changed
= 1;
140 /*****************************************************************************
142 *****************************************************************************
143 * Put a PES in the decoder's fifo.
144 *****************************************************************************/
145 void input_DecodePES( decoder_fifo_t
* p_decoder_fifo
, pes_packet_t
* p_pes
)
147 vlc_mutex_lock( &p_decoder_fifo
->data_lock
);
149 p_pes
->p_next
= NULL
;
150 *p_decoder_fifo
->pp_last
= p_pes
;
151 p_decoder_fifo
->pp_last
= &p_pes
->p_next
;
152 p_decoder_fifo
->i_depth
++;
154 /* Warn the decoder that it's got work to do. */
155 vlc_cond_signal( &p_decoder_fifo
->data_wait
);
156 vlc_mutex_unlock( &p_decoder_fifo
->data_lock
);
159 /*****************************************************************************
160 * input_EscapeDiscontinuity: send a NULL packet to the decoders
161 *****************************************************************************/
162 void input_EscapeDiscontinuity( input_thread_t
* p_input
)
166 for( i_es
= 0; i_es
< p_input
->stream
.i_selected_es_number
; i_es
++ )
168 es_descriptor_t
* p_es
= p_input
->stream
.pp_selected_es
[i_es
];
170 if( p_es
->p_decoder_fifo
!= NULL
)
172 for( i
= 0; i
< PADDING_PACKET_NUMBER
; i
++ )
174 input_NullPacket( p_input
, p_es
);
180 /*****************************************************************************
181 * input_EscapeAudioDiscontinuity: send a NULL packet to the audio decoders
182 *****************************************************************************/
183 void input_EscapeAudioDiscontinuity( input_thread_t
* p_input
)
187 for( i_es
= 0; i_es
< p_input
->stream
.i_selected_es_number
; i_es
++ )
189 es_descriptor_t
* p_es
= p_input
->stream
.pp_selected_es
[i_es
];
191 if( p_es
->p_decoder_fifo
!= NULL
&& p_es
->b_audio
)
193 for( i
= 0; i
< PADDING_PACKET_NUMBER
; i
++ )
195 input_NullPacket( p_input
, p_es
);
201 /*****************************************************************************
202 * CreateDecoderConfig: create a decoder_config_t
203 *****************************************************************************/
204 static decoder_config_t
* CreateDecoderConfig( input_thread_t
* p_input
,
205 es_descriptor_t
* p_es
)
207 decoder_config_t
* p_config
;
209 p_config
= (decoder_config_t
*)malloc( sizeof(decoder_config_t
) );
210 if( p_config
== NULL
)
212 intf_ErrMsg( "Unable to allocate memory in CreateDecoderConfig" );
217 if( (p_config
->p_decoder_fifo
=
218 (decoder_fifo_t
*)malloc( sizeof(decoder_fifo_t
) )) == NULL
)
220 intf_ErrMsg( "Out of memory" );
225 /* Select a new ES */
226 p_input
->stream
.i_selected_es_number
++;
227 p_input
->stream
.pp_selected_es
= realloc(
228 p_input
->stream
.pp_selected_es
,
229 p_input
->stream
.i_selected_es_number
230 * sizeof(es_descriptor_t
*) );
231 if( p_input
->stream
.pp_selected_es
== NULL
)
233 intf_ErrMsg( "Unable to realloc memory" );
234 free( p_config
->p_decoder_fifo
);
239 p_input
->stream
.pp_selected_es
[p_input
->stream
.i_selected_es_number
- 1]
242 /* Initialize the p_config structure */
243 vlc_mutex_init(&p_config
->p_decoder_fifo
->data_lock
);
244 vlc_cond_init(&p_config
->p_decoder_fifo
->data_wait
);
245 p_es
->p_decoder_fifo
= p_config
->p_decoder_fifo
;
247 p_config
->i_id
= p_es
->i_id
;
248 p_config
->i_type
= p_es
->i_type
;
249 p_config
->p_demux_data
= p_es
->p_demux_data
;
251 p_config
->p_stream_ctrl
= &p_input
->stream
.control
;
253 p_config
->p_decoder_fifo
->p_first
= NULL
;
254 p_config
->p_decoder_fifo
->pp_last
= &p_config
->p_decoder_fifo
->p_first
;
255 p_config
->p_decoder_fifo
->i_depth
= 0;
256 p_config
->p_decoder_fifo
->b_die
= p_config
->p_decoder_fifo
->b_error
= 0;
257 p_config
->p_decoder_fifo
->p_packets_mgt
= p_input
->p_method_data
;
262 /*****************************************************************************
263 * DeleteDecoderConfig: create a decoder_config_t
264 *****************************************************************************/
265 static void DeleteDecoderConfig( decoder_config_t
* p_config
)
267 intf_StatMsg( "input stats: killing decoder for 0x%x, type 0x%x, %d PES in FIFO",
268 p_config
->i_id
, p_config
->i_type
,
269 p_config
->p_decoder_fifo
->i_depth
);
270 /* Free all packets still in the decoder fifo. */
271 input_DeletePES( p_config
->p_decoder_fifo
->p_packets_mgt
,
272 p_config
->p_decoder_fifo
->p_first
);
274 /* Destroy the lock and cond */
275 vlc_cond_destroy( &p_config
->p_decoder_fifo
->data_wait
);
276 vlc_mutex_destroy( &p_config
->p_decoder_fifo
->data_lock
);
278 free( p_config
->p_decoder_fifo
);