]> git.sesse.net Git - vlc/blob - src/lpcm_decoder/lpcm_decoder_thread.c
22f1de64fef99ef6e449115eaf1563ab8ea33990
[vlc] / src / lpcm_decoder / lpcm_decoder_thread.c
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 $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *          Henri Fallon <henri@videolan.org>
9  *
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.
14  * 
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.
19  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include "defs.h"
29
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>                                              /* getpid() */
32 #endif
33
34 #include <stdio.h>                                           /* "intf_msg.h" */
35 #include <string.h>                                    /* memcpy(), memset() */
36 #include <stdlib.h>                                      /* malloc(), free() */
37
38 #include "config.h"
39 #include "common.h"
40 #include "threads.h"
41 #include "mtime.h"
42
43 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
44
45 #include "stream_control.h"
46 #include "input_ext-dec.h"
47
48 #include "audio_output.h"
49
50 #include "lpcm_decoder_thread.h"
51
52 /*****************************************************************************
53  * Local prototypes
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);
59
60 /*****************************************************************************
61  * lpcmdec_CreateThread: creates an lpcm decoder thread
62  *****************************************************************************/
63 vlc_thread_t lpcmdec_CreateThread( adec_config_t * p_config )
64 {
65     lpcmdec_thread_t *   p_lpcmdec;
66     intf_DbgMsg( "LPCM: creating lpcm decoder thread" );
67
68     /* Allocate the memory needed to store the thread's structure */
69     if( (p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t)) )
70             == NULL) 
71     {
72         intf_ErrMsg( "LPCM : error : cannot create lpcmdec_thread_t" );
73         return 0;
74     }
75
76     /*
77      * Initialize the thread properties
78      */
79     p_lpcmdec->p_config = p_config;
80     p_lpcmdec->p_fifo = p_config->decoder_config.p_decoder_fifo;
81
82     /*
83      * Initialize the output properties
84      */
85     p_lpcmdec->p_aout_fifo = NULL;
86
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 ) )
90     {
91         intf_ErrMsg( "LPCM : error : cannot spawn thread" );
92         free (p_lpcmdec);
93         return 0;
94     }
95
96     intf_DbgMsg( "LPCM Debug: lpcm decoder thread (%p) created\n", p_lpcmdec );
97     return p_lpcmdec->thread_id;
98 }
99
100 /* Following functions are local */
101
102 /*****************************************************************************
103  * InitThread : initialize an lpcm decoder thread
104  *****************************************************************************/
105 static int InitThread (lpcmdec_thread_t * p_lpcmdec)
106 {
107
108     intf_DbgMsg ( "lpcm Debug: initializing lpcm decoder thread %p", 
109                    p_lpcmdec );
110
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,
115             NULL, NULL);
116
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 )
121     {
122         return -1;
123     }
124
125     intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p initialized\n", 
126                  p_lpcmdec );
127     return( 0 );
128 }
129
130 /*****************************************************************************
131  * RunThread : lpcm decoder thread
132  *****************************************************************************/
133 static void RunThread (lpcmdec_thread_t * p_lpcmdec)
134 {
135     intf_DbgMsg( "LPCM Debug: running lpcm decoder thread (%p) (pid== %i)", 
136                  p_lpcmdec, getpid() );
137
138     /* Initializing the lpcm decoder thread */
139     if (InitThread (p_lpcmdec)) 
140     {
141         p_lpcmdec->p_fifo->b_error = 1;
142     }
143
144     /* lpcm decoder thread's main loop */
145    
146     while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
147     {
148         byte_t * buffer,p_temp[LPCMDEC_FRAME_SIZE];
149         int i_loop;
150         byte_t byte1, byte2;
151     
152         if( DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts )
153         {
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;
157         }
158         else
159         { 
160             p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
161                 LAST_MDATE;
162         }
163
164         buffer = ((byte_t *)p_lpcmdec->p_aout_fifo->buffer) + 
165                   (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);
166     
167         RemoveBits32(&p_lpcmdec->bit_stream);
168         byte1 = GetBits(&p_lpcmdec->bit_stream, 8) ;
169         byte2 = GetBits(&p_lpcmdec->bit_stream, 8) ;
170         
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) )
177         {
178             byte1 = byte2;
179             byte2 = GetBits(&p_lpcmdec->bit_stream, 8);
180         }
181         
182         GetChunk( &p_lpcmdec->bit_stream, p_temp, LPCMDEC_FRAME_SIZE);
183         
184         for( i_loop = 0; i_loop < LPCMDEC_FRAME_SIZE/2; i_loop++ )
185         {
186             buffer[2*i_loop]=p_temp[2*i_loop+1];
187             buffer[2*i_loop+1]=p_temp[2*i_loop];
188         }
189         
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);
195         
196         intf_DbgMsg( "LPCM Debug: %x", *buffer );
197
198     }
199
200     /* If b_error is set, the lpcm decoder thread enters the error loop */
201     if (p_lpcmdec->p_fifo->b_error)
202     {
203         ErrorThread (p_lpcmdec);
204     }
205
206     /* End of the lpcm decoder thread */
207     EndThread (p_lpcmdec);
208 }
209
210 /*****************************************************************************
211  * ErrorThread : lpcm decoder's RunThread() error loop
212  *****************************************************************************/
213 static void ErrorThread( lpcmdec_thread_t * p_lpcmdec )
214 {
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 );
218
219     /* Wait until a `die' order is sent */
220     while( !p_lpcmdec->p_fifo->b_die ) 
221     {
222         /* Trash all received PES packets */
223         while( !DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo) ) 
224         {
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 );
228         }
229
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 );
233     }
234
235     /* We can release the lock before leaving */
236     vlc_mutex_unlock( &p_lpcmdec->p_fifo->data_lock );
237 }
238
239 /*****************************************************************************
240  * EndThread : lpcm decoder thread destruction
241  *****************************************************************************/
242 static void EndThread( lpcmdec_thread_t * p_lpcmdec )
243 {
244     intf_DbgMsg( "LPCM Debug: destroying lpcm decoder thread %p", p_lpcmdec );
245
246     /* If the audio output fifo was created, we destroy it */
247     if( p_lpcmdec->p_aout_fifo != NULL ) 
248     {
249         aout_DestroyFifo( p_lpcmdec->p_aout_fifo );
250
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) );
255     }
256
257     /* Destroy descriptor */
258     free( p_lpcmdec );
259
260     intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p destroyed", p_lpcmdec );
261 }