mirror of
https://github.com/videolan/vlc.git
synced 2025-01-19 06:08:18 +08:00
More S/PDIF fixes.
This commit is contained in:
parent
a29bce0ba1
commit
9a9f8a1e7a
@ -442,7 +442,8 @@ PLUGINS="${PLUGINS} misc/dummy/dummy misc/null/null"
|
||||
PLUGINS="${PLUGINS} control/rc/rc misc/logger/logger access/file access/udp access/http misc/network/ipv4 misc/memcpy/memcpy"
|
||||
PLUGINS="${PLUGINS} demux/mpeg/es demux/mpeg/audio demux/mpeg/mpeg_system demux/mpeg/ps demux/mpeg/ts"
|
||||
PLUGINS="${PLUGINS} codec/mpeg_video/idct/idct codec/mpeg_video/idct/idctclassic codec/mpeg_video/motion/motion codec/mpeg_video/mpeg_video codec/spudec/spudec"
|
||||
#PLUGINS="${PLUGINS} codec/a52old/imdct/imdct codec/a52old/downmix/downmix codec/mpeg_audio/mpeg_audio codec/a52old/a52old codec/lpcm/lpcm codec/spdif/spdif"
|
||||
PLUGINS="${PLUGINS} codec/spdif"
|
||||
#PLUGINS="${PLUGINS} codec/a52old/imdct/imdct codec/a52old/downmix/downmix codec/mpeg_audio/mpeg_audio codec/a52old/a52old codec/lpcm/lpcm"
|
||||
PLUGINS="${PLUGINS} video_filter/deinterlace/deinterlace video_filter/invert video_filter/wall video_filter/transform video_filter/distort video_filter/clone video_filter/crop"
|
||||
PLUGINS="${PLUGINS} audio_filter/converter/float32tos16"
|
||||
PLUGINS="${PLUGINS} audio_filter/resampler/trivial"
|
||||
@ -1155,7 +1156,7 @@ then
|
||||
a52_LDFLAGS="${a52_LDFLAGS} -L${real_a52_tree}/liba52/.libs"
|
||||
LDFLAGS="${save_LDFLAGS} ${a52_LDFLAGS}"
|
||||
AC_CHECK_LIB(a52, a52_free, [
|
||||
BUILTINS="${BUILTINS} codec/a52/a52"
|
||||
BUILTINS="${BUILTINS} codec/a52"
|
||||
a52_LDFLAGS="${a52_LDFLAGS} -la52 -lm"
|
||||
a52_CFLAGS="${a52_CFLAGS} -DUSE_A52DEC_TREE"
|
||||
],[
|
||||
@ -1186,7 +1187,7 @@ then
|
||||
LDFLAGS="${save_LDFLAGS} ${test_LDFLAGS}"
|
||||
AC_CHECK_HEADERS(a52dec/a52.h, [
|
||||
AC_CHECK_LIB(a52, a52_free, [
|
||||
BUILTINS="${BUILTINS} codec/a52/a52"
|
||||
BUILTINS="${BUILTINS} codec/a52"
|
||||
a52_LDFLAGS="${a52_LDFLAGS} ${test_LDFLAGS} -la52 -lm"
|
||||
a52_CFLAGS="${a52_CFLAGS} ${test_CFLAGS}"
|
||||
],[
|
||||
|
@ -129,12 +129,16 @@
|
||||
#define VOLUME_MAX 1024
|
||||
#define VOLUME_MIN 0
|
||||
|
||||
/* Max number of pre-filters per input, and max-number of post-filters */
|
||||
/* Max number of pre-filters per input, and max number of post-filters */
|
||||
#define AOUT_MAX_FILTERS 10
|
||||
|
||||
/* Max number of inputs */
|
||||
#define AOUT_MAX_INPUTS 5
|
||||
|
||||
/* Buffers which arrive in advance of more than AOUT_MAX_PREPARE_TIME
|
||||
* will cause the calling thread to sleep */
|
||||
#define AOUT_MAX_PREPARE_TIME (mtime_t)(.5*CLOCK_FREQ)
|
||||
|
||||
/*****************************************************************************
|
||||
* Video configuration
|
||||
*****************************************************************************/
|
||||
|
@ -2,7 +2,7 @@
|
||||
* oss.c : OSS /dev/dsp module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000-2002 VideoLAN
|
||||
* $Id: oss.c,v 1.4 2002/08/09 23:47:23 massiot Exp $
|
||||
* $Id: oss.c,v 1.5 2002/08/11 01:27:01 massiot Exp $
|
||||
*
|
||||
* Authors: Michel Kaempf <maxx@via.ecp.fr>
|
||||
* Samuel Hocevar <sam@zoy.org>
|
||||
@ -293,39 +293,44 @@ static int OSSThread( aout_instance_t * p_aout )
|
||||
int i_bytes_per_sample;
|
||||
aout_buffer_t * p_buffer;
|
||||
mtime_t next_date;
|
||||
int i_tmp;
|
||||
int i_tmp, i_size;
|
||||
byte_t * p_bytes;
|
||||
|
||||
/* Get the presentation date of the next write() operation. It
|
||||
* is equal to the current date + duration of buffered samples.
|
||||
* Order is important here, since GetBufInfo is believed to take
|
||||
* more time than mdate(). */
|
||||
if( !p_sys->b_initialized )
|
||||
{
|
||||
msleep( THREAD_SLEEP );
|
||||
continue;
|
||||
}
|
||||
|
||||
i_bytes_per_sample = aout_FormatToSize( &p_aout->output.output, 1 );
|
||||
next_date = (mtime_t)GetBufInfo( p_aout ) * 1000000
|
||||
/ i_bytes_per_sample
|
||||
/ p_aout->output.output.i_rate;
|
||||
next_date += mdate();
|
||||
if ( p_aout->output.output.i_format != AOUT_FMT_SPDIF )
|
||||
{
|
||||
/* Get the presentation date of the next write() operation. It
|
||||
* is equal to the current date + duration of buffered samples.
|
||||
* Order is important here, since GetBufInfo is believed to take
|
||||
* more time than mdate(). */
|
||||
next_date = (mtime_t)GetBufInfo( p_aout ) * 1000000
|
||||
/ aout_FormatToByterate( &p_aout->output.output,
|
||||
p_aout->output.output.i_rate );
|
||||
next_date += mdate();
|
||||
}
|
||||
|
||||
p_buffer = aout_OutputNextBuffer( p_aout, next_date );
|
||||
|
||||
if ( p_buffer != NULL )
|
||||
{
|
||||
p_bytes = p_buffer->p_buffer;
|
||||
i_size = aout_FormatToSize( &p_aout->output.output,
|
||||
p_buffer->i_nb_samples );
|
||||
}
|
||||
else
|
||||
{
|
||||
p_bytes = alloca( DEFAULT_FRAME_SIZE * i_bytes_per_sample );
|
||||
memset( p_bytes, 0, DEFAULT_FRAME_SIZE * i_bytes_per_sample );
|
||||
i_size = aout_FormatToSize( &p_aout->output.output,
|
||||
DEFAULT_FRAME_SIZE );
|
||||
p_bytes = alloca( i_size );
|
||||
memset( p_bytes, 0, i_size );
|
||||
}
|
||||
|
||||
i_tmp = write( p_sys->i_fd, p_bytes,
|
||||
DEFAULT_FRAME_SIZE * i_bytes_per_sample );
|
||||
i_tmp = write( p_sys->i_fd, p_bytes, i_size );
|
||||
|
||||
if( i_tmp < 0 )
|
||||
{
|
||||
|
@ -1 +1,2 @@
|
||||
a52_SOURCES = a52.c
|
||||
spdif_SOURCES = spdif.c
|
@ -4,7 +4,7 @@
|
||||
* (http://liba52.sf.net/).
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001, 2002 VideoLAN
|
||||
* $Id: a52.c,v 1.2 2002/08/07 21:36:56 massiot Exp $
|
||||
* $Id: a52.c,v 1.1 2002/08/11 01:27:01 massiot Exp $
|
||||
*
|
||||
* Authors: Gildas Bazin <gbazin@netcourrier.com>
|
||||
* Christophe Massiot <massiot@via.ecp.fr>
|
||||
@ -45,17 +45,43 @@
|
||||
# include "a52dec/a52.h"
|
||||
#endif
|
||||
|
||||
#include "a52.h"
|
||||
#define A52_FRAME_SIZE 1536
|
||||
|
||||
#define A52DEC_FRAME_SIZE 1536
|
||||
/*****************************************************************************
|
||||
* a52_thread_t : a52 decoder thread descriptor
|
||||
*****************************************************************************/
|
||||
typedef struct a52_thread_s
|
||||
{
|
||||
/*
|
||||
* liba52 properties
|
||||
*/
|
||||
a52_state_t * p_a52_state;
|
||||
vlc_bool_t b_dynrng;
|
||||
|
||||
/* The bit stream structure handles the PES stream at the bit level */
|
||||
bit_stream_t bit_stream;
|
||||
|
||||
/*
|
||||
* Input properties
|
||||
*/
|
||||
decoder_fifo_t * p_fifo; /* stores the PES stream data */
|
||||
data_packet_t * p_data;
|
||||
|
||||
/*
|
||||
* Output properties
|
||||
*/
|
||||
aout_instance_t * p_aout; /* opaque */
|
||||
aout_input_t * p_aout_input; /* opaque */
|
||||
audio_sample_format_t output_format;
|
||||
mtime_t last_date;
|
||||
} a52_thread_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int OpenDecoder ( vlc_object_t * );
|
||||
static int RunDecoder ( decoder_fifo_t * );
|
||||
static int DecodeFrame ( a52_thread_t *, u8 * );
|
||||
static int DecodeFrame ( a52_thread_t *, const byte_t * );
|
||||
static int InitThread ( a52_thread_t *, decoder_fifo_t * );
|
||||
static void EndThread ( a52_thread_t * );
|
||||
|
||||
@ -102,44 +128,44 @@ static int OpenDecoder( vlc_object_t *p_this )
|
||||
*****************************************************************************/
|
||||
static int RunDecoder( decoder_fifo_t *p_fifo )
|
||||
{
|
||||
a52_thread_t *p_a52;
|
||||
a52_thread_t *p_dec;
|
||||
|
||||
/* Allocate the memory needed to store the thread's structure */
|
||||
p_a52 = (a52_thread_t *)malloc( sizeof(a52_thread_t) );
|
||||
if( p_a52 == NULL )
|
||||
p_dec = (a52_thread_t *)malloc( sizeof(a52_thread_t) );
|
||||
if( p_dec == NULL )
|
||||
{
|
||||
msg_Err( p_fifo, "out of memory" );
|
||||
DecoderError( p_fifo );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( InitThread( p_a52, p_fifo ) )
|
||||
if( InitThread( p_dec, p_fifo ) )
|
||||
{
|
||||
msg_Err( p_a52->p_fifo, "could not initialize thread" );
|
||||
msg_Err( p_dec->p_fifo, "could not initialize thread" );
|
||||
DecoderError( p_fifo );
|
||||
free( p_a52 );
|
||||
free( p_dec );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* liba52 decoder thread's main loop */
|
||||
while( !p_a52->p_fifo->b_die && !p_a52->p_fifo->b_error )
|
||||
while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
|
||||
{
|
||||
int i_frame_size, i_flags, i_rate, i_bit_rate;
|
||||
mtime_t pts;
|
||||
/* Temporary buffer to store the raw frame to be decoded */
|
||||
u8 p_frame_buffer[3840];
|
||||
byte_t p_frame_buffer[3840];
|
||||
|
||||
/* Look for sync word - should be 0x0b77 */
|
||||
RealignBits(&p_a52->bit_stream);
|
||||
while( (ShowBits( &p_a52->bit_stream, 16 ) ) != 0x0b77 &&
|
||||
(!p_a52->p_fifo->b_die) && (!p_a52->p_fifo->b_error))
|
||||
RealignBits( &p_dec->bit_stream );
|
||||
while( (ShowBits( &p_dec->bit_stream, 16 ) ) != 0x0b77 &&
|
||||
(!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error))
|
||||
{
|
||||
RemoveBits( &p_a52->bit_stream, 8 );
|
||||
RemoveBits( &p_dec->bit_stream, 8 );
|
||||
}
|
||||
|
||||
/* Get A/52 frame header */
|
||||
GetChunk( &p_a52->bit_stream, p_frame_buffer, 7 );
|
||||
if( p_a52->p_fifo->b_die ) break;
|
||||
GetChunk( &p_dec->bit_stream, p_frame_buffer, 7 );
|
||||
if( p_dec->p_fifo->b_die ) break;
|
||||
|
||||
/* Check if frame is valid and get frame info */
|
||||
i_frame_size = a52_syncinfo( p_frame_buffer, &i_flags, &i_rate,
|
||||
@ -147,62 +173,62 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
|
||||
|
||||
if( !i_frame_size )
|
||||
{
|
||||
msg_Warn( p_a52->p_fifo, "a52_syncinfo failed" );
|
||||
msg_Warn( p_dec->p_fifo, "a52_syncinfo failed" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( (p_a52->p_aout_input != NULL) &&
|
||||
( (p_a52->output_format.i_rate != i_rate)
|
||||
/* || (p_a52->output_format.i_channels != i_channels) */ ) )
|
||||
if( (p_dec->p_aout_input != NULL) &&
|
||||
( (p_dec->output_format.i_rate != i_rate)
|
||||
/* || (p_dec->output_format.i_channels != i_channels) */ ) )
|
||||
{
|
||||
/* Parameters changed - this should not happen. */
|
||||
aout_InputDelete( p_a52->p_aout, p_a52->p_aout_input );
|
||||
p_a52->p_aout_input = NULL;
|
||||
aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
|
||||
p_dec->p_aout_input = NULL;
|
||||
}
|
||||
|
||||
/* Creating the audio input if not created yet. */
|
||||
if( p_a52->p_aout_input == NULL )
|
||||
if( p_dec->p_aout_input == NULL )
|
||||
{
|
||||
p_a52->output_format.i_rate = i_rate;
|
||||
/* p_a52->output_format.i_channels = i_channels; */
|
||||
p_a52->p_aout_input = aout_InputNew( p_a52->p_fifo,
|
||||
&p_a52->p_aout,
|
||||
&p_a52->output_format );
|
||||
p_dec->output_format.i_rate = i_rate;
|
||||
/* p_dec->output_format.i_channels = i_channels; */
|
||||
p_dec->p_aout_input = aout_InputNew( p_dec->p_fifo,
|
||||
&p_dec->p_aout,
|
||||
&p_dec->output_format );
|
||||
|
||||
if ( p_a52->p_aout_input == NULL )
|
||||
if ( p_dec->p_aout_input == NULL )
|
||||
{
|
||||
p_a52->p_fifo->b_error = 1;
|
||||
p_dec->p_fifo->b_error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the Presentation Time Stamp */
|
||||
CurrentPTS( &p_a52->bit_stream, &pts, NULL );
|
||||
CurrentPTS( &p_dec->bit_stream, &pts, NULL );
|
||||
if ( pts != 0 )
|
||||
{
|
||||
p_a52->last_date = pts;
|
||||
p_dec->last_date = pts;
|
||||
}
|
||||
|
||||
/* Get the complete frame */
|
||||
GetChunk( &p_a52->bit_stream, p_frame_buffer + 7,
|
||||
GetChunk( &p_dec->bit_stream, p_frame_buffer + 7,
|
||||
i_frame_size - 7 );
|
||||
if( p_a52->p_fifo->b_die ) break;
|
||||
if( p_dec->p_fifo->b_die ) break;
|
||||
|
||||
if( DecodeFrame( p_a52, p_frame_buffer ) )
|
||||
if( DecodeFrame( p_dec, p_frame_buffer ) )
|
||||
{
|
||||
p_a52->p_fifo->b_error = 1;
|
||||
p_dec->p_fifo->b_error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If b_error is set, the decoder thread enters the error loop */
|
||||
if( p_a52->p_fifo->b_error )
|
||||
if( p_dec->p_fifo->b_error )
|
||||
{
|
||||
DecoderError( p_a52->p_fifo );
|
||||
DecoderError( p_dec->p_fifo );
|
||||
}
|
||||
|
||||
/* End of the liba52 decoder thread */
|
||||
EndThread( p_a52 );
|
||||
/* End of the a52 decoder thread */
|
||||
EndThread( p_dec );
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -210,28 +236,28 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
|
||||
/*****************************************************************************
|
||||
* InitThread: initialize data before entering main loop
|
||||
*****************************************************************************/
|
||||
static int InitThread( a52_thread_t * p_a52, decoder_fifo_t * p_fifo )
|
||||
static int InitThread( a52_thread_t * p_dec, decoder_fifo_t * p_fifo )
|
||||
{
|
||||
/* Initialize the thread properties */
|
||||
p_a52->p_aout = NULL;
|
||||
p_a52->p_aout_input = NULL;
|
||||
p_a52->p_fifo = p_fifo;
|
||||
p_a52->output_format.i_format = AOUT_FMT_FLOAT32;
|
||||
p_a52->output_format.i_channels = 2; /* FIXME ! */
|
||||
p_a52->last_date = 0;
|
||||
p_dec->p_aout = NULL;
|
||||
p_dec->p_aout_input = NULL;
|
||||
p_dec->p_fifo = p_fifo;
|
||||
p_dec->output_format.i_format = AOUT_FMT_FLOAT32;
|
||||
p_dec->output_format.i_channels = 2; /* FIXME ! */
|
||||
p_dec->last_date = 0;
|
||||
|
||||
/* Initialize liba52 */
|
||||
p_a52->p_a52_state = a52_init( 0 );
|
||||
if( p_a52->p_a52_state == NULL )
|
||||
p_dec->p_a52_state = a52_init( 0 );
|
||||
if( p_dec->p_a52_state == NULL )
|
||||
{
|
||||
msg_Err( p_a52->p_fifo, "unable to initialize liba52" );
|
||||
msg_Err( p_dec->p_fifo, "unable to initialize liba52" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
p_a52->b_dynrng = config_GetInt( p_a52->p_fifo, "a52-dynrng" );
|
||||
p_dec->b_dynrng = config_GetInt( p_dec->p_fifo, "a52-dynrng" );
|
||||
|
||||
/* Init the BitStream */
|
||||
InitBitstream( &p_a52->bit_stream, p_a52->p_fifo,
|
||||
/* Init the Bitstream */
|
||||
InitBitstream( &p_dec->bit_stream, p_dec->p_fifo,
|
||||
NULL, NULL );
|
||||
|
||||
return 0;
|
||||
@ -240,7 +266,7 @@ static int InitThread( a52_thread_t * p_a52, decoder_fifo_t * p_fifo )
|
||||
/*****************************************************************************
|
||||
* Interleave: helper function to interleave channels
|
||||
*****************************************************************************/
|
||||
static void Interleave( float * p_out, float * p_in, int i_channels )
|
||||
static void Interleave( float * p_out, const float * p_in, int i_channels )
|
||||
{
|
||||
int i, j;
|
||||
|
||||
@ -256,57 +282,57 @@ static void Interleave( float * p_out, float * p_in, int i_channels )
|
||||
/*****************************************************************************
|
||||
* DecodeFrame: decode an ATSC A/52 frame.
|
||||
*****************************************************************************/
|
||||
static int DecodeFrame( a52_thread_t * p_a52, u8 * p_frame_buffer )
|
||||
static int DecodeFrame( a52_thread_t * p_dec, const byte_t * p_frame_buffer )
|
||||
{
|
||||
sample_t i_sample_level = 1;
|
||||
aout_buffer_t * p_buffer;
|
||||
int i, i_flags;
|
||||
int i_bytes_per_block = 256 * p_a52->output_format.i_channels
|
||||
int i_bytes_per_block = 256 * p_dec->output_format.i_channels
|
||||
* sizeof(float);
|
||||
|
||||
if( !p_a52->last_date )
|
||||
if( !p_dec->last_date )
|
||||
{
|
||||
/* We've just started the stream, wait for the first PTS. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
p_buffer = aout_BufferNew( p_a52->p_aout, p_a52->p_aout_input,
|
||||
A52DEC_FRAME_SIZE );
|
||||
p_buffer = aout_BufferNew( p_dec->p_aout, p_dec->p_aout_input,
|
||||
A52_FRAME_SIZE );
|
||||
if ( p_buffer == NULL ) return -1;
|
||||
p_buffer->start_date = p_a52->last_date;
|
||||
p_a52->last_date += (mtime_t)(A52DEC_FRAME_SIZE * 1000000)
|
||||
/ p_a52->output_format.i_rate;
|
||||
p_buffer->end_date = p_a52->last_date;
|
||||
p_buffer->start_date = p_dec->last_date;
|
||||
p_dec->last_date += (mtime_t)(A52_FRAME_SIZE * 1000000)
|
||||
/ p_dec->output_format.i_rate;
|
||||
p_buffer->end_date = p_dec->last_date;
|
||||
|
||||
/* FIXME */
|
||||
i_flags = A52_STEREO | A52_ADJUST_LEVEL;
|
||||
|
||||
/* Do the actual decoding now */
|
||||
a52_frame( p_a52->p_a52_state, p_frame_buffer,
|
||||
a52_frame( p_dec->p_a52_state, p_frame_buffer,
|
||||
&i_flags, &i_sample_level, 0 );
|
||||
|
||||
if( !p_a52->b_dynrng )
|
||||
if( !p_dec->b_dynrng )
|
||||
{
|
||||
a52_dynrng( p_a52->p_a52_state, NULL, NULL );
|
||||
a52_dynrng( p_dec->p_a52_state, NULL, NULL );
|
||||
}
|
||||
|
||||
for ( i = 0; i < 6; i++ )
|
||||
{
|
||||
sample_t * p_samples;
|
||||
|
||||
if( a52_block( p_a52->p_a52_state ) )
|
||||
if( a52_block( p_dec->p_a52_state ) )
|
||||
{
|
||||
msg_Warn( p_a52->p_fifo, "a52_block failed for block %i", i );
|
||||
msg_Warn( p_dec->p_fifo, "a52_block failed for block %i", i );
|
||||
}
|
||||
|
||||
p_samples = a52_samples( p_a52->p_a52_state );
|
||||
p_samples = a52_samples( p_dec->p_a52_state );
|
||||
|
||||
/* Interleave the *$£%ù samples */
|
||||
Interleave( (float *)(p_buffer->p_buffer + i * i_bytes_per_block),
|
||||
p_samples, p_a52->output_format.i_channels );
|
||||
p_samples, p_dec->output_format.i_channels );
|
||||
}
|
||||
|
||||
aout_BufferPlay( p_a52->p_aout, p_a52->p_aout_input, p_buffer );
|
||||
aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer );
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -314,14 +340,14 @@ static int DecodeFrame( a52_thread_t * p_a52, u8 * p_frame_buffer )
|
||||
/*****************************************************************************
|
||||
* EndThread : liba52 decoder thread destruction
|
||||
*****************************************************************************/
|
||||
static void EndThread (a52_thread_t *p_a52)
|
||||
static void EndThread( a52_thread_t * p_dec )
|
||||
{
|
||||
if ( p_a52->p_aout_input != NULL )
|
||||
if ( p_dec->p_aout_input != NULL )
|
||||
{
|
||||
aout_InputDelete( p_a52->p_aout, p_a52->p_aout_input );
|
||||
aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
|
||||
}
|
||||
|
||||
a52_free( p_a52->p_a52_state );
|
||||
free( p_a52 );
|
||||
a52_free( p_dec->p_a52_state );
|
||||
free( p_dec );
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
a52_SOURCES = a52.c
|
@ -1,53 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* a52.h: ATSC A/52 aka AC-3 decoder plugin for vlc.
|
||||
* This plugin makes use of liba52 to decode A/52 audio
|
||||
* (http://liba52.sf.net/).
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: a52.h,v 1.2 2002/08/07 21:36:56 massiot Exp $
|
||||
*
|
||||
* Authors: Gildas Bazin <gbazin@netcourrier.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* a52_thread_t : a52 decoder thread descriptor
|
||||
*****************************************************************************/
|
||||
typedef struct a52_thread_s
|
||||
{
|
||||
/*
|
||||
* liba52 properties
|
||||
*/
|
||||
a52_state_t * p_a52_state;
|
||||
vlc_bool_t b_dynrng;
|
||||
|
||||
/* The bit stream structure handles the PES stream at the bit level */
|
||||
bit_stream_t bit_stream;
|
||||
|
||||
/*
|
||||
* Input properties
|
||||
*/
|
||||
decoder_fifo_t * p_fifo; /* stores the PES stream data */
|
||||
data_packet_t * p_data;
|
||||
|
||||
/*
|
||||
* Output properties
|
||||
*/
|
||||
aout_instance_t * p_aout; /* opaque */
|
||||
aout_input_t * p_aout_input; /* opaque */
|
||||
audio_sample_format_t output_format;
|
||||
mtime_t last_date;
|
||||
} a52_thread_t;
|
382
modules/codec/spdif.c
Normal file
382
modules/codec/spdif.c
Normal file
@ -0,0 +1,382 @@
|
||||
/*****************************************************************************
|
||||
* spdif.c: A52 pass-through to external decoder with enabled soundcard
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001-2002 VideoLAN
|
||||
* $Id: spdif.c,v 1.1 2002/08/11 01:27:01 massiot Exp $
|
||||
*
|
||||
* Authors: Stéphane Borel <stef@via.ecp.fr>
|
||||
* Juha Yrjola <jyrjola@cc.hut.fi>
|
||||
* German Gomez Garcia <german@piraos.com>
|
||||
* Christophe Massiot <massiot@via.ecp.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* memcpy() */
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/decoder.h>
|
||||
#include <vlc/aout.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define A52_FRAME_SIZE 1536
|
||||
|
||||
/*****************************************************************************
|
||||
* spdif_thread_t : A52 pass-through thread descriptor
|
||||
*****************************************************************************/
|
||||
typedef struct spdif_thread_s
|
||||
{
|
||||
/*
|
||||
* Thread properties
|
||||
*/
|
||||
vlc_thread_t thread_id; /* id for thread functions */
|
||||
|
||||
/*
|
||||
* Input properties
|
||||
*/
|
||||
decoder_fifo_t * p_fifo; /* stores the PES stream data */
|
||||
|
||||
/* The bit stream structure handles the PES stream at the bit level */
|
||||
bit_stream_t bit_stream;
|
||||
|
||||
/*
|
||||
* Output properties
|
||||
*/
|
||||
aout_instance_t * p_aout; /* opaque */
|
||||
aout_input_t * p_aout_input; /* opaque */
|
||||
audio_sample_format_t output_format;
|
||||
} spdif_thread_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Local prototypes
|
||||
****************************************************************************/
|
||||
static int OpenDecoder ( vlc_object_t * );
|
||||
static int RunDecoder ( decoder_fifo_t * );
|
||||
|
||||
static int InitThread ( spdif_thread_t *, decoder_fifo_t * );
|
||||
static void EndThread ( spdif_thread_t * );
|
||||
|
||||
int SyncInfo ( const byte_t *, int *, int *, int * );
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
set_description( _("SPDIF pass-through A52 decoder") );
|
||||
set_capability( "decoder", 0 );
|
||||
set_callbacks( OpenDecoder, NULL );
|
||||
add_shortcut( "pass_through" );
|
||||
add_shortcut( "pass" );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* OpenDecoder: probe the decoder and return score
|
||||
*****************************************************************************
|
||||
* Tries to launch a decoder and return score so that the interface is able
|
||||
* to chose.
|
||||
*****************************************************************************/
|
||||
static int OpenDecoder( vlc_object_t *p_this )
|
||||
{
|
||||
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
|
||||
|
||||
if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') )
|
||||
{
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
p_fifo->pf_run = RunDecoder;
|
||||
return VLC_SUCCESS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* RunDecoder: the whole thing
|
||||
****************************************************************************
|
||||
* This function is called just after the thread is launched.
|
||||
****************************************************************************/
|
||||
static int RunDecoder( decoder_fifo_t *p_fifo )
|
||||
{
|
||||
spdif_thread_t * p_dec;
|
||||
mtime_t last_date = 0;
|
||||
|
||||
/* Allocate the memory needed to store the thread's structure */
|
||||
p_dec = malloc( sizeof(spdif_thread_t) );
|
||||
if( p_dec == NULL )
|
||||
{
|
||||
msg_Err( p_fifo, "out of memory" );
|
||||
DecoderError( p_fifo );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( InitThread( p_dec, p_fifo ) )
|
||||
{
|
||||
|
||||
msg_Err( p_fifo, "could not initialize thread" );
|
||||
DecoderError( p_fifo );
|
||||
free( p_dec );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* liba52 decoder thread's main loop */
|
||||
while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
|
||||
{
|
||||
int i_frame_size, i_flags, i_rate, i_bit_rate;
|
||||
mtime_t pts;
|
||||
/* Temporary buffer to store the raw frame to be decoded */
|
||||
byte_t p_header[7];
|
||||
aout_buffer_t * p_buffer;
|
||||
|
||||
/* Look for sync word - should be 0x0b77 */
|
||||
RealignBits( &p_dec->bit_stream );
|
||||
while( (ShowBits( &p_dec->bit_stream, 16 ) ) != 0x0b77 &&
|
||||
(!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error))
|
||||
{
|
||||
RemoveBits( &p_dec->bit_stream, 8 );
|
||||
}
|
||||
|
||||
/* Get A/52 frame header */
|
||||
GetChunk( &p_dec->bit_stream, p_header, 7 );
|
||||
if( p_dec->p_fifo->b_die ) break;
|
||||
|
||||
/* Check if frame is valid and get frame info */
|
||||
i_frame_size = SyncInfo( p_header, &i_flags, &i_rate,
|
||||
&i_bit_rate );
|
||||
|
||||
if( !i_frame_size )
|
||||
{
|
||||
msg_Warn( p_dec->p_fifo, "a52_syncinfo failed" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( (p_dec->p_aout_input != NULL) &&
|
||||
( (p_dec->output_format.i_rate != i_rate) ) )
|
||||
{
|
||||
/* Parameters changed - this should not happen. */
|
||||
aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
|
||||
p_dec->p_aout_input = NULL;
|
||||
}
|
||||
|
||||
/* Creating the audio input if not created yet. */
|
||||
if( p_dec->p_aout_input == NULL )
|
||||
{
|
||||
p_dec->output_format.i_rate = i_rate;
|
||||
/* p_dec->output_format.i_channels = i_channels; */
|
||||
p_dec->p_aout_input = aout_InputNew( p_dec->p_fifo,
|
||||
&p_dec->p_aout,
|
||||
&p_dec->output_format );
|
||||
|
||||
if ( p_dec->p_aout_input == NULL )
|
||||
{
|
||||
p_dec->p_fifo->b_error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the Presentation Time Stamp */
|
||||
CurrentPTS( &p_dec->bit_stream, &pts, NULL );
|
||||
if ( pts != 0 )
|
||||
{
|
||||
last_date = pts;
|
||||
}
|
||||
|
||||
if ( !last_date )
|
||||
{
|
||||
byte_t p_junk[3840];
|
||||
|
||||
/* We've just started the stream, wait for the first PTS. */
|
||||
GetChunk( &p_dec->bit_stream, p_junk, i_frame_size - 7 );
|
||||
continue;
|
||||
}
|
||||
|
||||
p_buffer = aout_BufferNew( p_dec->p_aout, p_dec->p_aout_input, 1 );
|
||||
if ( p_buffer == NULL ) return -1;
|
||||
p_buffer->start_date = last_date;
|
||||
last_date += (mtime_t)(A52_FRAME_SIZE * 1000000)
|
||||
/ p_dec->output_format.i_rate;
|
||||
p_buffer->end_date = last_date;
|
||||
|
||||
/* Get the whole frame. */
|
||||
memcpy( p_buffer->p_buffer, p_header, 7 );
|
||||
GetChunk( &p_dec->bit_stream, p_buffer->p_buffer + 7,
|
||||
i_frame_size - 7 );
|
||||
if( p_dec->p_fifo->b_die ) break;
|
||||
|
||||
/* Send the buffer to the mixer. */
|
||||
aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer );
|
||||
}
|
||||
|
||||
/* If b_error is set, the spdif thread enters the error loop */
|
||||
if( p_dec->p_fifo->b_error )
|
||||
{
|
||||
DecoderError( p_dec->p_fifo );
|
||||
}
|
||||
|
||||
/* End of the spdif decoder thread */
|
||||
EndThread( p_dec );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* InitThread: initialize thread data and create output fifo
|
||||
****************************************************************************/
|
||||
static int InitThread( spdif_thread_t * p_dec, decoder_fifo_t * p_fifo )
|
||||
{
|
||||
/* Initialize the thread properties */
|
||||
p_dec->p_aout = NULL;
|
||||
p_dec->p_aout_input = NULL;
|
||||
p_dec->p_fifo = p_fifo;
|
||||
p_dec->output_format.i_format = AOUT_FMT_A52;
|
||||
p_dec->output_format.i_channels = -1;
|
||||
|
||||
/* Init the Bitstream */
|
||||
InitBitstream( &p_dec->bit_stream, p_dec->p_fifo,
|
||||
NULL, NULL );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* EndThread : spdif thread destruction
|
||||
*****************************************************************************/
|
||||
static void EndThread( spdif_thread_t * p_dec )
|
||||
{
|
||||
if ( p_dec->p_aout_input != NULL )
|
||||
{
|
||||
aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
|
||||
}
|
||||
|
||||
free( p_dec );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Local structures and tables
|
||||
****************************************************************************/
|
||||
typedef struct sync_frame_s
|
||||
{
|
||||
struct syncinfo
|
||||
{
|
||||
u8 syncword[2];
|
||||
u8 crc1[2];
|
||||
u8 code;
|
||||
} syncinfo;
|
||||
|
||||
struct bsi
|
||||
{
|
||||
u8 bsidmod;
|
||||
u8 acmod;
|
||||
} bsi;
|
||||
} sync_frame_t;
|
||||
|
||||
typedef struct frame_size_s
|
||||
{
|
||||
u16 i_bit_rate;
|
||||
u16 i_frame_size[3];
|
||||
} frame_size_t;
|
||||
|
||||
typedef struct info_s
|
||||
{
|
||||
int i_bit_rate;
|
||||
int i_frame_size;
|
||||
int i_sample_rate;
|
||||
int i_bs_mod;
|
||||
} info_t;
|
||||
|
||||
static const frame_size_t p_frame_size_code[64] =
|
||||
{
|
||||
{ 32 ,{64 ,69 ,96 } },
|
||||
{ 32 ,{64 ,70 ,96 } },
|
||||
{ 40 ,{80 ,87 ,120 } },
|
||||
{ 40 ,{80 ,88 ,120 } },
|
||||
{ 48 ,{96 ,104 ,144 } },
|
||||
{ 48 ,{96 ,105 ,144 } },
|
||||
{ 56 ,{112 ,121 ,168 } },
|
||||
{ 56 ,{112 ,122 ,168 } },
|
||||
{ 64 ,{128 ,139 ,192 } },
|
||||
{ 64 ,{128 ,140 ,192 } },
|
||||
{ 80 ,{160 ,174 ,240 } },
|
||||
{ 80 ,{160 ,175 ,240 } },
|
||||
{ 96 ,{192 ,208 ,288 } },
|
||||
{ 96 ,{192 ,209 ,288 } },
|
||||
{ 112 ,{224 ,243 ,336 } },
|
||||
{ 112 ,{224 ,244 ,336 } },
|
||||
{ 128 ,{256 ,278 ,384 } },
|
||||
{ 128 ,{256 ,279 ,384 } },
|
||||
{ 160 ,{320 ,348 ,480 } },
|
||||
{ 160 ,{320 ,349 ,480 } },
|
||||
{ 192 ,{384 ,417 ,576 } },
|
||||
{ 192 ,{384 ,418 ,576 } },
|
||||
{ 224 ,{448 ,487 ,672 } },
|
||||
{ 224 ,{448 ,488 ,672 } },
|
||||
{ 256 ,{512 ,557 ,768 } },
|
||||
{ 256 ,{512 ,558 ,768 } },
|
||||
{ 320 ,{640 ,696 ,960 } },
|
||||
{ 320 ,{640 ,697 ,960 } },
|
||||
{ 384 ,{768 ,835 ,1152 } },
|
||||
{ 384 ,{768 ,836 ,1152 } },
|
||||
{ 448 ,{896 ,975 ,1344 } },
|
||||
{ 448 ,{896 ,976 ,1344 } },
|
||||
{ 512 ,{1024 ,1114 ,1536 } },
|
||||
{ 512 ,{1024 ,1115 ,1536 } },
|
||||
{ 576 ,{1152 ,1253 ,1728 } },
|
||||
{ 576 ,{1152 ,1254 ,1728 } },
|
||||
{ 640 ,{1280 ,1393 ,1920 } },
|
||||
{ 640 ,{1280 ,1394 ,1920 } }
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* SyncInfo: parse A52 sync info
|
||||
****************************************************************************
|
||||
* NB : i_flags is unused, this is just to mimick liba52's a52_syncinfo
|
||||
* Returns the frame size
|
||||
****************************************************************************/
|
||||
static int SyncInfo( const byte_t * p_buffer, int * pi_flags, int * pi_rate,
|
||||
int * pi_bitrate )
|
||||
{
|
||||
static const int p_sample_rates[4] = { 48000, 44100, 32000, -1 };
|
||||
int i_frame_rate_code;
|
||||
int i_frame_size_code;
|
||||
const sync_frame_t * p_sync_frame;
|
||||
|
||||
p_sync_frame = (const sync_frame_t *)p_buffer;
|
||||
|
||||
/* Compute frame rate */
|
||||
i_frame_rate_code = (p_sync_frame->syncinfo.code >> 6) & 0x03;
|
||||
*pi_rate = p_sample_rates[i_frame_rate_code];
|
||||
if ( *pi_rate == -1 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( ( ( p_sync_frame->bsi.bsidmod >> 3 ) & 0x1f ) != 0x08 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute frame size */
|
||||
i_frame_size_code = p_sync_frame->syncinfo.code & 0x3f;
|
||||
*pi_bitrate = p_frame_size_code[i_frame_size_code].i_bit_rate;
|
||||
|
||||
return ( 2 * p_frame_size_code[i_frame_size_code]
|
||||
.i_frame_size[i_frame_rate_code] );
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
@ -1,431 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* spdif.c: A52 pass-through to external decoder with enabled soundcard
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: spdif.c,v 1.2 2002/08/08 00:35:11 sam Exp $
|
||||
*
|
||||
* Authors: Stéphane Borel <stef@via.ecp.fr>
|
||||
* Juha Yrjola <jyrjola@cc.hut.fi>
|
||||
* German Gomez Garcia <german@piraos.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* memcpy() */
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/decoder.h>
|
||||
#include <vlc/aout.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "spdif.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Local prototypes
|
||||
****************************************************************************/
|
||||
static int OpenDecoder ( vlc_object_t * );
|
||||
static int RunDecoder ( decoder_fifo_t * );
|
||||
|
||||
static int InitThread ( spdif_thread_t * );
|
||||
static void EndThread ( spdif_thread_t * );
|
||||
static void BitstreamCallback ( bit_stream_t *, vlc_bool_t );
|
||||
|
||||
int parse_syncinfo ( spdif_thread_t * );
|
||||
|
||||
/****************************************************************************
|
||||
* Local structures and tables
|
||||
****************************************************************************/
|
||||
static const frame_size_t p_frame_size_code[64] =
|
||||
{
|
||||
{ 32 ,{64 ,69 ,96 } },
|
||||
{ 32 ,{64 ,70 ,96 } },
|
||||
{ 40 ,{80 ,87 ,120 } },
|
||||
{ 40 ,{80 ,88 ,120 } },
|
||||
{ 48 ,{96 ,104 ,144 } },
|
||||
{ 48 ,{96 ,105 ,144 } },
|
||||
{ 56 ,{112 ,121 ,168 } },
|
||||
{ 56 ,{112 ,122 ,168 } },
|
||||
{ 64 ,{128 ,139 ,192 } },
|
||||
{ 64 ,{128 ,140 ,192 } },
|
||||
{ 80 ,{160 ,174 ,240 } },
|
||||
{ 80 ,{160 ,175 ,240 } },
|
||||
{ 96 ,{192 ,208 ,288 } },
|
||||
{ 96 ,{192 ,209 ,288 } },
|
||||
{ 112 ,{224 ,243 ,336 } },
|
||||
{ 112 ,{224 ,244 ,336 } },
|
||||
{ 128 ,{256 ,278 ,384 } },
|
||||
{ 128 ,{256 ,279 ,384 } },
|
||||
{ 160 ,{320 ,348 ,480 } },
|
||||
{ 160 ,{320 ,349 ,480 } },
|
||||
{ 192 ,{384 ,417 ,576 } },
|
||||
{ 192 ,{384 ,418 ,576 } },
|
||||
{ 224 ,{448 ,487 ,672 } },
|
||||
{ 224 ,{448 ,488 ,672 } },
|
||||
{ 256 ,{512 ,557 ,768 } },
|
||||
{ 256 ,{512 ,558 ,768 } },
|
||||
{ 320 ,{640 ,696 ,960 } },
|
||||
{ 320 ,{640 ,697 ,960 } },
|
||||
{ 384 ,{768 ,835 ,1152 } },
|
||||
{ 384 ,{768 ,836 ,1152 } },
|
||||
{ 448 ,{896 ,975 ,1344 } },
|
||||
{ 448 ,{896 ,976 ,1344 } },
|
||||
{ 512 ,{1024 ,1114 ,1536 } },
|
||||
{ 512 ,{1024 ,1115 ,1536 } },
|
||||
{ 576 ,{1152 ,1253 ,1728 } },
|
||||
{ 576 ,{1152 ,1254 ,1728 } },
|
||||
{ 640 ,{1280 ,1393 ,1920 } },
|
||||
{ 640 ,{1280 ,1394 ,1920 } }
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
set_description( _("SPDIF pass-through A52 decoder") );
|
||||
set_capability( "decoder", 0 );
|
||||
set_callbacks( OpenDecoder, NULL );
|
||||
add_shortcut( "pass_through" );
|
||||
add_shortcut( "pass" );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* OpenDecoder: probe the decoder and return score
|
||||
*****************************************************************************
|
||||
* Tries to launch a decoder and return score so that the interface is able
|
||||
* to chose.
|
||||
*****************************************************************************/
|
||||
static int OpenDecoder( vlc_object_t *p_this )
|
||||
{
|
||||
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
|
||||
|
||||
if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') )
|
||||
{
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
p_fifo->pf_run = RunDecoder;
|
||||
return VLC_SUCCESS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* RunDecoder: the whole thing
|
||||
****************************************************************************
|
||||
* This function is called just after the thread is launched.
|
||||
****************************************************************************/
|
||||
static int RunDecoder( decoder_fifo_t *p_fifo )
|
||||
{
|
||||
spdif_thread_t * p_spdif;
|
||||
mtime_t i_frame_time;
|
||||
vlc_bool_t b_sync;
|
||||
/* PTS of the current frame */
|
||||
mtime_t i_current_pts = 0;
|
||||
u16 i_length;
|
||||
|
||||
/* Allocate the memory needed to store the thread's structure */
|
||||
p_spdif = malloc( sizeof(spdif_thread_t) );
|
||||
|
||||
if( p_spdif == NULL )
|
||||
{
|
||||
msg_Err( p_fifo, "out of memory" );
|
||||
DecoderError( p_fifo );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
p_spdif->p_fifo = p_fifo;
|
||||
|
||||
if (InitThread( p_spdif ) )
|
||||
{
|
||||
|
||||
if( p_fifo->b_error )
|
||||
{
|
||||
msg_Err( p_fifo, "could not initialize thread" );
|
||||
}
|
||||
|
||||
DecoderError( p_fifo );
|
||||
free( p_spdif );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Compute the theorical duration of an A52 frame */
|
||||
i_frame_time = 1000000 * A52_FRAME_SIZE /
|
||||
p_spdif->info.i_sample_rate;
|
||||
i_length = p_spdif->info.i_frame_size;
|
||||
|
||||
while( !p_spdif->p_fifo->b_die && !p_spdif->p_fifo->b_error )
|
||||
{
|
||||
p_spdif->p_bytes[0] = 0x0b;
|
||||
p_spdif->p_bytes[1] = 0x77;
|
||||
|
||||
/* Handle the dates */
|
||||
if( p_spdif->i_real_pts )
|
||||
{
|
||||
mtime_t i_delta = p_spdif->i_real_pts - i_current_pts -
|
||||
i_frame_time;
|
||||
if( i_delta > i_frame_time || i_delta < -i_frame_time )
|
||||
{
|
||||
msg_Warn( p_fifo,
|
||||
"date discontinuity (%d)", i_delta );
|
||||
}
|
||||
i_current_pts = p_spdif->i_real_pts;
|
||||
p_spdif->i_real_pts = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
i_current_pts += i_frame_time;
|
||||
}
|
||||
|
||||
/* wait a little to avoid an input flood from the a52 input */
|
||||
mwait( i_current_pts - 500000 );
|
||||
|
||||
vlc_mutex_lock (&p_spdif->p_aout_fifo->data_lock);
|
||||
|
||||
p_spdif->p_aout_fifo->date[p_spdif->p_aout_fifo->i_end_frame] =
|
||||
i_current_pts;
|
||||
|
||||
p_spdif->p_aout_fifo->i_end_frame =
|
||||
(p_spdif->p_aout_fifo->i_end_frame + 1 ) & AOUT_FIFO_SIZE;
|
||||
|
||||
p_spdif->p_bytes = ((u8*)(p_spdif->p_aout_fifo->buffer)) +
|
||||
(p_spdif->p_aout_fifo->i_end_frame * i_length );
|
||||
|
||||
vlc_mutex_unlock (&p_spdif->p_aout_fifo->data_lock);
|
||||
|
||||
/* Find syncword again in case of stream discontinuity */
|
||||
/* Here we have p_spdif->i_pts == 0
|
||||
* Therefore a non-zero value after a call to GetBits() means the PES
|
||||
* has changed. */
|
||||
b_sync = 0;
|
||||
while( !p_spdif->p_fifo->b_die
|
||||
&& !p_spdif->p_fifo->b_error
|
||||
&& !b_sync )
|
||||
{
|
||||
while( !p_spdif->p_fifo->b_die
|
||||
&& !p_spdif->p_fifo->b_error
|
||||
&& GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
|
||||
p_spdif->i_real_pts = p_spdif->i_pts;
|
||||
p_spdif->i_pts = 0;
|
||||
b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
|
||||
}
|
||||
RemoveBits( &p_spdif->bit_stream, 8 );
|
||||
|
||||
/* Read data from bitstream */
|
||||
GetChunk( &p_spdif->bit_stream, p_spdif->p_bytes + 2, i_length - 2 );
|
||||
}
|
||||
|
||||
/* If b_error is set, the spdif thread enters the error loop */
|
||||
if( p_spdif->p_fifo->b_error )
|
||||
{
|
||||
DecoderError( p_spdif->p_fifo );
|
||||
}
|
||||
|
||||
/* End of the spdif decoder thread */
|
||||
EndThread( p_spdif );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* InitThread: initialize thread data and create output fifo
|
||||
****************************************************************************/
|
||||
static int InitThread( spdif_thread_t * p_spdif )
|
||||
{
|
||||
vlc_bool_t b_sync = 0;
|
||||
|
||||
/* Temporary buffer to store first A52 frame */
|
||||
p_spdif->p_bytes = malloc( SPDIF_FRAME_SIZE );
|
||||
|
||||
if( p_spdif->p_bytes == NULL )
|
||||
{
|
||||
free( p_spdif->p_bytes );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the thread properties
|
||||
*/
|
||||
p_spdif->p_fifo = p_spdif->p_fifo;
|
||||
|
||||
InitBitstream( &p_spdif->bit_stream, p_spdif->p_fifo,
|
||||
BitstreamCallback, (void*)p_spdif );
|
||||
|
||||
/* Find syncword */
|
||||
while( !p_spdif->p_fifo->b_die
|
||||
&& !p_spdif->p_fifo->b_error
|
||||
&& !b_sync )
|
||||
{
|
||||
while( !p_spdif->p_fifo->b_die
|
||||
&& !p_spdif->p_fifo->b_error
|
||||
&& GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
|
||||
p_spdif->i_real_pts = p_spdif->i_pts;
|
||||
p_spdif->i_pts = 0;
|
||||
b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
|
||||
}
|
||||
|
||||
if( p_spdif->p_fifo->b_die || p_spdif->p_fifo->b_error )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
RemoveBits( &p_spdif->bit_stream, 8 );
|
||||
|
||||
/* Check stream properties */
|
||||
if( parse_syncinfo( p_spdif ) < 0 )
|
||||
{
|
||||
msg_Err( p_spdif->p_fifo, "stream not valid" );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Check that we can handle the rate
|
||||
* FIXME: we should check that we have the same rate for all fifos
|
||||
* but all rates should be supported by the decoder (32, 44.1, 48) */
|
||||
if( p_spdif->info.i_sample_rate != 48000 )
|
||||
{
|
||||
msg_Err( p_spdif->p_fifo,
|
||||
"only 48000 Hz streams tested, expect weird things!" );
|
||||
}
|
||||
|
||||
/* The audio output need to be ready for an A52 stream */
|
||||
p_spdif->i_previous_format = config_GetInt( p_spdif->p_fifo,
|
||||
"audio-format" );
|
||||
config_PutInt( p_spdif->p_fifo, "audio-format", 8 );
|
||||
|
||||
/* Creating the audio output fifo */
|
||||
p_spdif->p_aout_fifo =
|
||||
aout_CreateFifo( p_spdif->p_fifo, AOUT_FIFO_SPDIF,
|
||||
1, p_spdif->info.i_sample_rate,
|
||||
p_spdif->info.i_frame_size, NULL );
|
||||
|
||||
if( p_spdif->p_aout_fifo == NULL )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
msg_Dbg( p_spdif->p_fifo, "aout fifo #%d created",
|
||||
p_spdif->p_aout_fifo->i_fifo );
|
||||
|
||||
/* Put read data into fifo */
|
||||
memcpy( (u8*)(p_spdif->p_aout_fifo->buffer) +
|
||||
(p_spdif->p_aout_fifo->i_end_frame *
|
||||
p_spdif->info.i_frame_size ),
|
||||
p_spdif->p_bytes, sizeof(sync_frame_t) );
|
||||
free( p_spdif->p_bytes );
|
||||
p_spdif->p_bytes = ((u8*)(p_spdif->p_aout_fifo->buffer) +
|
||||
(p_spdif->p_aout_fifo->i_end_frame *
|
||||
p_spdif->info.i_frame_size ));
|
||||
|
||||
GetChunk( &p_spdif->bit_stream, p_spdif->p_bytes + sizeof(sync_frame_t),
|
||||
p_spdif->info.i_frame_size - sizeof(sync_frame_t) );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* EndThread : spdif thread destruction
|
||||
*****************************************************************************/
|
||||
static void EndThread( spdif_thread_t * p_spdif )
|
||||
{
|
||||
/* If the audio output fifo was created, we destroy it */
|
||||
if( p_spdif->p_aout_fifo != NULL )
|
||||
{
|
||||
aout_DestroyFifo( p_spdif->p_aout_fifo );
|
||||
|
||||
/* Make sure the output thread leaves the NextFrame() function */
|
||||
vlc_mutex_lock( &(p_spdif->p_aout_fifo->data_lock ) );
|
||||
vlc_cond_signal( &(p_spdif->p_aout_fifo->data_wait ) );
|
||||
vlc_mutex_unlock( &(p_spdif->p_aout_fifo->data_lock ) );
|
||||
|
||||
}
|
||||
|
||||
/* restore previous setting for output format */
|
||||
config_PutInt( p_spdif->p_fifo, "audio-format",
|
||||
p_spdif->i_previous_format );
|
||||
|
||||
/* Destroy descriptor */
|
||||
free( p_spdif );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* BitstreamCallback: Import parameters from the new data/PES packet
|
||||
*****************************************************************************
|
||||
* This function is called by input's NextDataPacket.
|
||||
*****************************************************************************/
|
||||
static void BitstreamCallback( bit_stream_t * p_bit_stream,
|
||||
vlc_bool_t b_new_pes )
|
||||
{
|
||||
spdif_thread_t * p_spdif;
|
||||
|
||||
if( b_new_pes )
|
||||
{
|
||||
p_spdif = (spdif_thread_t *)p_bit_stream->p_callback_arg;
|
||||
|
||||
/* p_bit_stream->p_byte += 3; */
|
||||
|
||||
p_spdif->i_pts =
|
||||
p_bit_stream->p_decoder_fifo->p_first->i_pts;
|
||||
p_bit_stream->p_decoder_fifo->p_first->i_pts = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* parse_syncinfo: parse A52 sync info
|
||||
****************************************************************************/
|
||||
int parse_syncinfo( spdif_thread_t *p_spdif )
|
||||
{
|
||||
int p_sample_rates[4] = { 48000, 44100, 32000, -1 };
|
||||
int i_frame_rate_code;
|
||||
int i_frame_size_code;
|
||||
sync_frame_t * p_sync_frame;
|
||||
|
||||
/* Read sync frame */
|
||||
GetChunk( &p_spdif->bit_stream, p_spdif->p_bytes + 2,
|
||||
sizeof(sync_frame_t) - 2 );
|
||||
if( p_spdif->p_fifo->b_die ) return -1;
|
||||
|
||||
p_sync_frame = (sync_frame_t*)p_spdif->p_bytes;
|
||||
|
||||
/* Compute frame rate */
|
||||
i_frame_rate_code = (p_sync_frame->syncinfo.code >> 6) & 0x03;
|
||||
p_spdif->info.i_sample_rate = p_sample_rates[i_frame_rate_code];
|
||||
if( p_spdif->info.i_sample_rate == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Compute frame size */
|
||||
i_frame_size_code = p_sync_frame->syncinfo.code & 0x3f;
|
||||
p_spdif->info.i_frame_size = 2 *
|
||||
p_frame_size_code[i_frame_size_code].i_frame_size[i_frame_rate_code];
|
||||
p_spdif->info.i_bit_rate =
|
||||
p_frame_size_code[i_frame_size_code].i_bit_rate;
|
||||
|
||||
if( ( ( p_sync_frame->bsi.bsidmod >> 3 ) & 0x1f ) != 0x08 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
p_spdif->info.i_bs_mod = p_sync_frame->bsi.bsidmod & 0x7;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* spdif.h: header for A52 pass-through
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: spdif.h,v 1.1 2002/08/04 17:23:42 sam Exp $
|
||||
*
|
||||
* Authors: Stéphane Borel <stef@via.ecp.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* information about A52 frame
|
||||
****************************************************************************/
|
||||
typedef struct sync_frame_s
|
||||
{
|
||||
struct syncinfo
|
||||
{
|
||||
u8 syncword[2];
|
||||
u8 crc1[2];
|
||||
u8 code;
|
||||
} syncinfo;
|
||||
|
||||
struct bsi
|
||||
{
|
||||
u8 bsidmod;
|
||||
u8 acmod;
|
||||
} bsi;
|
||||
} sync_frame_t;
|
||||
|
||||
typedef struct frame_size_s
|
||||
{
|
||||
u16 i_bit_rate;
|
||||
u16 i_frame_size[3];
|
||||
} frame_size_t;
|
||||
|
||||
typedef struct info_s
|
||||
{
|
||||
int i_bit_rate;
|
||||
int i_frame_size;
|
||||
int i_sample_rate;
|
||||
int i_bs_mod;
|
||||
} info_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* spdif_thread_t : A52 pass-through thread descriptor
|
||||
*****************************************************************************/
|
||||
typedef struct spdif_thread_s
|
||||
{
|
||||
/*
|
||||
* Thread properties
|
||||
*/
|
||||
vlc_thread_t thread_id; /* id for thread functions */
|
||||
|
||||
/*
|
||||
* Input properties
|
||||
*/
|
||||
decoder_fifo_t * p_fifo; /* stores the PES stream data */
|
||||
|
||||
/* The bit stream structure handles the PES stream at the bit level */
|
||||
bit_stream_t bit_stream;
|
||||
int i_available;
|
||||
|
||||
/*
|
||||
* Decoder properties
|
||||
*/
|
||||
info_t info;
|
||||
u8 * p_bytes;
|
||||
|
||||
/* current pes date */
|
||||
mtime_t i_pts;
|
||||
mtime_t i_real_pts;
|
||||
|
||||
/*
|
||||
* Output properties
|
||||
*/
|
||||
int i_previous_format;
|
||||
aout_fifo_t * p_aout_fifo; /* stores the decompressed audio frames */
|
||||
|
||||
} spdif_thread_t;
|
||||
|
@ -2,7 +2,7 @@
|
||||
* audio_output.c : audio output instance
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2002 VideoLAN
|
||||
* $Id: audio_output.c,v 1.91 2002/08/09 23:47:23 massiot Exp $
|
||||
* $Id: audio_output.c,v 1.92 2002/08/11 01:27:01 massiot Exp $
|
||||
*
|
||||
* Authors: Christophe Massiot <massiot@via.ecp.fr>
|
||||
*
|
||||
@ -137,6 +137,9 @@ void aout_BufferPlay( aout_instance_t * p_aout, aout_input_t * p_input,
|
||||
/ p_input->input.i_rate;
|
||||
}
|
||||
|
||||
/* If the buffer is too early, wait a while. */
|
||||
mwait( p_buffer->start_date - AOUT_MAX_PREPARE_TIME );
|
||||
|
||||
aout_InputPlay( p_aout, p_input, p_buffer );
|
||||
|
||||
/* Run the mixer if it is able to run. */
|
||||
|
Loading…
Reference in New Issue
Block a user