]> git.sesse.net Git - vlc/blob - src/input/input_dec.c
* ALL: Introduction of a new api for decoders.
[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.62 2003/09/02 20:19:26 gbazin 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 #include "vlc_block.h"
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_t * CreateDecoder( input_thread_t *, es_descriptor_t * );
39 static int         DecoderThread( decoder_t * );
40 static void        DeleteDecoder( decoder_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     vlc_value_t    val;
49     decoder_t      *p_dec;
50     int            i_priority;
51
52     /* Create the decoder configuration structure */
53     p_dec = CreateDecoder( p_input, p_es );
54     if( p_dec == NULL )
55     {
56         msg_Err( p_input, "could not create decoder" );
57         return NULL;
58     }
59
60     p_dec->p_module = NULL;
61
62     /* If we are in sout mode, search for packetizer module */
63     var_Get( p_input, "sout", &val );
64     if( !p_es->b_force_decoder && val.psz_string && *val.psz_string )
65     {
66         free( val.psz_string );
67         val.b_bool = VLC_TRUE;
68
69         if( p_es->i_cat == AUDIO_ES )
70         {
71             var_Get( p_input, "sout-audio", &val );
72         }
73         else if( p_es->i_cat == VIDEO_ES )
74         {
75             var_Get( p_input, "sout-video", &val );
76         }
77
78         if( val.b_bool )
79         {
80             p_dec->p_module =
81                 module_Need( p_dec, "packetizer", "$packetizer" );
82         }
83     }
84     else
85     {
86         /* default Get a suitable decoder module */
87         p_dec->p_module = module_Need( p_dec, "decoder", "$codec" );
88
89         if( val.psz_string ) free( val.psz_string );
90     }
91
92     if( p_dec->p_module == NULL )
93     {
94         msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'.\n"
95                  "VLC probably does not support this sound or video format.",
96                  (char*)&p_dec->p_fifo->i_fourcc );
97
98         DeleteDecoder( p_dec );
99         vlc_object_destroy( p_dec );
100         return NULL;
101     }
102
103     if ( p_es->i_cat == AUDIO_ES )
104     {
105         i_priority = VLC_THREAD_PRIORITY_AUDIO;
106     }
107     else
108     {
109         i_priority = VLC_THREAD_PRIORITY_VIDEO;
110     }
111
112     /* Spawn the decoder thread */
113     if( vlc_thread_create( p_dec, "decoder", DecoderThread,
114                            i_priority, VLC_FALSE ) )
115     {
116         msg_Err( p_dec, "cannot spawn decoder thread \"%s\"",
117                          p_dec->p_module->psz_object_name );
118         module_Unneed( p_dec, p_dec->p_module );
119         DeleteDecoder( p_dec );
120         vlc_object_destroy( p_dec );
121         return NULL;
122     }
123
124     p_input->stream.b_changed = 1;
125
126     return p_dec->p_fifo;
127 }
128
129 /*****************************************************************************
130  * input_EndDecoder: kills a decoder thread and waits until it's finished
131  *****************************************************************************/
132 void input_EndDecoder( input_thread_t * p_input, es_descriptor_t * p_es )
133 {
134     int i_dummy;
135     decoder_t *p_dec = p_es->p_decoder_fifo->p_dec;
136
137     p_es->p_decoder_fifo->b_die = 1;
138
139     /* Make sure the thread leaves the NextDataPacket() function by
140      * sending it a few null packets. */
141     for( i_dummy = 0; i_dummy < PADDING_PACKET_NUMBER; i_dummy++ )
142     {
143         input_NullPacket( p_input, p_es );
144     }
145
146     if( p_es->p_pes != NULL )
147     {
148         input_DecodePES( p_es->p_decoder_fifo, p_es->p_pes );
149     }
150
151     /* Waiting for the thread to exit */
152     /* I thought that unlocking was better since thread join can be long
153      * but it actually creates late pictures and freezes --stef */
154     /* vlc_mutex_unlock( &p_input->stream.stream_lock ); */
155     vlc_thread_join( p_dec );
156     /* vlc_mutex_lock( &p_input->stream.stream_lock ); */
157
158     /* Unneed module */
159     module_Unneed( p_dec, p_dec->p_module );
160
161     /* Delete decoder configuration */
162     DeleteDecoder( p_dec );
163
164     /* Delete the decoder */
165     vlc_object_destroy( p_dec );
166
167     /* Tell the input there is no more decoder */
168     p_es->p_decoder_fifo = NULL;
169
170     p_input->stream.b_changed = 1;
171 }
172
173 /*****************************************************************************
174  * input_DecodePES
175  *****************************************************************************
176  * Put a PES in the decoder's fifo.
177  *****************************************************************************/
178 void input_DecodePES( decoder_fifo_t * p_decoder_fifo, pes_packet_t * p_pes )
179 {
180     vlc_mutex_lock( &p_decoder_fifo->data_lock );
181
182     p_pes->p_next = NULL;
183     *p_decoder_fifo->pp_last = p_pes;
184     p_decoder_fifo->pp_last = &p_pes->p_next;
185     p_decoder_fifo->i_depth++;
186
187     /* Warn the decoder that it's got work to do. */
188     vlc_cond_signal( &p_decoder_fifo->data_wait );
189     vlc_mutex_unlock( &p_decoder_fifo->data_lock );
190 }
191
192 /*****************************************************************************
193  * Create a NULL packet for padding in case of a data loss
194  *****************************************************************************/
195 void input_NullPacket( input_thread_t * p_input,
196                        es_descriptor_t * p_es )
197 {
198     data_packet_t *             p_pad_data;
199     pes_packet_t *              p_pes;
200
201     if( (p_pad_data = input_NewPacketForce( p_input->p_method_data,
202                     PADDING_PACKET_SIZE)) == NULL )
203     {
204         msg_Err( p_input, "no new packet" );
205         p_input->b_error = 1;
206         return;
207     }
208
209     memset( p_pad_data->p_payload_start, 0, PADDING_PACKET_SIZE );
210     p_pad_data->b_discard_payload = 1;
211     p_pes = p_es->p_pes;
212
213     if( p_pes != NULL )
214     {
215         p_pes->b_discontinuity = 1;
216         p_pes->p_last->p_next = p_pad_data;
217         p_pes->p_last = p_pad_data;
218         p_pes->i_nb_data++;
219     }
220     else
221     {
222         if( (p_pes = input_NewPES( p_input->p_method_data )) == NULL )
223         {
224             msg_Err( p_input, "no PES packet" );
225             p_input->b_error = 1;
226             return;
227         }
228
229         p_pes->i_rate = p_input->stream.control.i_rate;
230         p_pes->p_first = p_pes->p_last = p_pad_data;
231         p_pes->i_nb_data = 1;
232         p_pes->b_discontinuity = 1;
233         input_DecodePES( p_es->p_decoder_fifo, p_pes );
234     }
235 }
236
237 /*****************************************************************************
238  * input_EscapeDiscontinuity: send a NULL packet to the decoders
239  *****************************************************************************/
240 void input_EscapeDiscontinuity( input_thread_t * p_input )
241 {
242     unsigned int i_es, i;
243
244     for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
245     {
246         es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
247
248         if( p_es->p_decoder_fifo != NULL )
249         {
250             for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
251             {
252                 input_NullPacket( p_input, p_es );
253             }
254         }
255     }
256 }
257
258 /*****************************************************************************
259  * input_EscapeAudioDiscontinuity: send a NULL packet to the audio decoders
260  *****************************************************************************/
261 void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
262 {
263     unsigned int i_es, i;
264
265     for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
266     {
267         es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
268
269         if( p_es->p_decoder_fifo != NULL && p_es->i_cat == AUDIO_ES )
270         {
271             for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
272             {
273                 input_NullPacket( p_input, p_es );
274             }
275         }
276     }
277 }
278
279 /*****************************************************************************
280  * CreateDecoderFifo: create a decoder_fifo_t
281  *****************************************************************************/
282 static decoder_t * CreateDecoder( input_thread_t * p_input,
283                                   es_descriptor_t * p_es )
284 {
285     decoder_t * p_dec;
286
287     p_dec = vlc_object_create( p_input, VLC_OBJECT_DECODER );
288     if( p_dec == NULL )
289     {
290         msg_Err( p_input, "out of memory" );
291         return NULL;
292     }
293
294     p_dec->pf_init = 0;
295     p_dec->pf_decode = 0;
296     p_dec->pf_end = 0;
297     p_dec->pf_run = 0;
298
299     /* Select a new ES */
300     INSERT_ELEM( p_input->stream.pp_selected_es,
301                  p_input->stream.i_selected_es_number,
302                  p_input->stream.i_selected_es_number,
303                  p_es );
304
305     /* Allocate the memory needed to store the decoder's fifo */
306     //p_dec->p_fifo = (decoder_fifo_t *)malloc(sizeof(decoder_fifo_t));
307     p_dec->p_fifo = vlc_object_create( p_input, VLC_OBJECT_DECODER_FIFO );
308     if( p_dec->p_fifo == NULL )
309     {
310         msg_Err( p_input, "out of memory" );
311         return NULL;
312     }
313
314     /* Initialize the decoder fifo */
315     //memset( p_dec->p_fifo, 0, sizeof(decoder_fifo_t) );
316     p_dec->p_module = NULL;
317
318     /* Initialize the p_fifo structure */
319     vlc_mutex_init( p_input, &p_dec->p_fifo->data_lock );
320     vlc_cond_init( p_input, &p_dec->p_fifo->data_wait );
321     p_es->p_decoder_fifo = p_dec->p_fifo;
322
323     p_dec->p_fifo->i_id = p_es->i_id;
324     p_dec->p_fifo->i_fourcc = p_es->i_fourcc;
325     p_dec->p_fifo->p_demux_data   = p_es->p_demux_data;
326     p_dec->p_fifo->p_waveformatex = p_es->p_waveformatex;
327     p_dec->p_fifo->p_bitmapinfoheader = p_es->p_bitmapinfoheader;
328     p_dec->p_fifo->p_stream_ctrl = &p_input->stream.control;
329     p_dec->p_fifo->p_sout = p_input->stream.p_sout;
330
331     p_dec->p_fifo->p_first = NULL;
332     p_dec->p_fifo->pp_last = &p_dec->p_fifo->p_first;
333     p_dec->p_fifo->i_depth = 0;
334     p_dec->p_fifo->b_die = p_dec->p_fifo->b_error = 0;
335     p_dec->p_fifo->p_packets_mgt = p_input->p_method_data;
336
337     p_dec->p_fifo->p_dec = p_dec;
338
339     vlc_object_attach( p_dec->p_fifo, p_input );
340     vlc_object_attach( p_dec, p_input );
341
342     return p_dec;
343 }
344
345 /*****************************************************************************
346  * DecoderThread: the decoding main loop
347  *****************************************************************************/
348 static int DecoderThread( decoder_t * p_dec )
349 {
350     pes_packet_t  *p_pes;
351     data_packet_t *p_data;
352     block_t       *p_block;
353
354     /* Temporary wrapper to keep old decoder api functional */
355     if( p_dec->pf_run )
356     {
357         p_dec->pf_run( p_dec->p_fifo );
358         return 0;
359     }
360
361
362     /* Initialize the decoder */
363     p_dec->p_fifo->b_error = p_dec->pf_init( p_dec );
364
365     /* The decoder's main loop */
366     while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
367     {
368         int i_size;
369
370         input_ExtractPES( p_dec->p_fifo, &p_pes );
371         if( !p_pes )
372         {
373             p_dec->p_fifo->b_error = 1;
374             break;
375         }
376
377         for( i_size = 0, p_data = p_pes->p_first;
378              p_data != NULL; p_data = p_data->p_next )
379         {
380             i_size += p_data->p_payload_end - p_data->p_payload_start;
381         }
382         p_block = block_New( p_dec, i_size );
383         for( i_size = 0, p_data = p_pes->p_first;
384              p_data != NULL; p_data = p_data->p_next )
385         {
386             memcpy( p_block->p_buffer + i_size, p_data->p_payload_start,
387                     p_data->p_payload_end - p_data->p_payload_start );
388             i_size += p_data->p_payload_end - p_data->p_payload_start;
389         }
390
391         p_block->i_pts = p_pes->i_pts;
392         p_block->i_dts = p_pes->i_dts;
393         p_dec->p_fifo->b_error = p_dec->pf_decode( p_dec, p_block );
394
395         input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
396     }
397
398     /* If b_error is set, the decoder thread enters the error loop */
399     if( p_dec->p_fifo->b_error )
400     {
401         /* Wait until a `die' order is sent */
402         while( !p_dec->p_fifo->b_die )
403         {
404             /* Trash all received PES packets */
405             input_ExtractPES( p_dec->p_fifo, NULL );
406         }
407     }
408
409     /* End of the decoder */
410     p_dec->pf_end( p_dec );
411
412     return 0;
413 }
414
415 /*****************************************************************************
416  * DeleteDecoderFifo: destroy a decoder_fifo_t
417  *****************************************************************************/
418 static void DeleteDecoder( decoder_t * p_dec )
419 {
420     vlc_object_detach( p_dec );
421     vlc_object_detach( p_dec->p_fifo );
422
423     msg_Dbg( p_dec,
424              "killing decoder for 0x%x, fourcc `%4.4s', %d PES in FIFO",
425              p_dec->p_fifo->i_id, (char*)&p_dec->p_fifo->i_fourcc,
426              p_dec->p_fifo->i_depth );
427
428     /* Free all packets still in the decoder fifo. */
429     input_DeletePES( p_dec->p_fifo->p_packets_mgt,
430                      p_dec->p_fifo->p_first );
431
432     /* Destroy the lock and cond */
433     vlc_cond_destroy( &p_dec->p_fifo->data_wait );
434     vlc_mutex_destroy( &p_dec->p_fifo->data_lock );
435
436     /* Free fifo */
437     vlc_object_destroy( p_dec->p_fifo );
438     //free( p_dec->p_fifo );
439 }