1 /*****************************************************************************
2 * a52.c: A/52 basic parser
3 *****************************************************************************
4 * Copyright (C) 2001-2002 VideoLAN
5 * $Id: a52.c,v 1.27 2003/10/08 21:03:36 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;
59 block_bytestream_t bytestream;
62 * Decoder output properties
64 aout_instance_t * p_aout; /* opaque */
65 aout_input_t * p_aout_input; /* opaque */
66 audio_sample_format_t aout_format;
67 aout_buffer_t * p_aout_buffer; /* current aout buffer being filled */
70 * Packetizer output properties
72 sout_packetizer_input_t *p_sout_input;
73 sout_format_t sout_format;
74 sout_buffer_t * p_sout_buffer; /* current sout buffer */
79 uint8_t *p_out_buffer; /* output buffer */
80 audio_date_t end_date;
83 int i_frame_size, i_bit_rate;
84 unsigned int i_rate, i_channels, i_channels_conf;
96 /****************************************************************************
98 ****************************************************************************/
99 static int OpenDecoder ( vlc_object_t * );
100 static int OpenPacketizer( vlc_object_t * );
102 static int InitDecoder ( decoder_t * );
103 static int RunDecoder ( decoder_t *, block_t * );
104 static int EndDecoder ( decoder_t * );
106 static int SyncInfo ( const byte_t *, int *, int *, int *,int * );
108 static int GetOutBuffer ( decoder_t *, uint8_t ** );
109 static int GetAoutBuffer( decoder_t *, aout_buffer_t ** );
110 static int GetSoutBuffer( decoder_t *, sout_buffer_t ** );
111 static int SendOutBuffer( decoder_t * );
113 /*****************************************************************************
115 *****************************************************************************/
117 set_description( _("A/52 parser") );
118 set_capability( "decoder", 100 );
119 set_callbacks( OpenDecoder, NULL );
122 set_description( _("A/52 audio packetizer") );
123 set_capability( "packetizer", 10 );
124 set_callbacks( OpenPacketizer, NULL );
127 /*****************************************************************************
128 * OpenDecoder: probe the decoder and return score
129 *****************************************************************************/
130 static int OpenDecoder( vlc_object_t *p_this )
132 decoder_t *p_dec = (decoder_t*)p_this;
134 if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ')
135 && p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2','b') )
140 p_dec->pf_init = InitDecoder;
141 p_dec->pf_decode = RunDecoder;
142 p_dec->pf_end = EndDecoder;
144 /* Allocate the memory needed to store the decoder's structure */
146 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
148 msg_Err( p_dec, "out of memory" );
151 p_dec->p_sys->b_packetizer = VLC_FALSE;
156 static int OpenPacketizer( vlc_object_t *p_this )
158 decoder_t *p_dec = (decoder_t*)p_this;
160 int i_ret = OpenDecoder( p_this );
162 if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
167 /*****************************************************************************
168 * InitDecoder: Initalize the decoder
169 *****************************************************************************/
170 static int InitDecoder( decoder_t *p_dec )
172 p_dec->p_sys->i_state = STATE_NOSYNC;
173 p_dec->p_sys->b_synchro = VLC_FALSE;
175 p_dec->p_sys->p_out_buffer = NULL;
176 aout_DateSet( &p_dec->p_sys->end_date, 0 );
178 p_dec->p_sys->p_aout = NULL;
179 p_dec->p_sys->p_aout_input = NULL;
180 p_dec->p_sys->p_aout_buffer = NULL;
181 p_dec->p_sys->aout_format.i_format = VLC_FOURCC('a','5','2',' ');
183 p_dec->p_sys->p_sout_input = NULL;
184 p_dec->p_sys->p_sout_buffer = NULL;
185 p_dec->p_sys->sout_format.i_cat = AUDIO_ES;
186 p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
188 p_dec->p_sys->p_chain = NULL;
193 /****************************************************************************
194 * RunDecoder: the whole thing
195 ****************************************************************************
196 * This function is called just after the thread is launched.
197 ****************************************************************************/
198 static int RunDecoder( decoder_t *p_dec, block_t *p_block )
200 decoder_sys_t *p_sys = p_dec->p_sys;
201 uint8_t p_header[A52_HEADER_SIZE];
203 if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
205 /* We've just started the stream, wait for the first PTS. */
206 block_Release( p_block );
212 block_ChainAppend( &p_sys->p_chain, p_block );
216 block_ChainAppend( &p_sys->p_chain, p_block );
217 p_sys->bytestream = block_BytestreamInit( p_dec, p_sys->p_chain, 0 );
222 switch( p_sys->i_state )
226 while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
229 if( p_header[0] == 0x0b && p_header[1] == 0x77 )
231 p_sys->i_state = STATE_SYNC;
234 block_SkipByte( &p_sys->bytestream );
235 p_sys->b_synchro = VLC_FALSE;
237 if( p_sys->i_state != STATE_SYNC )
239 block_ChainRelease( p_sys->p_chain );
240 p_sys->p_chain = NULL;
247 /* New frame, set the Presentation Time Stamp */
248 p_sys->pts = p_sys->bytestream.p_block->i_pts;
249 if( p_sys->pts != 0 &&
250 p_sys->pts != aout_DateGet( &p_sys->end_date ) )
252 aout_DateSet( &p_sys->end_date, p_sys->pts );
254 p_sys->i_state = STATE_HEADER;
258 /* Get A/52 frame header (A52_HEADER_SIZE bytes) */
259 if( block_PeekBytes( &p_sys->bytestream, p_header,
260 A52_HEADER_SIZE ) != VLC_SUCCESS )
266 /* Check if frame is valid and get frame info */
267 p_sys->i_frame_size = SyncInfo( p_header,
269 &p_sys->i_channels_conf,
271 &p_sys->i_bit_rate );
272 if( !p_sys->i_frame_size )
274 msg_Dbg( p_dec, "emulated sync word" );
275 block_SkipByte( &p_sys->bytestream );
276 p_sys->i_state = STATE_NOSYNC;
277 p_sys->b_synchro = VLC_FALSE;
280 p_sys->i_state = STATE_DATA;
283 /* TODO: If p_block == NULL, flush the buffer without checking the
286 if( !p_sys->b_synchro )
288 /* Check if next expected frame contains the sync word */
289 if( block_PeekOffsetBytes( &p_sys->bytestream,
290 p_sys->i_frame_size, p_header, 2 )
297 if( p_header[0] != 0x0b || p_header[1] != 0x77 )
299 msg_Dbg( p_dec, "emulated sync word "
300 "(no sync on following frame)" );
301 p_sys->i_state = STATE_NOSYNC;
302 block_SkipByte( &p_sys->bytestream );
303 p_sys->b_synchro = VLC_FALSE;
308 if( !p_sys->p_out_buffer )
309 if( GetOutBuffer( p_dec, &p_sys->p_out_buffer ) != VLC_SUCCESS )
314 /* Copy the whole frame into the buffer */
315 if( block_GetBytes( &p_sys->bytestream, p_sys->p_out_buffer,
316 p_sys->i_frame_size ) != VLC_SUCCESS )
322 p_sys->p_chain = block_BytestreamFlush( &p_sys->bytestream );
324 SendOutBuffer( p_dec );
325 p_sys->i_state = STATE_NOSYNC;
326 p_sys->b_synchro = VLC_TRUE;
328 /* Make sure we don't reuse the same pts twice */
329 if( p_sys->pts == p_sys->bytestream.p_block->i_pts )
330 p_sys->pts = p_sys->bytestream.p_block->i_pts = 0;
337 /*****************************************************************************
338 * EndDecoder: clean up the decoder
339 *****************************************************************************/
340 static int EndDecoder( decoder_t *p_dec )
342 if( p_dec->p_sys->p_aout_input != NULL )
344 if( p_dec->p_sys->p_aout_buffer )
346 aout_DecDeleteBuffer( p_dec->p_sys->p_aout,
347 p_dec->p_sys->p_aout_input,
348 p_dec->p_sys->p_aout_buffer );
351 aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input );
354 if( p_dec->p_sys->p_sout_input != NULL )
356 if( p_dec->p_sys->p_sout_buffer )
358 sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout,
359 p_dec->p_sys->p_sout_buffer );
362 sout_InputDelete( p_dec->p_sys->p_sout_input );
365 if( p_dec->p_sys->p_chain ) block_ChainRelease( p_dec->p_sys->p_chain );
367 free( p_dec->p_sys );
372 /*****************************************************************************
374 *****************************************************************************/
375 static int GetOutBuffer( decoder_t *p_dec, uint8_t **pp_out_buffer )
377 decoder_sys_t *p_sys = p_dec->p_sys;
380 if( p_sys->b_packetizer )
382 i_ret = GetSoutBuffer( p_dec, &p_sys->p_sout_buffer );
384 p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL;
388 i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer );
390 p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer : NULL;
396 /*****************************************************************************
398 *****************************************************************************/
399 static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer )
401 decoder_sys_t *p_sys = p_dec->p_sys;
403 if( p_sys->p_aout_input != NULL &&
404 ( p_sys->aout_format.i_rate != p_sys->i_rate
405 || p_sys->aout_format.i_original_channels != p_sys->i_channels_conf
406 || (int)p_sys->aout_format.i_bytes_per_frame != p_sys->i_frame_size ) )
408 /* Parameters changed - this should not happen. */
409 aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
410 p_sys->p_aout_input = NULL;
413 /* Creating the audio input if not created yet. */
414 if( p_sys->p_aout_input == NULL )
416 p_sys->aout_format.i_rate = p_sys->i_rate;
417 p_sys->aout_format.i_original_channels = p_sys->i_channels_conf;
418 p_sys->aout_format.i_physical_channels
419 = p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
420 p_sys->aout_format.i_bytes_per_frame = p_sys->i_frame_size;
421 p_sys->aout_format.i_frame_length = A52_FRAME_NB;
422 aout_DateInit( &p_sys->end_date, p_sys->i_rate );
423 aout_DateSet( &p_sys->end_date, p_sys->pts );
424 p_sys->p_aout_input = aout_DecNew( p_dec,
426 &p_sys->aout_format );
427 if( p_sys->p_aout_input == NULL )
434 *pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
436 if( *pp_buffer == NULL )
441 (*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date );
442 (*pp_buffer)->end_date =
443 aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB );
448 /*****************************************************************************
450 *****************************************************************************/
451 static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer )
453 decoder_sys_t *p_sys = p_dec->p_sys;
455 if( p_sys->p_sout_input != NULL &&
456 ( p_sys->sout_format.i_sample_rate != (int)p_sys->i_rate
457 || p_sys->sout_format.i_channels != (int)p_sys->i_channels ) )
459 /* Parameters changed - this should not happen. */
462 /* Creating the sout input if not created yet. */
463 if( p_sys->p_sout_input == NULL )
465 p_sys->sout_format.i_sample_rate = p_sys->i_rate;
466 p_sys->sout_format.i_channels = p_sys->i_channels;
467 p_sys->sout_format.i_block_align = 0;
468 p_sys->sout_format.i_bitrate = p_sys->i_bit_rate;
469 p_sys->sout_format.i_extra_data = 0;
470 p_sys->sout_format.p_extra_data = NULL;
472 aout_DateInit( &p_sys->end_date, p_sys->i_rate );
473 aout_DateSet( &p_sys->end_date, p_sys->pts );
475 p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format );
476 if( p_sys->p_sout_input == NULL )
478 msg_Err( p_dec, "cannot add a new stream" );
482 msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
483 p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
486 *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout,
487 p_sys->i_frame_size );
488 if( *pp_buffer == NULL )
493 (*pp_buffer)->i_pts =
494 (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date );
496 (*pp_buffer)->i_length =
497 aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB )
498 - (*pp_buffer)->i_pts;
503 /*****************************************************************************
505 *****************************************************************************/
506 static int SendOutBuffer( decoder_t *p_dec )
508 decoder_sys_t *p_sys = p_dec->p_sys;
510 if( p_sys->b_packetizer )
512 sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer );
513 p_sys->p_sout_buffer = NULL;
517 /* We have all we need, send the buffer to the aout core. */
518 aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input,
519 p_sys->p_aout_buffer );
520 p_sys->p_aout_buffer = NULL;
523 p_sys->p_out_buffer = NULL;
528 /*****************************************************************************
529 * SyncInfo: parse A/52 sync info
530 *****************************************************************************
531 * This code is borrowed from liba52 by Aaron Holtzman & Michel Lespinasse,
532 * since we don't want to oblige S/PDIF people to use liba52 just to get
534 *****************************************************************************/
535 static int SyncInfo( const byte_t * p_buf,
536 int * pi_channels, int * pi_channels_conf,
537 int * pi_sample_rate, int * pi_bit_rate )
539 static const uint8_t halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
540 static const int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112,
541 128, 160, 192, 224, 256, 320, 384, 448,
543 static const uint8_t lfeon[8] = { 0x10, 0x10, 0x04, 0x04,
544 0x04, 0x01, 0x04, 0x01 };
550 if ((p_buf[0] != 0x0b) || (p_buf[1] != 0x77)) /* syncword */
553 if (p_buf[5] >= 0x60) /* bsid >= 12 */
555 half = halfrate[p_buf[5] >> 3];
557 /* acmod, dsurmod and lfeon */
558 acmod = p_buf[6] >> 5;
559 if ( (p_buf[6] & 0xf8) == 0x50 )
561 /* Dolby surround = stereo + Dolby */
563 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
564 | AOUT_CHAN_DOLBYSTEREO;
566 else switch ( acmod )
569 /* Dual-mono = stereo + dual-mono */
571 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
572 | AOUT_CHAN_DUALMONO;
577 *pi_channels_conf = AOUT_CHAN_CENTER;
582 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
587 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
593 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
594 | AOUT_CHAN_REARCENTER;
599 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
600 | AOUT_CHAN_REARCENTER;
605 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
606 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
611 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
612 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
618 if ( p_buf[6] & lfeon[acmod] )
621 *pi_channels_conf |= AOUT_CHAN_LFE;
624 frmsizecod = p_buf[4] & 63;
625 if (frmsizecod >= 38)
627 bitrate = rate [frmsizecod >> 1];
628 *pi_bit_rate = (bitrate * 1000) >> half;
630 switch (p_buf[4] & 0xc0) {
632 *pi_sample_rate = 48000 >> half;
635 *pi_sample_rate = 44100 >> half;
636 return 2 * (320 * bitrate / 147 + (frmsizecod & 1));
638 *pi_sample_rate = 32000 >> half;