]> git.sesse.net Git - vlc/blob - src/input/input_ctrl.c
* input/input_pcr.c :
[vlc] / src / input / input_ctrl.c
1 /*******************************************************************************
2  * input_ctrl.c: Decodeur control
3  * (c)1999 VideoLAN
4  *******************************************************************************
5  * Control the extraction and the decoding of the programs elements carried in
6  * a stream.
7  *******************************************************************************/
8
9 /*******************************************************************************
10  * Preamble
11  *******************************************************************************/
12 #include <errno.h>
13 #include <pthread.h>
14 #include <sys/uio.h>                                                 /* iovec */
15 #include <stdlib.h>                               /* atoi(), malloc(), free() */
16 #include <string.h>
17 #include <stdio.h>
18 #include <unistd.h>
19
20 #include <X11/Xlib.h>
21 #include <X11/extensions/XShm.h>
22 #include <sys/soundcard.h>
23 #include <netinet/in.h>                                              /* ntohs */
24
25 #include "common.h"
26 #include "config.h"
27 #include "mtime.h"
28 #include "intf_msg.h"
29 #include "debug.h"
30
31 #include "input.h"
32 #include "input_netlist.h"
33
34 #include "decoder_fifo.h"
35
36 #include "audio_output.h"
37 #include "audio_dsp.h"
38 #include "audio_decoder.h"
39
40 #include "video.h"
41 #include "video_output.h"
42 #include "video_decoder.h"
43
44
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 )
54 {
55     int i_es_loop, i_selected_es_loop;
56     
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 );
60
61     /* Find out which PID we need. */
62     for( i_es_loop = 0; i_es_loop < INPUT_MAX_ES; i_es_loop++ )
63     {
64         if( p_input->p_es[i_es_loop].i_id == i_current_id )
65         {
66             if( p_input->p_es[i_es_loop].p_dec != NULL )
67             {
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",
71                             i_current_id);
72                 return( -1 );
73             }
74
75             intf_DbgMsg("Requesting selection of PID %d\n",
76                         i_current_id);
77
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++ );
81             
82             if( i_selected_es_loop == INPUT_MAX_SELECTED_ES )
83             {
84                 /* array full */
85                 pthread_mutex_unlock( &p_input->es_lock );
86                 intf_ErrMsg("input error: MAX_SELECTED_ES reached: try increasing it in config.h\n");
87                 return( -1 );
88             }
89
90             /* Don't decode PSI streams ! */
91             if( p_input->p_es[i_es_loop].b_psi )
92             {
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 );
95                 return( -1 );
96             }
97             else
98             {
99                 /* Spawn the decoder. */
100                 switch( p_input->p_es[i_es_loop].i_type )
101                 {
102                     case MPEG1_AUDIO_ES:
103                     case MPEG2_AUDIO_ES:
104                         /* Spawn audio thread. */
105                         if( ((adec_thread_t*)(p_input->p_es[i_es_loop].p_dec) =
106                             adec_CreateThread( p_input )) == NULL )
107                         {
108                             intf_ErrMsg("Could not start audio decoder\n");
109                             pthread_mutex_unlock( &p_input->es_lock );
110                             return( -1 );
111                         }
112                         break;
113
114                     case MPEG1_VIDEO_ES:
115                     case MPEG2_VIDEO_ES:
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 )
120                         {
121                             intf_ErrMsg("Could not start video decoder\n");
122                             pthread_mutex_unlock( &p_input->es_lock );
123                             return( -1 );
124                         }
125                         break;
126
127                     default:
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 );
132                         return( -1 );
133                         break;
134                 }
135
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;
140                 
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 );
145                 return( 0 );
146             }
147         }
148     }
149     
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);
153     return( -1 );
154 }
155
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
160  * decoder thread
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 )
165 {
166     int i_selected_es_loop, i_last_selected;
167
168     /* Since this function is intended to be called by interface, lock the
169        structure. */
170     pthread_mutex_lock( &p_input->es_lock );
171
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++ )
175     {
176         if( p_input->pp_selected_es[i_selected_es_loop] )
177         {
178             if( p_input->pp_selected_es[i_selected_es_loop]->i_id == i_current_id )
179             {
180                 if( !(p_input->pp_selected_es[i_selected_es_loop]->p_dec) )
181                 {
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",
185                                 i_current_id);
186                     return( -1 );
187                 }
188
189                 intf_DbgMsg("input debug: requesting termination of PID %d\n",
190                             i_current_id);
191
192                 /* Cancel the decoder. */
193                 switch( p_input->pp_selected_es[i_selected_es_loop]->i_type )
194                 {
195                     case MPEG1_AUDIO_ES:
196                     case MPEG2_AUDIO_ES:
197                         adec_DestroyThread( (adec_thread_t*)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
198                         break;
199
200                     case MPEG1_VIDEO_ES:
201                     case MPEG2_VIDEO_ES:
202                         vdec_DestroyThread( (vdec_thread_t*)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) /*, NULL */ );
203                         break;
204                 }
205
206                 /* Unmark stream. */
207                 p_input->pp_selected_es[i_selected_es_loop]->p_dec = NULL;
208
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;
213                      i_last_selected++ );
214
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;
219
220                 pthread_mutex_unlock( &p_input->es_lock );
221                 return( 0 );
222             }
223         }
224     }
225
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);
229     return( -1 );
230 }
231
232
233
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 )
241 {
242   boolean_t b_is_recv = 0;
243     int i_index = 0;
244
245    /* Since this function is intended to be called by interface, lock the
246        structure. */
247     pthread_mutex_lock( &p_input->es_lock );
248
249     /* Scan the table */
250     while( i_index < INPUT_MAX_SELECTED_ES && !p_input->pp_selected_es[i_index] )
251     {
252       if( p_input->pp_selected_es[i_index]->i_id == i_id )
253       {
254         b_is_recv = 1;
255         break;
256       }
257     }
258
259     /* Unlock the structure */
260     pthread_mutex_unlock( &p_input->es_lock );
261
262     return( b_is_recv );
263 }