]> git.sesse.net Git - vlc/blob - src/lpcm_decoder/lpcm_decoder_thread.c
* Mandatory step for video output IV and the audio output quality
[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.14 2001/05/01 04:18:18 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_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     lpcm_byte_stream_t * byte_stream;
108
109     intf_DbgMsg ( "LPCM Debug: initializing lpcm decoder thread %p", p_lpcmdec );
110
111     /* Our first job is to initialize the bit stream structure with the
112      * beginning of the input stream */
113     vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
114     while (DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
115         if (p_lpcmdec->p_fifo->b_die) {
116             vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
117             return -1;
118         }
119         vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
120     }
121     p_lpcmdec->p_data = DECODER_FIFO_START (*p_lpcmdec->p_fifo)->p_first;
122     byte_stream = lpcm_byte_stream (&p_lpcmdec->lpcm_decoder);
123     byte_stream->p_byte = p_lpcmdec->p_data->p_payload_start;
124     byte_stream->p_end = p_lpcmdec->p_data->p_payload_end;
125     byte_stream->info = p_lpcmdec;
126     vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
127
128     /* Creating the audio output fifo */
129     p_lpcmdec->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_STEREO_FIFO, 2, 0, 0,
130                                               LPCMDEC_FRAME_SIZE, NULL  );
131     if ( p_lpcmdec->p_aout_fifo == NULL )
132     {
133         return -1;
134     }
135
136     intf_DbgMsg ( "LPCM Debug: lpcm decoder thread %p initialized", p_lpcmdec );
137     return 0;
138 }
139
140 /*****************************************************************************
141  * RunThread : lpcm decoder thread
142  *****************************************************************************/
143 static void RunThread (lpcmdec_thread_t * p_lpcmdec)
144 {
145     int sync;
146
147     intf_DbgMsg( "LPCM Debug: running lpcm decoder thread (%p) (pid== %i)", p_lpcmdec, getpid() );
148
149     /* Fucking holy piece of shit ! */
150     //msleep (INPUT_PTS_DELAY);
151
152     /* Initializing the lpcm decoder thread */
153     if (InitThread (p_lpcmdec)) 
154     {
155         p_lpcmdec->p_fifo->b_error = 1;
156     }
157
158     sync = 0;
159     p_lpcmdec->sync_ptr = 0;
160
161     /* lpcm decoder thread's main loop */
162     /* FIXME : do we have enough room to store the decoded frames ?? */
163    
164     while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
165     {
166         s16 * buffer;
167         lpcm_sync_info_t sync_info;
168
169         if (!sync)
170         {
171             /* have to find a synchro point */
172         }
173     
174         if (DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts)
175         {
176             p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts;
177             DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts = 0;
178         }
179         else
180         {
181             p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = LAST_MDATE;
182         }
183
184         p_lpcmdec->p_aout_fifo->l_rate = sync_info.sample_rate;
185
186         buffer = ((s16 *)p_lpcmdec->p_aout_fifo->buffer) + (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);
187
188         if (lpcm_decode_frame (&p_lpcmdec->lpcm_decoder, buffer))
189         {
190             sync = 0;
191             goto bad_frame;
192         }
193
194         vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
195         p_lpcmdec->p_aout_fifo->l_end_frame = (p_lpcmdec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
196         vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
197         vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
198
199         intf_DbgMsg( "LPCM Debug: %x", *buffer );
200
201     bad_frame:
202         continue;
203     }
204
205     /* If b_error is set, the lpcm decoder thread enters the error loop */
206     if (p_lpcmdec->p_fifo->b_error)
207     {
208         ErrorThread (p_lpcmdec);
209     }
210
211     /* End of the lpcm decoder thread */
212     EndThread (p_lpcmdec);
213 }
214
215 /*****************************************************************************
216  * ErrorThread : lpcm decoder's RunThread() error loop
217  *****************************************************************************/
218 static void ErrorThread (lpcmdec_thread_t * p_lpcmdec)
219 {
220     /* We take the lock, because we are going to read/write the start/end
221      * indexes of the decoder fifo */
222     vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
223
224     /* Wait until a `die' order is sent */
225     while (!p_lpcmdec->p_fifo->b_die) {
226         /* Trash all received PES packets */
227         while (!DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
228             p_lpcmdec->p_fifo->pf_delete_pes(p_lpcmdec->p_fifo->p_packets_mgt,
229                     DECODER_FIFO_START(*p_lpcmdec->p_fifo));
230             DECODER_FIFO_INCSTART (*p_lpcmdec->p_fifo);
231         }
232
233         /* Waiting for the input thread to put new PES packets in the fifo */
234         vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
235     }
236
237     /* We can release the lock before leaving */
238     vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
239 }
240
241 /*****************************************************************************
242  * EndThread : lpcm decoder thread destruction
243  *****************************************************************************/
244 static void EndThread (lpcmdec_thread_t * p_lpcmdec)
245 {
246     intf_DbgMsg( "LPCM Debug: destroying lpcm decoder thread %p", p_lpcmdec );
247
248     /* If the audio output fifo was created, we destroy it */
249     if (p_lpcmdec->p_aout_fifo != NULL) {
250         aout_DestroyFifo (p_lpcmdec->p_aout_fifo);
251
252         /* Make sure the output thread leaves the NextFrame() function */
253         vlc_mutex_lock (&(p_lpcmdec->p_aout_fifo->data_lock));
254         vlc_cond_signal (&(p_lpcmdec->p_aout_fifo->data_wait));
255         vlc_mutex_unlock (&(p_lpcmdec->p_aout_fifo->data_lock));
256     }
257
258     /* Destroy descriptor */
259     free (p_lpcmdec);
260
261     intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p destroyed", p_lpcmdec );
262 }
263
264 void lpcm_byte_stream_next (lpcm_byte_stream_t * p_byte_stream)
265 {
266 //    lpcmdec_thread_t * p_lpcmdec = p_byte_stream->info;
267
268     /* We are looking for the next TS packet that contains real data,
269      * and not just a PES header */
270 }