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