]> git.sesse.net Git - vlc/blob - modules/codec/a52.c
More S/PDIF fixes.
[vlc] / modules / codec / a52.c
1 /*****************************************************************************
2  * a52.c: ATSC A/52 aka AC-3 decoder plugin for vlc.
3  *   This plugin makes use of liba52 to decode A/52 audio
4  *   (http://liba52.sf.net/).
5  *****************************************************************************
6  * Copyright (C) 2001, 2002 VideoLAN
7  * $Id: a52.c,v 1.1 2002/08/11 01:27:01 massiot Exp $
8  *
9  * Authors: Gildas Bazin <gbazin@netcourrier.com>
10  *          Christophe Massiot <massiot@via.ecp.fr>
11  *      
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <vlc/vlc.h>
31 #include <vlc/aout.h>
32 #include <vlc/decoder.h>
33
34 #include <stdlib.h>                                      /* malloc(), free() */
35 #include <string.h>                                              /* strdup() */
36 #ifdef HAVE_STDINT_H
37 #   include <stdint.h>                                         /* int16_t .. */
38 #elif HAVE_INTTYPES_H
39 #   include <inttypes.h>                                       /* int16_t .. */
40 #endif
41
42 #ifdef USE_A52DEC_TREE                                 /* liba52 header file */
43 #   include "include/a52.h"
44 #else
45 #   include "a52dec/a52.h"
46 #endif
47
48 #define A52_FRAME_SIZE 1536 
49
50 /*****************************************************************************
51  * a52_thread_t : a52 decoder thread descriptor
52  *****************************************************************************/
53 typedef struct a52_thread_s
54 {
55     /*
56      * liba52 properties
57      */
58     a52_state_t *       p_a52_state;
59     vlc_bool_t          b_dynrng;
60
61     /* The bit stream structure handles the PES stream at the bit level */
62     bit_stream_t        bit_stream;
63
64     /*
65      * Input properties
66      */
67     decoder_fifo_t *    p_fifo;                /* stores the PES stream data */
68     data_packet_t *     p_data;
69
70     /*
71      * Output properties
72      */
73     aout_instance_t *   p_aout; /* opaque */
74     aout_input_t *      p_aout_input; /* opaque */
75     audio_sample_format_t output_format;
76     mtime_t             last_date;
77 } a52_thread_t;
78
79 /*****************************************************************************
80  * Local prototypes
81  *****************************************************************************/
82 static int  OpenDecoder    ( vlc_object_t * );
83 static int  RunDecoder     ( decoder_fifo_t * );
84 static int  DecodeFrame    ( a52_thread_t *, const byte_t * );
85 static int  InitThread     ( a52_thread_t *, decoder_fifo_t * );
86 static void EndThread      ( a52_thread_t * );
87
88 /*****************************************************************************
89  * Module descriptor
90  *****************************************************************************/
91 #define DYNRNG_TEXT N_("A/52 dynamic range compression")
92 #define DYNRNG_LONGTEXT N_( \
93     "Dynamic range compression makes the loud sounds softer, and the soft " \
94     "sounds louder, so you can more easily listen to the stream in a noisy " \
95     "environment without disturbing anyone. If you disable the dynamic range "\
96     "compression the playback will be more adapted to a movie theater or a " \
97     "listening room.")
98
99 vlc_module_begin();
100     add_category_hint( N_("Miscellaneous"), NULL );
101     add_bool( "a52-dynrng", 1, NULL, DYNRNG_TEXT, DYNRNG_LONGTEXT );
102     set_description( _("a52 ATSC A/52 aka AC-3 audio decoder module") );
103     set_capability( "decoder", 60 );
104     set_callbacks( OpenDecoder, NULL );
105 vlc_module_end();
106
107 /*****************************************************************************
108  * OpenDecoder: probe the decoder and return score
109  *****************************************************************************
110  * Tries to launch a decoder and return score so that the interface is able
111  * to choose.
112  *****************************************************************************/
113 static int OpenDecoder( vlc_object_t *p_this )
114 {
115     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
116     
117     if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') )
118     {   
119         return VLC_EGENERIC;
120     }
121
122     p_fifo->pf_run = RunDecoder;
123     return VLC_SUCCESS;
124 }
125
126 /*****************************************************************************
127  * RunDecoder: this function is called just after the thread is created
128  *****************************************************************************/
129 static int RunDecoder( decoder_fifo_t *p_fifo )
130 {
131     a52_thread_t *p_dec;
132
133     /* Allocate the memory needed to store the thread's structure */
134     p_dec = (a52_thread_t *)malloc( sizeof(a52_thread_t) );
135     if( p_dec == NULL )
136     {
137         msg_Err( p_fifo, "out of memory" );
138         DecoderError( p_fifo );
139         return -1;
140     }
141
142     if( InitThread( p_dec, p_fifo ) )
143     {
144         msg_Err( p_dec->p_fifo, "could not initialize thread" );
145         DecoderError( p_fifo );
146         free( p_dec );
147         return -1;
148     }
149
150     /* liba52 decoder thread's main loop */
151     while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
152     {
153         int i_frame_size, i_flags, i_rate, i_bit_rate;
154         mtime_t pts;
155         /* Temporary buffer to store the raw frame to be decoded */
156         byte_t p_frame_buffer[3840];
157
158         /* Look for sync word - should be 0x0b77 */
159         RealignBits( &p_dec->bit_stream );
160         while( (ShowBits( &p_dec->bit_stream, 16 ) ) != 0x0b77 && 
161                (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error))
162         {
163             RemoveBits( &p_dec->bit_stream, 8 );
164         }
165
166         /* Get A/52 frame header */
167         GetChunk( &p_dec->bit_stream, p_frame_buffer, 7 );
168         if( p_dec->p_fifo->b_die ) break;
169
170         /* Check if frame is valid and get frame info */
171         i_frame_size = a52_syncinfo( p_frame_buffer, &i_flags, &i_rate,
172                                      &i_bit_rate );
173
174         if( !i_frame_size )
175         {
176             msg_Warn( p_dec->p_fifo, "a52_syncinfo failed" );
177             continue;
178         }
179
180         if( (p_dec->p_aout_input != NULL) &&
181             ( (p_dec->output_format.i_rate != i_rate)
182                /* || (p_dec->output_format.i_channels != i_channels) */ ) )
183         {
184             /* Parameters changed - this should not happen. */
185             aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
186             p_dec->p_aout_input = NULL;
187         }
188
189         /* Creating the audio input if not created yet. */
190         if( p_dec->p_aout_input == NULL )
191         {
192             p_dec->output_format.i_rate = i_rate;
193             /* p_dec->output_format.i_channels = i_channels; */
194             p_dec->p_aout_input = aout_InputNew( p_dec->p_fifo,
195                                                  &p_dec->p_aout,
196                                                  &p_dec->output_format );
197
198             if ( p_dec->p_aout_input == NULL )
199             {
200                 p_dec->p_fifo->b_error = 1;
201                 break;
202             }
203         }
204
205         /* Set the Presentation Time Stamp */
206         CurrentPTS( &p_dec->bit_stream, &pts, NULL );
207         if ( pts != 0 )
208         {
209             p_dec->last_date = pts;
210         }
211
212         /* Get the complete frame */
213         GetChunk( &p_dec->bit_stream, p_frame_buffer + 7,
214                   i_frame_size - 7 );
215         if( p_dec->p_fifo->b_die ) break;
216
217         if( DecodeFrame( p_dec, p_frame_buffer ) )
218         {
219             p_dec->p_fifo->b_error = 1;
220             break;
221         }
222     }
223
224     /* If b_error is set, the decoder thread enters the error loop */
225     if( p_dec->p_fifo->b_error )
226     {
227         DecoderError( p_dec->p_fifo );
228     }
229
230     /* End of the a52 decoder thread */
231     EndThread( p_dec );
232
233     return 0;
234 }
235
236 /*****************************************************************************
237  * InitThread: initialize data before entering main loop
238  *****************************************************************************/
239 static int InitThread( a52_thread_t * p_dec, decoder_fifo_t * p_fifo )
240 {
241     /* Initialize the thread properties */
242     p_dec->p_aout = NULL;
243     p_dec->p_aout_input = NULL;
244     p_dec->p_fifo = p_fifo;
245     p_dec->output_format.i_format = AOUT_FMT_FLOAT32;
246     p_dec->output_format.i_channels = 2; /* FIXME ! */
247     p_dec->last_date = 0;
248
249     /* Initialize liba52 */
250     p_dec->p_a52_state = a52_init( 0 );
251     if( p_dec->p_a52_state == NULL )
252     {
253         msg_Err( p_dec->p_fifo, "unable to initialize liba52" );
254         return -1;
255     }
256
257     p_dec->b_dynrng = config_GetInt( p_dec->p_fifo, "a52-dynrng" );
258
259     /* Init the Bitstream */
260     InitBitstream( &p_dec->bit_stream, p_dec->p_fifo,
261                    NULL, NULL );
262
263     return 0;
264 }
265
266 /*****************************************************************************
267  * Interleave: helper function to interleave channels
268  *****************************************************************************/
269 static void Interleave( float * p_out, const float * p_in, int i_channels )
270 {
271     int i, j;
272
273     for ( j = 0; j < i_channels; j++ )
274     {
275         for ( i = 0; i < 256; i++ )
276         {
277             p_out[i * i_channels + j] = p_in[j * 256 + i];
278         }
279     }
280 }
281
282 /*****************************************************************************
283  * DecodeFrame: decode an ATSC A/52 frame.
284  *****************************************************************************/
285 static int DecodeFrame( a52_thread_t * p_dec, const byte_t * p_frame_buffer )
286 {
287     sample_t        i_sample_level = 1;
288     aout_buffer_t * p_buffer;
289     int             i, i_flags;
290     int             i_bytes_per_block = 256 * p_dec->output_format.i_channels
291                       * sizeof(float);
292
293     if( !p_dec->last_date )
294     {
295         /* We've just started the stream, wait for the first PTS. */
296         return 0;
297     }
298
299     p_buffer = aout_BufferNew( p_dec->p_aout, p_dec->p_aout_input,
300                                A52_FRAME_SIZE );
301     if ( p_buffer == NULL ) return -1;
302     p_buffer->start_date = p_dec->last_date;
303     p_dec->last_date += (mtime_t)(A52_FRAME_SIZE * 1000000)
304                           / p_dec->output_format.i_rate;
305     p_buffer->end_date = p_dec->last_date;
306
307     /* FIXME */
308     i_flags = A52_STEREO | A52_ADJUST_LEVEL;
309
310     /* Do the actual decoding now */
311     a52_frame( p_dec->p_a52_state, p_frame_buffer,
312                &i_flags, &i_sample_level, 0 );
313
314     if( !p_dec->b_dynrng )
315     {
316         a52_dynrng( p_dec->p_a52_state, NULL, NULL );
317     }
318
319     for ( i = 0; i < 6; i++ )
320     {
321         sample_t * p_samples;
322
323         if( a52_block( p_dec->p_a52_state ) )
324         {
325             msg_Warn( p_dec->p_fifo, "a52_block failed for block %i", i );
326         }
327
328         p_samples = a52_samples( p_dec->p_a52_state );
329
330         /* Interleave the *$£%ù samples */
331         Interleave( (float *)(p_buffer->p_buffer + i * i_bytes_per_block),
332                     p_samples, p_dec->output_format.i_channels );
333     }
334
335     aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer );
336
337     return 0;
338 }
339
340 /*****************************************************************************
341  * EndThread : liba52 decoder thread destruction
342  *****************************************************************************/
343 static void EndThread( a52_thread_t * p_dec )
344 {
345     if ( p_dec->p_aout_input != NULL )
346     {
347         aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
348     }
349
350     a52_free( p_dec->p_a52_state );
351     free( p_dec );
352 }
353