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