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.17 2001/11/28 15:08:06 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 *****************************************************************************/
30 #include <string.h> /* memcpy(), memset() */
31 #include <sys/types.h> /* off_t */
39 #include "stream_control.h"
40 #include "input_ext-dec.h"
41 #include "input_ext-intf.h"
42 #include "input_ext-plugins.h"
46 static decoder_config_t * CreateDecoderConfig( input_thread_t * p_input,
47 es_descriptor_t * p_es );
48 static void DeleteDecoderConfig( decoder_config_t * p_config );
50 /*****************************************************************************
51 * input_RunDecoder: spawns a new decoder thread
52 *****************************************************************************/
53 vlc_thread_t input_RunDecoder( input_thread_t * p_input,
54 es_descriptor_t * p_es )
56 probedata_t probedata;
57 vlc_thread_t thread_id;
59 /* Get a suitable module */
60 probedata.i_type = p_es->i_type;
62 p_es->p_module = module_Need( MODULE_CAPABILITY_DEC, &probedata );
63 if( p_es->p_module == NULL )
65 intf_ErrMsg( "input error: no suitable decoder module for type 0x%x",
70 /* Create the decoder configuration structure */
71 p_es->p_config = CreateDecoderConfig( p_input, p_es );
73 if( p_es->p_config == NULL )
75 intf_ErrMsg( "input error: could not create decoder config" );
76 module_Unneed( p_es->p_module );
80 /* Spawn the decoder thread */
81 if ( vlc_thread_create( &thread_id, "decoder",
82 (vlc_thread_func_t)p_es->p_module->
83 p_functions->dec.functions.dec.pf_RunThread,
84 (void *)p_es->p_config) )
86 intf_ErrMsg( "input error: can't spawn decoder thread \"%s\"",
87 p_es->p_module->psz_name );
88 free( p_es->p_config );
89 module_Unneed( p_es->p_module );
93 intf_DbgMsg( "input debug: decoder \"%s\"thread created",
94 p_es->p_module->psz_name );
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;
138 /*****************************************************************************
140 *****************************************************************************
141 * Put a PES in the decoder's fifo.
142 *****************************************************************************/
143 void input_DecodePES( decoder_fifo_t * p_decoder_fifo, pes_packet_t * p_pes )
145 vlc_mutex_lock( &p_decoder_fifo->data_lock );
147 if( !DECODER_FIFO_ISFULL( *p_decoder_fifo ) )
149 p_decoder_fifo->buffer[p_decoder_fifo->i_end] = p_pes;
150 DECODER_FIFO_INCEND( *p_decoder_fifo );
152 /* Warn the decoder that it's got work to do. */
153 vlc_cond_signal( &p_decoder_fifo->data_wait );
157 /* The FIFO is full !!! This should not happen. */
158 p_decoder_fifo->pf_delete_pes( p_decoder_fifo->p_packets_mgt,
160 intf_ErrMsg( "PES trashed - decoder fifo full !" );
162 vlc_mutex_unlock( &p_decoder_fifo->data_lock );
165 /*****************************************************************************
166 * input_EscapeDiscontinuity: send a NULL packet to the decoders
167 *****************************************************************************/
168 void input_EscapeDiscontinuity( input_thread_t * p_input,
169 pgrm_descriptor_t * p_pgrm )
173 for( i_es = 0; i_es < p_pgrm->i_es_number; i_es++ )
175 es_descriptor_t * p_es = p_pgrm->pp_es[i_es];
177 if( p_es->p_decoder_fifo != NULL )
179 for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
181 input_NullPacket( p_input, p_es );
187 /*****************************************************************************
188 * input_EscapeAudioDiscontinuity: send a NULL packet to the audio decoders
189 *****************************************************************************/
190 void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
194 for( i_pgrm = 0; i_pgrm < p_input->stream.i_pgrm_number; i_pgrm++ )
196 pgrm_descriptor_t * p_pgrm = p_input->stream.pp_programs[i_pgrm];
198 for( i_es = 0; i_es < p_pgrm->i_es_number; i_es++ )
200 es_descriptor_t * p_es = p_pgrm->pp_es[i_es];
202 if( p_es->p_decoder_fifo != NULL && p_es->b_audio )
204 for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
206 input_NullPacket( p_input, p_es );
213 /*****************************************************************************
214 * CreateDecoderConfig: create a decoder_config_t
215 *****************************************************************************/
216 static decoder_config_t * CreateDecoderConfig( input_thread_t * p_input,
217 es_descriptor_t * p_es )
219 decoder_config_t * p_config;
221 p_config = (decoder_config_t *)malloc( sizeof(decoder_config_t) );
222 if( p_config == NULL )
224 intf_ErrMsg( "Unable to allocate memory in CreateDecoderConfig" );
229 if( (p_config->p_decoder_fifo =
230 (decoder_fifo_t *)malloc( sizeof(decoder_fifo_t) )) == NULL )
232 intf_ErrMsg( "Out of memory" );
237 /* Select a new ES */
238 p_input->stream.i_selected_es_number++;
239 p_input->stream.pp_selected_es = realloc(
240 p_input->stream.pp_selected_es,
241 p_input->stream.i_selected_es_number
242 * sizeof(es_descriptor_t *) );
243 if( p_input->stream.pp_selected_es == NULL )
245 intf_ErrMsg( "Unable to realloc memory" );
246 free( p_config->p_decoder_fifo );
250 p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number - 1]
253 /* Initialize the p_config structure */
254 vlc_mutex_init(&p_config->p_decoder_fifo->data_lock);
255 vlc_cond_init(&p_config->p_decoder_fifo->data_wait);
256 p_es->p_decoder_fifo = p_config->p_decoder_fifo;
258 p_config->pf_init_bit_stream = p_input->pf_init_bit_stream;
260 p_config->i_id = p_es->i_id;
261 p_config->i_type = p_es->i_type;
262 p_config->p_stream_ctrl = &p_input->stream.control;
264 p_config->p_decoder_fifo->i_start = p_config->p_decoder_fifo->i_end = 0;
265 p_config->p_decoder_fifo->b_die = p_config->p_decoder_fifo->b_error = 0;
266 p_config->p_decoder_fifo->p_packets_mgt = p_input->p_method_data;
267 p_config->p_decoder_fifo->pf_delete_pes = p_input->pf_delete_pes;
272 /*****************************************************************************
273 * DeleteDecoderConfig: create a decoder_config_t
274 *****************************************************************************/
275 static void DeleteDecoderConfig( decoder_config_t * p_config )
277 /* Free all packets still in the decoder fifo. */
279 while( !DECODER_FIFO_ISEMPTY( *p_config->p_decoder_fifo ) )
281 p_config->p_decoder_fifo->pf_delete_pes(
282 p_config->p_decoder_fifo->p_packets_mgt,
283 DECODER_FIFO_START( *p_config->p_decoder_fifo ) );
284 DECODER_FIFO_INCSTART( *p_config->p_decoder_fifo );
288 /* Destroy the lock and cond */
289 vlc_cond_destroy( &p_config->p_decoder_fifo->data_wait );
290 vlc_mutex_destroy( &p_config->p_decoder_fifo->data_lock );
292 free( p_config->p_decoder_fifo );