1 /*****************************************************************************
2 * lpcm_decoder_thread.c: lpcm decoder thread
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
5 * $Id: lpcm_decoder_thread.c,v 1.14 2001/05/01 04:18:18 sam Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
29 #include <unistd.h> /* getpid() */
31 #include <stdio.h> /* "intf_msg.h" */
32 #include <string.h> /* memcpy(), memset() */
33 #include <stdlib.h> /* malloc(), free() */
40 #include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
42 #include "stream_control.h"
43 #include "input_ext-dec.h"
45 #include "audio_output.h"
47 #include "lpcm_decoder.h"
48 #include "lpcm_decoder_thread.h"
50 #define LPCMDEC_FRAME_SIZE (2*1536) /* May be useless */
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))) == NULL) {
70 intf_ErrMsg ( "lpcm error: cannot create lpcmdec_thread_t" );
75 * Initialize the thread properties
77 p_lpcmdec->p_config = p_config;
78 p_lpcmdec->p_fifo = p_config->decoder_config.p_decoder_fifo;
81 /* Initialize the lpcm decoder structures */
82 lpcm_init (&p_lpcmdec->lpcm_decoder);
85 * Initialize the output properties
87 p_lpcmdec->p_aout_fifo = NULL;
89 /* Spawn the lpcm decoder thread */
90 if (vlc_thread_create(&p_lpcmdec->thread_id, "lpcm decoder", (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", 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)
107 lpcm_byte_stream_t * byte_stream;
109 intf_DbgMsg ( "LPCM Debug: initializing lpcm decoder thread %p", p_lpcmdec );
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);
114 while (DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
115 if (p_lpcmdec->p_fifo->b_die) {
116 vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
119 vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
121 p_lpcmdec->p_data = DECODER_FIFO_START (*p_lpcmdec->p_fifo)->p_first;
122 byte_stream = lpcm_byte_stream (&p_lpcmdec->lpcm_decoder);
123 byte_stream->p_byte = p_lpcmdec->p_data->p_payload_start;
124 byte_stream->p_end = p_lpcmdec->p_data->p_payload_end;
125 byte_stream->info = p_lpcmdec;
126 vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
128 /* Creating the audio output fifo */
129 p_lpcmdec->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_STEREO_FIFO, 2, 0, 0,
130 LPCMDEC_FRAME_SIZE, NULL );
131 if ( p_lpcmdec->p_aout_fifo == NULL )
136 intf_DbgMsg ( "LPCM Debug: lpcm decoder thread %p initialized", p_lpcmdec );
140 /*****************************************************************************
141 * RunThread : lpcm decoder thread
142 *****************************************************************************/
143 static void RunThread (lpcmdec_thread_t * p_lpcmdec)
147 intf_DbgMsg( "LPCM Debug: running lpcm decoder thread (%p) (pid== %i)", p_lpcmdec, getpid() );
149 /* Fucking holy piece of shit ! */
150 //msleep (INPUT_PTS_DELAY);
152 /* Initializing the lpcm decoder thread */
153 if (InitThread (p_lpcmdec))
155 p_lpcmdec->p_fifo->b_error = 1;
159 p_lpcmdec->sync_ptr = 0;
161 /* lpcm decoder thread's main loop */
162 /* FIXME : do we have enough room to store the decoded frames ?? */
164 while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
167 lpcm_sync_info_t sync_info;
171 /* have to find a synchro point */
174 if (DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts)
176 p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts;
177 DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts = 0;
181 p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = LAST_MDATE;
184 p_lpcmdec->p_aout_fifo->l_rate = sync_info.sample_rate;
186 buffer = ((s16 *)p_lpcmdec->p_aout_fifo->buffer) + (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);
188 if (lpcm_decode_frame (&p_lpcmdec->lpcm_decoder, buffer))
194 vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
195 p_lpcmdec->p_aout_fifo->l_end_frame = (p_lpcmdec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
196 vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
197 vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
199 intf_DbgMsg( "LPCM Debug: %x", *buffer );
205 /* If b_error is set, the lpcm decoder thread enters the error loop */
206 if (p_lpcmdec->p_fifo->b_error)
208 ErrorThread (p_lpcmdec);
211 /* End of the lpcm decoder thread */
212 EndThread (p_lpcmdec);
215 /*****************************************************************************
216 * ErrorThread : lpcm decoder's RunThread() error loop
217 *****************************************************************************/
218 static void ErrorThread (lpcmdec_thread_t * p_lpcmdec)
220 /* We take the lock, because we are going to read/write the start/end
221 * indexes of the decoder fifo */
222 vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
224 /* Wait until a `die' order is sent */
225 while (!p_lpcmdec->p_fifo->b_die) {
226 /* Trash all received PES packets */
227 while (!DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
228 p_lpcmdec->p_fifo->pf_delete_pes(p_lpcmdec->p_fifo->p_packets_mgt,
229 DECODER_FIFO_START(*p_lpcmdec->p_fifo));
230 DECODER_FIFO_INCSTART (*p_lpcmdec->p_fifo);
233 /* Waiting for the input thread to put new PES packets in the fifo */
234 vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
237 /* We can release the lock before leaving */
238 vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
241 /*****************************************************************************
242 * EndThread : lpcm decoder thread destruction
243 *****************************************************************************/
244 static void EndThread (lpcmdec_thread_t * p_lpcmdec)
246 intf_DbgMsg( "LPCM Debug: destroying lpcm decoder thread %p", p_lpcmdec );
248 /* If the audio output fifo was created, we destroy it */
249 if (p_lpcmdec->p_aout_fifo != NULL) {
250 aout_DestroyFifo (p_lpcmdec->p_aout_fifo);
252 /* Make sure the output thread leaves the NextFrame() function */
253 vlc_mutex_lock (&(p_lpcmdec->p_aout_fifo->data_lock));
254 vlc_cond_signal (&(p_lpcmdec->p_aout_fifo->data_wait));
255 vlc_mutex_unlock (&(p_lpcmdec->p_aout_fifo->data_lock));
258 /* Destroy descriptor */
261 intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p destroyed", p_lpcmdec );
264 void lpcm_byte_stream_next (lpcm_byte_stream_t * p_byte_stream)
266 // lpcmdec_thread_t * p_lpcmdec = p_byte_stream->info;
268 /* We are looking for the next TS packet that contains real data,
269 * and not just a PES header */