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