* Preamble
*****************************************************************************/
-#include <vlc/vlc.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
#include <vlc_codec.h>
#include <vlc_aout.h>
} stream_info;
#endif
- vlc_bool_t b_stream_info;
+ bool b_stream_info;
/*
* Common properties
*/
- audio_date_t end_date;
+ date_t end_date;
mtime_t i_pts;
int i_frame_size, i_frame_length, i_bits_per_sample;
STATE_SEND_DATA
};
-static int pi_channels_maps[7] =
+static const int pi_channels_maps[7] =
{
0,
AOUT_CHAN_CENTER,
void *client_data);
static void Interleave32( int32_t *p_out, const int32_t * const *pp_in,
- int i_nb_channels, int i_samples );
+ const int *pi_order, int i_nb_channels, int i_samples );
+static void Interleave24( int8_t *p_out, const int32_t * const *pp_in,
+ const int *pi_order, int i_nb_channels, int i_samples );
static void Interleave16( int16_t *p_out, const int32_t * const *pp_in,
- int i_nb_channels, int i_samples );
+ const int *pi_order, int i_nb_channels, int i_samples );
static void decoder_state_error( decoder_t *p_dec,
FLAC__StreamDecoderState state );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
-vlc_module_begin();
+vlc_module_begin ()
- set_category( CAT_INPUT );
- set_subcategory( SUBCAT_INPUT_ACODEC );
+ set_category( CAT_INPUT )
+ set_subcategory( SUBCAT_INPUT_ACODEC )
+ add_shortcut( "flac" )
#ifdef USE_LIBFLAC
- set_description( _("Flac audio decoder") );
- set_capability( "decoder", 100 );
- set_callbacks( OpenDecoder, CloseDecoder );
-
- add_submodule();
- set_description( _("Flac audio encoder") );
- set_capability( "encoder", 100 );
- set_callbacks( OpenEncoder, CloseEncoder );
-
- add_submodule();
+ set_description( N_("Flac audio decoder") )
+ set_capability( "decoder", 100 )
+ set_callbacks( OpenDecoder, CloseDecoder )
+
+ add_submodule ()
+ add_shortcut( "flac" )
+ set_description( N_("Flac audio encoder") )
+ set_capability( "encoder", 100 )
+ set_callbacks( OpenEncoder, CloseEncoder )
+
+ add_submodule ()
+ add_shortcut( "flac" )
#endif
- set_description( _("Flac audio packetizer") );
- set_capability( "packetizer", 100 );
- set_callbacks( OpenPacketizer, CloseDecoder );
+ set_description( N_("Flac audio packetizer") )
+ set_capability( "packetizer", 100 )
+ set_callbacks( OpenPacketizer, CloseDecoder )
- add_shortcut( "flac" );
-vlc_module_end();
+vlc_module_end ()
/*****************************************************************************
* OpenDecoder: probe the decoder and return score
decoder_t *p_dec = (decoder_t*)p_this;
decoder_sys_t *p_sys;
- if( p_dec->fmt_in.i_codec != VLC_FOURCC('f','l','a','c') )
+ if( p_dec->fmt_in.i_codec != VLC_CODEC_FLAC )
{
return VLC_EGENERIC;
}
/* Allocate the memory needed to store the decoder's structure */
- if( ( p_dec->p_sys = p_sys =
- (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
- {
- msg_Err( p_dec, "out of memory" );
- return VLC_EGENERIC;
- }
+ if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
+ return VLC_ENOMEM;
/* Misc init */
- aout_DateSet( &p_sys->end_date, 0 );
+ date_Set( &p_sys->end_date, 0 );
p_sys->i_state = STATE_NOSYNC;
- p_sys->b_stream_info = VLC_FALSE;
+ p_sys->b_stream_info = false;
p_sys->p_block=NULL;
- p_sys->bytestream = block_BytestreamInit( p_dec );
+ p_sys->bytestream = block_BytestreamInit();
#ifdef USE_LIBFLAC
/* Take care of flac init */
/* Set output properties */
p_dec->fmt_out.i_cat = AUDIO_ES;
- p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2');
+ p_dec->fmt_out.i_codec = VLC_CODEC_FL32;
/* Set callbacks */
#ifdef USE_LIBFLAC
p_dec->pf_packetize = PacketizeBlock;
/* Set output properties */
- p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','a','c');
+ p_dec->fmt_out.i_codec = VLC_CODEC_FLAC;
if( i_ret != VLC_SUCCESS )
{
FLAC__stream_decoder_delete( p_sys->p_flac );
#endif
- if( p_sys->p_block ) free( p_sys->p_block );
+ free( p_sys->p_block );
free( p_sys );
}
if( !p_sys->b_stream_info ) return;
- if( p_dec->fmt_out.i_codec == VLC_FOURCC('f','l','a','c') )
+ if( p_dec->fmt_out.i_codec == VLC_CODEC_FLAC )
{
p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
p_dec->fmt_out.p_extra =
if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
{
p_sys->i_state = STATE_NOSYNC;
- block_BytestreamFlush( &p_sys->bytestream );
+ block_BytestreamEmpty( &p_sys->bytestream );
}
-// aout_DateSet( &p_sys->end_date, 0 );
+ date_Set( &p_sys->end_date, 0 );
block_Release( *pp_block );
return NULL;
}
return NULL;
}
- if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
+ if( !date_Get( &p_sys->end_date ) && !(*pp_block)->i_pts )
{
/* We've just started the stream, wait for the first PTS. */
block_Release( *pp_block );
return NULL;
}
- else if( !aout_DateGet( &p_sys->end_date ) )
+ else if( !date_Get( &p_sys->end_date ) )
{
/* The first PTS is as good as anything else. */
- aout_DateSet( &p_sys->end_date, (*pp_block)->i_pts );
+ p_sys->i_rate = p_dec->fmt_out.audio.i_rate;
+ date_Init( &p_sys->end_date, p_sys->i_rate, 1 );
+ date_Set( &p_sys->end_date, (*pp_block)->i_pts );
}
block_BytestreamPush( &p_sys->bytestream, *pp_block );
/* New frame, set the Presentation Time Stamp */
p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
if( p_sys->i_pts != 0 &&
- p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
+ p_sys->i_pts != date_Get( &p_sys->end_date ) )
{
- aout_DateSet( &p_sys->end_date, p_sys->i_pts );
+ date_Set( &p_sys->end_date, p_sys->i_pts );
}
p_sys->i_state = STATE_HEADER;
if( p_sys->i_rate != p_dec->fmt_out.audio.i_rate )
{
p_dec->fmt_out.audio.i_rate = p_sys->i_rate;
- aout_DateInit( &p_sys->end_date, p_sys->i_rate );
+ date_Init( &p_sys->end_date, p_sys->i_rate, 1 );
}
p_sys->i_state = STATE_NEXT_SYNC;
p_sys->i_frame_size = 1;
/* Date management */
p_sout_block->i_pts =
- p_sout_block->i_dts = aout_DateGet( &p_sys->end_date );
- aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );
+ p_sout_block->i_dts = date_Get( &p_sys->end_date );
+ date_Increment( &p_sys->end_date, p_sys->i_frame_length );
p_sout_block->i_length =
- aout_DateGet( &p_sys->end_date ) - p_sout_block->i_pts;
+ date_Get( &p_sys->end_date ) - p_sout_block->i_pts;
return p_sout_block;
}
DecoderReadCallback( const FLAC__StreamDecoder *decoder, FLAC__byte buffer[],
unsigned *bytes, void *client_data )
{
+ VLC_UNUSED(decoder);
decoder_t *p_dec = (decoder_t *)client_data;
decoder_sys_t *p_sys = p_dec->p_sys;
const FLAC__Frame *frame,
const FLAC__int32 *const buffer[], void *client_data )
{
+ /* XXX it supposes our internal format is WG4 */
+ static const int ppi_reorder[1+8][8] = {
+ {-1},
+ { 0, },
+ { 0, 1 },
+ { 0, 1, 2 },
+ { 0, 1, 2, 3 },
+ { 0, 1, 3, 4, 2 },
+ { 0, 1, 4, 5, 2, 3 },
+
+ { 0, 1, 6, 2, 3, 4, 5 }, /* 7.0 Unspecified by flac */
+ { 0, 1, 6, 7, 2, 3, 4, 5 }, /* 7.1 Unspecified by flac */
+ };
+
+ VLC_UNUSED(decoder);
decoder_t *p_dec = (decoder_t *)client_data;
decoder_sys_t *p_sys = p_dec->p_sys;
+ if( p_dec->fmt_out.audio.i_channels <= 0 ||
+ p_dec->fmt_out.audio.i_channels > 8 )
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+ const int * const pi_reorder = ppi_reorder[p_dec->fmt_out.audio.i_channels];
+
p_sys->p_aout_buffer =
- p_dec->pf_aout_buffer_new( p_dec, frame->header.blocksize );
+ decoder_NewAudioBuffer( p_dec, frame->header.blocksize );
if( p_sys->p_aout_buffer == NULL )
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
switch( frame->header.bits_per_sample )
{
case 16:
- Interleave16( (int16_t *)p_sys->p_aout_buffer->p_buffer, buffer,
+ Interleave16( (int16_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
+ frame->header.channels, frame->header.blocksize );
+ break;
+ case 24:
+ Interleave24( (int8_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
frame->header.channels, frame->header.blocksize );
break;
default:
- Interleave32( (int32_t *)p_sys->p_aout_buffer->p_buffer, buffer,
+ Interleave32( (int32_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
frame->header.channels, frame->header.blocksize );
}
/* Date management (already done by packetizer) */
- p_sys->p_aout_buffer->start_date = p_sys->p_block->i_pts;
- p_sys->p_aout_buffer->end_date =
- p_sys->p_block->i_pts + p_sys->p_block->i_length;
+ p_sys->p_aout_buffer->i_pts = p_sys->p_block->i_pts;
+ p_sys->p_aout_buffer->i_length = p_sys->p_block->i_length;
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
const FLAC__StreamMetadata *metadata,
void *client_data )
{
+ VLC_UNUSED(decoder);
decoder_t *p_dec = (decoder_t *)client_data;
decoder_sys_t *p_sys = p_dec->p_sys;
switch( metadata->data.stream_info.bits_per_sample )
{
case 8:
- p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');
+ p_dec->fmt_out.i_codec = VLC_CODEC_S8;
break;
case 16:
- p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
+ p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
+ break;
+ case 24:
+ p_dec->fmt_out.i_codec = VLC_CODEC_S24N;
break;
default:
msg_Dbg( p_dec, "strange bit/sample value: %d",
metadata->data.stream_info.bits_per_sample );
- p_dec->fmt_out.i_codec = VLC_FOURCC('f','i','3','2');
+ p_dec->fmt_out.i_codec = VLC_CODEC_FI32;
break;
}
}
p_dec->fmt_out.audio.i_bitspersample =
metadata->data.stream_info.bits_per_sample;
- aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate );
+ date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
msg_Dbg( p_dec, "channels:%d samplerate:%d bitspersamples:%d",
p_dec->fmt_out.audio.i_channels, p_dec->fmt_out.audio.i_rate,
p_dec->fmt_out.audio.i_bitspersample );
- p_sys->b_stream_info = VLC_TRUE;
+ p_sys->b_stream_info = true;
p_sys->stream_info = metadata->data.stream_info;
return;
FLAC__StreamDecoderErrorStatus status,
void *client_data )
{
+ VLC_UNUSED(decoder);
decoder_t *p_dec = (decoder_t *)client_data;
switch( status )
* Interleave: helper function to interleave channels
*****************************************************************************/
static void Interleave32( int32_t *p_out, const int32_t * const *pp_in,
+ const int pi_index[],
+ int i_nb_channels, int i_samples )
+{
+ int i, j;
+ for ( j = 0; j < i_samples; j++ )
+ {
+ for ( i = 0; i < i_nb_channels; i++ )
+ {
+ p_out[j * i_nb_channels + i] = pp_in[pi_index[i]][j];
+ }
+ }
+}
+
+static void Interleave24( int8_t *p_out, const int32_t * const *pp_in,
+ const int pi_index[],
int i_nb_channels, int i_samples )
{
int i, j;
{
for ( i = 0; i < i_nb_channels; i++ )
{
- p_out[j * i_nb_channels + i] = pp_in[i][j];
+ const int i_index = pi_index[i];
+#ifdef WORDS_BIGENDIAN
+ p_out[3*(j * i_nb_channels + i)+0] = (pp_in[i_index][j] >> 16) & 0xff;
+ p_out[3*(j * i_nb_channels + i)+1] = (pp_in[i_index][j] >> 8 ) & 0xff;
+ p_out[3*(j * i_nb_channels + i)+2] = (pp_in[i_index][j] >> 0 ) & 0xff;
+#else
+ p_out[3*(j * i_nb_channels + i)+2] = (pp_in[i_index][j] >> 16) & 0xff;
+ p_out[3*(j * i_nb_channels + i)+1] = (pp_in[i_index][j] >> 8 ) & 0xff;
+ p_out[3*(j * i_nb_channels + i)+0] = (pp_in[i_index][j] >> 0 ) & 0xff;
+#endif
}
}
}
+
static void Interleave16( int16_t *p_out, const int32_t * const *pp_in,
+ const int pi_index[],
int i_nb_channels, int i_samples )
{
int i, j;
{
for ( i = 0; i < i_nb_channels; i++ )
{
- p_out[j * i_nb_channels + i] = (int32_t)(pp_in[i][j]);
+ p_out[j * i_nb_channels + i] = (int32_t)(pp_in[pi_index[i]][j]);
}
}
}
{
decoder_sys_t *p_sys = p_dec->p_sys;
int i_header, i_temp, i_read;
- int i_blocksize = 0, i_blocksize_hint = 0, i_sample_rate_hint = 0;
+ unsigned i_blocksize = 0;
+ int i_blocksize_hint = 0, i_sample_rate_hint = 0;
uint64_t i_sample_number = 0;
- vlc_bool_t b_variable_blocksize = ( p_sys->b_stream_info &&
+ bool b_variable_blocksize = ( p_sys->b_stream_info &&
p_sys->stream_info.min_blocksize != p_sys->stream_info.max_blocksize );
- vlc_bool_t b_fixed_blocksize = ( p_sys->b_stream_info &&
+ bool b_fixed_blocksize = ( p_sys->b_stream_info &&
p_sys->stream_info.min_blocksize == p_sys->stream_info.max_blocksize );
/* Check syncword */
if( i_blocksize_hint && b_variable_blocksize )
{
i_sample_number = read_utf8( &p_buf[i_header++], &i_read );
- if( i_sample_number == I64C(0xffffffffffffffff) ) return 0;
+ if( i_sample_number == INT64_C(0xffffffffffffffff) ) return 0;
}
else
{
i_sample_number = read_utf8( &p_buf[i_header++], &i_read );
- if( i_sample_number == I64C(0xffffffffffffffff) ) return 0;
+ if( i_sample_number == INT64_C(0xffffffffffffffff) ) return 0;
if( p_sys->b_stream_info )
i_sample_number *= p_sys->stream_info.min_blocksize;
return 0;
}
+ /* Sanity check using stream info header when possible */
+ if( p_sys->b_stream_info )
+ {
+ if( i_blocksize < p_sys->stream_info.min_blocksize ||
+ i_blocksize > p_sys->stream_info.max_blocksize )
+ return 0;
+ }
return i_blocksize;
}
i = 6;
}
else {
- return I64C(0xffffffffffffffff);
+ return INT64_C(0xffffffffffffffff);
}
for( j = 1; j <= i; j++ )
{
if( !(p_buf[j] & 0x80) || (p_buf[j] & 0x40) ) /* 10xxxxxx */
{
- return I64C(0xffffffffffffffff);
+ return INT64_C(0xffffffffffffffff);
}
i_result <<= 6;
i_result |= (p_buf[j] & 0x3F);
}
/* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
-static uint8_t const flac_crc8_table[256] = {
+static const uint8_t flac_crc8_table[256] = {
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
encoder_t *p_enc = (encoder_t *)p_this;
encoder_sys_t *p_sys;
- if( p_enc->fmt_out.i_codec != VLC_FOURCC('f','l','a','c') &&
+ if( p_enc->fmt_out.i_codec != VLC_CODEC_FLAC &&
!p_enc->b_force )
{
return VLC_EGENERIC;
/* Allocate the memory needed to store the decoder's structure */
if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
- {
- msg_Err( p_enc, "out of memory" );
- return VLC_EGENERIC;
- }
+ return VLC_ENOMEM;
p_enc->p_sys = p_sys;
p_enc->pf_encode_audio = Encode;
- p_enc->fmt_out.i_codec = VLC_FOURCC('f','l','a','c');
+ p_enc->fmt_out.i_codec = VLC_CODEC_FLAC;
p_sys->i_headers = 0;
p_sys->p_buffer = 0;
FLAC__stream_encoder_set_sample_rate( p_sys->p_flac,
p_enc->fmt_in.audio.i_rate );
FLAC__stream_encoder_set_bits_per_sample( p_sys->p_flac, 16 );
- p_enc->fmt_in.i_codec = AOUT_FMT_S16_NE;
+ p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
/* Get and store the STREAMINFO metadata block as a p_extra */
p_sys->p_chain = 0;
block_t *p_chain;
unsigned int i;
- p_sys->i_pts = p_aout_buf->start_date -
+ p_sys->i_pts = p_aout_buf->i_pts -
(mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
(mtime_t)p_enc->fmt_in.audio.i_rate;
p_sys->i_samples_delay += p_aout_buf->i_nb_samples;
/* Convert samples to FLAC__int32 */
- if( p_sys->i_buffer < p_aout_buf->i_nb_bytes * 2 )
+ if( p_sys->i_buffer < p_aout_buf->i_buffer * 2 )
{
p_sys->p_buffer =
- realloc( p_sys->p_buffer, p_aout_buf->i_nb_bytes * 2 );
- p_sys->i_buffer = p_aout_buf->i_nb_bytes * 2;
+ realloc( p_sys->p_buffer, p_aout_buf->i_buffer * 2 );
+ p_sys->i_buffer = p_aout_buf->i_buffer * 2;
}
- for( i = 0 ; i < p_aout_buf->i_nb_bytes / 2 ; i++ )
+ for( i = 0 ; i < p_aout_buf->i_buffer / 2 ; i++ )
{
p_sys->p_buffer[i]= ((int16_t *)p_aout_buf->p_buffer)[i];
}
FLAC__stream_encoder_delete( p_sys->p_flac );
- if( p_sys->p_buffer ) free( p_sys->p_buffer );
+ free( p_sys->p_buffer );
free( p_sys );
}
const FLAC__StreamMetadata *metadata,
void *client_data )
{
+ VLC_UNUSED(encoder);
encoder_t *p_enc = (encoder_t *)client_data;
msg_Err( p_enc, "MetadataCallback: %i", metadata->type );
unsigned bytes, unsigned samples,
unsigned current_frame, void *client_data )
{
+ VLC_UNUSED(encoder); VLC_UNUSED(current_frame);
encoder_t *p_enc = (encoder_t *)client_data;
encoder_sys_t *p_sys = p_enc->p_sys;
block_t *p_block;