1 /*****************************************************************************
2 * lpcm_decoder_thread.c: lpcm decoder thread
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
5 * $Id: lpcm_decoder_thread.c,v 1.18 2001/11/06 18:13:21 massiot 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 /* Init the BitStream */
112 p_lpcmdec->p_config->decoder_config.pf_init_bit_stream(
113 &p_lpcmdec->bit_stream,
114 p_lpcmdec->p_config->decoder_config.p_decoder_fifo,
117 /* Creating the audio output fifo */
118 p_lpcmdec->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_STEREO_FIFO, 2, 48000,
119 0, LPCMDEC_FRAME_SIZE/2, NULL );
120 if ( p_lpcmdec->p_aout_fifo == NULL )
125 intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p initialized\n",
130 /*****************************************************************************
131 * RunThread : lpcm decoder thread
132 *****************************************************************************/
133 static void RunThread (lpcmdec_thread_t * p_lpcmdec)
135 intf_DbgMsg( "LPCM Debug: running lpcm decoder thread (%p) (pid== %i)",
136 p_lpcmdec, getpid() );
138 /* Initializing the lpcm decoder thread */
139 if (InitThread (p_lpcmdec))
141 p_lpcmdec->p_fifo->b_error = 1;
144 /* lpcm decoder thread's main loop */
146 while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
148 byte_t * buffer,p_temp[LPCMDEC_FRAME_SIZE];
152 if( DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts )
154 p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
155 DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts;
156 DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts = 0;
160 p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
164 buffer = ((byte_t *)p_lpcmdec->p_aout_fifo->buffer) +
165 (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);
167 RemoveBits32(&p_lpcmdec->bit_stream);
168 byte1 = GetBits(&p_lpcmdec->bit_stream, 8) ;
169 byte2 = GetBits(&p_lpcmdec->bit_stream, 8) ;
171 /* I only have 2 test streams. As far as I understand
172 * after the RemoveBits and the 2 GetBits, we should be exactly
173 * where we whant : the sync word : 0x0180.
174 * If not, we got and find it. */
175 while( ( byte1 != 0x01 || byte2 != 0x80 ) && (!p_lpcmdec->p_fifo->b_die)
176 && (!p_lpcmdec->p_fifo->b_error) )
179 byte2 = GetBits(&p_lpcmdec->bit_stream, 8);
182 GetChunk( &p_lpcmdec->bit_stream, p_temp, LPCMDEC_FRAME_SIZE);
184 for( i_loop = 0; i_loop < LPCMDEC_FRAME_SIZE/2; i_loop++ )
186 buffer[2*i_loop]=p_temp[2*i_loop+1];
187 buffer[2*i_loop+1]=p_temp[2*i_loop];
190 vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
191 p_lpcmdec->p_aout_fifo->l_end_frame =
192 (p_lpcmdec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
193 vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
194 vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
196 intf_DbgMsg( "LPCM Debug: %x", *buffer );
200 /* If b_error is set, the lpcm decoder thread enters the error loop */
201 if (p_lpcmdec->p_fifo->b_error)
203 ErrorThread (p_lpcmdec);
206 /* End of the lpcm decoder thread */
207 EndThread (p_lpcmdec);
210 /*****************************************************************************
211 * ErrorThread : lpcm decoder's RunThread() error loop
212 *****************************************************************************/
213 static void ErrorThread( lpcmdec_thread_t * p_lpcmdec )
215 /* We take the lock, because we are going to read/write the start/end
216 * indexes of the decoder fifo */
217 vlc_mutex_lock( &p_lpcmdec->p_fifo->data_lock );
219 /* Wait until a `die' order is sent */
220 while( !p_lpcmdec->p_fifo->b_die )
222 /* Trash all received PES packets */
223 while( !DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo) )
225 p_lpcmdec->p_fifo->pf_delete_pes( p_lpcmdec->p_fifo->p_packets_mgt,
226 DECODER_FIFO_START(*p_lpcmdec->p_fifo ));
227 DECODER_FIFO_INCSTART( *p_lpcmdec->p_fifo );
230 /* Waiting for the input thread to put new PES packets in the fifo */
231 vlc_cond_wait ( &p_lpcmdec->p_fifo->data_wait,
232 &p_lpcmdec->p_fifo->data_lock );
235 /* We can release the lock before leaving */
236 vlc_mutex_unlock( &p_lpcmdec->p_fifo->data_lock );
239 /*****************************************************************************
240 * EndThread : lpcm decoder thread destruction
241 *****************************************************************************/
242 static void EndThread( lpcmdec_thread_t * p_lpcmdec )
244 intf_DbgMsg( "LPCM Debug: destroying lpcm decoder thread %p", p_lpcmdec );
246 /* If the audio output fifo was created, we destroy it */
247 if( p_lpcmdec->p_aout_fifo != NULL )
249 aout_DestroyFifo( p_lpcmdec->p_aout_fifo );
251 /* Make sure the output thread leaves the NextFrame() function */
252 vlc_mutex_lock( &(p_lpcmdec->p_aout_fifo->data_lock) );
253 vlc_cond_signal( &(p_lpcmdec->p_aout_fifo->data_wait) );
254 vlc_mutex_unlock( &(p_lpcmdec->p_aout_fifo->data_lock) );
257 /* Destroy descriptor */
260 intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p destroyed", p_lpcmdec );