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