1 /*****************************************************************************
2 * lpcm_decoder_thread.c: lpcm decoder thread
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
5 * $Id: lpcm_decoder_thread.c,v 1.17 2001/09/06 04:28:36 henri Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
8 * Henri Fallon <henri@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
31 #include <unistd.h> /* getpid() */
34 #include <stdio.h> /* "intf_msg.h" */
35 #include <string.h> /* memcpy(), memset() */
36 #include <stdlib.h> /* malloc(), free() */
43 #include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
45 #include "stream_control.h"
46 #include "input_ext-dec.h"
48 #include "audio_output.h"
50 #include "lpcm_decoder_thread.h"
52 /*****************************************************************************
54 *****************************************************************************/
55 static int InitThread (lpcmdec_thread_t * p_adec);
56 static void RunThread (lpcmdec_thread_t * p_adec);
57 static void ErrorThread (lpcmdec_thread_t * p_adec);
58 static void EndThread (lpcmdec_thread_t * p_adec);
60 /*****************************************************************************
61 * lpcmdec_CreateThread: creates an lpcm decoder thread
62 *****************************************************************************/
63 vlc_thread_t lpcmdec_CreateThread( adec_config_t * p_config )
65 lpcmdec_thread_t * p_lpcmdec;
66 intf_DbgMsg( "LPCM: creating lpcm decoder thread" );
68 /* Allocate the memory needed to store the thread's structure */
69 if( (p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t)) )
72 intf_ErrMsg( "LPCM : error : cannot create lpcmdec_thread_t" );
77 * Initialize the thread properties
79 p_lpcmdec->p_config = p_config;
80 p_lpcmdec->p_fifo = p_config->decoder_config.p_decoder_fifo;
83 * Initialize the output properties
85 p_lpcmdec->p_aout_fifo = NULL;
87 /* Spawn the lpcm decoder thread */
88 if( vlc_thread_create( &p_lpcmdec->thread_id, "lpcm decoder",
89 (vlc_thread_func_t)RunThread, (void *)p_lpcmdec ) )
91 intf_ErrMsg( "LPCM : error : cannot spawn thread" );
96 intf_DbgMsg( "LPCM Debug: lpcm decoder thread (%p) created\n", p_lpcmdec );
97 return p_lpcmdec->thread_id;
100 /* Following functions are local */
102 /*****************************************************************************
103 * InitThread : initialize an lpcm decoder thread
104 *****************************************************************************/
105 static int InitThread (lpcmdec_thread_t * p_lpcmdec)
108 intf_DbgMsg ( "lpcm Debug: initializing lpcm decoder thread %p",
111 /* Our first job is to initialize the bit stream structure with the
112 * beginning of the input stream */
113 vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
115 while (DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo))
117 if (p_lpcmdec->p_fifo->b_die)
119 vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
122 vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait,
123 &p_lpcmdec->p_fifo->data_lock);
126 p_lpcmdec->p_data = DECODER_FIFO_START (*p_lpcmdec->p_fifo)->p_first;
128 vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
129 /* Init the BitStream */
130 p_lpcmdec->p_config->decoder_config.pf_init_bit_stream(
131 &p_lpcmdec->bit_stream,
132 p_lpcmdec->p_config->decoder_config.p_decoder_fifo,
135 /* Creating the audio output fifo */
136 p_lpcmdec->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_STEREO_FIFO, 2, 48000,
137 0, LPCMDEC_FRAME_SIZE/2, NULL );
138 if ( p_lpcmdec->p_aout_fifo == NULL )
142 intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p initialized\n",
147 /*****************************************************************************
148 * RunThread : lpcm decoder thread
149 *****************************************************************************/
150 static void RunThread (lpcmdec_thread_t * p_lpcmdec)
152 intf_DbgMsg( "LPCM Debug: running lpcm decoder thread (%p) (pid== %i)",
153 p_lpcmdec, getpid() );
155 /* Initializing the lpcm decoder thread */
156 if (InitThread (p_lpcmdec))
158 p_lpcmdec->p_fifo->b_error = 1;
161 /* lpcm decoder thread's main loop */
163 while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
165 byte_t * buffer,p_temp[LPCMDEC_FRAME_SIZE];
169 if( DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts )
171 p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
172 DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts;
173 DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts = 0;
177 p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
181 buffer = ((byte_t *)p_lpcmdec->p_aout_fifo->buffer) +
182 (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);
184 RemoveBits32(&p_lpcmdec->bit_stream);
185 byte1 = GetBits(&p_lpcmdec->bit_stream, 8) ;
186 byte2 = GetBits(&p_lpcmdec->bit_stream, 8) ;
188 /* I only have 2 test streams. As far as I understand
189 * after the RemoveBits and the 2 GetBits, we should be exactly
190 * where we whant : the sync word : 0x0180.
191 * If not, we got and find it. */
192 while( ( byte1 != 0x01 || byte2 != 0x80 ) && (!p_lpcmdec->p_fifo->b_die)
193 && (!p_lpcmdec->p_fifo->b_error) )
196 byte2 = GetBits(&p_lpcmdec->bit_stream, 8);
199 GetChunk( &p_lpcmdec->bit_stream, p_temp, LPCMDEC_FRAME_SIZE);
201 for( i_loop = 0; i_loop < LPCMDEC_FRAME_SIZE/2; i_loop++ )
203 buffer[2*i_loop]=p_temp[2*i_loop+1];
204 buffer[2*i_loop+1]=p_temp[2*i_loop];
207 vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
208 p_lpcmdec->p_aout_fifo->l_end_frame =
209 (p_lpcmdec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
210 vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
211 vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
213 intf_DbgMsg( "LPCM Debug: %x", *buffer );
217 /* If b_error is set, the lpcm decoder thread enters the error loop */
218 if (p_lpcmdec->p_fifo->b_error)
220 ErrorThread (p_lpcmdec);
223 /* End of the lpcm decoder thread */
224 EndThread (p_lpcmdec);
227 /*****************************************************************************
228 * ErrorThread : lpcm decoder's RunThread() error loop
229 *****************************************************************************/
230 static void ErrorThread( lpcmdec_thread_t * p_lpcmdec )
232 /* We take the lock, because we are going to read/write the start/end
233 * indexes of the decoder fifo */
234 vlc_mutex_lock( &p_lpcmdec->p_fifo->data_lock );
236 /* Wait until a `die' order is sent */
237 while( !p_lpcmdec->p_fifo->b_die )
239 /* Trash all received PES packets */
240 while( !DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo) )
242 p_lpcmdec->p_fifo->pf_delete_pes( p_lpcmdec->p_fifo->p_packets_mgt,
243 DECODER_FIFO_START(*p_lpcmdec->p_fifo ));
244 DECODER_FIFO_INCSTART( *p_lpcmdec->p_fifo );
247 /* Waiting for the input thread to put new PES packets in the fifo */
248 vlc_cond_wait ( &p_lpcmdec->p_fifo->data_wait,
249 &p_lpcmdec->p_fifo->data_lock );
252 /* We can release the lock before leaving */
253 vlc_mutex_unlock( &p_lpcmdec->p_fifo->data_lock );
256 /*****************************************************************************
257 * EndThread : lpcm decoder thread destruction
258 *****************************************************************************/
259 static void EndThread( lpcmdec_thread_t * p_lpcmdec )
261 intf_DbgMsg( "LPCM Debug: destroying lpcm decoder thread %p", p_lpcmdec );
263 /* If the audio output fifo was created, we destroy it */
264 if( p_lpcmdec->p_aout_fifo != NULL )
266 aout_DestroyFifo( p_lpcmdec->p_aout_fifo );
268 /* Make sure the output thread leaves the NextFrame() function */
269 vlc_mutex_lock( &(p_lpcmdec->p_aout_fifo->data_lock) );
270 vlc_cond_signal( &(p_lpcmdec->p_aout_fifo->data_wait) );
271 vlc_mutex_unlock( &(p_lpcmdec->p_aout_fifo->data_lock) );
274 /* Destroy descriptor */
277 intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p destroyed", p_lpcmdec );