1 /*****************************************************************************
2 * a52.c: A/52 basic parser
3 *****************************************************************************
4 * Copyright (C) 2001-2002 VideoLAN
5 * $Id: a52.c,v 1.24 2003/09/30 20:23:03 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 int i_out_buffer; /* position in output buffer */
85 audio_date_t end_date;
88 int i_frame_size, i_bit_rate;
89 unsigned int i_rate, i_channels, i_channels_conf;
101 /****************************************************************************
103 ****************************************************************************/
104 static int OpenDecoder ( vlc_object_t * );
105 static int OpenPacketizer( vlc_object_t * );
107 static int InitDecoder ( decoder_t * );
108 static int RunDecoder ( decoder_t *, block_t * );
109 static int EndDecoder ( decoder_t * );
111 static int SyncInfo ( const byte_t *, int *, int *, int *,int * );
113 static int GetOutBuffer ( decoder_t *, uint8_t ** );
114 static int GetAoutBuffer( decoder_t *, aout_buffer_t ** );
115 static int GetSoutBuffer( decoder_t *, sout_buffer_t ** );
116 static int SendOutBuffer( decoder_t * );
118 /*****************************************************************************
120 *****************************************************************************/
122 set_description( _("A/52 parser") );
123 set_capability( "decoder", 100 );
124 set_callbacks( OpenDecoder, NULL );
127 set_description( _("A/52 audio packetizer") );
128 set_capability( "packetizer", 10 );
129 set_callbacks( OpenPacketizer, NULL );
132 /*****************************************************************************
133 * OpenDecoder: probe the decoder and return score
134 *****************************************************************************/
135 static int OpenDecoder( vlc_object_t *p_this )
137 decoder_t *p_dec = (decoder_t*)p_this;
139 if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ')
140 && p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2','b') )
145 p_dec->pf_init = InitDecoder;
146 p_dec->pf_decode = RunDecoder;
147 p_dec->pf_end = EndDecoder;
149 /* Allocate the memory needed to store the decoder's structure */
151 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
153 msg_Err( p_dec, "out of memory" );
156 p_dec->p_sys->b_packetizer = VLC_FALSE;
161 static int OpenPacketizer( vlc_object_t *p_this )
163 decoder_t *p_dec = (decoder_t*)p_this;
165 int i_ret = OpenDecoder( p_this );
167 if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
172 /*****************************************************************************
173 * InitDecoder: Initalize the decoder
174 *****************************************************************************/
175 static int InitDecoder( decoder_t *p_dec )
177 p_dec->p_sys->i_state = STATE_NOSYNC;
178 p_dec->p_sys->b_synchro = VLC_FALSE;
180 p_dec->p_sys->p_out_buffer = NULL;
181 p_dec->p_sys->i_out_buffer = 0;
182 aout_DateSet( &p_dec->p_sys->end_date, 0 );
184 p_dec->p_sys->p_aout = NULL;
185 p_dec->p_sys->p_aout_input = NULL;
186 p_dec->p_sys->p_aout_buffer = NULL;
187 p_dec->p_sys->aout_format.i_format = VLC_FOURCC('a','5','2',' ');
189 p_dec->p_sys->p_sout_input = NULL;
190 p_dec->p_sys->p_sout_buffer = NULL;
191 p_dec->p_sys->sout_format.i_cat = AUDIO_ES;
192 p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
194 p_dec->p_sys->p_chain = NULL;
199 /****************************************************************************
200 * RunDecoder: the whole thing
201 ****************************************************************************
202 * This function is called just after the thread is launched.
203 ****************************************************************************/
204 static int RunDecoder( decoder_t *p_dec, block_t *p_block )
206 decoder_sys_t *p_sys = p_dec->p_sys;
207 uint8_t p_header[A52_HEADER_SIZE];
211 block_ChainAppend( &p_sys->p_chain, p_block );
215 block_ChainAppend( &p_sys->p_chain, p_block );
216 p_sys->bytestream = block_BytestreamInit( p_dec, p_sys->p_chain, 0 );
221 switch( p_sys->i_state )
225 while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
228 if( p_header[0] == 0x0b && p_header[1] == 0x77 )
230 p_sys->i_state = STATE_SYNC;
233 block_SkipByte( &p_sys->bytestream );
234 p_dec->p_sys->b_synchro = VLC_FALSE;
236 if( p_sys->i_state != STATE_SYNC )
238 block_ChainRelease( p_sys->p_chain );
239 p_sys->p_chain = NULL;
246 /* New frame, set the Presentation Time Stamp */
247 p_sys->pts = p_sys->bytestream.p_block->i_pts;
248 if( p_sys->pts != 0 &&
249 p_sys->pts != aout_DateGet( &p_sys->end_date ) )
251 aout_DateSet( &p_sys->end_date, p_sys->pts );
253 p_sys->i_state = STATE_HEADER;
257 /* Get A/52 frame header (A52_HEADER_SIZE bytes) */
258 if( block_PeekBytes( &p_sys->bytestream, p_header,
259 A52_HEADER_SIZE ) != VLC_SUCCESS )
265 /* Check if frame is valid and get frame info */
266 p_sys->i_frame_size = SyncInfo( p_header,
268 &p_sys->i_channels_conf,
270 &p_sys->i_bit_rate );
271 if( !p_sys->i_frame_size )
273 msg_Dbg( p_dec, "emulated sync word" );
274 block_SkipByte( &p_sys->bytestream );
275 p_sys->i_state = STATE_NOSYNC;
276 p_dec->p_sys->b_synchro = VLC_FALSE;
279 p_sys->i_state = STATE_DATA;
282 /* TODO: If p_block == NULL, flush the buffer without checking the
285 if( !p_dec->p_sys->b_synchro )
287 /* Check if next expected frame contains the sync word */
288 if( block_PeekOffsetBytes( &p_sys->bytestream,
289 p_sys->i_frame_size, p_header, 2 )
296 if( p_header[0] != 0x0b || p_header[1] != 0x77 )
298 msg_Dbg( p_dec, "emulated sync word "
299 "(no sync on following frame)" );
300 p_sys->i_state = STATE_NOSYNC;
301 block_SkipByte( &p_sys->bytestream );
302 p_dec->p_sys->b_synchro = VLC_FALSE;
307 if( !p_dec->p_sys->p_out_buffer )
308 if( GetOutBuffer( p_dec, &p_sys->p_out_buffer ) != VLC_SUCCESS )
313 /* Copy the whole frame into the buffer */
314 if( block_GetBytes( &p_sys->bytestream, p_sys->p_out_buffer,
315 p_sys->i_frame_size ) != VLC_SUCCESS )
321 p_sys->p_chain = block_BytestreamFlush( &p_sys->bytestream );
323 SendOutBuffer( p_dec );
324 p_sys->i_state = STATE_NOSYNC;
325 p_dec->p_sys->b_synchro = VLC_TRUE;
327 /* Make sure we don't reuse the same pts twice */
328 if( p_sys->pts == p_sys->bytestream.p_block->i_pts )
329 p_sys->pts = p_sys->bytestream.p_block->i_pts = 0;
336 /*****************************************************************************
337 * EndDecoder: clean up the decoder
338 *****************************************************************************/
339 static int EndDecoder( decoder_t *p_dec )
341 if( p_dec->p_sys->p_aout_input != NULL )
343 if( p_dec->p_sys->p_aout_buffer )
345 aout_DecDeleteBuffer( p_dec->p_sys->p_aout,
346 p_dec->p_sys->p_aout_input,
347 p_dec->p_sys->p_aout_buffer );
350 aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input );
353 if( p_dec->p_sys->p_sout_input != NULL )
355 if( p_dec->p_sys->p_sout_buffer )
357 sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout,
358 p_dec->p_sys->p_sout_buffer );
361 sout_InputDelete( p_dec->p_sys->p_sout_input );
364 if( p_dec->p_sys->p_chain ) block_ChainRelease( p_sys->p_chain );
366 free( p_dec->p_sys );
371 /*****************************************************************************
373 *****************************************************************************/
374 static int GetOutBuffer( decoder_t *p_dec, uint8_t **pp_out_buffer )
376 decoder_sys_t *p_sys = p_dec->p_sys;
379 if( p_sys->b_packetizer )
381 i_ret= GetSoutBuffer( p_dec, &p_sys->p_sout_buffer );
383 p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL;
387 i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer );
389 p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer : NULL;
395 /*****************************************************************************
397 *****************************************************************************/
398 static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer )
400 decoder_sys_t *p_sys = p_dec->p_sys;
402 if( p_sys->p_aout_input != NULL &&
403 ( p_sys->aout_format.i_rate != p_sys->i_rate
404 || p_sys->aout_format.i_original_channels != p_sys->i_channels_conf
405 || (int)p_sys->aout_format.i_bytes_per_frame != p_sys->i_frame_size ) )
407 /* Parameters changed - this should not happen. */
408 aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
409 p_sys->p_aout_input = NULL;
412 /* Creating the audio input if not created yet. */
413 if( p_sys->p_aout_input == NULL )
415 p_sys->aout_format.i_rate = p_sys->i_rate;
416 p_sys->aout_format.i_original_channels = p_sys->i_channels_conf;
417 p_sys->aout_format.i_physical_channels
418 = p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
419 p_sys->aout_format.i_bytes_per_frame = p_sys->i_frame_size;
420 p_sys->aout_format.i_frame_length = A52_FRAME_NB;
421 aout_DateInit( &p_sys->end_date, p_sys->i_rate );
422 aout_DateSet( &p_sys->end_date, p_sys->pts );
423 p_sys->p_aout_input = aout_DecNew( p_dec,
425 &p_sys->aout_format );
427 if ( p_sys->p_aout_input == NULL )
434 if( !aout_DateGet( &p_sys->end_date ) )
436 /* We've just started the stream, wait for the first PTS. */
441 *pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
443 if( *pp_buffer == NULL )
448 (*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date );
449 (*pp_buffer)->end_date =
450 aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB );
455 /*****************************************************************************
457 *****************************************************************************/
458 static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer )
460 decoder_sys_t *p_sys = p_dec->p_sys;
462 if( p_sys->p_sout_input != NULL &&
463 ( p_sys->sout_format.i_sample_rate != (int)p_sys->i_rate
464 || p_sys->sout_format.i_channels != (int)p_sys->i_channels ) )
466 /* Parameters changed - this should not happen. */
469 /* Creating the sout input if not created yet. */
470 if( p_sys->p_sout_input == NULL )
472 p_sys->sout_format.i_sample_rate = p_sys->i_rate;
473 p_sys->sout_format.i_channels = p_sys->i_channels;
474 p_sys->sout_format.i_block_align = 0;
475 p_sys->sout_format.i_bitrate = p_sys->i_bit_rate;
476 p_sys->sout_format.i_extra_data = 0;
477 p_sys->sout_format.p_extra_data = NULL;
479 aout_DateInit( &p_sys->end_date, p_sys->i_rate );
480 aout_DateSet( &p_sys->end_date, p_sys->pts );
482 p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format );
483 if( p_sys->p_sout_input == NULL )
485 msg_Err( p_dec, "cannot add a new stream" );
489 msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
490 p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
493 if( !aout_DateGet( &p_sys->end_date ) )
495 /* We've just started the stream, wait for the first PTS. */
500 *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout,
501 p_sys->i_frame_size );
502 if( *pp_buffer == NULL )
507 (*pp_buffer)->i_pts =
508 (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date );
510 (*pp_buffer)->i_length =
511 aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB )
512 - (*pp_buffer)->i_pts;
517 /*****************************************************************************
519 *****************************************************************************/
520 static int SendOutBuffer( decoder_t *p_dec )
522 decoder_sys_t *p_sys = p_dec->p_sys;
524 if( p_sys->b_packetizer )
526 sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer );
527 p_sys->p_sout_buffer = NULL;
531 /* We have all we need, send the buffer to the aout core. */
532 aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input,
533 p_sys->p_aout_buffer );
534 p_sys->p_aout_buffer = NULL;
537 p_dec->p_sys->p_out_buffer = NULL;
542 /*****************************************************************************
543 * SyncInfo: parse A/52 sync info
544 *****************************************************************************
545 * This code is borrowed from liba52 by Aaron Holtzman & Michel Lespinasse,
546 * since we don't want to oblige S/PDIF people to use liba52 just to get
548 *****************************************************************************/
549 static int SyncInfo( const byte_t * p_buf,
550 int * pi_channels, int * pi_channels_conf,
551 int * pi_sample_rate, int * pi_bit_rate )
553 static const uint8_t halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
554 static const int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112,
555 128, 160, 192, 224, 256, 320, 384, 448,
557 static const uint8_t lfeon[8] = { 0x10, 0x10, 0x04, 0x04,
558 0x04, 0x01, 0x04, 0x01 };
564 if ((p_buf[0] != 0x0b) || (p_buf[1] != 0x77)) /* syncword */
567 if (p_buf[5] >= 0x60) /* bsid >= 12 */
569 half = halfrate[p_buf[5] >> 3];
571 /* acmod, dsurmod and lfeon */
572 acmod = p_buf[6] >> 5;
573 if ( (p_buf[6] & 0xf8) == 0x50 )
575 /* Dolby surround = stereo + Dolby */
577 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
578 | AOUT_CHAN_DOLBYSTEREO;
580 else switch ( acmod )
583 /* Dual-mono = stereo + dual-mono */
585 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
586 | AOUT_CHAN_DUALMONO;
591 *pi_channels_conf = AOUT_CHAN_CENTER;
596 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
601 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
607 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
608 | AOUT_CHAN_REARCENTER;
613 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
614 | AOUT_CHAN_REARCENTER;
619 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
620 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
625 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
626 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
632 if ( p_buf[6] & lfeon[acmod] )
635 *pi_channels_conf |= AOUT_CHAN_LFE;
638 frmsizecod = p_buf[4] & 63;
639 if (frmsizecod >= 38)
641 bitrate = rate [frmsizecod >> 1];
642 *pi_bit_rate = (bitrate * 1000) >> half;
644 switch (p_buf[4] & 0xc0) {
646 *pi_sample_rate = 48000 >> half;
649 *pi_sample_rate = 44100 >> half;
650 return 2 * (320 * bitrate / 147 + (frmsizecod & 1));
652 *pi_sample_rate = 32000 >> half;