]> git.sesse.net Git - vlc/blob - src/input/input_dec.c
* ALL: WinCE compilation fixes (mostly nonexistent headers). A lot of
[vlc] / src / input / input_dec.c
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.50 2002/11/10 18:04:23 sam Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *
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.
13  * 
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>
28 #include <string.h>                                    /* memcpy(), memset() */
29
30 #include <vlc/vlc.h>
31
32 #ifdef HAVE_SYS_TYPES_H
33 #   include <sys/types.h>                                           /* off_t */
34 #endif
35
36 #include "stream_control.h"
37 #include "input_ext-dec.h"
38 #include "input_ext-intf.h"
39 #include "input_ext-plugins.h"
40
41 static decoder_fifo_t * CreateDecoderFifo( input_thread_t *,
42                                            es_descriptor_t * );
43 static void             DeleteDecoderFifo( decoder_fifo_t * );
44
45 /*****************************************************************************
46  * input_RunDecoder: spawns a new decoder thread
47  *****************************************************************************/
48 decoder_fifo_t * input_RunDecoder( input_thread_t * p_input,
49                                    es_descriptor_t * p_es )
50 {
51     decoder_fifo_t *p_fifo;
52     int i_priority;
53
54     /* Create the decoder configuration structure */
55     p_fifo = CreateDecoderFifo( p_input, p_es );
56
57     if( p_fifo == NULL )
58     {
59         msg_Err( p_input, "could not create decoder fifo" );
60         return NULL;
61     }
62
63     /* Get a suitable module */
64     p_fifo->p_module = module_Need( p_fifo, "decoder", "$codec" );
65     if( p_fifo->p_module == NULL )
66     {
67         msg_Err( p_fifo, "no suitable decoder module for fourcc `%4.4s'",
68                        (char*)&p_fifo->i_fourcc );
69         DeleteDecoderFifo( p_fifo );
70         vlc_object_destroy( p_fifo );
71         return NULL;
72     }
73
74     if ( p_es->i_cat == AUDIO_ES )
75     {
76         i_priority = VLC_THREAD_PRIORITY_AUDIO;
77     }
78     else
79     {
80         i_priority = VLC_THREAD_PRIORITY_VIDEO;
81     }
82
83     /* Spawn the decoder thread */
84     if( vlc_thread_create( p_fifo, "decoder", p_fifo->pf_run,
85                            i_priority, VLC_FALSE ) )
86     {
87         msg_Err( p_fifo, "cannot spawn decoder thread \"%s\"",
88                          p_fifo->p_module->psz_object_name );
89         module_Unneed( p_fifo, p_fifo->p_module );
90         return NULL;
91     }
92
93     p_input->stream.b_changed = 1;
94
95     return p_fifo;
96 }
97
98
99 /*****************************************************************************
100  * input_EndDecoder: kills a decoder thread and waits until it's finished
101  *****************************************************************************/
102 void input_EndDecoder( input_thread_t * p_input, es_descriptor_t * p_es )
103 {
104     int i_dummy;
105
106     p_es->p_decoder_fifo->b_die = 1;
107
108     /* Make sure the thread leaves the NextDataPacket() function by
109      * sending it a few null packets. */
110     for( i_dummy = 0; i_dummy < PADDING_PACKET_NUMBER; i_dummy++ )
111     {
112         input_NullPacket( p_input, p_es );
113     }
114
115     if( p_es->p_pes != NULL )
116     {
117         input_DecodePES( p_es->p_decoder_fifo, p_es->p_pes );
118     }
119
120     /* Waiting for the thread to exit */
121     /* I thought that unlocking was better since thread join can be long
122      * but it actually creates late pictures and freezes --stef */
123     /* vlc_mutex_unlock( &p_input->stream.stream_lock ); */
124     vlc_thread_join( p_es->p_decoder_fifo );
125     /* vlc_mutex_lock( &p_input->stream.stream_lock ); */
126
127     /* Delete decoder configuration */
128     DeleteDecoderFifo( p_es->p_decoder_fifo );
129
130     /* Unneed module */
131     module_Unneed( p_es->p_decoder_fifo, p_es->p_decoder_fifo->p_module );
132
133     /* Delete the fifo */
134     vlc_object_destroy( p_es->p_decoder_fifo );
135
136     /* Tell the input there is no more decoder */
137     p_es->p_decoder_fifo = NULL;
138
139     p_input->stream.b_changed = 1;
140 }
141
142 /*****************************************************************************
143  * input_DecodePES
144  *****************************************************************************
145  * Put a PES in the decoder's fifo.
146  *****************************************************************************/
147 void input_DecodePES( decoder_fifo_t * p_decoder_fifo, pes_packet_t * p_pes )
148 {
149     vlc_mutex_lock( &p_decoder_fifo->data_lock );
150
151     p_pes->p_next = NULL;
152     *p_decoder_fifo->pp_last = p_pes;
153     p_decoder_fifo->pp_last = &p_pes->p_next;
154     p_decoder_fifo->i_depth++;
155
156     /* Warn the decoder that it's got work to do. */
157     vlc_cond_signal( &p_decoder_fifo->data_wait );
158     vlc_mutex_unlock( &p_decoder_fifo->data_lock );
159 }
160
161 /****************************************************************************
162  * input_ExtractPES
163  *****************************************************************************
164  * Extract a PES from the fifo. If pp_pes is NULL then the PES is just
165  * deleted, otherwise *pp_pes will point to this PES.
166  ****************************************************************************/
167 void input_ExtractPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes )
168 {
169     pes_packet_t *p_pes;
170
171     vlc_mutex_lock( &p_fifo->data_lock );
172
173     if( p_fifo->p_first == NULL )
174     {
175         if( p_fifo->b_die )
176         {
177             vlc_mutex_unlock( &p_fifo->data_lock );
178             if( pp_pes ) *pp_pes = NULL;
179             return;
180         }
181
182         /* Signal the input thread we're waiting. This is only
183          * needed in case of slave clock (ES plug-in) but it won't
184          * harm. */
185         vlc_cond_signal( &p_fifo->data_wait );
186
187         /* Wait for the input to tell us when we received a packet. */
188         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
189     }
190
191     p_pes = p_fifo->p_first;
192     p_fifo->p_first = p_pes->p_next;
193     p_pes->p_next = NULL;
194     p_fifo->i_depth--;
195
196     if( !p_fifo->p_first )
197     {
198         /* No PES in the FIFO. p_last is no longer valid. */
199         p_fifo->pp_last = &p_fifo->p_first;
200     }
201
202     vlc_mutex_unlock( &p_fifo->data_lock );
203
204     if( pp_pes )
205         *pp_pes = p_pes;
206     else
207         input_DeletePES( p_fifo->p_packets_mgt, p_pes );
208 }
209
210 /****************************************************************************
211  * input_FlushPESFifo
212  *****************************************************************************
213  * Empties the PES fifo of the decoder.
214  ****************************************************************************/
215 void input_FlushPESFifo( decoder_fifo_t *p_fifo )
216 {
217     pes_packet_t * p_pes;
218
219     vlc_mutex_lock( &p_fifo->data_lock );
220     while( p_fifo->p_first )
221     {
222         p_pes = p_fifo->p_first;
223         p_fifo->p_first = p_fifo->p_first->p_next;
224         input_DeletePES( p_fifo->p_packets_mgt, p_pes );
225     }
226     /* No PES in the FIFO. p_last is no longer valid. */
227     p_fifo->pp_last = &p_fifo->p_first;
228     vlc_mutex_unlock( &p_fifo->data_lock );
229 }
230
231 /*****************************************************************************
232  * input_EscapeDiscontinuity: send a NULL packet to the decoders
233  *****************************************************************************/
234 void input_EscapeDiscontinuity( input_thread_t * p_input )
235 {
236     int     i_es, i;
237
238     for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
239     {
240         es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
241
242         if( p_es->p_decoder_fifo != NULL )
243         {
244             for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
245             {
246                 input_NullPacket( p_input, p_es );
247             }
248         }
249     }
250 }
251
252 /*****************************************************************************
253  * input_EscapeAudioDiscontinuity: send a NULL packet to the audio decoders
254  *****************************************************************************/
255 void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
256 {
257     int     i_es, i;
258
259     for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
260     {
261         es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
262
263         if( p_es->p_decoder_fifo != NULL && p_es->i_cat == AUDIO_ES )
264         {
265             for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
266             {
267                 input_NullPacket( p_input, p_es );
268             }
269         }
270     }
271 }
272
273 /*****************************************************************************
274  * CreateDecoderFifo: create a decoder_fifo_t
275  *****************************************************************************/
276 static decoder_fifo_t * CreateDecoderFifo( input_thread_t * p_input,
277                                            es_descriptor_t * p_es )
278 {
279     decoder_fifo_t * p_fifo;
280
281     /* Decoder FIFO */
282     p_fifo = vlc_object_create( p_input, VLC_OBJECT_DECODER );
283     if( p_fifo == NULL )
284     {
285         msg_Err( p_input, "out of memory" );
286         return NULL;
287     }
288
289     /* Select a new ES */
290     INSERT_ELEM( p_input->stream.pp_selected_es,
291                  p_input->stream.i_selected_es_number,
292                  p_input->stream.i_selected_es_number,
293                  p_es );
294
295     /* Initialize the p_fifo structure */
296     vlc_mutex_init( p_input, &p_fifo->data_lock );
297     vlc_cond_init( p_input, &p_fifo->data_wait );
298     p_es->p_decoder_fifo = p_fifo;
299
300     p_fifo->i_id = p_es->i_id;
301     p_fifo->i_fourcc = p_es->i_fourcc;
302     p_fifo->p_demux_data = p_es->p_demux_data;
303     
304     p_fifo->p_stream_ctrl = &p_input->stream.control;
305     p_fifo->p_sout = p_input->stream.p_sout;
306
307     p_fifo->p_first = NULL;
308     p_fifo->pp_last = &p_fifo->p_first;
309     p_fifo->i_depth = 0;
310     p_fifo->b_die = p_fifo->b_error = 0;
311     p_fifo->p_packets_mgt = p_input->p_method_data;
312
313     vlc_object_attach( p_fifo, p_input );
314
315     return p_fifo;
316 }
317
318 /*****************************************************************************
319  * DeleteDecoderFifo: destroy a decoder_fifo_t
320  *****************************************************************************/
321 static void DeleteDecoderFifo( decoder_fifo_t * p_fifo )
322 {
323     vlc_object_detach( p_fifo );
324
325     msg_Dbg( p_fifo, "killing decoder for 0x%x, fourcc `%4.4s', %d PES in FIFO",
326                      p_fifo->i_id, (char*)&p_fifo->i_fourcc, p_fifo->i_depth );
327
328     /* Free all packets still in the decoder fifo. */
329     input_DeletePES( p_fifo->p_packets_mgt,
330                      p_fifo->p_first );
331
332     /* Destroy the lock and cond */
333     vlc_cond_destroy( &p_fifo->data_wait );
334     vlc_mutex_destroy( &p_fifo->data_lock );
335 }
336