]> git.sesse.net Git - vlc/blob - src/lpcm_decoder/lpcm_decoder_thread.c
f3643e37fcf84f469d9ad4b0fdbb0772b0aa5f8e
[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.11 2001/03/21 13:42:34 sam Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
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.
13  * 
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "defs.h"
28
29 #include <unistd.h>                                              /* getpid() */
30
31 #include <stdio.h>                                           /* "intf_msg.h" */
32 #include <stdlib.h>                                      /* malloc(), free() */
33
34 #include "config.h"
35 #include "common.h"
36 #include "threads.h"
37 #include "mtime.h"
38
39 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
40
41 #include "stream_control.h"
42 #include "input_ext-dec.h"
43
44 #include "audio_output.h"
45
46 #include "lpcm_decoder.h"
47 #include "lpcm_decoder_thread.h"
48
49 #define LPCMDEC_FRAME_SIZE (2*1536)                    /* May not be usefull */
50
51 /*****************************************************************************
52  * Local prototypes
53  *****************************************************************************/
54 static int      InitThread              (lpcmdec_thread_t * p_adec);
55 static void     RunThread               (lpcmdec_thread_t * p_adec);
56 static void     ErrorThread             (lpcmdec_thread_t * p_adec);
57 static void     EndThread               (lpcmdec_thread_t * p_adec);
58
59 /*****************************************************************************
60  * lpcmdec_CreateThread: creates an lpcm decoder thread
61  *****************************************************************************/
62 vlc_thread_t lpcmdec_CreateThread (adec_config_t * p_config)
63 {
64     lpcmdec_thread_t *   p_lpcmdec;
65     intf_DbgMsg ( "lpcm: creating lpcm decoder thread" );
66
67     /* Allocate the memory needed to store the thread's structure */
68     if ((p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t))) == NULL) {
69         intf_ErrMsg ( "lpcm error: cannot create lpcmdec_thread_t" );
70         return 0;
71     }
72
73     /*
74      * Initialize the thread properties
75      */
76     p_lpcmdec->p_config = p_config;
77     p_lpcmdec->p_fifo = p_config->decoder_config.p_decoder_fifo;
78
79
80     /* Initialize the lpcm decoder structures */
81     lpcm_init (&p_lpcmdec->lpcm_decoder);
82
83     /*
84      * Initialize the output properties
85      */
86     p_lpcmdec->p_aout = p_config->p_aout;
87     p_lpcmdec->p_aout_fifo = NULL;
88
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" );
92         free (p_lpcmdec);
93         return 0;
94     }
95
96     intf_DbgMsg ( "LPCM Debug: lpcm decoder thread (%p) created", 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     aout_fifo_t         aout_fifo;
108     lpcm_byte_stream_t * byte_stream;
109
110     intf_DbgMsg ( "LPCM Debug: initializing lpcm decoder thread %p", p_lpcmdec );
111
112     /* Our first job is to initialize the bit stream structure with the
113      * beginning of the input stream */
114     vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
115     while (DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
116         if (p_lpcmdec->p_fifo->b_die) {
117             vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
118             return -1;
119         }
120         vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
121     }
122     p_lpcmdec->p_data = DECODER_FIFO_START (*p_lpcmdec->p_fifo)->p_first;
123     byte_stream = lpcm_byte_stream (&p_lpcmdec->lpcm_decoder);
124     byte_stream->p_byte = p_lpcmdec->p_data->p_payload_start;
125     byte_stream->p_end = p_lpcmdec->p_data->p_payload_end;
126     byte_stream->info = p_lpcmdec;
127     vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
128
129     aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
130     aout_fifo.i_channels = 2;
131     aout_fifo.b_stereo = 1;
132
133     aout_fifo.l_frame_size = LPCMDEC_FRAME_SIZE;
134
135     /* Creating the audio output fifo */
136     if ((p_lpcmdec->p_aout_fifo = aout_CreateFifo(p_lpcmdec->p_aout, &aout_fifo)) == NULL) {
137         return -1;
138     }
139
140     intf_DbgMsg ( "LPCM Debug: lpcm decoder thread %p initialized", p_lpcmdec );
141     return 0;
142 }
143
144 /*****************************************************************************
145  * RunThread : lpcm decoder thread
146  *****************************************************************************/
147 static void RunThread (lpcmdec_thread_t * p_lpcmdec)
148 {
149     int sync;
150
151     intf_DbgMsg( "LPCM Debug: running lpcm decoder thread (%p) (pid== %i)", p_lpcmdec, getpid() );
152
153     /* Fucking holy piece of shit ! */
154     //msleep (INPUT_PTS_DELAY);
155
156     /* Initializing the lpcm decoder thread */
157     if (InitThread (p_lpcmdec)) 
158     {
159         p_lpcmdec->p_fifo->b_error = 1;
160     }
161
162     sync = 0;
163     p_lpcmdec->sync_ptr = 0;
164
165     /* lpcm decoder thread's main loop */
166     /* FIXME : do we have enough room to store the decoded frames ?? */
167    
168     while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
169     {
170         s16 * buffer;
171         lpcm_sync_info_t sync_info;
172
173         if (!sync)
174         {
175             /* have to find a synchro point */
176         }
177     
178         if (DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts)
179         {
180             p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts;
181             DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts = 0;
182         }
183         else
184         {
185             p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = LAST_MDATE;
186         }
187
188         p_lpcmdec->p_aout_fifo->l_rate = sync_info.sample_rate;
189
190         buffer = ((s16 *)p_lpcmdec->p_aout_fifo->buffer) + (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);
191
192         if (lpcm_decode_frame (&p_lpcmdec->lpcm_decoder, buffer))
193         {
194             sync = 0;
195             goto bad_frame;
196         }
197
198         vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
199         p_lpcmdec->p_aout_fifo->l_end_frame = (p_lpcmdec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
200         vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
201         vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
202
203         intf_DbgMsg( "LPCM Debug: %x", *buffer );
204         bad_frame:
205     }
206
207     /* If b_error is set, the lpcm decoder thread enters the error loop */
208     if (p_lpcmdec->p_fifo->b_error)
209     {
210         ErrorThread (p_lpcmdec);
211     }
212
213     /* End of the lpcm decoder thread */
214     EndThread (p_lpcmdec);
215 }
216
217 /*****************************************************************************
218  * ErrorThread : lpcm decoder's RunThread() error loop
219  *****************************************************************************/
220 static void ErrorThread (lpcmdec_thread_t * p_lpcmdec)
221 {
222     /* We take the lock, because we are going to read/write the start/end
223      * indexes of the decoder fifo */
224     vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
225
226     /* Wait until a `die' order is sent */
227     while (!p_lpcmdec->p_fifo->b_die) {
228         /* Trash all received PES packets */
229         while (!DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
230             p_lpcmdec->p_fifo->pf_delete_pes(p_lpcmdec->p_fifo->p_packets_mgt,
231                     DECODER_FIFO_START(*p_lpcmdec->p_fifo));
232             DECODER_FIFO_INCSTART (*p_lpcmdec->p_fifo);
233         }
234
235         /* Waiting for the input thread to put new PES packets in the fifo */
236         vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
237     }
238
239     /* We can release the lock before leaving */
240     vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
241 }
242
243 /*****************************************************************************
244  * EndThread : lpcm decoder thread destruction
245  *****************************************************************************/
246 static void EndThread (lpcmdec_thread_t * p_lpcmdec)
247 {
248     intf_DbgMsg( "LPCM Debug: destroying lpcm decoder thread %p", p_lpcmdec );
249
250     /* If the audio output fifo was created, we destroy it */
251     if (p_lpcmdec->p_aout_fifo != NULL) {
252         aout_DestroyFifo (p_lpcmdec->p_aout_fifo);
253
254         /* Make sure the output thread leaves the NextFrame() function */
255         vlc_mutex_lock (&(p_lpcmdec->p_aout_fifo->data_lock));
256         vlc_cond_signal (&(p_lpcmdec->p_aout_fifo->data_wait));
257         vlc_mutex_unlock (&(p_lpcmdec->p_aout_fifo->data_lock));
258     }
259
260     /* Destroy descriptor */
261     free (p_lpcmdec);
262
263     intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p destroyed", p_lpcmdec );
264 }
265
266 void lpcm_byte_stream_next (lpcm_byte_stream_t * p_byte_stream)
267 {
268 //    lpcmdec_thread_t * p_lpcmdec = p_byte_stream->info;
269
270     /* We are looking for the next TS packet that contains real data,
271      * and not just a PES header */
272 }