1 /*****************************************************************************
2 * lpcm_decoder_thread.c: lpcm decoder thread
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
5 * $Id: lpcm_decoder_thread.c,v 1.6 2000/12/22 13:04:45 sam Exp $
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 <stdlib.h> /* malloc(), free() */
33 #include <sys/types.h> /* on BSD, uio.h needs types.h */
34 #include <sys/uio.h> /* "input.h" */
41 #include "debug.h" /* "input_netlist.h" */
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.h"
51 #include "lpcm_decoder_thread.h"
53 #define LPCMDEC_FRAME_SIZE (2*1536) /* May not be usefull */
55 /*****************************************************************************
57 *****************************************************************************/
58 static int InitThread (lpcmdec_thread_t * p_adec);
59 static void RunThread (lpcmdec_thread_t * p_adec);
60 static void ErrorThread (lpcmdec_thread_t * p_adec);
61 static void EndThread (lpcmdec_thread_t * p_adec);
63 /*****************************************************************************
64 * lpcmdec_CreateThread: creates an lpcm decoder thread
65 *****************************************************************************/
66 vlc_thread_t lpcmdec_CreateThread (adec_config_t * p_config)
68 lpcmdec_thread_t * p_lpcmdec;
69 intf_DbgMsg ( "LPCM Debug: creating lpcm decoder thread" );
71 /* Allocate the memory needed to store the thread's structure */
72 if ((p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t))) == NULL) {
73 intf_ErrMsg ( "LPCM Error: not enough memory for lpcmdec_CreateThread() to create the new thread" );
78 * Initialize the thread properties
80 p_lpcmdec->p_config = p_config;
81 p_lpcmdec->p_fifo = p_config->decoder_config.p_decoder_fifo;
84 /* Initialize the lpcm decoder structures */
85 lpcm_init (&p_lpcmdec->lpcm_decoder);
88 * Initialize the output properties
90 p_lpcmdec->p_aout = p_config->p_aout;
91 p_lpcmdec->p_aout_fifo = NULL;
93 /* Spawn the lpcm decoder thread */
94 if (vlc_thread_create(&p_lpcmdec->thread_id, "lpcm decoder", (vlc_thread_func_t)RunThread, (void *)p_lpcmdec)) {
95 intf_ErrMsg ( "LPCM Error: can't spawn lpcm decoder thread" );
100 intf_DbgMsg ( "LPCM Debug: lpcm decoder thread (%p) created", p_lpcmdec );
101 return p_lpcmdec->thread_id;
104 /* Following functions are local */
106 /*****************************************************************************
107 * InitThread : initialize an lpcm decoder thread
108 *****************************************************************************/
109 static int InitThread (lpcmdec_thread_t * p_lpcmdec)
111 aout_fifo_t aout_fifo;
112 lpcm_byte_stream_t * byte_stream;
114 intf_DbgMsg ( "LPCM Debug: initializing lpcm decoder thread %p", p_lpcmdec );
116 /* Our first job is to initialize the bit stream structure with the
117 * beginning of the input stream */
118 vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
119 while (DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
120 if (p_lpcmdec->p_fifo->b_die) {
121 vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
124 vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
126 p_lpcmdec->p_data = DECODER_FIFO_START (*p_lpcmdec->p_fifo)->p_first;
127 byte_stream = lpcm_byte_stream (&p_lpcmdec->lpcm_decoder);
128 byte_stream->p_byte = p_lpcmdec->p_data->p_payload_start;
129 byte_stream->p_end = p_lpcmdec->p_data->p_payload_end;
130 byte_stream->info = p_lpcmdec;
131 vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
133 aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
134 aout_fifo.i_channels = 2;
135 aout_fifo.b_stereo = 1;
137 aout_fifo.l_frame_size = LPCMDEC_FRAME_SIZE;
139 /* Creating the audio output fifo */
140 if ((p_lpcmdec->p_aout_fifo = aout_CreateFifo(p_lpcmdec->p_aout, &aout_fifo)) == NULL) {
144 intf_DbgMsg ( "LPCM Debug: lpcm decoder thread %p initialized", p_lpcmdec );
148 /*****************************************************************************
149 * RunThread : lpcm decoder thread
150 *****************************************************************************/
151 static void RunThread (lpcmdec_thread_t * p_lpcmdec)
155 intf_DbgMsg( "LPCM Debug: running lpcm decoder thread (%p) (pid== %i)", p_lpcmdec, getpid() );
157 /* Fucking holy piece of shit ! */
158 //msleep (INPUT_PTS_DELAY);
160 /* Initializing the lpcm decoder thread */
161 if (InitThread (p_lpcmdec))
163 p_lpcmdec->p_fifo->b_error = 1;
167 p_lpcmdec->sync_ptr = 0;
169 /* lpcm decoder thread's main loop */
170 /* FIXME : do we have enough room to store the decoded frames ?? */
172 while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
175 lpcm_sync_info_t sync_info;
179 /* have to find a synchro point */
182 if (DECODER_FIFO_START(*p_lpcmdec->p_fifo)->b_has_pts)
184 p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts;
185 DECODER_FIFO_START(*p_lpcmdec->p_fifo)->b_has_pts = 0;
189 p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = LAST_MDATE;
192 p_lpcmdec->p_aout_fifo->l_rate = sync_info.sample_rate;
194 buffer = ((s16 *)p_lpcmdec->p_aout_fifo->buffer) + (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);
196 if (lpcm_decode_frame (&p_lpcmdec->lpcm_decoder, buffer))
202 vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
203 p_lpcmdec->p_aout_fifo->l_end_frame = (p_lpcmdec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
204 vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
205 vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
207 intf_DbgMsg( "LPCM Debug: %x", *buffer );
211 /* If b_error is set, the lpcm decoder thread enters the error loop */
212 if (p_lpcmdec->p_fifo->b_error)
214 ErrorThread (p_lpcmdec);
217 /* End of the lpcm decoder thread */
218 EndThread (p_lpcmdec);
221 /*****************************************************************************
222 * ErrorThread : lpcm decoder's RunThread() error loop
223 *****************************************************************************/
224 static void ErrorThread (lpcmdec_thread_t * p_lpcmdec)
226 /* We take the lock, because we are going to read/write the start/end
227 * indexes of the decoder fifo */
228 vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
230 /* Wait until a `die' order is sent */
231 while (!p_lpcmdec->p_fifo->b_die) {
232 /* Trash all received PES packets */
233 while (!DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
234 p_lpcmdec->p_fifo->pf_delete_pes(p_lpcmdec->p_fifo->p_packets_mgt,
235 DECODER_FIFO_START(*p_lpcmdec->p_fifo));
236 DECODER_FIFO_INCSTART (*p_lpcmdec->p_fifo);
239 /* Waiting for the input thread to put new PES packets in the fifo */
240 vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
243 /* We can release the lock before leaving */
244 vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
247 /*****************************************************************************
248 * EndThread : lpcm decoder thread destruction
249 *****************************************************************************/
250 static void EndThread (lpcmdec_thread_t * p_lpcmdec)
252 intf_DbgMsg( "LPCM Debug: destroying lpcm decoder thread %p", p_lpcmdec );
254 /* If the audio output fifo was created, we destroy it */
255 if (p_lpcmdec->p_aout_fifo != NULL) {
256 aout_DestroyFifo (p_lpcmdec->p_aout_fifo);
258 /* Make sure the output thread leaves the NextFrame() function */
259 vlc_mutex_lock (&(p_lpcmdec->p_aout_fifo->data_lock));
260 vlc_cond_signal (&(p_lpcmdec->p_aout_fifo->data_wait));
261 vlc_mutex_unlock (&(p_lpcmdec->p_aout_fifo->data_lock));
264 /* Destroy descriptor */
267 intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p destroyed", p_lpcmdec );
270 void lpcm_byte_stream_next (lpcm_byte_stream_t * p_byte_stream)
272 // lpcmdec_thread_t * p_lpcmdec = p_byte_stream->info;
274 /* We are looking for the next TS packet that contains real data,
275 * and not just a PES header */