]> git.sesse.net Git - vlc/blob - modules/codec/a52.c
* ALL: moved i_bitrate out of audio_format_t into es_format_t
[vlc] / modules / codec / a52.c
1 /*****************************************************************************
2  * a52.c: parse A/52 audio sync info and packetize the stream
3  *****************************************************************************
4  * Copyright (C) 2001-2002 VideoLAN
5  * $Id: a52.c,v 1.30 2003/11/16 22:54:12 gbazin Exp $
6  *
7  * Authors: Stéphane Borel <stef@via.ecp.fr>
8  *          Christophe Massiot <massiot@via.ecp.fr>
9  *          Gildas Bazin <gbazin@netcourrier.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>                                              /* memcpy() */
32
33 #include <vlc/vlc.h>
34 #include <vlc/decoder.h>
35 #include <vlc/input.h>
36
37 #include "vlc_block_helper.h"
38
39 #define A52_HEADER_SIZE 7
40
41 /*****************************************************************************
42  * decoder_sys_t : decoder descriptor
43  *****************************************************************************/
44 struct decoder_sys_t
45 {
46     /* Module mode */
47     vlc_bool_t b_packetizer;
48
49     /*
50      * Input properties
51      */
52     int i_state;
53
54     block_bytestream_t bytestream;
55
56     /*
57      * Common properties
58      */
59     audio_date_t   end_date;
60
61     mtime_t i_pts;
62     int i_frame_size, i_bit_rate;
63     unsigned int i_rate, i_channels, i_channels_conf;
64
65 };
66
67 enum {
68
69     STATE_NOSYNC,
70     STATE_SYNC,
71     STATE_HEADER,
72     STATE_NEXT_SYNC,
73     STATE_GET_DATA,
74     STATE_SEND_DATA
75 };
76
77 /****************************************************************************
78  * Local prototypes
79  ****************************************************************************/
80 static int  OpenDecoder   ( vlc_object_t * );
81 static int  OpenPacketizer( vlc_object_t * );
82 static void CloseDecoder  ( vlc_object_t * );
83 static void *DecodeBlock  ( decoder_t *, block_t ** );
84
85 static int  SyncInfo      ( const byte_t *, int *, int *, int *,int * );
86
87 static uint8_t       *GetOutBuffer ( decoder_t *, void ** );
88 static aout_buffer_t *GetAoutBuffer( decoder_t * );
89 static block_t       *GetSoutBuffer( decoder_t * );
90
91 /*****************************************************************************
92  * Module descriptor
93  *****************************************************************************/
94 vlc_module_begin();
95     set_description( _("A/52 parser") );
96     set_capability( "decoder", 100 );
97     set_callbacks( OpenDecoder, CloseDecoder );
98
99     add_submodule();
100     set_description( _("A/52 audio packetizer") );
101     set_capability( "packetizer", 10 );
102     set_callbacks( OpenPacketizer, CloseDecoder );
103 vlc_module_end();
104
105 /*****************************************************************************
106  * OpenDecoder: probe the decoder and return score
107  *****************************************************************************/
108 static int OpenDecoder( vlc_object_t *p_this )
109 {
110     decoder_t *p_dec = (decoder_t*)p_this;
111     decoder_sys_t *p_sys;
112
113     if( p_dec->fmt_in.i_codec != VLC_FOURCC('a','5','2',' ')
114           && p_dec->fmt_in.i_codec != VLC_FOURCC('a','5','2','b') )
115     {
116         return VLC_EGENERIC;
117     }
118
119     /* Allocate the memory needed to store the decoder's structure */
120     if( ( p_dec->p_sys = p_sys =
121           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
122     {
123         msg_Err( p_dec, "out of memory" );
124         return VLC_EGENERIC;
125     }
126
127     /* Misc init */
128     p_sys->b_packetizer = VLC_FALSE;
129     p_sys->i_state = STATE_NOSYNC;
130     aout_DateSet( &p_sys->end_date, 0 );
131
132     p_sys->bytestream = block_BytestreamInit( p_dec );
133
134     /* Set output properties */
135     p_dec->fmt_out.i_cat = AUDIO_ES;
136     p_dec->fmt_out.i_codec = VLC_FOURCC('a','5','2',' ');
137
138     /* Set callback */
139     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
140         DecodeBlock;
141     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
142         DecodeBlock;
143
144     return VLC_SUCCESS;
145 }
146
147 static int OpenPacketizer( vlc_object_t *p_this )
148 {
149     decoder_t *p_dec = (decoder_t*)p_this;
150
151     int i_ret = OpenDecoder( p_this );
152
153     if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
154
155     return i_ret;
156 }
157
158 /****************************************************************************
159  * DecodeBlock: the whole thing
160  ****************************************************************************
161  * This function is called just after the thread is launched.
162  ****************************************************************************/
163 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
164 {
165     decoder_sys_t *p_sys = p_dec->p_sys;
166     uint8_t p_header[A52_HEADER_SIZE];
167     uint8_t *p_buf;
168     void *p_out_buffer;
169
170     if( !pp_block || !*pp_block ) return NULL;
171
172     if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
173     {
174         /* We've just started the stream, wait for the first PTS. */
175         block_Release( *pp_block );
176         return NULL;
177     }
178
179     if( (*pp_block)->b_discontinuity )
180     {
181         p_sys->i_state = STATE_NOSYNC;
182     }
183
184     block_BytestreamPush( &p_sys->bytestream, *pp_block );
185
186     while( 1 )
187     {
188         switch( p_sys->i_state )
189         {
190         case STATE_NOSYNC:
191             while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
192                    == VLC_SUCCESS )
193             {
194                 if( p_header[0] == 0x0b && p_header[1] == 0x77 )
195                 {
196                     p_sys->i_state = STATE_SYNC;
197                     break;
198                 }
199                 block_SkipByte( &p_sys->bytestream );
200             }
201             if( p_sys->i_state != STATE_SYNC )
202             {
203                 block_BytestreamFlush( &p_sys->bytestream );
204
205                 /* Need more data */
206                 return NULL;
207             }
208
209         case STATE_SYNC:
210             /* New frame, set the Presentation Time Stamp */
211             p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
212             if( p_sys->i_pts != 0 &&
213                 p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
214             {
215                 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
216             }
217             p_sys->i_state = STATE_HEADER;
218
219         case STATE_HEADER:
220             /* Get A/52 frame header (A52_HEADER_SIZE bytes) */
221             if( block_PeekBytes( &p_sys->bytestream, p_header,
222                                  A52_HEADER_SIZE ) != VLC_SUCCESS )
223             {
224                 /* Need more data */
225                 return NULL;
226             }
227
228             /* Check if frame is valid and get frame info */
229             p_sys->i_frame_size = SyncInfo( p_header,
230                                             &p_sys->i_channels,
231                                             &p_sys->i_channels_conf,
232                                             &p_sys->i_rate,
233                                             &p_sys->i_bit_rate );
234             if( !p_sys->i_frame_size )
235             {
236                 msg_Dbg( p_dec, "emulated sync word" );
237                 block_SkipByte( &p_sys->bytestream );
238                 p_sys->i_state = STATE_NOSYNC;
239                 break;
240             }
241             p_sys->i_state = STATE_NEXT_SYNC;
242
243         case STATE_NEXT_SYNC:
244             /* TODO: If pp_block == NULL, flush the buffer without checking the
245              * next sync word */
246
247             /* Check if next expected frame contains the sync word */
248             if( block_PeekOffsetBytes( &p_sys->bytestream,
249                                        p_sys->i_frame_size, p_header, 2 )
250                 != VLC_SUCCESS )
251             {
252                 /* Need more data */
253                 return NULL;
254             }
255
256             if( p_header[0] != 0x0b || p_header[1] != 0x77 )
257             {
258                 msg_Dbg( p_dec, "emulated sync word "
259                          "(no sync on following frame)" );
260                 p_sys->i_state = STATE_NOSYNC;
261                 block_SkipByte( &p_sys->bytestream );
262                 break;
263             }
264             p_sys->i_state = STATE_SEND_DATA;
265             break;
266
267         case STATE_GET_DATA:
268             /* Make sure we have enough data.
269              * (Not useful if we went through NEXT_SYNC) */
270             if( block_WaitBytes( &p_sys->bytestream,
271                                  p_sys->i_frame_size ) != VLC_SUCCESS )
272             {
273                 /* Need more data */
274                 return NULL;
275             }
276             p_sys->i_state = STATE_SEND_DATA;
277
278         case STATE_SEND_DATA:
279             if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
280             {
281                 //p_dec->b_error = VLC_TRUE;
282                 return NULL;
283             }
284
285             /* Copy the whole frame into the buffer. When we reach this point
286              * we already know we have enough data available. */
287             block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );
288
289             /* Make sure we don't reuse the same pts twice */
290             if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
291                 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
292
293             /* So p_block doesn't get re-added several times */
294             *pp_block = block_BytestreamPop( &p_sys->bytestream );
295
296             p_sys->i_state = STATE_NOSYNC;
297
298             return p_out_buffer;
299         }
300     }
301
302     return NULL;
303 }
304
305 /*****************************************************************************
306  * CloseDecoder: clean up the decoder
307  *****************************************************************************/
308 static void CloseDecoder( vlc_object_t *p_this )
309 {
310     decoder_t *p_dec = (decoder_t*)p_this;
311     decoder_sys_t *p_sys = p_dec->p_sys;
312
313     block_BytestreamRelease( &p_sys->bytestream );
314
315     free( p_sys );
316 }
317
318 /*****************************************************************************
319  * GetOutBuffer:
320  *****************************************************************************/
321 static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
322 {
323     decoder_sys_t *p_sys = p_dec->p_sys;
324     uint8_t *p_buf;
325
326     if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
327     {
328         msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
329                   p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
330
331         aout_DateInit( &p_sys->end_date, p_sys->i_rate );
332         aout_DateSet( &p_sys->end_date, p_sys->i_pts );
333     }
334
335     p_dec->fmt_out.audio.i_rate     = p_sys->i_rate;
336     p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
337     p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size;
338     p_dec->fmt_out.audio.i_frame_length = A52_FRAME_NB;
339
340     p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
341     p_dec->fmt_out.audio.i_physical_channels =
342         p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
343
344     p_dec->fmt_out.i_bitrate = p_sys->i_bit_rate;
345
346     if( p_sys->b_packetizer )
347     {
348         block_t *p_sout_buffer = GetSoutBuffer( p_dec );
349         p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
350         *pp_out_buffer = p_sout_buffer;
351     }
352     else
353     {
354         aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec );
355         p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
356         *pp_out_buffer = p_aout_buffer;
357     }
358
359     return p_buf;
360 }
361
362 /*****************************************************************************
363  * GetAoutBuffer:
364  *****************************************************************************/
365 static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
366 {
367     decoder_sys_t *p_sys = p_dec->p_sys;
368     aout_buffer_t *p_buf;
369
370     p_buf = p_dec->pf_aout_buffer_new( p_dec, A52_FRAME_NB  );
371     if( p_buf == NULL ) return NULL;
372
373     p_buf->start_date = aout_DateGet( &p_sys->end_date );
374     p_buf->end_date = aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB );
375
376     return p_buf;
377 }
378
379 /*****************************************************************************
380  * GetSoutBuffer:
381  *****************************************************************************/
382 static block_t *GetSoutBuffer( decoder_t *p_dec )
383 {
384     decoder_sys_t *p_sys = p_dec->p_sys;
385     block_t *p_block;
386
387     p_block = block_New( p_dec, p_sys->i_frame_size );
388     if( p_block == NULL ) return NULL;
389
390     p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
391
392     p_block->i_length = aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB ) -
393         p_block->i_pts;
394
395     return p_block;
396 }
397
398 /*****************************************************************************
399  * SyncInfo: parse A/52 sync info
400  *****************************************************************************
401  * This code is borrowed from liba52 by Aaron Holtzman & Michel Lespinasse,
402  * since we don't want to oblige S/PDIF people to use liba52 just to get
403  * their SyncInfo...
404  *****************************************************************************/
405 static int SyncInfo( const byte_t * p_buf,
406                      int * pi_channels, int * pi_channels_conf,
407                      int * pi_sample_rate, int * pi_bit_rate )
408 {
409     static const uint8_t halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
410     static const int rate[] = { 32,  40,  48,  56,  64,  80,  96, 112,
411                                 128, 160, 192, 224, 256, 320, 384, 448,
412                                 512, 576, 640 };
413     static const uint8_t lfeon[8] = { 0x10, 0x10, 0x04, 0x04,
414                                       0x04, 0x01, 0x04, 0x01 };
415     int frmsizecod;
416     int bitrate;
417     int half;
418     int acmod;
419
420     if ((p_buf[0] != 0x0b) || (p_buf[1] != 0x77))        /* syncword */
421         return 0;
422
423     if (p_buf[5] >= 0x60)                /* bsid >= 12 */
424         return 0;
425     half = halfrate[p_buf[5] >> 3];
426
427     /* acmod, dsurmod and lfeon */
428     acmod = p_buf[6] >> 5;
429     if ( (p_buf[6] & 0xf8) == 0x50 )
430     {
431         /* Dolby surround = stereo + Dolby */
432         *pi_channels = 2;
433         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
434                             | AOUT_CHAN_DOLBYSTEREO;
435     }
436     else switch ( acmod )
437     {
438     case 0x0:
439         /* Dual-mono = stereo + dual-mono */
440         *pi_channels = 2;
441         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
442                             | AOUT_CHAN_DUALMONO;
443         break;
444     case 0x1:
445         /* Mono */
446         *pi_channels = 1;
447         *pi_channels_conf = AOUT_CHAN_CENTER;
448         break;
449     case 0x2:
450         /* Stereo */
451         *pi_channels = 2;
452         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
453         break;
454     case 0x3:
455         /* 3F */
456         *pi_channels = 3;
457         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
458                             | AOUT_CHAN_CENTER;
459         break;
460     case 0x4:
461         /* 2F1R */
462         *pi_channels = 3;
463         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
464                             | AOUT_CHAN_REARCENTER;
465         break;
466     case 0x5:
467         /* 3F1R */
468         *pi_channels = 4;
469         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
470                             | AOUT_CHAN_REARCENTER;
471         break;
472     case 0x6:
473         /* 2F2R */
474         *pi_channels = 4;
475         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
476                             | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
477         break;
478     case 0x7:
479         /* 3F2R */
480         *pi_channels = 5;
481         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
482                             | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
483         break;
484     default:
485         return 0;
486     }
487
488     if ( p_buf[6] & lfeon[acmod] )
489     {
490         (*pi_channels)++;
491         *pi_channels_conf |= AOUT_CHAN_LFE;
492     }
493
494     frmsizecod = p_buf[4] & 63;
495     if (frmsizecod >= 38)
496         return 0;
497     bitrate = rate [frmsizecod >> 1];
498     *pi_bit_rate = (bitrate * 1000) >> half;
499
500     switch (p_buf[4] & 0xc0) {
501     case 0:
502         *pi_sample_rate = 48000 >> half;
503         return 4 * bitrate;
504     case 0x40:
505         *pi_sample_rate = 44100 >> half;
506         return 2 * (320 * bitrate / 147 + (frmsizecod & 1));
507     case 0x80:
508         *pi_sample_rate = 32000 >> half;
509         return 6 * bitrate;
510     default:
511         return 0;
512     }
513 }