1 /*****************************************************************************
2 * audio_decoder_thread.c: MPEG1 Layer I-II audio decoder thread
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
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.
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.
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 *****************************************************************************/
26 * - optimiser les NeedBits() et les GetBits() du code là où c'est possible ;
27 * - vlc_cond_signal() / vlc_cond_wait() ;
31 /*****************************************************************************
33 *****************************************************************************/
36 #include <unistd.h> /* getpid() */
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" */
48 #include "debug.h" /* "input_netlist.h" */
50 #include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
52 #include "input.h" /* pes_packet_t */
53 #include "input_netlist.h" /* input_NetlistFreePES() */
54 #include "decoder_fifo.h" /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
56 #include "audio_output.h" /* aout_fifo_t (for audio_decoder.h) */
58 #include "audio_decoder.h"
59 #include "audio_decoder_thread.h"
60 #include "audio_math.h" /* DCT32(), PCM() */
62 #define ADEC_FRAME_SIZE (2*1152)
64 /*****************************************************************************
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);
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 )
80 adec_thread_t * p_adec;
82 intf_DbgMsg ( "adec debug: creating audio decoder thread\n" );
84 /* Allocate the memory needed to store the thread's structure */
85 if ( (p_adec = (adec_thread_t *)malloc (sizeof(adec_thread_t))) == NULL )
87 intf_ErrMsg ( "adec error: not enough memory for adec_CreateThread() to create the new thread\n" );
92 * Initialize the thread properties
98 * Initialize the input properties
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;
107 /* Initialize the bit stream structure */
108 p_adec->p_input = p_input;
111 * Initialize the decoder properties
113 adec_init ( &p_adec->audio_decoder );
116 * Initialize the output properties
118 p_adec->p_aout = p_input->p_aout;
119 p_adec->p_aout_fifo = NULL;
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) )
124 intf_ErrMsg ("adec error: can't spawn audio decoder thread\n");
129 intf_DbgMsg ("adec debug: audio decoder thread (%p) created\n", p_adec);
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
141 *****************************************************************************/
142 void adec_DestroyThread (adec_thread_t * p_adec)
144 intf_DbgMsg ("adec debug: requesting termination of audio decoder thread %p\n", p_adec);
146 /* Ask thread to kill itself */
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));
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);
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)
167 aout_fifo_t aout_fifo;
168 adec_byte_stream_t * byte_stream;
170 intf_DbgMsg ("adec debug: initializing audio decoder thread %p\n", p_adec);
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) )
179 vlc_mutex_unlock ( &p_adec->fifo.data_lock );
182 vlc_cond_wait ( &p_adec->fifo.data_wait, &p_adec->fifo.data_lock );
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;
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 );
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;
198 /* Creating the audio output fifo */
199 if ( (p_adec->p_aout_fifo = aout_CreateFifo(p_adec->p_aout, &aout_fifo)) == NULL )
204 intf_DbgMsg ( "adec debug: audio decoder thread %p initialized\n", p_adec );
208 /*****************************************************************************
209 * RunThread : audio decoder thread
210 *****************************************************************************
211 * Audio decoder thread. This function does only returns when the thread is
213 *****************************************************************************/
214 static void RunThread (adec_thread_t * p_adec)
218 intf_DbgMsg ( "adec debug: running audio decoder thread (%p) (pid == %i)\n", p_adec, getpid() );
220 msleep ( INPUT_PTS_DELAY );
222 /* Initializing the audio decoder thread */
223 if( InitThread (p_adec) )
230 /* Audio decoder thread's main loop */
231 while( (!p_adec->b_die) && (!p_adec->b_error) )
234 adec_sync_info_t sync_info;
238 /* have to find a synchro point */
239 adec_byte_stream_t * p_byte_stream;
241 intf_DbgMsg ( "adec: sync\n" );
244 p_byte_stream = adec_byte_stream ( &p_adec->audio_decoder );
247 adec_byte_stream_next ( p_byte_stream );
248 } while ( 0 && (!p_adec->align) && (!p_adec->b_die)
249 && (!p_adec->b_error) );
254 if( DECODER_FIFO_START( p_adec->fifo)->b_has_pts )
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;
262 p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
266 if( adec_sync_frame (&p_adec->audio_decoder, &sync_info) )
272 p_adec->p_aout_fifo->l_rate = sync_info.sample_rate;
274 buffer = ((s16 *)p_adec->p_aout_fifo->buffer)
275 + (p_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE);
277 if( adec_decode_frame (&p_adec->audio_decoder, buffer) )
283 vlc_mutex_lock (&p_adec->p_aout_fifo->data_lock);
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);
293 /* If b_error is set, the audio decoder thread enters the error loop */
294 if( p_adec->b_error )
296 ErrorThread( p_adec );
299 /* End of the audio decoder thread */
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
309 *****************************************************************************/
310 static void ErrorThread ( adec_thread_t *p_adec )
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 );
316 /* Wait until a `die' order is sent */
317 while ( !p_adec->b_die )
319 /* Trash all received PES packets */
320 while ( !DECODER_FIFO_ISEMPTY(p_adec->fifo) )
322 input_NetlistFreePES ( p_adec->p_input,
323 DECODER_FIFO_START(p_adec->fifo) );
324 DECODER_FIFO_INCSTART ( p_adec->fifo );
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 );
331 /* We can release the lock before leaving */
332 vlc_mutex_unlock ( &p_adec->fifo.data_lock );
335 /*****************************************************************************
336 * EndThread : audio decoder thread destruction
337 *****************************************************************************
338 * This function is called when the thread ends after a sucessful
340 *****************************************************************************/
341 static void EndThread ( adec_thread_t *p_adec )
343 intf_DbgMsg ( "adec debug: destroying audio decoder thread %p\n", p_adec );
345 /* If the audio output fifo was created, we destroy it */
346 if ( p_adec->p_aout_fifo != NULL )
348 aout_DestroyFifo ( p_adec->p_aout_fifo );
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));
355 /* Destroy descriptor */
358 intf_DbgMsg ("adec debug: audio decoder thread %p destroyed\n", p_adec);
361 void adec_byte_stream_next ( adec_byte_stream_t * p_byte_stream )
363 adec_thread_t * p_adec = p_byte_stream->info;
365 /* We are looking for the next TS packet that contains real data,
366 * and not just a PES header */
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)
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);
378 /* Is the input thread dying ? */
379 if (p_adec->p_input->b_die)
381 vlc_mutex_unlock (&(p_adec->fifo.data_lock));
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
390 input_NetlistFreePES (p_adec->p_input, DECODER_FIFO_START(p_adec->fifo));
391 DECODER_FIFO_INCSTART (p_adec->fifo);
393 while (DECODER_FIFO_ISEMPTY(p_adec->fifo))
395 vlc_cond_wait (&p_adec->fifo.data_wait, &p_adec->fifo.data_lock);
396 if (p_adec->p_input->b_die)
398 vlc_mutex_unlock (&(p_adec->fifo.data_lock));
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)
410 /* We can release the fifo's data lock */
411 vlc_mutex_unlock (&p_adec->fifo.data_lock);
413 /* Perhaps the next TS packet of the current PES packet contains
414 * real data (ie its payload's size is greater than 0) */
417 p_adec->p_ts = p_adec->p_ts->p_next_ts;
419 } while (p_adec->p_ts->i_payload_start == p_adec->p_ts->i_payload_end);
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;