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