]> git.sesse.net Git - vlc/blob - src/lpcm_decoder/lpcm_decoder_thread.c
New features for libdvdcss: we have three ways now to decode a title key.
[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.17 2001/09/06 04:28:36 henri 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     /* 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     
115     while (DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) 
116     {
117         if (p_lpcmdec->p_fifo->b_die) 
118         {
119             vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
120             return -1;
121         }
122         vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, 
123                        &p_lpcmdec->p_fifo->data_lock);
124     }
125   
126     p_lpcmdec->p_data = DECODER_FIFO_START (*p_lpcmdec->p_fifo)->p_first;
127     
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,
133             NULL, NULL);
134
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 )
139     {
140         return -1;
141     }
142     intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p initialized\n", 
143                  p_lpcmdec );
144     return( 0 );
145 }
146
147 /*****************************************************************************
148  * RunThread : lpcm decoder thread
149  *****************************************************************************/
150 static void RunThread (lpcmdec_thread_t * p_lpcmdec)
151 {
152     intf_DbgMsg( "LPCM Debug: running lpcm decoder thread (%p) (pid== %i)", 
153                  p_lpcmdec, getpid() );
154
155     /* Initializing the lpcm decoder thread */
156     if (InitThread (p_lpcmdec)) 
157     {
158         p_lpcmdec->p_fifo->b_error = 1;
159     }
160
161     /* lpcm decoder thread's main loop */
162    
163     while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
164     {
165         byte_t * buffer,p_temp[LPCMDEC_FRAME_SIZE];
166         int i_loop;
167         byte_t byte1, byte2;
168     
169         if( DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts )
170         {
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;
174         }
175         else
176         { 
177             p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
178                 LAST_MDATE;
179         }
180
181         buffer = ((byte_t *)p_lpcmdec->p_aout_fifo->buffer) + 
182                   (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);
183     
184         RemoveBits32(&p_lpcmdec->bit_stream);
185         byte1 = GetBits(&p_lpcmdec->bit_stream, 8) ;
186         byte2 = GetBits(&p_lpcmdec->bit_stream, 8) ;
187         
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) )
194         {
195             byte1 = byte2;
196             byte2 = GetBits(&p_lpcmdec->bit_stream, 8);
197         }
198         
199         GetChunk( &p_lpcmdec->bit_stream, p_temp, LPCMDEC_FRAME_SIZE);
200         
201         for( i_loop = 0; i_loop < LPCMDEC_FRAME_SIZE/2; i_loop++ )
202         {
203             buffer[2*i_loop]=p_temp[2*i_loop+1];
204             buffer[2*i_loop+1]=p_temp[2*i_loop];
205         }
206         
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);
212         
213         intf_DbgMsg( "LPCM Debug: %x", *buffer );
214
215     }
216
217     /* If b_error is set, the lpcm decoder thread enters the error loop */
218     if (p_lpcmdec->p_fifo->b_error)
219     {
220         ErrorThread (p_lpcmdec);
221     }
222
223     /* End of the lpcm decoder thread */
224     EndThread (p_lpcmdec);
225 }
226
227 /*****************************************************************************
228  * ErrorThread : lpcm decoder's RunThread() error loop
229  *****************************************************************************/
230 static void ErrorThread( lpcmdec_thread_t * p_lpcmdec )
231 {
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 );
235
236     /* Wait until a `die' order is sent */
237     while( !p_lpcmdec->p_fifo->b_die ) 
238     {
239         /* Trash all received PES packets */
240         while( !DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo) ) 
241         {
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 );
245         }
246
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 );
250     }
251
252     /* We can release the lock before leaving */
253     vlc_mutex_unlock( &p_lpcmdec->p_fifo->data_lock );
254 }
255
256 /*****************************************************************************
257  * EndThread : lpcm decoder thread destruction
258  *****************************************************************************/
259 static void EndThread( lpcmdec_thread_t * p_lpcmdec )
260 {
261     intf_DbgMsg( "LPCM Debug: destroying lpcm decoder thread %p", p_lpcmdec );
262
263     /* If the audio output fifo was created, we destroy it */
264     if( p_lpcmdec->p_aout_fifo != NULL ) 
265     {
266         aout_DestroyFifo( p_lpcmdec->p_aout_fifo );
267
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) );
272     }
273
274     /* Destroy descriptor */
275     free( p_lpcmdec );
276
277     intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p destroyed", p_lpcmdec );
278 }