]> git.sesse.net Git - vlc/blob - src/input/input_dec.c
* ALL: the first libvlc commit.
[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.37 2002/06/01 12:32:01 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 #include <sys/types.h>                                              /* off_t */
30
31 #include <vlc/vlc.h>
32
33 #include "stream_control.h"
34 #include "input_ext-dec.h"
35 #include "input_ext-intf.h"
36 #include "input_ext-plugins.h"
37
38 static decoder_fifo_t * CreateDecoderFifo( input_thread_t *,
39                                            es_descriptor_t * );
40 static void             DeleteDecoderFifo( decoder_fifo_t * );
41
42 /*****************************************************************************
43  * input_RunDecoder: spawns a new decoder thread
44  *****************************************************************************/
45 decoder_fifo_t * input_RunDecoder( input_thread_t * p_input,
46                                    es_descriptor_t * p_es )
47 {
48     char * psz_plugin = NULL;
49
50     if( p_es->i_type == MPEG1_AUDIO_ES || p_es->i_type == MPEG2_AUDIO_ES )
51     {
52         psz_plugin = config_GetPsz( p_input, "mpeg-adec" );
53     }
54     if( p_es->i_type == AC3_AUDIO_ES )
55     {
56         psz_plugin = config_GetPsz( p_input, "ac3-adec" );
57     }
58
59     /* Get a suitable module */
60     p_es->p_module = module_Need( p_input, MODULE_CAPABILITY_DECODER,
61                                   psz_plugin, (void *)&p_es->i_type );
62     if( psz_plugin ) free( psz_plugin );
63     if( p_es->p_module == NULL )
64     {
65         msg_Err( p_input, "no suitable decoder module for type 0x%x",
66                           p_es->i_type );
67         return NULL;
68     }
69
70     /* Create the decoder configuration structure */
71     p_es->p_decoder_fifo = CreateDecoderFifo( p_input, p_es );
72
73     if( p_es->p_decoder_fifo == NULL )
74     {
75         msg_Err( p_input, "could not create decoder fifo" );
76         module_Unneed( p_es->p_module );
77         return NULL;
78     }
79
80     /* Spawn the decoder thread */
81     if ( vlc_thread_create( p_es->p_decoder_fifo, "decoder",
82                  p_es->p_module->p_functions->dec.functions.dec.pf_run, 0 ) )
83     {
84         msg_Err( p_input, "cannot spawn decoder thread \"%s\"",
85                            p_es->p_module->psz_object_name );
86         DeleteDecoderFifo( p_es->p_decoder_fifo );
87         module_Unneed( p_es->p_module );
88         return NULL;
89     }
90
91     p_input->stream.b_changed = 1;
92
93     return p_es->p_decoder_fifo;
94 }
95
96
97 /*****************************************************************************
98  * input_EndDecoder: kills a decoder thread and waits until it's finished
99  *****************************************************************************/
100 void input_EndDecoder( input_thread_t * p_input, es_descriptor_t * p_es )
101 {
102     int i_dummy;
103
104     p_es->p_decoder_fifo->b_die = 1;
105
106     /* Make sure the thread leaves the NextDataPacket() function by
107      * sending it a few null packets. */
108     for( i_dummy = 0; i_dummy < PADDING_PACKET_NUMBER; i_dummy++ )
109     {
110         input_NullPacket( p_input, p_es );
111     }
112
113     if( p_es->p_pes != NULL )
114     {
115         input_DecodePES( p_es->p_decoder_fifo, p_es->p_pes );
116     }
117
118     /* Waiting for the thread to exit */
119     /* I thought that unlocking was better since thread join can be long
120      * but it actually creates late pictures and freezes --stef */
121 //    vlc_mutex_unlock( &p_input->stream.stream_lock );
122     vlc_thread_join( p_es->p_decoder_fifo );
123 //    vlc_mutex_lock( &p_input->stream.stream_lock );
124
125     /* Delete decoder configuration */
126     DeleteDecoderFifo( p_es->p_decoder_fifo );
127
128     /* Unneed module */
129     module_Unneed( p_es->p_module );
130
131     /* Tell the input there is no more decoder */
132     p_es->p_decoder_fifo = NULL;
133
134     p_input->stream.b_changed = 1;
135 }
136
137 /*****************************************************************************
138  * input_DecodePES
139  *****************************************************************************
140  * Put a PES in the decoder's fifo.
141  *****************************************************************************/
142 void input_DecodePES( decoder_fifo_t * p_decoder_fifo, pes_packet_t * p_pes )
143 {
144     vlc_mutex_lock( &p_decoder_fifo->data_lock );
145
146     p_pes->p_next = NULL;
147     *p_decoder_fifo->pp_last = p_pes;
148     p_decoder_fifo->pp_last = &p_pes->p_next;
149     p_decoder_fifo->i_depth++;
150
151     /* Warn the decoder that it's got work to do. */
152     vlc_cond_signal( &p_decoder_fifo->data_wait );
153     vlc_mutex_unlock( &p_decoder_fifo->data_lock );
154 }
155
156 /*****************************************************************************
157  * input_EscapeDiscontinuity: send a NULL packet to the decoders
158  *****************************************************************************/
159 void input_EscapeDiscontinuity( input_thread_t * p_input )
160 {
161     int     i_es, i;
162
163     for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
164     {
165         es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
166
167         if( p_es->p_decoder_fifo != NULL )
168         {
169             for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
170             {
171                 input_NullPacket( p_input, p_es );
172             }
173         }
174     }
175 }
176
177 /*****************************************************************************
178  * input_EscapeAudioDiscontinuity: send a NULL packet to the audio decoders
179  *****************************************************************************/
180 void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
181 {
182     int     i_es, i;
183
184     for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
185     {
186         es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
187
188         if( p_es->p_decoder_fifo != NULL && p_es->b_audio )
189         {
190             for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
191             {
192                 input_NullPacket( p_input, p_es );
193             }
194         }
195     }
196 }
197
198 /*****************************************************************************
199  * CreateDecoderFifo: create a decoder_fifo_t
200  *****************************************************************************/
201 static decoder_fifo_t * CreateDecoderFifo( input_thread_t * p_input,
202                                            es_descriptor_t * p_es )
203 {
204     decoder_fifo_t * p_fifo;
205
206     /* Decoder FIFO */
207     p_fifo = vlc_object_create( p_input, VLC_OBJECT_DECODER );
208     if( p_fifo == NULL )
209     {
210         msg_Err( p_input, "out of memory" );
211         return NULL;
212     }
213
214     /* Select a new ES */
215     p_input->stream.i_selected_es_number++;
216     p_input->stream.pp_selected_es = realloc(
217                                           p_input->stream.pp_selected_es,
218                                           p_input->stream.i_selected_es_number
219                                            * sizeof(es_descriptor_t *) );
220     if( p_input->stream.pp_selected_es == NULL )
221     {
222         msg_Err( p_input, "out of memory" );
223         vlc_object_destroy( p_fifo );
224         return NULL;
225     }
226
227     p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number - 1]
228             = p_es;
229
230     /* Initialize the p_fifo structure */
231     vlc_mutex_init( p_input, &p_fifo->data_lock );
232     vlc_cond_init( &p_fifo->data_wait );
233     p_es->p_decoder_fifo = p_fifo;
234
235     p_fifo->i_id = p_es->i_id;
236     p_fifo->i_type = p_es->i_type;
237     p_fifo->p_demux_data = p_es->p_demux_data;
238     
239     p_fifo->p_stream_ctrl = &p_input->stream.control;
240
241     p_fifo->p_first = NULL;
242     p_fifo->pp_last = &p_fifo->p_first;
243     p_fifo->i_depth = 0;
244     p_fifo->b_die = p_fifo->b_error = 0;
245     p_fifo->p_packets_mgt = p_input->p_method_data;
246
247     vlc_object_attach( p_fifo, p_input );
248
249     return p_fifo;
250 }
251
252 /*****************************************************************************
253  * DeleteDecoderFifo: destroy a decoder_fifo_t
254  *****************************************************************************/
255 static void DeleteDecoderFifo( decoder_fifo_t * p_fifo )
256 {
257     vlc_object_unlink_all( p_fifo );
258
259     msg_Dbg( p_fifo, "killing decoder for 0x%x, type 0x%x, %d PES in FIFO",
260                      p_fifo->i_id, p_fifo->i_type, p_fifo->i_depth );
261
262     /* Free all packets still in the decoder fifo. */
263     input_DeletePES( p_fifo->p_packets_mgt,
264                      p_fifo->p_first );
265
266     /* Destroy the lock and cond */
267     vlc_cond_destroy( &p_fifo->data_wait );
268     vlc_mutex_destroy( &p_fifo->data_lock );
269
270     vlc_object_destroy( p_fifo );
271 }
272