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