]> git.sesse.net Git - vlc/blob - src/ac3_decoder/ac3_decoder_thread.c
. normalement on devrait se prendre 1 seul mail par commit gr�ce aux
[vlc] / src / ac3_decoder / ac3_decoder_thread.c
1 /*****************************************************************************
2  * ac3_decoder_thread.c: ac3 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  * TODO :
26  *
27  * - vérifier l'état de la fifo de sortie avant d'y stocker les samples
28  *   décodés ;
29  * - vlc_cond_signal() / vlc_cond_wait()
30  *
31  */
32
33 /*****************************************************************************
34  * Preamble
35  *****************************************************************************/
36 #include "defs.h"
37
38 #include <unistd.h>                                              /* getpid() */
39
40 #include <stdio.h>                                           /* "intf_msg.h" */
41 #include <stdlib.h>                                      /* malloc(), free() */
42 #include <sys/types.h>                        /* on BSD, uio.h needs types.h */
43 #include <sys/uio.h>                                            /* "input.h" */
44
45 #include "config.h"
46 #include "common.h"
47 #include "threads.h"
48 #include "mtime.h"
49 #include "plugins.h"
50 #include "debug.h"                                      /* "input_netlist.h" */
51
52 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
53
54 #include "input.h"                                           /* pes_packet_t */
55 #include "input_netlist.h"                         /* input_NetlistFreePES() */
56 #include "decoder_fifo.h"         /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
57
58 #include "audio_output.h"
59
60 #include "ac3_decoder.h"
61 #include "ac3_decoder_thread.h"
62
63 #define AC3DEC_FRAME_SIZE (2*1536) 
64 typedef s16 ac3dec_frame_t[ AC3DEC_FRAME_SIZE ];
65
66 /*****************************************************************************
67  * Local prototypes
68  *****************************************************************************/
69 static int      InitThread              ( ac3dec_thread_t * p_adec );
70 static void     RunThread               ( ac3dec_thread_t * p_adec );
71 static void     ErrorThread             ( ac3dec_thread_t * p_adec );
72 static void     EndThread               ( ac3dec_thread_t * p_adec );
73
74 /*****************************************************************************
75  * ac3dec_CreateThread: creates an ac3 decoder thread
76  *****************************************************************************/
77 ac3dec_thread_t * ac3dec_CreateThread( input_thread_t * p_input )
78 {
79     ac3dec_thread_t *   p_ac3dec;
80
81     intf_DbgMsg("ac3dec debug: creating ac3 decoder thread\n");
82
83     /* Allocate the memory needed to store the thread's structure */
84     if ( (p_ac3dec = (ac3dec_thread_t *)malloc( sizeof(ac3dec_thread_t) )) == NULL )
85     {
86         intf_ErrMsg("ac3dec error: not enough memory for ac3dec_CreateThread() to create the new thread\n");
87         return( NULL );
88     }
89
90     /*
91      * Initialize the thread properties
92      */
93     p_ac3dec->b_die = 0;
94     p_ac3dec->b_error = 0;
95
96     /*
97      * Initialize the input properties
98      */
99     /* Initialize the decoder fifo's data lock and conditional variable and set
100      * its buffer as empty */
101     vlc_mutex_init( &p_ac3dec->fifo.data_lock );
102     vlc_cond_init( &p_ac3dec->fifo.data_wait );
103     p_ac3dec->fifo.i_start = 0;
104     p_ac3dec->fifo.i_end = 0;
105
106     /* Initialize the ac3 decoder structures */
107     ac3_init (&p_ac3dec->ac3_decoder);
108
109     /* Initialize the bit stream structure */
110     p_ac3dec->p_input = p_input;
111
112     /*
113      * Initialize the output properties
114      */
115     p_ac3dec->p_aout = p_input->p_aout;
116     p_ac3dec->p_aout_fifo = NULL;
117
118     /* Spawn the ac3 decoder thread */
119     if ( vlc_thread_create(&p_ac3dec->thread_id, "ac3 decoder", (vlc_thread_func_t)RunThread, (void *)p_ac3dec) )
120     {
121         intf_ErrMsg( "ac3dec error: can't spawn ac3 decoder thread\n" );
122         free( p_ac3dec );
123         return( NULL );
124     }
125
126     intf_DbgMsg( "ac3dec debug: ac3 decoder thread (%p) created\n", p_ac3dec );
127     return( p_ac3dec );
128 }
129
130 /*****************************************************************************
131  * ac3dec_DestroyThread: destroys an ac3 decoder thread
132  *****************************************************************************/
133 void ac3dec_DestroyThread( ac3dec_thread_t * p_ac3dec )
134 {
135     intf_DbgMsg( "ac3dec debug: requesting termination of ac3 decoder thread %p\n", p_ac3dec );
136
137     /* Ask thread to kill itself */
138     p_ac3dec->b_die = 1;
139
140     /* Make sure the decoder thread leaves the GetByte() function */
141     vlc_mutex_lock( &(p_ac3dec->fifo.data_lock) );
142     vlc_cond_signal( &(p_ac3dec->fifo.data_wait) );
143     vlc_mutex_unlock( &(p_ac3dec->fifo.data_lock) );
144
145     /* Waiting for the decoder thread to exit */
146     /* Remove this as soon as the "status" flag is implemented */
147     vlc_thread_join( p_ac3dec->thread_id );
148 }
149
150 /* Following functions are local */
151
152 /*****************************************************************************
153  * InitThread : initialize an ac3 decoder thread
154  *****************************************************************************/
155 static int InitThread( ac3dec_thread_t * p_ac3dec )
156 {
157     aout_fifo_t         aout_fifo;
158     ac3_byte_stream_t * byte_stream;
159
160     intf_DbgMsg( "ac3dec debug: initializing ac3 decoder thread %p\n", p_ac3dec );
161
162     /* Our first job is to initialize the bit stream structure with the
163      * beginning of the input stream */
164     vlc_mutex_lock( &p_ac3dec->fifo.data_lock );
165     while ( DECODER_FIFO_ISEMPTY(p_ac3dec->fifo) )
166     {
167         if ( p_ac3dec->b_die )
168         {
169             vlc_mutex_unlock( &p_ac3dec->fifo.data_lock );
170             return( -1 );
171         }
172         vlc_cond_wait( &p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock );
173     }
174     p_ac3dec->p_ts = DECODER_FIFO_START( p_ac3dec->fifo )->p_first_ts;
175     byte_stream = ac3_byte_stream (&p_ac3dec->ac3_decoder);
176     byte_stream->p_byte =
177         p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_start;
178     byte_stream->p_end =
179         p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_end;
180     byte_stream->info = p_ac3dec;
181     vlc_mutex_unlock( &p_ac3dec->fifo.data_lock );
182
183     aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
184     aout_fifo.i_channels = 2;
185     aout_fifo.b_stereo = 1;
186
187     aout_fifo.l_frame_size = AC3DEC_FRAME_SIZE;
188
189     /* Creating the audio output fifo */
190     if ( (p_ac3dec->p_aout_fifo = aout_CreateFifo(p_ac3dec->p_aout, &aout_fifo)) == NULL )
191     {
192         return( -1 );
193     }
194
195     intf_DbgMsg( "ac3dec debug: ac3 decoder thread %p initialized\n", p_ac3dec );
196     return( 0 );
197 }
198
199 /*****************************************************************************
200  * RunThread : ac3 decoder thread
201  *****************************************************************************/
202 static void RunThread( ac3dec_thread_t * p_ac3dec )
203 {
204     int sync;
205
206     intf_DbgMsg( "ac3dec debug: running ac3 decoder thread (%p) (pid == %i)\n", p_ac3dec, getpid() );
207
208     msleep( INPUT_PTS_DELAY );
209
210     /* Initializing the ac3 decoder thread */
211     if ( InitThread(p_ac3dec) ) /* XXX?? */
212     {
213         p_ac3dec->b_error = 1;
214     }
215
216     sync = 0;
217     p_ac3dec->sync_ptr = 0;
218
219     /* ac3 decoder thread's main loop */
220     /* FIXME : do we have enough room to store the decoded frames ?? */
221     while ( (!p_ac3dec->b_die) && (!p_ac3dec->b_error) )
222     {
223         s16 * buffer;
224         ac3_sync_info_t sync_info;
225
226         if (!sync) { /* have to find a synchro point */
227             int ptr;
228             ac3_byte_stream_t * p_byte_stream;
229
230             printf ("sync\n");
231
232             p_byte_stream = ac3_byte_stream (&p_ac3dec->ac3_decoder);
233
234             /* first read till next ac3 magic header */
235             do {
236                 ac3_byte_stream_next (p_byte_stream);
237             } while ((!p_ac3dec->sync_ptr) &&
238                      (!p_ac3dec->b_die) &&
239                      (!p_ac3dec->b_error));
240             /* skip the specified number of bytes */
241
242             ptr = p_ac3dec->sync_ptr;
243             while (--ptr && (!p_ac3dec->b_die) && (!p_ac3dec->b_error)) {
244                 if (p_byte_stream->p_byte >= p_byte_stream->p_end) {
245                     ac3_byte_stream_next (p_byte_stream);                   
246                 }
247                 p_byte_stream->p_byte++;
248             }
249
250             /* we are in sync now */
251
252             sync = 1;
253             p_ac3dec->sync_ptr = 0;
254         }
255
256         if ( DECODER_FIFO_START(p_ac3dec->fifo)->b_has_pts )
257         {
258                 p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(p_ac3dec->fifo)->i_pts;
259                 DECODER_FIFO_START(p_ac3dec->fifo)->b_has_pts = 0;
260         }
261         else
262         {
263                 p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->l_end_frame] = LAST_MDATE;
264         }
265
266         if (ac3_sync_frame (&p_ac3dec->ac3_decoder, &sync_info)) {
267             sync = 0;
268             goto bad_frame;
269         }
270
271         p_ac3dec->p_aout_fifo->l_rate = sync_info.sample_rate;
272
273         buffer = ((ac3dec_frame_t *)p_ac3dec->p_aout_fifo->buffer)[ p_ac3dec->p_aout_fifo->l_end_frame ];
274
275         if (ac3_decode_frame (&p_ac3dec->ac3_decoder, buffer)) {
276             sync = 0;
277             goto bad_frame;
278         }
279
280         vlc_mutex_lock( &p_ac3dec->p_aout_fifo->data_lock );
281         p_ac3dec->p_aout_fifo->l_end_frame = (p_ac3dec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
282         vlc_cond_signal( &p_ac3dec->p_aout_fifo->data_wait );
283         vlc_mutex_unlock( &p_ac3dec->p_aout_fifo->data_lock );
284
285 bad_frame:
286     }
287
288     /* If b_error is set, the ac3 decoder thread enters the error loop */
289     if ( p_ac3dec->b_error )
290     {
291         ErrorThread( p_ac3dec );
292     }
293
294     /* End of the ac3 decoder thread */
295     EndThread( p_ac3dec );
296 }
297
298 /*****************************************************************************
299  * ErrorThread : ac3 decoder's RunThread() error loop
300  *****************************************************************************/
301 static void ErrorThread( ac3dec_thread_t * p_ac3dec )
302 {
303     /* We take the lock, because we are going to read/write the start/end
304      * indexes of the decoder fifo */
305     vlc_mutex_lock( &p_ac3dec->fifo.data_lock );
306
307     /* Wait until a `die' order is sent */
308     while( !p_ac3dec->b_die )
309     {
310         /* Trash all received PES packets */
311         while( !DECODER_FIFO_ISEMPTY(p_ac3dec->fifo) )
312         {
313             input_NetlistFreePES( p_ac3dec->p_input, DECODER_FIFO_START(p_ac3dec->fifo) );
314             DECODER_FIFO_INCSTART( p_ac3dec->fifo );
315         }
316
317         /* Waiting for the input thread to put new PES packets in the fifo */
318         vlc_cond_wait( &p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock );
319     }
320
321     /* We can release the lock before leaving */
322     vlc_mutex_unlock( &p_ac3dec->fifo.data_lock );
323 }
324
325 /*****************************************************************************
326  * EndThread : ac3 decoder thread destruction
327  *****************************************************************************/
328 static void EndThread( ac3dec_thread_t * p_ac3dec )
329 {
330     intf_DbgMsg( "ac3dec debug: destroying ac3 decoder thread %p\n", p_ac3dec );
331
332     /* If the audio output fifo was created, we destroy it */
333     if ( p_ac3dec->p_aout_fifo != NULL )
334     {
335         aout_DestroyFifo( p_ac3dec->p_aout_fifo );
336
337         /* Make sure the output thread leaves the NextFrame() function */
338         vlc_mutex_lock( &(p_ac3dec->p_aout_fifo->data_lock) );
339         vlc_cond_signal( &(p_ac3dec->p_aout_fifo->data_wait) );
340         vlc_mutex_unlock( &(p_ac3dec->p_aout_fifo->data_lock) );
341     }
342
343     /* Destroy descriptor */
344     free( p_ac3dec );
345
346     intf_DbgMsg( "ac3dec debug: ac3 decoder thread %p destroyed\n", p_ac3dec );
347 }
348
349 void ac3_byte_stream_next (ac3_byte_stream_t * p_byte_stream)
350 {
351     ac3dec_thread_t * p_ac3dec = p_byte_stream->info;
352
353     /* We are looking for the next TS packet that contains real data,
354      * and not just a PES header */
355     do {
356         /* We were reading the last TS packet of this PES packet... It's
357          * time to jump to the next PES packet */
358         if (p_ac3dec->p_ts->p_next_ts == NULL) {
359             int ptr;
360
361             /* We are going to read/write the start and end indexes of the 
362              * decoder fifo and to use the fifo's conditional variable, 
363              * that's why we need to take the lock before */ 
364             vlc_mutex_lock (&p_ac3dec->fifo.data_lock);
365             
366             /* Is the input thread dying ? */
367             if (p_ac3dec->p_input->b_die) {
368                 vlc_mutex_unlock (&(p_ac3dec->fifo.data_lock));
369                 return;
370             }
371
372             /* We should increase the start index of the decoder fifo, but
373              * if we do this now, the input thread could overwrite the
374              * pointer to the current PES packet, and we weren't able to
375              * give it back to the netlist. That's why we free the PES
376              * packet first. */
377             input_NetlistFreePES (p_ac3dec->p_input, DECODER_FIFO_START(p_ac3dec->fifo) );
378
379             DECODER_FIFO_INCSTART (p_ac3dec->fifo);
380
381             while (DECODER_FIFO_ISEMPTY(p_ac3dec->fifo)) {
382                 vlc_cond_wait (&p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock );
383
384                 if (p_ac3dec->p_input->b_die) {
385                     vlc_mutex_unlock (&(p_ac3dec->fifo.data_lock));
386                     return;
387                 }
388             }
389
390             /* The next byte could be found in the next PES packet */
391             p_ac3dec->p_ts = DECODER_FIFO_START (p_ac3dec->fifo)->p_first_ts;
392
393             /* parse ac3 magic header */
394             ptr = p_ac3dec->p_ts->buffer [p_ac3dec->p_ts->i_payload_start+2];
395             ptr <<= 8;
396             ptr |= p_ac3dec->p_ts->buffer [p_ac3dec->p_ts->i_payload_start+3];
397             p_ac3dec->sync_ptr = ptr;
398             p_ac3dec->p_ts->i_payload_start += 4;
399
400             /* We can release the fifo's data lock */
401             vlc_mutex_unlock (&p_ac3dec->fifo.data_lock);
402         }
403
404         /* Perhaps the next TS packet of the current PES packet contains 
405          * real data (ie its payload's size is greater than 0) */
406         else {
407             p_ac3dec->p_ts = p_ac3dec->p_ts->p_next_ts;
408         }
409     } while (p_ac3dec->p_ts->i_payload_start == p_ac3dec->p_ts->i_payload_end);
410     p_byte_stream->p_byte =
411         p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_start; 
412     p_byte_stream->p_end =
413         p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_end; 
414 }