]> git.sesse.net Git - vlc/blob - src/ac3_decoder/ac3_decoder.c
043a4baa35921bd78af77eca4df1080dc666af35
[vlc] / src / ac3_decoder / ac3_decoder.c
1 /*****************************************************************************
2  * ac3_decoder.c: ac3 decoder thread
3  * (c)1999 VideoLAN
4  *****************************************************************************/
5
6 /*****************************************************************************
7  * Preamble
8  *****************************************************************************/
9 #include <unistd.h>                                              /* getpid() */
10
11 #include <stdio.h>                                           /* "intf_msg.h" */
12 #include <stdlib.h>                                      /* malloc(), free() */
13 #include <sys/soundcard.h>                               /* "audio_output.h" */
14 #include <sys/uio.h>                                            /* "input.h" */
15
16 #include "common.h"
17 #include "config.h"
18 #include "mtime.h"
19 #include "vlc_thread.h"
20 #include "debug.h"                                      /* "input_netlist.h" */
21
22 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
23
24 #include "input.h"                                           /* pes_packet_t */
25 #include "input_netlist.h"                         /* input_NetlistFreePES() */
26 #include "decoder_fifo.h"         /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
27
28 #include "audio_output.h"
29
30 #include "ac3_decoder.h"
31
32 /*****************************************************************************
33  * Local prototypes
34  *****************************************************************************/
35 static int      InitThread              ( ac3dec_thread_t * p_adec );
36 static void     RunThread               ( ac3dec_thread_t * p_adec );
37 static void     ErrorThread             ( ac3dec_thread_t * p_adec );
38 static void     EndThread               ( ac3dec_thread_t * p_adec );
39
40 //static byte_t   GetByte                 ( bit_stream_t * p_bit_stream );
41 //static void     NeedBits                ( bit_stream_t * p_bit_stream, int i_bits );
42 //static void     DumpBits                ( bit_stream_t * p_bit_stream, int i_bits );
43 //static int      FindHeader              ( adec_thread_t * p_adec );
44
45 /*****************************************************************************
46  * ac3dec_CreateThread: creates an ac3 decoder thread
47  *****************************************************************************/
48 ac3dec_thread_t * ac3dec_CreateThread( input_thread_t * p_input )
49 {
50     ac3dec_thread_t *   p_ac3dec;
51
52     intf_DbgMsg("ac3dec debug: creating ac3 decoder thread\n");
53
54     /* Allocate the memory needed to store the thread's structure */
55     if ( (p_ac3dec = (ac3dec_thread_t *)malloc( sizeof(ac3dec_thread_t) )) == NULL )
56     {
57         intf_ErrMsg("ac3dec error: not enough memory for ac3dec_CreateThread() to create the new thread\n");
58         return( NULL );
59     }
60
61     /*
62      * Initialize the thread properties
63      */
64     p_ac3dec->b_die = 0;
65     p_ac3dec->b_error = 0;
66
67     /*
68      * Initialize the input properties
69      */
70     /* Initialize the decoder fifo's data lock and conditional variable and set
71      * its buffer as empty */
72     vlc_mutex_init( &p_ac3dec->fifo.data_lock );
73     vlc_cond_init( &p_ac3dec->fifo.data_wait );
74     p_ac3dec->fifo.i_start = 0;
75     p_ac3dec->fifo.i_end = 0;
76     /* Initialize the bit stream structure */
77     p_ac3dec->bit_stream.p_input = p_input;
78     p_ac3dec->bit_stream.p_decoder_fifo = &p_ac3dec->fifo;
79     p_ac3dec->bit_stream.fifo.buffer = 0;
80     p_ac3dec->bit_stream.fifo.i_available = 0;
81
82     /*
83      * Initialize the output properties
84      */
85     p_ac3dec->p_aout = p_input->p_aout;
86     p_ac3dec->p_aout_fifo = NULL;
87
88     /* Spawn the ac3 decoder thread */
89     if ( vlc_thread_create(&p_ac3dec->thread_id, "ac3 decoder", (vlc_thread_func_t)RunThread, (void *)p_ac3dec) )
90     {
91         intf_ErrMsg( "ac3dec error: can't spawn ac3 decoder thread\n" );
92         free( p_ac3dec );
93         return( NULL );
94     }
95
96     intf_DbgMsg( "ac3dec debug: ac3 decoder thread (%p) created\n", p_ac3dec );
97     return( p_ac3dec );
98 }
99
100 /*****************************************************************************
101  * ac3dec_DestroyThread: destroys an ac3 decoder thread
102  *****************************************************************************/
103 void ac3dec_DestroyThread( ac3dec_thread_t * p_ac3dec )
104 {
105     intf_DbgMsg( "ac3dec debug: requesting termination of ac3 decoder thread %p\n", p_ac3dec );
106
107     /* Ask thread to kill itself */
108     p_ac3dec->b_die = 1;
109     /* Make sure the decoder thread leaves the GetByte() function */
110     vlc_mutex_lock( &(p_ac3dec->fifo.data_lock) );
111     vlc_cond_signal( &(p_ac3dec->fifo.data_wait) );
112     vlc_mutex_unlock( &(p_ac3dec->fifo.data_lock) );
113
114     /* Waiting for the decoder thread to exit */
115     /* Remove this as soon as the "status" flag is implemented */
116     vlc_thread_join( p_ac3dec->thread_id );
117 }
118
119 /* Following functions are local */
120
121 /*****************************************************************************
122  * decode_find_sync()
123  *****************************************************************************/
124 static __inline__ int decode_find_sync( ac3dec_thread_t * p_ac3dec )
125 {
126     while ( (!p_ac3dec->b_die) && (!p_ac3dec->b_error) )
127     {
128         NeedBits( &(p_ac3dec->bit_stream), 16 );
129         if ( (p_ac3dec->bit_stream.fifo.buffer >> (32 - 16)) == 0x0b77 )
130         {
131             DumpBits( &(p_ac3dec->bit_stream), 16 );
132             p_ac3dec->total_bits_read = 16;
133             return( 0 );
134         }
135         DumpBits( &(p_ac3dec->bit_stream), 1 );
136     }
137     return( -1 );
138 }
139
140 /*****************************************************************************
141  * InitThread : initialize an ac3 decoder thread
142  *****************************************************************************/
143 static int InitThread( ac3dec_thread_t * p_ac3dec )
144 {
145     aout_fifo_t         aout_fifo;
146
147     intf_DbgMsg( "ac3dec debug: initializing ac3 decoder thread %p\n", p_ac3dec );
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_ac3dec->fifo.data_lock );
152     while ( DECODER_FIFO_ISEMPTY(p_ac3dec->fifo) )
153     {
154         vlc_cond_wait( &p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock );
155     }
156     p_ac3dec->bit_stream.p_ts = DECODER_FIFO_START( p_ac3dec->fifo )->p_first_ts;
157     p_ac3dec->bit_stream.i_byte = p_ac3dec->bit_stream.p_ts->i_payload_start;
158     vlc_mutex_unlock( &p_ac3dec->fifo.data_lock );
159
160     aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
161     aout_fifo.b_stereo = 1;
162
163     aout_fifo.l_frame_size = AC3DEC_FRAME_SIZE;
164
165     /* Creating the audio output fifo */
166     if ( (p_ac3dec->p_aout_fifo = aout_CreateFifo(p_ac3dec->p_aout, &aout_fifo)) == NULL )
167     {
168         return( -1 );
169     }
170
171     intf_DbgMsg( "ac3dec debug: ac3 decoder thread %p initialized\n", p_ac3dec );
172     return( 0 );
173 }
174
175 /*****************************************************************************
176  * RunThread : ac3 decoder thread
177  *****************************************************************************/
178 static void RunThread( ac3dec_thread_t * p_ac3dec )
179 {
180     intf_DbgMsg( "ac3dec debug: running ac3 decoder thread (%p) (pid == %i)\n", p_ac3dec, getpid() );
181
182     /* Initializing the ac3 decoder thread */
183     if ( InitThread(p_ac3dec) )
184     {
185         p_ac3dec->b_error = 1;
186     }
187
188     /* ac3 decoder thread's main loop */
189     while ( (!p_ac3dec->b_die) && (!p_ac3dec->b_error) )
190     {
191         if ( decode_find_sync(p_ac3dec) == 0 )
192         {
193             fprintf( stderr, "ac3dec debug: decode_find_sync() == 0\n" );
194         }
195     }
196
197     /* If b_error is set, the ac3 decoder thread enters the error loop */
198     if ( p_ac3dec->b_error )
199     {
200         ErrorThread( p_ac3dec );
201     }
202
203     /* End of the ac3 decoder thread */
204     EndThread( p_ac3dec );
205 }
206
207 /*****************************************************************************
208  * ErrorThread : ac3 decoder's RunThread() error loop
209  *****************************************************************************/
210 static void ErrorThread( ac3dec_thread_t * p_ac3dec )
211 {
212     /* We take the lock, because we are going to read/write the start/end
213      * indexes of the decoder fifo */
214     vlc_mutex_lock( &p_ac3dec->fifo.data_lock );
215
216     /* Wait until a `die' order is sent */
217     while( !p_ac3dec->b_die )
218     {
219         /* Trash all received PES packets */
220         while( !DECODER_FIFO_ISEMPTY(p_ac3dec->fifo) )
221         {
222             input_NetlistFreePES( p_ac3dec->bit_stream.p_input, DECODER_FIFO_START(p_ac3dec->fifo) );
223             DECODER_FIFO_INCSTART( p_ac3dec->fifo );
224         }
225
226         /* Waiting for the input thread to put new PES packets in the fifo */
227         vlc_cond_wait( &p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock );
228     }
229
230     /* We can release the lock before leaving */
231     vlc_mutex_unlock( &p_ac3dec->fifo.data_lock );
232 }
233
234 /*****************************************************************************
235  * EndThread : ac3 decoder thread destruction
236  *****************************************************************************/
237 static void EndThread( ac3dec_thread_t * p_ac3dec )
238 {
239     intf_DbgMsg( "ac3dec debug: destroying ac3 decoder thread %p\n", p_ac3dec );
240
241     /* If the audio output fifo was created, we destroy it */
242     if ( p_ac3dec->p_aout_fifo != NULL )
243     {
244         aout_DestroyFifo( p_ac3dec->p_aout_fifo );
245     }
246
247     /* Destroy descriptor */
248     free( p_ac3dec );
249
250     intf_DbgMsg( "ac3dec debug: ac3 decoder thread %p destroyed\n", p_ac3dec );
251 }