]> git.sesse.net Git - vlc/blob - src/audio_decoder/audio_decoder_thread.c
. fix� une b�vue dans la YUV 8 bits
[vlc] / src / audio_decoder / audio_decoder_thread.c
1 /*****************************************************************************
2  * audio_decoder_thread.c: MPEG1 Layer I-II audio decoder thread
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  *
6  * Authors:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*
24  * TODO :
25  *
26  * - optimiser les NeedBits() et les GetBits() du code là où c'est possible ;
27  * - vlc_cond_signal() / vlc_cond_wait() ;
28  *
29  */
30
31 /*****************************************************************************
32  * Preamble
33  *****************************************************************************/
34 #include "defs.h"
35
36 #include <unistd.h>                                              /* getpid() */
37
38 #include <stdio.h>                                           /* "intf_msg.h" */
39 #include <stdlib.h>                                      /* malloc(), free() */
40 #include <sys/types.h>                        /* on BSD, uio.h needs types.h */
41 #include <sys/uio.h>                                            /* "input.h" */
42
43 #include "threads.h"
44 #include "common.h"
45 #include "config.h"
46 #include "mtime.h"
47 #include "plugins.h"
48 #include "debug.h"                                      /* "input_netlist.h" */
49
50 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
51
52 #include "input.h"                                           /* pes_packet_t */
53 #include "input_netlist.h"                         /* input_NetlistFreePES() */
54 #include "decoder_fifo.h"         /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
55
56 #include "audio_output.h"               /* aout_fifo_t (for audio_decoder.h) */
57
58 #include "audio_decoder.h"
59 #include "audio_decoder_thread.h"
60 #include "audio_math.h"                                    /* DCT32(), PCM() */
61
62 #define ADEC_FRAME_SIZE (2*1152)
63
64 /*****************************************************************************
65  * Local prototypes
66  *****************************************************************************/
67 static int      InitThread             (adec_thread_t * p_adec);
68 static void     RunThread              (adec_thread_t * p_adec);
69 static void     ErrorThread            (adec_thread_t * p_adec);
70 static void     EndThread              (adec_thread_t * p_adec);
71
72 /*****************************************************************************
73  * adec_CreateThread: creates an audio decoder thread
74  *****************************************************************************
75  * This function creates a new audio decoder thread, and returns a pointer to
76  * its description. On error, it returns NULL.
77  *****************************************************************************/
78 adec_thread_t * adec_CreateThread ( input_thread_t * p_input )
79 {
80     adec_thread_t *     p_adec;
81
82     intf_DbgMsg ( "adec debug: creating audio decoder thread\n" );
83
84     /* Allocate the memory needed to store the thread's structure */
85     if ( (p_adec = (adec_thread_t *)malloc (sizeof(adec_thread_t))) == NULL ) 
86     {
87         intf_ErrMsg ( "adec error: not enough memory for adec_CreateThread() to create the new thread\n" );
88         return NULL;
89     }
90
91     /*
92      * Initialize the thread properties
93      */
94     p_adec->b_die = 0;
95     p_adec->b_error = 0;
96
97     /*
98      * Initialize the input properties
99      */
100     /* Initialize the decoder fifo's data lock and conditional variable and set
101      * its buffer as empty */
102     vlc_mutex_init ( &p_adec->fifo.data_lock );
103     vlc_cond_init ( &p_adec->fifo.data_wait );
104     p_adec->fifo.i_start = 0;
105     p_adec->fifo.i_end = 0;
106
107     /* Initialize the bit stream structure */
108     p_adec->p_input = p_input;
109
110     /*
111      * Initialize the decoder properties
112      */
113     adec_init ( &p_adec->audio_decoder );
114
115     /*
116      * Initialize the output properties
117      */
118     p_adec->p_aout = p_input->p_aout;
119     p_adec->p_aout_fifo = NULL;
120
121     /* Spawn the audio decoder thread */
122     if ( vlc_thread_create(&p_adec->thread_id, "audio decoder", (vlc_thread_func_t)RunThread, (void *)p_adec) ) 
123     {
124         intf_ErrMsg ("adec error: can't spawn audio decoder thread\n");
125         free (p_adec);
126         return NULL;
127     }
128
129     intf_DbgMsg ("adec debug: audio decoder thread (%p) created\n", p_adec);
130     return p_adec;
131 }
132
133 /*****************************************************************************
134  * adec_DestroyThread: destroys an audio decoder thread
135  *****************************************************************************
136  * This function asks an audio decoder thread to terminate. This function has
137  * not to wait until the decoder thread has really died, because the killer (ie
138  * this function's caller) is the input thread, that's why we are sure that no
139  * other thread will try to access to this thread's descriptor after its
140  * destruction.
141  *****************************************************************************/
142 void adec_DestroyThread (adec_thread_t * p_adec)
143 {
144     intf_DbgMsg ("adec debug: requesting termination of audio decoder thread %p\n", p_adec);
145
146     /* Ask thread to kill itself */
147     p_adec->b_die = 1;
148
149     /* Make sure the decoder thread leaves the GetByte() function */
150     vlc_mutex_lock (&(p_adec->fifo.data_lock));
151     vlc_cond_signal (&(p_adec->fifo.data_wait));
152     vlc_mutex_unlock (&(p_adec->fifo.data_lock));
153
154     /* Waiting for the decoder thread to exit */
155     /* Remove this as soon as the "status" flag is implemented */
156     vlc_thread_join (p_adec->thread_id);
157 }
158
159 /*****************************************************************************
160  * InitThread : initialize an audio decoder thread
161  *****************************************************************************
162  * This function is called from RunThread and performs the second step of the
163  * initialization. It returns 0 on success.
164  *****************************************************************************/
165 static int InitThread (adec_thread_t * p_adec)
166 {
167     aout_fifo_t          aout_fifo;
168     adec_byte_stream_t * byte_stream;
169
170     intf_DbgMsg ("adec debug: initializing audio decoder thread %p\n", p_adec);
171
172     /* Our first job is to initialize the bit stream structure with the
173      * beginning of the input stream */
174     vlc_mutex_lock ( &p_adec->fifo.data_lock );
175     while ( DECODER_FIFO_ISEMPTY(p_adec->fifo) ) 
176     {
177         if (p_adec->b_die) 
178         {
179             vlc_mutex_unlock ( &p_adec->fifo.data_lock );
180             return -1;
181         }
182         vlc_cond_wait ( &p_adec->fifo.data_wait, &p_adec->fifo.data_lock );
183     }
184     p_adec->p_ts = DECODER_FIFO_START ( p_adec->fifo )->p_first_ts;
185     byte_stream = adec_byte_stream ( &p_adec->audio_decoder );
186     byte_stream->p_byte =
187         p_adec->p_ts->buffer + p_adec->p_ts->i_payload_start;
188     byte_stream->p_end =
189         p_adec->p_ts->buffer + p_adec->p_ts->i_payload_end;
190     byte_stream->info = p_adec;
191     vlc_mutex_unlock ( &p_adec->fifo.data_lock );
192
193     aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
194     aout_fifo.i_channels = 2;
195     aout_fifo.b_stereo = 1;
196     aout_fifo.l_frame_size = ADEC_FRAME_SIZE;
197
198     /* Creating the audio output fifo */
199     if ( (p_adec->p_aout_fifo = aout_CreateFifo(p_adec->p_aout, &aout_fifo)) == NULL ) 
200     {
201         return -1;
202     }
203
204     intf_DbgMsg ( "adec debug: audio decoder thread %p initialized\n", p_adec );
205     return 0;
206 }
207
208 /*****************************************************************************
209  * RunThread : audio decoder thread
210  *****************************************************************************
211  * Audio decoder thread. This function does only returns when the thread is
212  * terminated.
213  *****************************************************************************/
214 static void RunThread (adec_thread_t * p_adec)
215 {
216     int sync;
217
218     intf_DbgMsg ( "adec debug: running audio decoder thread (%p) (pid == %i)\n", p_adec, getpid() );
219
220     msleep ( INPUT_PTS_DELAY );
221
222     /* Initializing the audio decoder thread */
223     if( InitThread (p_adec) )
224     {
225         p_adec->b_error = 1;
226     }
227
228     sync = 0;
229
230     /* Audio decoder thread's main loop */
231     while( (!p_adec->b_die) && (!p_adec->b_error) )
232     {
233         s16 * buffer;
234         adec_sync_info_t sync_info;
235
236         if ( !sync )
237         {
238             /* have to find a synchro point */
239             adec_byte_stream_t * p_byte_stream;
240             
241             intf_DbgMsg ( "adec: sync\n" );
242             
243             p_adec->align = 0;
244             p_byte_stream = adec_byte_stream ( &p_adec->audio_decoder );
245             do 
246             {
247                 adec_byte_stream_next ( p_byte_stream );
248             } while ( 0 && (!p_adec->align) && (!p_adec->b_die)
249                         && (!p_adec->b_error) );
250
251             sync = 1;
252         }
253
254         if( DECODER_FIFO_START( p_adec->fifo)->b_has_pts )
255         {
256             p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
257                 DECODER_FIFO_START( p_adec->fifo )->i_pts;
258             DECODER_FIFO_START(p_adec->fifo)->b_has_pts = 0;
259         }
260         else
261         {
262             p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
263                 LAST_MDATE;
264         }
265
266         if( adec_sync_frame (&p_adec->audio_decoder, &sync_info) )
267         {
268             sync = 0;
269             goto bad_frame;
270         }
271
272         p_adec->p_aout_fifo->l_rate = sync_info.sample_rate;
273
274         buffer = ((s16 *)p_adec->p_aout_fifo->buffer)
275                     + (p_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE);
276
277         if( adec_decode_frame (&p_adec->audio_decoder, buffer) )
278         {
279             sync = 0;
280             goto bad_frame;
281         }
282
283         vlc_mutex_lock (&p_adec->p_aout_fifo->data_lock);
284
285         p_adec->p_aout_fifo->l_end_frame =
286             (p_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
287         vlc_cond_signal (&p_adec->p_aout_fifo->data_wait);
288         vlc_mutex_unlock (&p_adec->p_aout_fifo->data_lock);
289
290         bad_frame:
291     }
292
293     /* If b_error is set, the audio decoder thread enters the error loop */
294     if( p_adec->b_error ) 
295     {
296         ErrorThread( p_adec );
297     }
298
299     /* End of the audio decoder thread */
300     EndThread( p_adec );
301 }
302
303 /*****************************************************************************
304  * ErrorThread : audio decoder's RunThread() error loop
305  *****************************************************************************
306  * This function is called when an error occured during thread main's loop. The
307  * thread can still receive feed, but must be ready to terminate as soon as
308  * possible.
309  *****************************************************************************/
310 static void ErrorThread ( adec_thread_t *p_adec )
311 {
312     /* We take the lock, because we are going to read/write the start/end
313      * indexes of the decoder fifo */
314     vlc_mutex_lock ( &p_adec->fifo.data_lock );
315
316     /* Wait until a `die' order is sent */
317     while ( !p_adec->b_die ) 
318     {
319         /* Trash all received PES packets */
320         while ( !DECODER_FIFO_ISEMPTY(p_adec->fifo) ) 
321         {
322             input_NetlistFreePES ( p_adec->p_input,
323                                    DECODER_FIFO_START(p_adec->fifo) );
324             DECODER_FIFO_INCSTART ( p_adec->fifo );
325         }
326
327         /* Waiting for the input thread to put new PES packets in the fifo */
328         vlc_cond_wait ( &p_adec->fifo.data_wait, &p_adec->fifo.data_lock );
329     }
330
331     /* We can release the lock before leaving */
332     vlc_mutex_unlock ( &p_adec->fifo.data_lock );
333 }
334
335 /*****************************************************************************
336  * EndThread : audio decoder thread destruction
337  *****************************************************************************
338  * This function is called when the thread ends after a sucessful
339  * initialization.
340  *****************************************************************************/
341 static void EndThread ( adec_thread_t *p_adec )
342 {
343     intf_DbgMsg ( "adec debug: destroying audio decoder thread %p\n", p_adec );
344
345     /* If the audio output fifo was created, we destroy it */
346     if ( p_adec->p_aout_fifo != NULL ) 
347     {
348         aout_DestroyFifo ( p_adec->p_aout_fifo );
349
350         /* Make sure the output thread leaves the NextFrame() function */
351         vlc_mutex_lock (&(p_adec->p_aout_fifo->data_lock));
352         vlc_cond_signal (&(p_adec->p_aout_fifo->data_wait));
353         vlc_mutex_unlock (&(p_adec->p_aout_fifo->data_lock));
354     }
355     /* Destroy descriptor */
356     free (p_adec);
357
358     intf_DbgMsg ("adec debug: audio decoder thread %p destroyed\n", p_adec);
359 }
360
361 void adec_byte_stream_next ( adec_byte_stream_t * p_byte_stream )
362 {
363     adec_thread_t * p_adec = p_byte_stream->info;
364
365     /* We are looking for the next TS packet that contains real data,
366      * and not just a PES header */
367     do 
368     {
369         /* We were reading the last TS packet of this PES packet... It's
370          * time to jump to the next PES packet */
371         if (p_adec->p_ts->p_next_ts == NULL) 
372         {
373             /* We are going to read/write the start and end indexes of the
374              * decoder fifo and to use the fifo's conditional variable,
375              * that's why we need to take the lock before */
376             vlc_mutex_lock (&p_adec->fifo.data_lock);
377
378             /* Is the input thread dying ? */
379             if (p_adec->p_input->b_die) 
380             {
381                 vlc_mutex_unlock (&(p_adec->fifo.data_lock));
382                 return;
383             }
384
385             /* We should increase the start index of the decoder fifo, but
386              * if we do this now, the input thread could overwrite the
387              * pointer to the current PES packet, and we weren't able to
388              * give it back to the netlist. That's why we free the PES
389              * packet first. */
390             input_NetlistFreePES (p_adec->p_input, DECODER_FIFO_START(p_adec->fifo));
391             DECODER_FIFO_INCSTART (p_adec->fifo);
392
393             while (DECODER_FIFO_ISEMPTY(p_adec->fifo)) 
394             {
395                 vlc_cond_wait (&p_adec->fifo.data_wait, &p_adec->fifo.data_lock);
396                 if (p_adec->p_input->b_die) 
397                 {
398                     vlc_mutex_unlock (&(p_adec->fifo.data_lock));
399                     return;
400                 }
401             }
402
403             /* The next byte could be found in the next PES packet */
404             p_adec->p_ts = DECODER_FIFO_START (p_adec->fifo)->p_first_ts;
405             if (DECODER_FIFO_START (p_adec->fifo)->b_data_alignment)
406             {
407                 p_adec->align = 1;
408             }
409
410             /* We can release the fifo's data lock */
411             vlc_mutex_unlock (&p_adec->fifo.data_lock);
412         }
413         /* Perhaps the next TS packet of the current PES packet contains
414          * real data (ie its payload's size is greater than 0) */
415         else 
416         {
417             p_adec->p_ts = p_adec->p_ts->p_next_ts;
418         }
419     } while (p_adec->p_ts->i_payload_start == p_adec->p_ts->i_payload_end);
420
421     /* We've found a TS packet which contains interesting data... */
422     p_byte_stream->p_byte =
423         p_adec->p_ts->buffer + p_adec->p_ts->i_payload_start;
424     p_byte_stream->p_end =
425         p_adec->p_ts->buffer + p_adec->p_ts->i_payload_end;
426 }