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.22 2001/12/30 07:09:56 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 probedata_t probedata;
49 vlc_thread_t thread_id;
51 /* Get a suitable module */
52 probedata.i_type = p_es->i_type;
54 p_es->p_module = module_Need( MODULE_CAPABILITY_DECODER, NULL, &probedata );
55 if( p_es->p_module == NULL )
57 intf_ErrMsg( "input error: no suitable decoder module for type 0x%x",
62 /* Create the decoder configuration structure */
63 p_es->p_config = CreateDecoderConfig( p_input, p_es );
65 if( p_es->p_config == NULL )
67 intf_ErrMsg( "input error: could not create decoder config" );
68 module_Unneed( p_es->p_module );
72 /* Spawn the decoder thread */
73 if ( vlc_thread_create( &thread_id, "decoder",
74 (vlc_thread_func_t)p_es->p_module->
75 p_functions->dec.functions.dec.pf_run,
76 (void *)p_es->p_config) )
78 intf_ErrMsg( "input error: can't spawn decoder thread \"%s\"",
79 p_es->p_module->psz_name );
80 free( p_es->p_config );
81 module_Unneed( p_es->p_module );
85 intf_DbgMsg( "input debug: decoder \"%s\"thread created",
86 p_es->p_module->psz_name );
92 /*****************************************************************************
93 * input_EndDecoder: kills a decoder thread and waits until it's finished
94 *****************************************************************************/
95 void input_EndDecoder( input_thread_t * p_input, es_descriptor_t * p_es )
99 p_es->p_decoder_fifo->b_die = 1;
101 /* Make sure the thread leaves the NextDataPacket() function by
102 * sending it a few null packets. */
103 for( i_dummy = 0; i_dummy < PADDING_PACKET_NUMBER; i_dummy++ )
105 input_NullPacket( p_input, p_es );
108 if( p_es->p_pes != NULL )
110 input_DecodePES( p_es->p_decoder_fifo, p_es->p_pes );
113 /* Waiting for the thread to exit */
114 /* I thought that unlocking was better since thread join can be long
115 * but it actually creates late pictures and freezes --stef */
116 // vlc_mutex_unlock( &p_input->stream.stream_lock );
117 vlc_thread_join( p_es->thread_id );
118 // vlc_mutex_lock( &p_input->stream.stream_lock );
120 /* Delete decoder configuration */
121 DeleteDecoderConfig( p_es->p_config );
124 module_Unneed( p_es->p_module );
126 /* Tell the input there is no more decoder */
127 p_es->p_decoder_fifo = NULL;
130 /*****************************************************************************
132 *****************************************************************************
133 * Put a PES in the decoder's fifo.
134 *****************************************************************************/
135 void input_DecodePES( decoder_fifo_t * p_decoder_fifo, pes_packet_t * p_pes )
137 vlc_mutex_lock( &p_decoder_fifo->data_lock );
139 p_pes->p_next = NULL;
140 *p_decoder_fifo->pp_last = p_pes;
141 p_decoder_fifo->pp_last = &p_pes->p_next;
142 p_decoder_fifo->i_depth++;
144 /* Warn the decoder that it's got work to do. */
145 vlc_cond_signal( &p_decoder_fifo->data_wait );
146 vlc_mutex_unlock( &p_decoder_fifo->data_lock );
149 /*****************************************************************************
150 * input_EscapeDiscontinuity: send a NULL packet to the decoders
151 *****************************************************************************/
152 void input_EscapeDiscontinuity( input_thread_t * p_input,
153 pgrm_descriptor_t * p_pgrm )
157 for( i_es = 0; i_es < p_pgrm->i_es_number; i_es++ )
159 es_descriptor_t * p_es = p_pgrm->pp_es[i_es];
161 if( p_es->p_decoder_fifo != NULL )
163 for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
165 input_NullPacket( p_input, p_es );
171 /*****************************************************************************
172 * input_EscapeAudioDiscontinuity: send a NULL packet to the audio decoders
173 *****************************************************************************/
174 void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
178 for( i_pgrm = 0; i_pgrm < p_input->stream.i_pgrm_number; i_pgrm++ )
180 pgrm_descriptor_t * p_pgrm = p_input->stream.pp_programs[i_pgrm];
182 for( i_es = 0; i_es < p_pgrm->i_es_number; i_es++ )
184 es_descriptor_t * p_es = p_pgrm->pp_es[i_es];
186 if( p_es->p_decoder_fifo != NULL && p_es->b_audio )
188 for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
190 input_NullPacket( p_input, p_es );
197 /*****************************************************************************
198 * CreateDecoderConfig: create a decoder_config_t
199 *****************************************************************************/
200 static decoder_config_t * CreateDecoderConfig( input_thread_t * p_input,
201 es_descriptor_t * p_es )
203 decoder_config_t * p_config;
205 p_config = (decoder_config_t *)malloc( sizeof(decoder_config_t) );
206 if( p_config == NULL )
208 intf_ErrMsg( "Unable to allocate memory in CreateDecoderConfig" );
213 if( (p_config->p_decoder_fifo =
214 (decoder_fifo_t *)malloc( sizeof(decoder_fifo_t) )) == NULL )
216 intf_ErrMsg( "Out of memory" );
221 /* Select a new ES */
222 p_input->stream.i_selected_es_number++;
223 p_input->stream.pp_selected_es = realloc(
224 p_input->stream.pp_selected_es,
225 p_input->stream.i_selected_es_number
226 * sizeof(es_descriptor_t *) );
227 if( p_input->stream.pp_selected_es == NULL )
229 intf_ErrMsg( "Unable to realloc memory" );
230 free( p_config->p_decoder_fifo );
234 p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number - 1]
237 /* Initialize the p_config structure */
238 vlc_mutex_init(&p_config->p_decoder_fifo->data_lock);
239 vlc_cond_init(&p_config->p_decoder_fifo->data_wait);
240 p_es->p_decoder_fifo = p_config->p_decoder_fifo;
242 p_config->pf_init_bit_stream = p_input->pf_init_bit_stream;
244 p_config->i_id = p_es->i_id;
245 p_config->i_type = p_es->i_type;
246 p_config->p_stream_ctrl = &p_input->stream.control;
248 p_config->p_decoder_fifo->p_first = NULL;
249 p_config->p_decoder_fifo->pp_last = &p_config->p_decoder_fifo->p_first;
250 p_config->p_decoder_fifo->i_depth = 0;
251 p_config->p_decoder_fifo->b_die = p_config->p_decoder_fifo->b_error = 0;
252 p_config->p_decoder_fifo->p_packets_mgt = p_input->p_method_data;
253 p_config->p_decoder_fifo->pf_delete_pes = p_input->pf_delete_pes;
258 /*****************************************************************************
259 * DeleteDecoderConfig: create a decoder_config_t
260 *****************************************************************************/
261 static void DeleteDecoderConfig( decoder_config_t * p_config )
263 intf_StatMsg( "input stats: killing decoder for 0x%x, type 0x%x, %d PES in FIFO",
264 p_config->i_id, p_config->i_type,
265 p_config->p_decoder_fifo->i_depth );
266 /* Free all packets still in the decoder fifo. */
267 p_config->p_decoder_fifo->pf_delete_pes(
268 p_config->p_decoder_fifo->p_packets_mgt,
269 p_config->p_decoder_fifo->p_first );
271 /* Destroy the lock and cond */
272 vlc_cond_destroy( &p_config->p_decoder_fifo->data_wait );
273 vlc_mutex_destroy( &p_config->p_decoder_fifo->data_lock );
275 free( p_config->p_decoder_fifo );