1 /*****************************************************************************
2 * a52.c: A/52 basic parser
3 *****************************************************************************
4 * Copyright (C) 2001-2002 VideoLAN
5 * $Id: a52.c,v 1.26 2003/10/01 18:32:13 gbazin Exp $
7 * Authors: Stéphane Borel <stef@via.ecp.fr>
8 * Christophe Massiot <massiot@via.ecp.fr>
9 * Gildas Bazin <gbazin@netcourrier.com>
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.
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.
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 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
31 #include <string.h> /* memcpy() */
35 #include <vlc/decoder.h>
36 #include <vlc/input.h>
44 #include "vlc_block_helper.h"
46 #define A52_HEADER_SIZE 7
48 /*****************************************************************************
49 * decoder_sys_t : decoder descriptor
50 *****************************************************************************/
54 vlc_bool_t b_packetizer;
63 block_bytestream_t bytestream;
66 * Decoder output properties
68 aout_instance_t * p_aout; /* opaque */
69 aout_input_t * p_aout_input; /* opaque */
70 audio_sample_format_t aout_format;
71 aout_buffer_t * p_aout_buffer; /* current aout buffer being filled */
74 * Packetizer output properties
76 sout_packetizer_input_t *p_sout_input;
77 sout_format_t sout_format;
78 sout_buffer_t * p_sout_buffer; /* current sout buffer */
83 uint8_t *p_out_buffer; /* output buffer */
84 audio_date_t end_date;
87 int i_frame_size, i_bit_rate;
88 unsigned int i_rate, i_channels, i_channels_conf;
100 /****************************************************************************
102 ****************************************************************************/
103 static int OpenDecoder ( vlc_object_t * );
104 static int OpenPacketizer( vlc_object_t * );
106 static int InitDecoder ( decoder_t * );
107 static int RunDecoder ( decoder_t *, block_t * );
108 static int EndDecoder ( decoder_t * );
110 static int SyncInfo ( const byte_t *, int *, int *, int *,int * );
112 static int GetOutBuffer ( decoder_t *, uint8_t ** );
113 static int GetAoutBuffer( decoder_t *, aout_buffer_t ** );
114 static int GetSoutBuffer( decoder_t *, sout_buffer_t ** );
115 static int SendOutBuffer( decoder_t * );
117 /*****************************************************************************
119 *****************************************************************************/
121 set_description( _("A/52 parser") );
122 set_capability( "decoder", 100 );
123 set_callbacks( OpenDecoder, NULL );
126 set_description( _("A/52 audio packetizer") );
127 set_capability( "packetizer", 10 );
128 set_callbacks( OpenPacketizer, NULL );
131 /*****************************************************************************
132 * OpenDecoder: probe the decoder and return score
133 *****************************************************************************/
134 static int OpenDecoder( vlc_object_t *p_this )
136 decoder_t *p_dec = (decoder_t*)p_this;
138 if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ')
139 && p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2','b') )
144 p_dec->pf_init = InitDecoder;
145 p_dec->pf_decode = RunDecoder;
146 p_dec->pf_end = EndDecoder;
148 /* Allocate the memory needed to store the decoder's structure */
150 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
152 msg_Err( p_dec, "out of memory" );
155 p_dec->p_sys->b_packetizer = VLC_FALSE;
160 static int OpenPacketizer( vlc_object_t *p_this )
162 decoder_t *p_dec = (decoder_t*)p_this;
164 int i_ret = OpenDecoder( p_this );
166 if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
171 /*****************************************************************************
172 * InitDecoder: Initalize the decoder
173 *****************************************************************************/
174 static int InitDecoder( decoder_t *p_dec )
176 p_dec->p_sys->i_state = STATE_NOSYNC;
177 p_dec->p_sys->b_synchro = VLC_FALSE;
179 p_dec->p_sys->p_out_buffer = NULL;
180 aout_DateSet( &p_dec->p_sys->end_date, 0 );
182 p_dec->p_sys->p_aout = NULL;
183 p_dec->p_sys->p_aout_input = NULL;
184 p_dec->p_sys->p_aout_buffer = NULL;
185 p_dec->p_sys->aout_format.i_format = VLC_FOURCC('a','5','2',' ');
187 p_dec->p_sys->p_sout_input = NULL;
188 p_dec->p_sys->p_sout_buffer = NULL;
189 p_dec->p_sys->sout_format.i_cat = AUDIO_ES;
190 p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
192 p_dec->p_sys->p_chain = NULL;
197 /****************************************************************************
198 * RunDecoder: the whole thing
199 ****************************************************************************
200 * This function is called just after the thread is launched.
201 ****************************************************************************/
202 static int RunDecoder( decoder_t *p_dec, block_t *p_block )
204 decoder_sys_t *p_sys = p_dec->p_sys;
205 uint8_t p_header[A52_HEADER_SIZE];
207 if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
209 /* We've just started the stream, wait for the first PTS. */
210 block_Release( p_block );
216 block_ChainAppend( &p_sys->p_chain, p_block );
220 block_ChainAppend( &p_sys->p_chain, p_block );
221 p_sys->bytestream = block_BytestreamInit( p_dec, p_sys->p_chain, 0 );
226 switch( p_sys->i_state )
230 while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
233 if( p_header[0] == 0x0b && p_header[1] == 0x77 )
235 p_sys->i_state = STATE_SYNC;
238 block_SkipByte( &p_sys->bytestream );
239 p_sys->b_synchro = VLC_FALSE;
241 if( p_sys->i_state != STATE_SYNC )
243 block_ChainRelease( p_sys->p_chain );
244 p_sys->p_chain = NULL;
251 /* New frame, set the Presentation Time Stamp */
252 p_sys->pts = p_sys->bytestream.p_block->i_pts;
253 if( p_sys->pts != 0 &&
254 p_sys->pts != aout_DateGet( &p_sys->end_date ) )
256 aout_DateSet( &p_sys->end_date, p_sys->pts );
258 p_sys->i_state = STATE_HEADER;
262 /* Get A/52 frame header (A52_HEADER_SIZE bytes) */
263 if( block_PeekBytes( &p_sys->bytestream, p_header,
264 A52_HEADER_SIZE ) != VLC_SUCCESS )
270 /* Check if frame is valid and get frame info */
271 p_sys->i_frame_size = SyncInfo( p_header,
273 &p_sys->i_channels_conf,
275 &p_sys->i_bit_rate );
276 if( !p_sys->i_frame_size )
278 msg_Dbg( p_dec, "emulated sync word" );
279 block_SkipByte( &p_sys->bytestream );
280 p_sys->i_state = STATE_NOSYNC;
281 p_sys->b_synchro = VLC_FALSE;
284 p_sys->i_state = STATE_DATA;
287 /* TODO: If p_block == NULL, flush the buffer without checking the
290 if( !p_sys->b_synchro )
292 /* Check if next expected frame contains the sync word */
293 if( block_PeekOffsetBytes( &p_sys->bytestream,
294 p_sys->i_frame_size, p_header, 2 )
301 if( p_header[0] != 0x0b || p_header[1] != 0x77 )
303 msg_Dbg( p_dec, "emulated sync word "
304 "(no sync on following frame)" );
305 p_sys->i_state = STATE_NOSYNC;
306 block_SkipByte( &p_sys->bytestream );
307 p_sys->b_synchro = VLC_FALSE;
312 if( !p_sys->p_out_buffer )
313 if( GetOutBuffer( p_dec, &p_sys->p_out_buffer ) != VLC_SUCCESS )
318 /* Copy the whole frame into the buffer */
319 if( block_GetBytes( &p_sys->bytestream, p_sys->p_out_buffer,
320 p_sys->i_frame_size ) != VLC_SUCCESS )
326 p_sys->p_chain = block_BytestreamFlush( &p_sys->bytestream );
328 SendOutBuffer( p_dec );
329 p_sys->i_state = STATE_NOSYNC;
330 p_sys->b_synchro = VLC_TRUE;
332 /* Make sure we don't reuse the same pts twice */
333 if( p_sys->pts == p_sys->bytestream.p_block->i_pts )
334 p_sys->pts = p_sys->bytestream.p_block->i_pts = 0;
341 /*****************************************************************************
342 * EndDecoder: clean up the decoder
343 *****************************************************************************/
344 static int EndDecoder( decoder_t *p_dec )
346 if( p_dec->p_sys->p_aout_input != NULL )
348 if( p_dec->p_sys->p_aout_buffer )
350 aout_DecDeleteBuffer( p_dec->p_sys->p_aout,
351 p_dec->p_sys->p_aout_input,
352 p_dec->p_sys->p_aout_buffer );
355 aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input );
358 if( p_dec->p_sys->p_sout_input != NULL )
360 if( p_dec->p_sys->p_sout_buffer )
362 sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout,
363 p_dec->p_sys->p_sout_buffer );
366 sout_InputDelete( p_dec->p_sys->p_sout_input );
369 if( p_dec->p_sys->p_chain ) block_ChainRelease( p_dec->p_sys->p_chain );
371 free( p_dec->p_sys );
376 /*****************************************************************************
378 *****************************************************************************/
379 static int GetOutBuffer( decoder_t *p_dec, uint8_t **pp_out_buffer )
381 decoder_sys_t *p_sys = p_dec->p_sys;
384 if( p_sys->b_packetizer )
386 i_ret = GetSoutBuffer( p_dec, &p_sys->p_sout_buffer );
388 p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL;
392 i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer );
394 p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer : NULL;
400 /*****************************************************************************
402 *****************************************************************************/
403 static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer )
405 decoder_sys_t *p_sys = p_dec->p_sys;
407 if( p_sys->p_aout_input != NULL &&
408 ( p_sys->aout_format.i_rate != p_sys->i_rate
409 || p_sys->aout_format.i_original_channels != p_sys->i_channels_conf
410 || (int)p_sys->aout_format.i_bytes_per_frame != p_sys->i_frame_size ) )
412 /* Parameters changed - this should not happen. */
413 aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
414 p_sys->p_aout_input = NULL;
417 /* Creating the audio input if not created yet. */
418 if( p_sys->p_aout_input == NULL )
420 p_sys->aout_format.i_rate = p_sys->i_rate;
421 p_sys->aout_format.i_original_channels = p_sys->i_channels_conf;
422 p_sys->aout_format.i_physical_channels
423 = p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
424 p_sys->aout_format.i_bytes_per_frame = p_sys->i_frame_size;
425 p_sys->aout_format.i_frame_length = A52_FRAME_NB;
426 aout_DateInit( &p_sys->end_date, p_sys->i_rate );
427 aout_DateSet( &p_sys->end_date, p_sys->pts );
428 p_sys->p_aout_input = aout_DecNew( p_dec,
430 &p_sys->aout_format );
431 if( p_sys->p_aout_input == NULL )
438 *pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
440 if( *pp_buffer == NULL )
445 (*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date );
446 (*pp_buffer)->end_date =
447 aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB );
452 /*****************************************************************************
454 *****************************************************************************/
455 static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer )
457 decoder_sys_t *p_sys = p_dec->p_sys;
459 if( p_sys->p_sout_input != NULL &&
460 ( p_sys->sout_format.i_sample_rate != (int)p_sys->i_rate
461 || p_sys->sout_format.i_channels != (int)p_sys->i_channels ) )
463 /* Parameters changed - this should not happen. */
466 /* Creating the sout input if not created yet. */
467 if( p_sys->p_sout_input == NULL )
469 p_sys->sout_format.i_sample_rate = p_sys->i_rate;
470 p_sys->sout_format.i_channels = p_sys->i_channels;
471 p_sys->sout_format.i_block_align = 0;
472 p_sys->sout_format.i_bitrate = p_sys->i_bit_rate;
473 p_sys->sout_format.i_extra_data = 0;
474 p_sys->sout_format.p_extra_data = NULL;
476 aout_DateInit( &p_sys->end_date, p_sys->i_rate );
477 aout_DateSet( &p_sys->end_date, p_sys->pts );
479 p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format );
480 if( p_sys->p_sout_input == NULL )
482 msg_Err( p_dec, "cannot add a new stream" );
486 msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
487 p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
490 *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout,
491 p_sys->i_frame_size );
492 if( *pp_buffer == NULL )
497 (*pp_buffer)->i_pts =
498 (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date );
500 (*pp_buffer)->i_length =
501 aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB )
502 - (*pp_buffer)->i_pts;
507 /*****************************************************************************
509 *****************************************************************************/
510 static int SendOutBuffer( decoder_t *p_dec )
512 decoder_sys_t *p_sys = p_dec->p_sys;
514 if( p_sys->b_packetizer )
516 sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer );
517 p_sys->p_sout_buffer = NULL;
521 /* We have all we need, send the buffer to the aout core. */
522 aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input,
523 p_sys->p_aout_buffer );
524 p_sys->p_aout_buffer = NULL;
527 p_sys->p_out_buffer = NULL;
532 /*****************************************************************************
533 * SyncInfo: parse A/52 sync info
534 *****************************************************************************
535 * This code is borrowed from liba52 by Aaron Holtzman & Michel Lespinasse,
536 * since we don't want to oblige S/PDIF people to use liba52 just to get
538 *****************************************************************************/
539 static int SyncInfo( const byte_t * p_buf,
540 int * pi_channels, int * pi_channels_conf,
541 int * pi_sample_rate, int * pi_bit_rate )
543 static const uint8_t halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
544 static const int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112,
545 128, 160, 192, 224, 256, 320, 384, 448,
547 static const uint8_t lfeon[8] = { 0x10, 0x10, 0x04, 0x04,
548 0x04, 0x01, 0x04, 0x01 };
554 if ((p_buf[0] != 0x0b) || (p_buf[1] != 0x77)) /* syncword */
557 if (p_buf[5] >= 0x60) /* bsid >= 12 */
559 half = halfrate[p_buf[5] >> 3];
561 /* acmod, dsurmod and lfeon */
562 acmod = p_buf[6] >> 5;
563 if ( (p_buf[6] & 0xf8) == 0x50 )
565 /* Dolby surround = stereo + Dolby */
567 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
568 | AOUT_CHAN_DOLBYSTEREO;
570 else switch ( acmod )
573 /* Dual-mono = stereo + dual-mono */
575 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
576 | AOUT_CHAN_DUALMONO;
581 *pi_channels_conf = AOUT_CHAN_CENTER;
586 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
591 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
597 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
598 | AOUT_CHAN_REARCENTER;
603 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
604 | AOUT_CHAN_REARCENTER;
609 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
610 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
615 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
616 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
622 if ( p_buf[6] & lfeon[acmod] )
625 *pi_channels_conf |= AOUT_CHAN_LFE;
628 frmsizecod = p_buf[4] & 63;
629 if (frmsizecod >= 38)
631 bitrate = rate [frmsizecod >> 1];
632 *pi_bit_rate = (bitrate * 1000) >> half;
634 switch (p_buf[4] & 0xc0) {
636 *pi_sample_rate = 48000 >> half;
639 *pi_sample_rate = 44100 >> half;
640 return 2 * (320 * bitrate / 147 + (frmsizecod & 1));
642 *pi_sample_rate = 32000 >> half;