1 /*****************************************************************************
2 * a52.c: A/52 basic parser
3 *****************************************************************************
4 * Copyright (C) 2001-2002 VideoLAN
5 * $Id: a52.c,v 1.28 2003/10/23 20:51:20 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>
40 #include "vlc_block_helper.h"
42 #define A52_HEADER_SIZE 7
44 /*****************************************************************************
45 * decoder_sys_t : decoder descriptor
46 *****************************************************************************/
50 vlc_bool_t b_packetizer;
58 block_bytestream_t bytestream;
61 * Decoder output properties
63 aout_instance_t * p_aout; /* opaque */
64 aout_input_t * p_aout_input; /* opaque */
65 audio_sample_format_t aout_format;
66 aout_buffer_t * p_aout_buffer; /* current aout buffer being filled */
69 * Packetizer output properties
71 sout_packetizer_input_t *p_sout_input;
72 sout_format_t sout_format;
73 sout_buffer_t * p_sout_buffer; /* current sout buffer */
78 uint8_t *p_out_buffer; /* output buffer */
79 audio_date_t end_date;
82 int i_frame_size, i_bit_rate;
83 unsigned int i_rate, i_channels, i_channels_conf;
95 /****************************************************************************
97 ****************************************************************************/
98 static int OpenDecoder ( vlc_object_t * );
99 static int OpenPacketizer( vlc_object_t * );
101 static int InitDecoder ( decoder_t * );
102 static int RunDecoder ( decoder_t *, block_t * );
103 static int EndDecoder ( decoder_t * );
105 static int SyncInfo ( const byte_t *, int *, int *, int *,int * );
107 static int GetOutBuffer ( decoder_t *, uint8_t ** );
108 static int GetAoutBuffer( decoder_t *, aout_buffer_t ** );
109 static int GetSoutBuffer( decoder_t *, sout_buffer_t ** );
110 static int SendOutBuffer( decoder_t * );
112 /*****************************************************************************
114 *****************************************************************************/
116 set_description( _("A/52 parser") );
117 set_capability( "decoder", 100 );
118 set_callbacks( OpenDecoder, NULL );
121 set_description( _("A/52 audio packetizer") );
122 set_capability( "packetizer", 10 );
123 set_callbacks( OpenPacketizer, NULL );
126 /*****************************************************************************
127 * OpenDecoder: probe the decoder and return score
128 *****************************************************************************/
129 static int OpenDecoder( vlc_object_t *p_this )
131 decoder_t *p_dec = (decoder_t*)p_this;
133 if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ')
134 && p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2','b') )
139 p_dec->pf_init = InitDecoder;
140 p_dec->pf_decode = RunDecoder;
141 p_dec->pf_end = EndDecoder;
143 /* Allocate the memory needed to store the decoder's structure */
145 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
147 msg_Err( p_dec, "out of memory" );
150 p_dec->p_sys->b_packetizer = VLC_FALSE;
155 static int OpenPacketizer( vlc_object_t *p_this )
157 decoder_t *p_dec = (decoder_t*)p_this;
159 int i_ret = OpenDecoder( p_this );
161 if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
166 /*****************************************************************************
167 * InitDecoder: Initalize the decoder
168 *****************************************************************************/
169 static int InitDecoder( decoder_t *p_dec )
171 p_dec->p_sys->i_state = STATE_NOSYNC;
173 p_dec->p_sys->p_out_buffer = NULL;
174 aout_DateSet( &p_dec->p_sys->end_date, 0 );
176 p_dec->p_sys->p_aout = NULL;
177 p_dec->p_sys->p_aout_input = NULL;
178 p_dec->p_sys->p_aout_buffer = NULL;
179 p_dec->p_sys->aout_format.i_format = VLC_FOURCC('a','5','2',' ');
181 p_dec->p_sys->p_sout_input = NULL;
182 p_dec->p_sys->p_sout_buffer = NULL;
183 p_dec->p_sys->sout_format.i_cat = AUDIO_ES;
184 p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
186 p_dec->p_sys->p_chain = NULL;
191 /****************************************************************************
192 * RunDecoder: the whole thing
193 ****************************************************************************
194 * This function is called just after the thread is launched.
195 ****************************************************************************/
196 static int RunDecoder( decoder_t *p_dec, block_t *p_block )
198 decoder_sys_t *p_sys = p_dec->p_sys;
199 uint8_t p_header[A52_HEADER_SIZE];
201 if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
203 /* We've just started the stream, wait for the first PTS. */
204 block_Release( p_block );
208 if( p_block->b_discontinuity )
210 p_sys->i_state = STATE_SYNC;
215 block_ChainAppend( &p_sys->p_chain, p_block );
219 block_ChainAppend( &p_sys->p_chain, p_block );
220 p_sys->bytestream = block_BytestreamInit( p_dec, p_sys->p_chain, 0 );
225 switch( p_sys->i_state )
229 while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
232 if( p_header[0] == 0x0b && p_header[1] == 0x77 )
234 p_sys->i_state = STATE_SYNC;
237 block_SkipByte( &p_sys->bytestream );
239 if( p_sys->i_state != STATE_SYNC )
241 if( block_PeekByte( &p_sys->bytestream, p_header )
242 == VLC_SUCCESS && p_header[0] == 0x0b )
244 /* Start of a sync word, need more data */
248 block_ChainRelease( p_sys->p_chain );
249 p_sys->p_chain = NULL;
256 /* New frame, set the Presentation Time Stamp */
257 p_sys->pts = p_sys->bytestream.p_block->i_pts;
258 if( p_sys->pts != 0 &&
259 p_sys->pts != aout_DateGet( &p_sys->end_date ) )
261 aout_DateSet( &p_sys->end_date, p_sys->pts );
263 p_sys->i_state = STATE_HEADER;
267 /* Get A/52 frame header (A52_HEADER_SIZE bytes) */
268 if( block_PeekBytes( &p_sys->bytestream, p_header,
269 A52_HEADER_SIZE ) != VLC_SUCCESS )
275 /* Check if frame is valid and get frame info */
276 p_sys->i_frame_size = SyncInfo( p_header,
278 &p_sys->i_channels_conf,
280 &p_sys->i_bit_rate );
281 if( !p_sys->i_frame_size )
283 msg_Dbg( p_dec, "emulated sync word" );
284 block_SkipByte( &p_sys->bytestream );
285 p_sys->i_state = STATE_NOSYNC;
288 p_sys->i_state = STATE_DATA;
291 /* TODO: If p_block == NULL, flush the buffer without checking the
294 /* Check if next expected frame contains the sync word */
295 if( block_PeekOffsetBytes( &p_sys->bytestream,
296 p_sys->i_frame_size, p_header, 2 )
303 if( p_header[0] != 0x0b || p_header[1] != 0x77 )
305 msg_Dbg( p_dec, "emulated sync word "
306 "(no sync on following frame)" );
307 p_sys->i_state = STATE_NOSYNC;
308 block_SkipByte( &p_sys->bytestream );
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;
331 /* Make sure we don't reuse the same pts twice */
332 if( p_sys->pts == p_sys->bytestream.p_block->i_pts )
333 p_sys->pts = p_sys->bytestream.p_block->i_pts = 0;
340 /*****************************************************************************
341 * EndDecoder: clean up the decoder
342 *****************************************************************************/
343 static int EndDecoder( decoder_t *p_dec )
345 if( p_dec->p_sys->p_aout_input != NULL )
347 if( p_dec->p_sys->p_aout_buffer )
349 aout_DecDeleteBuffer( p_dec->p_sys->p_aout,
350 p_dec->p_sys->p_aout_input,
351 p_dec->p_sys->p_aout_buffer );
354 aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input );
357 if( p_dec->p_sys->p_sout_input != NULL )
359 if( p_dec->p_sys->p_sout_buffer )
361 sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout,
362 p_dec->p_sys->p_sout_buffer );
365 sout_InputDelete( p_dec->p_sys->p_sout_input );
368 if( p_dec->p_sys->p_chain ) block_ChainRelease( p_dec->p_sys->p_chain );
370 free( p_dec->p_sys );
375 /*****************************************************************************
377 *****************************************************************************/
378 static int GetOutBuffer( decoder_t *p_dec, uint8_t **pp_out_buffer )
380 decoder_sys_t *p_sys = p_dec->p_sys;
383 if( p_sys->b_packetizer )
385 i_ret = GetSoutBuffer( p_dec, &p_sys->p_sout_buffer );
387 p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL;
391 i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer );
393 p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer : NULL;
399 /*****************************************************************************
401 *****************************************************************************/
402 static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer )
404 decoder_sys_t *p_sys = p_dec->p_sys;
406 if( p_sys->p_aout_input != NULL &&
407 ( p_sys->aout_format.i_rate != p_sys->i_rate
408 || p_sys->aout_format.i_original_channels != p_sys->i_channels_conf
409 || (int)p_sys->aout_format.i_bytes_per_frame != p_sys->i_frame_size ) )
411 /* Parameters changed - this should not happen. */
412 aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
413 p_sys->p_aout_input = NULL;
416 /* Creating the audio input if not created yet. */
417 if( p_sys->p_aout_input == NULL )
419 p_sys->aout_format.i_rate = p_sys->i_rate;
420 p_sys->aout_format.i_original_channels = p_sys->i_channels_conf;
421 p_sys->aout_format.i_physical_channels
422 = p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
423 p_sys->aout_format.i_bytes_per_frame = p_sys->i_frame_size;
424 p_sys->aout_format.i_frame_length = A52_FRAME_NB;
425 aout_DateInit( &p_sys->end_date, p_sys->i_rate );
426 aout_DateSet( &p_sys->end_date, p_sys->pts );
427 p_sys->p_aout_input = aout_DecNew( p_dec,
429 &p_sys->aout_format );
430 if( p_sys->p_aout_input == NULL )
437 *pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
439 if( *pp_buffer == NULL )
444 (*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date );
445 (*pp_buffer)->end_date =
446 aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB );
451 /*****************************************************************************
453 *****************************************************************************/
454 static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer )
456 decoder_sys_t *p_sys = p_dec->p_sys;
458 if( p_sys->p_sout_input != NULL &&
459 ( p_sys->sout_format.i_sample_rate != (int)p_sys->i_rate
460 || p_sys->sout_format.i_channels != (int)p_sys->i_channels ) )
462 /* Parameters changed - this should not happen. */
465 /* Creating the sout input if not created yet. */
466 if( p_sys->p_sout_input == NULL )
468 p_sys->sout_format.i_sample_rate = p_sys->i_rate;
469 p_sys->sout_format.i_channels = p_sys->i_channels;
470 p_sys->sout_format.i_block_align = 0;
471 p_sys->sout_format.i_bitrate = p_sys->i_bit_rate;
472 p_sys->sout_format.i_extra_data = 0;
473 p_sys->sout_format.p_extra_data = NULL;
475 aout_DateInit( &p_sys->end_date, p_sys->i_rate );
476 aout_DateSet( &p_sys->end_date, p_sys->pts );
478 p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format );
479 if( p_sys->p_sout_input == NULL )
481 msg_Err( p_dec, "cannot add a new stream" );
485 msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
486 p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
489 *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout,
490 p_sys->i_frame_size );
491 if( *pp_buffer == NULL )
496 (*pp_buffer)->i_pts =
497 (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date );
499 (*pp_buffer)->i_length =
500 aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB )
501 - (*pp_buffer)->i_pts;
506 /*****************************************************************************
508 *****************************************************************************/
509 static int SendOutBuffer( decoder_t *p_dec )
511 decoder_sys_t *p_sys = p_dec->p_sys;
513 if( p_sys->b_packetizer )
515 sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer );
516 p_sys->p_sout_buffer = NULL;
520 /* We have all we need, send the buffer to the aout core. */
521 aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input,
522 p_sys->p_aout_buffer );
523 p_sys->p_aout_buffer = NULL;
526 p_sys->p_out_buffer = NULL;
531 /*****************************************************************************
532 * SyncInfo: parse A/52 sync info
533 *****************************************************************************
534 * This code is borrowed from liba52 by Aaron Holtzman & Michel Lespinasse,
535 * since we don't want to oblige S/PDIF people to use liba52 just to get
537 *****************************************************************************/
538 static int SyncInfo( const byte_t * p_buf,
539 int * pi_channels, int * pi_channels_conf,
540 int * pi_sample_rate, int * pi_bit_rate )
542 static const uint8_t halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
543 static const int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112,
544 128, 160, 192, 224, 256, 320, 384, 448,
546 static const uint8_t lfeon[8] = { 0x10, 0x10, 0x04, 0x04,
547 0x04, 0x01, 0x04, 0x01 };
553 if ((p_buf[0] != 0x0b) || (p_buf[1] != 0x77)) /* syncword */
556 if (p_buf[5] >= 0x60) /* bsid >= 12 */
558 half = halfrate[p_buf[5] >> 3];
560 /* acmod, dsurmod and lfeon */
561 acmod = p_buf[6] >> 5;
562 if ( (p_buf[6] & 0xf8) == 0x50 )
564 /* Dolby surround = stereo + Dolby */
566 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
567 | AOUT_CHAN_DOLBYSTEREO;
569 else switch ( acmod )
572 /* Dual-mono = stereo + dual-mono */
574 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
575 | AOUT_CHAN_DUALMONO;
580 *pi_channels_conf = AOUT_CHAN_CENTER;
585 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
590 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
596 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
597 | AOUT_CHAN_REARCENTER;
602 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
603 | AOUT_CHAN_REARCENTER;
608 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
609 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
614 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
615 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
621 if ( p_buf[6] & lfeon[acmod] )
624 *pi_channels_conf |= AOUT_CHAN_LFE;
627 frmsizecod = p_buf[4] & 63;
628 if (frmsizecod >= 38)
630 bitrate = rate [frmsizecod >> 1];
631 *pi_bit_rate = (bitrate * 1000) >> half;
633 switch (p_buf[4] & 0xc0) {
635 *pi_sample_rate = 48000 >> half;
638 *pi_sample_rate = 44100 >> half;
639 return 2 * (320 * bitrate / 147 + (frmsizecod & 1));
641 *pi_sample_rate = 32000 >> half;