]> git.sesse.net Git - vlc/blob - src/lpcm_decoder/lpcm_decoder_thread.c
Ajout des fichiers pour la gestion du lpcm.
[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 GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public
19  * License along with this program; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, 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 #include <sys/types.h>                        /* on BSD, uio.h needs types.h */
34 #include <sys/uio.h>                                            /* "input.h" */
35
36 #include "config.h"
37 #include "common.h"
38 #include "threads.h"
39 #include "mtime.h"
40 #include "plugins.h"
41 #include "debug.h"                                      /* "input_netlist.h" */
42
43 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
44
45 #include "input.h"                                           /* pes_packet_t */
46 #include "input_netlist.h"                         /* input_NetlistFreePES() */
47 #include "decoder_fifo.h"         /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
48
49 #include "audio_output.h"
50
51 #include "lpcm_decoder.h"
52 #include "lpcm_decoder_thread.h"
53
54 #define LPCMDEC_FRAME_SIZE (2*1536)                    /* May not be usefull */
55
56 /*****************************************************************************
57  * Local prototypes
58  *****************************************************************************/
59 static int      InitThread              (lpcmdec_thread_t * p_adec);
60 static void     RunThread               (lpcmdec_thread_t * p_adec);
61 static void     ErrorThread             (lpcmdec_thread_t * p_adec);
62 static void     EndThread               (lpcmdec_thread_t * p_adec);
63
64 /*****************************************************************************
65  * lpcmdec_CreateThread: creates an lpcm decoder thread
66  *****************************************************************************/
67 lpcmdec_thread_t * lpcmdec_CreateThread (input_thread_t * p_input)
68 {
69     lpcmdec_thread_t *   p_lpcmdec;
70     fprintf (stderr, "LPCM Debug: creating lpcm decoder thread\n");
71
72     /* Allocate the memory needed to store the thread's structure */
73     if ((p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t))) == NULL) {
74         fprintf (stderr, "LPCM Error: not enough memory for lpcmdec_CreateThread() to create the new thread\n");
75         return NULL;
76     }
77
78     /*
79      * Initialize the thread properties
80      */
81     p_lpcmdec->b_die = 0;
82     p_lpcmdec->b_error = 0;
83
84     /*
85      * Initialize the input properties
86      */
87     /* Initialize the decoder fifo's data lock and conditional variable and set
88      * its buffer as empty */
89     vlc_mutex_init (&p_lpcmdec->fifo.data_lock);
90     vlc_cond_init (&p_lpcmdec->fifo.data_wait);
91     p_lpcmdec->fifo.i_start = 0;
92     p_lpcmdec->fifo.i_end = 0;
93
94     /* Initialize the lpcm decoder structures */
95     lpcm_init (&p_lpcmdec->lpcm_decoder);
96
97     /* Initialize the bit stream structure */
98     p_lpcmdec->p_input = p_input;
99
100     /*
101      * Initialize the output properties
102      */
103     p_lpcmdec->p_aout = p_input->p_aout;
104     p_lpcmdec->p_aout_fifo = NULL;
105
106     /* Spawn the lpcm decoder thread */
107     if (vlc_thread_create(&p_lpcmdec->thread_id, "lpcm decoder", (vlc_thread_func_t)RunThread, (void *)p_lpcmdec)) {
108         fprintf  (stderr, "LPCM Error: can't spawn lpcm decoder thread\n");
109         free (p_lpcmdec);
110         return NULL;
111     }
112
113     fprintf (stderr, "LPCM Debug: lpcm decoder thread (%p) created\n", p_lpcmdec);
114     return p_lpcmdec;
115 }
116
117 /*****************************************************************************
118  * lpcmdec_DestroyThread: destroys an lpcm decoder thread
119  *****************************************************************************/
120 void lpcmdec_DestroyThread (lpcmdec_thread_t * p_lpcmdec)
121 {
122     fprintf (stderr, "LPCM Debug: requesting termination of lpcm decoder thread %p\n", p_lpcmdec);
123
124     /* Ask thread to kill itself */
125     p_lpcmdec->b_die = 1;
126
127     /* Make sure the decoder thread leaves the GetByte() function */
128     vlc_mutex_lock (&(p_lpcmdec->fifo.data_lock));
129     vlc_cond_signal (&(p_lpcmdec->fifo.data_wait));
130     vlc_mutex_unlock (&(p_lpcmdec->fifo.data_lock));
131
132     /* Waiting for the decoder thread to exit */
133     /* Remove this as soon as the "status" flag is implemented */
134     vlc_thread_join (p_lpcmdec->thread_id);
135 }
136
137 /* Following functions are local */
138
139 /*****************************************************************************
140  * InitThread : initialize an lpcm decoder thread
141  *****************************************************************************/
142 static int InitThread (lpcmdec_thread_t * p_lpcmdec)
143 {
144     aout_fifo_t         aout_fifo;
145     lpcm_byte_stream_t * byte_stream;
146
147     fprintf (stderr, "LPCM Debug: initializing lpcm decoder thread %p\n", p_lpcmdec);
148
149     /* Our first job is to initialize the bit stream structure with the
150      * beginning of the input stream */
151     vlc_mutex_lock (&p_lpcmdec->fifo.data_lock);
152     while (DECODER_FIFO_ISEMPTY(p_lpcmdec->fifo)) {
153         if (p_lpcmdec->b_die) {
154             vlc_mutex_unlock (&p_lpcmdec->fifo.data_lock);
155             return -1;
156         }
157         vlc_cond_wait (&p_lpcmdec->fifo.data_wait, &p_lpcmdec->fifo.data_lock);
158     }
159     p_lpcmdec->p_ts = DECODER_FIFO_START (p_lpcmdec->fifo)->p_first_ts;
160     byte_stream = lpcm_byte_stream (&p_lpcmdec->lpcm_decoder);
161     byte_stream->p_byte =
162         p_lpcmdec->p_ts->buffer + p_lpcmdec->p_ts->i_payload_start;
163     byte_stream->p_end =
164         p_lpcmdec->p_ts->buffer + p_lpcmdec->p_ts->i_payload_end;
165     byte_stream->info = p_lpcmdec;
166     vlc_mutex_unlock (&p_lpcmdec->fifo.data_lock);
167
168     aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
169     aout_fifo.i_channels = 2;
170     aout_fifo.b_stereo = 1;
171
172     aout_fifo.l_frame_size = LPCMDEC_FRAME_SIZE;
173
174     /* Creating the audio output fifo */
175     if ((p_lpcmdec->p_aout_fifo = aout_CreateFifo(p_lpcmdec->p_aout, &aout_fifo)) == NULL) {
176         return -1;
177     }
178
179     fprintf (stderr,"LPCM Debug: lpcm decoder thread %p initialized\n", p_lpcmdec);
180     return 0;
181 }
182
183 /*****************************************************************************
184  * RunThread : lpcm decoder thread
185  *****************************************************************************/
186 static void RunThread (lpcmdec_thread_t * p_lpcmdec)
187 {
188     int sync;
189
190     fprintf (stderr,"LPCM Debug: running lpcm decoder thread (%p) (pid== %i)\n", p_lpcmdec, getpid());
191
192     msleep (INPUT_PTS_DELAY);
193
194     /* Initializing the lpcm decoder thread */
195     if (InitThread (p_lpcmdec)) 
196     {
197         p_lpcmdec->b_error = 1;
198     }
199
200     sync = 0;
201     p_lpcmdec->sync_ptr = 0;
202
203     /* lpcm decoder thread's main loop */
204     /* FIXME : do we have enough room to store the decoded frames ?? */
205    
206     while ((!p_lpcmdec->b_die) && (!p_lpcmdec->b_error))
207     {
208             s16 * buffer;
209             lpcm_sync_info_t sync_info;
210
211             if (!sync)
212         {
213             /* have to find a synchro point */
214         }
215     
216         if (DECODER_FIFO_START(p_lpcmdec->fifo)->b_has_pts)
217         {
218                 p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(p_lpcmdec->fifo)->i_pts;
219                 DECODER_FIFO_START(p_lpcmdec->fifo)->b_has_pts = 0;
220         }
221         else
222         {
223                 p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = LAST_MDATE;
224         }
225
226         p_lpcmdec->p_aout_fifo->l_rate = sync_info.sample_rate;
227
228             buffer = ((s16 *)p_lpcmdec->p_aout_fifo->buffer) + (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);
229
230             if (lpcm_decode_frame (&p_lpcmdec->lpcm_decoder, buffer))
231         {
232                 sync = 0;
233                 goto bad_frame;
234             }
235
236             vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
237             p_lpcmdec->p_aout_fifo->l_end_frame = (p_lpcmdec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
238             vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
239             vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
240
241         fprintf(stderr, "LPCM Debug: %x\n", *buffer);
242         bad_frame:
243     }
244
245     /* If b_error is set, the lpcm decoder thread enters the error loop */
246     if (p_lpcmdec->b_error)
247     {
248         ErrorThread (p_lpcmdec);
249     }
250
251     /* End of the lpcm decoder thread */
252     EndThread (p_lpcmdec);
253 }
254
255 /*****************************************************************************
256  * ErrorThread : lpcm decoder's RunThread() error loop
257  *****************************************************************************/
258 static void ErrorThread (lpcmdec_thread_t * p_lpcmdec)
259 {
260     /* We take the lock, because we are going to read/write the start/end
261      * indexes of the decoder fifo */
262     vlc_mutex_lock (&p_lpcmdec->fifo.data_lock);
263
264     /* Wait until a `die' order is sent */
265     while (!p_lpcmdec->b_die) {
266         /* Trash all received PES packets */
267         while (!DECODER_FIFO_ISEMPTY(p_lpcmdec->fifo)) {
268             input_NetlistFreePES (p_lpcmdec->p_input, DECODER_FIFO_START(p_lpcmdec->fifo));
269             DECODER_FIFO_INCSTART (p_lpcmdec->fifo);
270         }
271
272         /* Waiting for the input thread to put new PES packets in the fifo */
273         vlc_cond_wait (&p_lpcmdec->fifo.data_wait, &p_lpcmdec->fifo.data_lock);
274     }
275
276     /* We can release the lock before leaving */
277     vlc_mutex_unlock (&p_lpcmdec->fifo.data_lock);
278 }
279
280 /*****************************************************************************
281  * EndThread : lpcm decoder thread destruction
282  *****************************************************************************/
283 static void EndThread (lpcmdec_thread_t * p_lpcmdec)
284 {
285     fprintf (stderr, "LPCM Debug: destroying lpcm decoder thread %p\n", p_lpcmdec);
286
287     /* If the audio output fifo was created, we destroy it */
288     if (p_lpcmdec->p_aout_fifo != NULL) {
289         aout_DestroyFifo (p_lpcmdec->p_aout_fifo);
290
291         /* Make sure the output thread leaves the NextFrame() function */
292         vlc_mutex_lock (&(p_lpcmdec->p_aout_fifo->data_lock));
293         vlc_cond_signal (&(p_lpcmdec->p_aout_fifo->data_wait));
294         vlc_mutex_unlock (&(p_lpcmdec->p_aout_fifo->data_lock));
295     }
296
297     /* Destroy descriptor */
298     free (p_lpcmdec);
299
300     fprintf (stderr, "LPCM Debug: lpcm decoder thread %p destroyed\n", p_lpcmdec);
301 }
302
303 void lpcm_byte_stream_next (lpcm_byte_stream_t * p_byte_stream)
304 {
305 //    lpcmdec_thread_t * p_lpcmdec = p_byte_stream->info;
306
307     /* We are looking for the next TS packet that contains real data,
308      * and not just a PES header */
309 }