1 /*******************************************************************************
2 * input_ctrl.c: Decodeur control
4 *******************************************************************************
5 * Control the extraction and the decoding of the programs elements carried in
7 *******************************************************************************/
9 /*******************************************************************************
11 *******************************************************************************/
14 #include <sys/uio.h> /* iovec */
15 #include <stdlib.h> /* atoi(), malloc(), free() */
21 #include <X11/extensions/XShm.h>
22 #include <sys/soundcard.h>
23 #include <netinet/in.h> /* ntohs */
32 #include "input_netlist.h"
34 #include "decoder_fifo.h"
36 #include "audio_output.h"
37 #include "audio_dsp.h"
38 #include "audio_decoder.h"
41 #include "video_output.h"
42 #include "video_decoder.h"
45 /******************************************************************************
46 * input_AddPgrmElem: Start the extraction and the decoding of a program element
47 ******************************************************************************
48 * Add the element given by its PID in the list of PID to extract and spawn
49 * the decoding thread.
50 * This function only modifies the table of selected es, but must NOT modify
51 * the table of ES itself.
52 ******************************************************************************/
53 int input_AddPgrmElem( input_thread_t *p_input, int i_current_id )
55 int i_es_loop, i_selected_es_loop;
57 /* Since this function is intended to be called by interface, lock the
58 * elementary stream structure. */
59 pthread_mutex_lock( &p_input->es_lock );
61 /* Find out which PID we need. */
62 for( i_es_loop = 0; i_es_loop < INPUT_MAX_ES; i_es_loop++ )
64 if( p_input->p_es[i_es_loop].i_id == i_current_id )
66 if( p_input->p_es[i_es_loop].p_dec != NULL )
68 /* We already have a decoder for that PID. */
69 pthread_mutex_unlock( &p_input->es_lock );
70 intf_ErrMsg("input error: PID %d already selected\n",
75 intf_DbgMsg("Requesting selection of PID %d\n",
78 /* Find a free spot in pp_selected_es. */
79 for( i_selected_es_loop = 0; p_input->pp_selected_es[i_selected_es_loop] != NULL
80 && i_selected_es_loop < INPUT_MAX_SELECTED_ES; i_selected_es_loop++ );
82 if( i_selected_es_loop == INPUT_MAX_SELECTED_ES )
85 pthread_mutex_unlock( &p_input->es_lock );
86 intf_ErrMsg("input error: MAX_SELECTED_ES reached: try increasing it in config.h\n");
90 /* Don't decode PSI streams ! */
91 if( p_input->p_es[i_es_loop].b_psi )
93 intf_ErrMsg("input_error: trying to decode PID %d which is the one of a PSI\n");
94 pthread_mutex_unlock( &p_input->es_lock );
99 /* Spawn the decoder. */
100 switch( p_input->p_es[i_es_loop].i_type )
104 /* Spawn audio thread. */
105 if( ((adec_thread_t*)(p_input->p_es[i_es_loop].p_dec) =
106 adec_CreateThread( p_input )) == NULL )
108 intf_ErrMsg("Could not start audio decoder\n");
109 pthread_mutex_unlock( &p_input->es_lock );
116 /* Spawn video thread. */
117 /* Les 2 pointeurs NULL ne doivent pas etre NULL sinon on segfault !!!! */
118 if( ((vdec_thread_t*)(p_input->p_es[i_es_loop].p_dec) =
119 vdec_CreateThread( p_input )) == NULL )
121 intf_ErrMsg("Could not start video decoder\n");
122 pthread_mutex_unlock( &p_input->es_lock );
128 /* That should never happen. */
129 intf_DbgMsg("input error: unknown stream type (%d)\n",
130 p_input->p_es[i_es_loop].i_type);
131 pthread_mutex_unlock( &p_input->es_lock );
136 /* Initialise the demux */
137 p_input->p_es[i_es_loop].p_pes_packet = NULL;
138 p_input->p_es[i_es_loop].i_continuity_counter = 0;
139 p_input->p_es[i_es_loop].b_random = 0;
141 /* Mark stream to be demultiplexed. */
142 intf_DbgMsg("Stream %d added in %d\n", i_current_id, i_selected_es_loop);
143 p_input->pp_selected_es[i_selected_es_loop] = &p_input->p_es[i_es_loop];
144 pthread_mutex_unlock( &p_input->es_lock );
150 /* We haven't found this PID in the current stream. */
151 pthread_mutex_unlock( &p_input->es_lock );
152 intf_ErrMsg("input error: can't find PID %d\n", i_current_id);
156 /******************************************************************************
157 * input_DelPgrmElem: Stop the decoding of a program element
158 ******************************************************************************
159 * Stop the extraction of the element given by its PID and kill the associated
161 * This function only modifies the table of selected es, but must NOT modify
162 * the table of ES itself.
163 ******************************************************************************/
164 int input_DelPgrmElem( input_thread_t *p_input, int i_current_id )
166 int i_selected_es_loop, i_last_selected;
168 /* Since this function is intended to be called by interface, lock the
170 pthread_mutex_lock( &p_input->es_lock );
172 /* Find out which PID we need. */
173 for( i_selected_es_loop = 0; i_selected_es_loop < INPUT_MAX_SELECTED_ES;
174 i_selected_es_loop++ )
176 if( p_input->pp_selected_es[i_selected_es_loop] )
178 if( p_input->pp_selected_es[i_selected_es_loop]->i_id == i_current_id )
180 if( !(p_input->pp_selected_es[i_selected_es_loop]->p_dec) )
182 /* We don't have a decoder for that PID. */
183 pthread_mutex_unlock( &p_input->es_lock );
184 intf_ErrMsg("input error: PID %d already deselected\n",
189 intf_DbgMsg("input debug: requesting termination of PID %d\n",
192 /* Cancel the decoder. */
193 switch( p_input->pp_selected_es[i_selected_es_loop]->i_type )
197 adec_DestroyThread( (adec_thread_t*)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
202 vdec_DestroyThread( (vdec_thread_t*)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) /*, NULL */ );
207 p_input->pp_selected_es[i_selected_es_loop]->p_dec = NULL;
209 /* Find last selected stream. */
210 for( i_last_selected = i_selected_es_loop;
211 p_input->pp_selected_es[i_last_selected]
212 && i_last_selected < INPUT_MAX_SELECTED_ES;
215 /* Exchange streams. */
216 p_input->pp_selected_es[i_selected_es_loop] =
217 p_input->pp_selected_es[i_last_selected];
218 p_input->pp_selected_es[i_last_selected] = NULL;
220 pthread_mutex_unlock( &p_input->es_lock );
226 /* We haven't found this PID in the current stream. */
227 pthread_mutex_unlock( &p_input->es_lock );
228 intf_ErrMsg("input error: can't find PID %d\n", i_current_id);
234 /******************************************************************************
235 * input_IsElemRecv: Test if an element given by its PID is currently received
236 ******************************************************************************
237 * Cannot return the position of the es in the pp_selected_es, for it can
238 * change once we have released the lock
239 ******************************************************************************/
240 boolean_t input_IsElemRecv( input_thread_t *p_input, int i_id )
242 boolean_t b_is_recv = 0;
245 /* Since this function is intended to be called by interface, lock the
247 pthread_mutex_lock( &p_input->es_lock );
250 while( i_index < INPUT_MAX_SELECTED_ES && !p_input->pp_selected_es[i_index] )
252 if( p_input->pp_selected_es[i_index]->i_id == i_id )
259 /* Unlock the structure */
260 pthread_mutex_unlock( &p_input->es_lock );