Commit 90a612c6 authored by Sam Hocevar's avatar Sam Hocevar

* ./modules/audio_filter/converter/fixed32tofloat32.c: fixed conversion.

  * ./modules/codec/mad/libmad.c: ported to the latest aout changes. Still
    doesn't work here, though.
parent 00724b73
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* fixed32float32.c : converter from fixed32 to float32 bits integer * fixed32float32.c : converter from fixed32 to float32 bits integer
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: fixed32tofloat32.c,v 1.6 2002/08/21 22:41:59 massiot Exp $ * $Id: fixed32tofloat32.c,v 1.7 2002/08/22 17:14:52 sam Exp $
* *
* Authors: Jean-Paul Saman <jpsaman@wxs.nl> * Authors: Jean-Paul Saman <jpsaman@wxs.nl>
* *
...@@ -87,31 +87,7 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, ...@@ -87,31 +87,7 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
for ( i = p_in_buf->i_nb_samples * p_filter->input.i_channels ; i-- ; ) for ( i = p_in_buf->i_nb_samples * p_filter->input.i_channels ; i-- ; )
{ {
/* convert vlc_fixed_t into s32 */ *p_out++ = (float)*p_in++ / -(float)FIXED32_MIN;
#if 0
s32 temp;
if ( *p_in >= 8 ) temp = 32767;
else if ( *p_in < -8 ) temp = -32768;
else temp = *p_in * (s32) 4096; // (32768/8);
#endif
/* convert s32 into float */
#if 0
if (temp >= 32768)
*p_out = (float) 1.0;
else if (temp <= -32768)
*p_out = (float) -1.0;
else *p_out = (float) (temp/32768.0);
#endif
/* combined conversion */
/* This has absolutely no chance of working. *p_in is s32, gcc
* doesn't know anything of vlc_fixed_t... --Meuuh */
if ( *p_in >= 8 ) *p_out = (float) 1.0;
else if ( *p_in < -8 ) *p_out = (float) -1.0;
else *p_out =(float) (*p_in/8.0);
p_in++; p_out++;
} }
p_out_buf->i_nb_samples = p_in_buf->i_nb_samples; p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
......
...@@ -42,19 +42,19 @@ ...@@ -42,19 +42,19 @@
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder ( vlc_object_t * ); static int OpenDecoder ( vlc_object_t * );
static int RunDecoder ( decoder_fifo_t * ); static int RunDecoder ( decoder_fifo_t * );
static int InitThread ( mad_adec_thread_t * p_mad_adec ); static int InitThread ( mad_adec_thread_t * );
static void EndThread ( mad_adec_thread_t * p_mad_adec ); static void EndThread ( mad_adec_thread_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
*****************************************************************************/ *****************************************************************************/
#define DOWNSCALE_TEXT N_("Mad audio downscale routine (fast,mp321)") #define DOWNSCALE_TEXT N_("mad audio downscale routine (fast,mpg321)")
#define DOWNSCALE_LONGTEXT N_( \ #define DOWNSCALE_LONGTEXT N_( \
"Specify the mad audio downscale routine you want to use. By default " \ "Specify the mad audio downscale routine you want to use. By default " \
"the mad plugin will use the fastest routine.") "the mad plugin will use the fastest routine.")
vlc_module_begin(); vlc_module_begin();
add_category_hint( N_("Miscellaneous"), NULL ); add_category_hint( N_("Libmad"), NULL );
add_string( "downscale", "fast", NULL, DOWNSCALE_TEXT, DOWNSCALE_LONGTEXT ); add_string( "downscale", "fast", NULL, DOWNSCALE_TEXT, DOWNSCALE_LONGTEXT );
set_description( _("libmad MPEG 1/2/3 audio decoder") ); set_description( _("libmad MPEG 1/2/3 audio decoder") );
set_capability( "decoder", 100 ); set_capability( "decoder", 100 );
...@@ -85,68 +85,71 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -85,68 +85,71 @@ static int OpenDecoder( vlc_object_t *p_this )
*****************************************************************************/ *****************************************************************************/
static int RunDecoder( decoder_fifo_t *p_fifo ) static int RunDecoder( decoder_fifo_t *p_fifo )
{ {
mad_adec_thread_t * p_mad_adec; mad_adec_thread_t * p_dec;
int i_ret;
/* Allocate the memory needed to store the thread's structure */ /* Allocate the memory needed to store the thread's structure */
p_mad_adec = (mad_adec_thread_t *) malloc(sizeof(mad_adec_thread_t)); p_dec = (mad_adec_thread_t *) malloc(sizeof(mad_adec_thread_t));
if (p_mad_adec == NULL) if (p_dec == NULL)
{ {
msg_Err( p_fifo, "out of memory" ); msg_Err( p_fifo, "out of memory" );
DecoderError( p_fifo ); DecoderError( p_fifo );
return( -1 ); return VLC_ENOMEM;
} }
/* /*
* Initialize the thread properties * Initialize the thread properties
*/ */
p_mad_adec->p_fifo = p_fifo; p_dec->p_fifo = p_fifo;
if( InitThread( p_mad_adec ) ) if( InitThread( p_dec ) )
{ {
msg_Err( p_fifo, "could not initialize thread" ); msg_Err( p_fifo, "could not initialize thread" );
DecoderError( p_fifo ); DecoderError( p_fifo );
free( p_mad_adec ); free( p_dec );
return( -1 ); return VLC_ETHREAD;
} }
/* mad decoder thread's main loop */ /* mad decoder thread's main loop */
while ((!p_mad_adec->p_fifo->b_die) && (!p_mad_adec->p_fifo->b_error)) while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
{ {
msg_Dbg( p_mad_adec->p_fifo, "starting libmad decoder" ); msg_Dbg( p_dec->p_fifo, "starting libmad decoder" );
if (mad_decoder_run(p_mad_adec->libmad_decoder, MAD_DECODER_MODE_SYNC)==-1) i_ret = mad_decoder_run( &p_dec->libmad_decoder,
MAD_DECODER_MODE_SYNC );
if( i_ret == -1 )
{ {
msg_Err( p_mad_adec->p_fifo, "libmad decoder returned abnormally" ); msg_Err( p_dec->p_fifo, "libmad decoder returned abnormally" );
DecoderError( p_mad_adec->p_fifo ); DecoderError( p_dec->p_fifo );
EndThread(p_mad_adec); EndThread(p_dec);
return( -1 ); return VLC_EGENERIC;
} }
} }
/* If b_error is set, the mad decoder thread enters the error loop */ /* If b_error is set, the mad decoder thread enters the error loop */
if (p_mad_adec->p_fifo->b_error) if (p_dec->p_fifo->b_error)
{ {
DecoderError( p_mad_adec->p_fifo ); DecoderError( p_dec->p_fifo );
} }
/* End of the mad decoder thread */ /* End of the mad decoder thread */
EndThread (p_mad_adec); EndThread (p_dec);
return( 0 ); return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* InitThread: initialize data before entering main loop * InitThread: initialize data before entering main loop
*****************************************************************************/ *****************************************************************************/
static int InitThread( mad_adec_thread_t * p_mad_adec ) static int InitThread( mad_adec_thread_t * p_dec )
{ {
decoder_fifo_t * p_fifo = p_mad_adec->p_fifo; decoder_fifo_t * p_fifo = p_dec->p_fifo;
char *psz_downscale = NULL; char *psz_downscale = NULL;
/* Initialize the thread properties */ /* Initialize the thread properties */
p_mad_adec->p_aout = NULL; p_dec->p_aout = NULL;
p_mad_adec->p_aout_input = NULL; p_dec->p_aout_input = NULL;
p_mad_adec->output_format.i_format = AOUT_FMT_FIXED32; p_dec->output_format.i_format = AOUT_FMT_FIXED32;
p_mad_adec->output_format.i_channels = 2; /* FIXME ! */ p_dec->output_format.i_channels = 2; /* FIXME ! */
/* /*
* Properties of audio for libmad * Properties of audio for libmad
...@@ -157,45 +160,43 @@ static int InitThread( mad_adec_thread_t * p_mad_adec ) ...@@ -157,45 +160,43 @@ static int InitThread( mad_adec_thread_t * p_mad_adec )
if ( strncmp(psz_downscale,"fast",4)==0 ) if ( strncmp(psz_downscale,"fast",4)==0 )
{ {
p_mad_adec->audio_scaling = FAST_SCALING; p_dec->audio_scaling = FAST_SCALING;
msg_Dbg( p_fifo, "downscale fast selected" ); msg_Dbg( p_fifo, "downscale fast selected" );
} }
else if ( strncmp(psz_downscale,"mpg321",7)==0 ) else if ( strncmp(psz_downscale,"mpg321",7)==0 )
{ {
p_mad_adec->audio_scaling = MPG321_SCALING; p_dec->audio_scaling = MPG321_SCALING;
msg_Dbg( p_fifo, "downscale mpg321 selected" ); msg_Dbg( p_fifo, "downscale mpg321 selected" );
} }
else else
{ {
p_mad_adec->audio_scaling = FAST_SCALING; p_dec->audio_scaling = FAST_SCALING;
msg_Dbg( p_fifo, "downscale default fast selected" ); msg_Dbg( p_fifo, "downscale default fast selected" );
} }
if (psz_downscale) free(psz_downscale); if (psz_downscale) free(psz_downscale);
/* Initialize the libmad decoder structures */ /* Initialize the libmad decoder structures */
p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder)); p_dec->i_current_pts = p_dec->i_next_pts = 0;
if (p_mad_adec->libmad_decoder == NULL)
{
msg_Err( p_mad_adec->p_fifo, "out of memory" );
return -1;
}
p_mad_adec->i_current_pts = p_mad_adec->i_next_pts = 0;
mad_decoder_init( p_mad_adec->libmad_decoder, mad_decoder_init( &p_dec->libmad_decoder,
p_mad_adec, /* vlc's thread structure and p_fifo playbuffer */ p_dec, /* vlc's thread structure and p_fifo playbuffer */
libmad_input, /* input_func */ libmad_input, /* input_func */
0, /* header_func */ NULL, /* header_func */
0, /* filter */ NULL, /* filter */
libmad_output3, /* output_func */ libmad_output, /* output_func */
0, /* error */ NULL, /* error */
0); /* message */ NULL ); /* message */
mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC); mad_decoder_options( &p_dec->libmad_decoder, MAD_OPTION_IGNORECRC );
/* /*
* Initialize the input properties * Initialize the input properties
*/ */
/* Init the Bitstream */
InitBitstream( &p_dec->bit_stream, p_dec->p_fifo, NULL, NULL );
/* Get the first data packet. */ /* Get the first data packet. */
vlc_mutex_lock( &p_fifo->data_lock ); vlc_mutex_lock( &p_fifo->data_lock );
while ( p_fifo->p_first == NULL ) while ( p_fifo->p_first == NULL )
...@@ -203,32 +204,30 @@ static int InitThread( mad_adec_thread_t * p_mad_adec ) ...@@ -203,32 +204,30 @@ static int InitThread( mad_adec_thread_t * p_mad_adec )
if ( p_fifo->b_die ) if ( p_fifo->b_die )
{ {
vlc_mutex_unlock( &p_fifo->data_lock ); vlc_mutex_unlock( &p_fifo->data_lock );
return( -1 ); return VLC_EGENERIC;
} }
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock ); vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
} }
vlc_mutex_unlock( &p_fifo->data_lock ); vlc_mutex_unlock( &p_fifo->data_lock );
p_mad_adec->p_data = p_fifo->p_first->p_first; p_dec->p_data = p_fifo->p_first->p_first;
return( 0 ); return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* EndThread : libmad decoder thread destruction * EndThread : libmad decoder thread destruction
*****************************************************************************/ *****************************************************************************/
static void EndThread (mad_adec_thread_t * p_mad_adec) static void EndThread (mad_adec_thread_t * p_dec)
{ {
/* If the audio output fifo was created, we destroy it */ /* If the audio output fifo was created, we destroy it */
if (p_mad_adec->p_aout_input != NULL) if (p_dec->p_aout_input != NULL)
{ {
aout_InputDelete( p_mad_adec->p_aout, p_mad_adec->p_aout_input ); aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
} }
/* mad_decoder_finish releases the memory allocated inside the struct */ /* mad_decoder_finish releases the memory allocated inside the struct */
mad_decoder_finish( p_mad_adec->libmad_decoder ); mad_decoder_finish( &p_dec->libmad_decoder );
/* Unlock the modules, p_mad_adec->p_fifo is released by the decoder subsystem */ free( p_dec );
free( p_mad_adec->libmad_decoder );
free( p_mad_adec );
} }
...@@ -29,7 +29,7 @@ typedef struct mad_adec_thread_s ...@@ -29,7 +29,7 @@ typedef struct mad_adec_thread_s
/* /*
* Decoder properties * Decoder properties
*/ */
struct mad_decoder *libmad_decoder; struct mad_decoder libmad_decoder;
mad_timer_t libmad_timer; mad_timer_t libmad_timer;
byte_t buffer[MAD_BUFFER_MDLEN]; byte_t buffer[MAD_BUFFER_MDLEN];
...@@ -38,6 +38,9 @@ typedef struct mad_adec_thread_s ...@@ -38,6 +38,9 @@ typedef struct mad_adec_thread_s
*/ */
vlc_thread_t thread_id; /* id for thread functions */ vlc_thread_t thread_id; /* id for thread functions */
/* The bit stream structure handles the PES stream at the bit level */
bit_stream_t bit_stream;
/* /*
* Input properties * Input properties
*/ */
...@@ -47,19 +50,14 @@ typedef struct mad_adec_thread_s ...@@ -47,19 +50,14 @@ typedef struct mad_adec_thread_s
/* Store i_pts for syncing audio frames */ /* Store i_pts for syncing audio frames */
mtime_t i_current_pts, i_next_pts; mtime_t i_current_pts, i_next_pts;
/*
* Output properties
*/
//old way aout_fifo_t * p_aout_fifo; /* stores the decompressed audio frames */
/* /*
* Output properties * Output properties
*/ */
aout_instance_t * p_aout; /* opaque */ aout_instance_t * p_aout; /* opaque */
aout_input_t * p_aout_input; /* opaque */ aout_input_t * p_aout_input; /* opaque */
audio_sample_format_t output_format; audio_sample_format_t output_format;
audio_date_t end_date;
mtime_t last_date;
enum mad_scaling audio_scaling; enum mad_scaling audio_scaling;
} mad_adec_thread_t; } mad_adec_thread_t;
......
...@@ -41,452 +41,198 @@ static void PrintFrameInfo(struct mad_header *Header); ...@@ -41,452 +41,198 @@ static void PrintFrameInfo(struct mad_header *Header);
* libmad_input: this function is called by libmad when the input buffer needs * libmad_input: this function is called by libmad when the input buffer needs
* to be filled. * to be filled.
*****************************************************************************/ *****************************************************************************/
enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream) enum mad_flow libmad_input( void *p_data, struct mad_stream *p_stream )
{ {
mad_adec_thread_t *p_mad_adec = (mad_adec_thread_t *) data; mad_adec_thread_t * p_dec = (mad_adec_thread_t *) p_data;
size_t ReadSize, Remaining; size_t i_wanted, i_left;
unsigned char *ReadStart;
if ( p_mad_adec->p_fifo->b_die == 1 ) { if ( p_dec->p_fifo->b_die )
msg_Dbg( p_mad_adec->p_fifo, "libmad_input stopping libmad decoder" ); {
msg_Dbg( p_dec->p_fifo, "stopping libmad decoder" );
return MAD_FLOW_STOP; return MAD_FLOW_STOP;
} }
if ( p_mad_adec->p_fifo->b_error == 1 ) { if ( p_dec->p_fifo->b_error )
msg_Warn( p_mad_adec->p_fifo, "libmad_input ignoring current audio frame" ); {
msg_Warn( p_dec->p_fifo, "ignoring current audio frame" );
return MAD_FLOW_IGNORE; return MAD_FLOW_IGNORE;
} }
/* libmad_stream_buffer does not consume the total buffer, it consumes only data /* libmad_stream_buffer does not consume the total buffer, it consumes
* for one frame only. So all data left in the buffer should be put back in front. * only data for one frame only. So all data left in the buffer should
*/ * be put back in front. */
if ((p_libmad_stream->buffer==NULL) || (p_libmad_stream->error==MAD_ERROR_BUFLEN)) if ( !p_stream->buffer || p_stream->error == MAD_ERROR_BUFLEN )
{ {
/* libmad does not consume all the buffer it's given. Some /* libmad does not consume all the buffer it's given. Some data,
* datas, part of a truncated frame, is left unused at the * part of a truncated frame, is left unused at the end of the
* end of the buffer. Those datas must be put back at the * buffer. Those datas must be put back at the beginning of the
* beginning of the buffer and taken in account for * buffer and taken in account for refilling the buffer. This
* refilling the buffer. This means that the input buffer * means that the input buffer must be large enough to hold a
* must be large enough to hold a complete frame at the * complete frame at the highest observable bit-rate (currently
* highest observable bit-rate (currently 448 kb/s). XXX=XXX * 448 kb/s). XXX=XXX Is 2016 bytes the size of the largest frame?
* Is 2016 bytes the size of the largest frame? * (448000*(1152/32000))/8 */
* (448000*(1152/32000))/8 if( p_stream->next_frame )
*/
if(p_libmad_stream->next_frame!=NULL)
{ {
Remaining=p_libmad_stream->bufend-p_libmad_stream->next_frame; i_left = p_stream->bufend - p_stream->next_frame;
if( p_mad_adec->buffer != p_libmad_stream->next_frame ) if( p_dec->buffer != p_stream->next_frame )
{ {
memcpy( p_mad_adec->buffer, memcpy( p_dec->buffer, p_stream->next_frame, i_left );
p_libmad_stream->next_frame, Remaining );
} }
ReadStart=p_mad_adec->buffer+Remaining; i_wanted = MAD_BUFFER_MDLEN - i_left;
ReadSize=(MAD_BUFFER_MDLEN)-Remaining;
/* Store time stamp of next frame */ /* Store timestamp for next frame */
p_mad_adec->i_current_pts = p_mad_adec->i_next_pts; p_dec->i_next_pts = p_dec->p_fifo->p_first->i_pts;
p_mad_adec->i_next_pts = p_mad_adec->p_fifo->p_first->i_pts;
} }
else else
{ {
ReadSize=(MAD_BUFFER_MDLEN); i_wanted = MAD_BUFFER_MDLEN;
ReadStart=p_mad_adec->buffer; i_left = 0;
Remaining=0;
p_mad_adec->i_next_pts = 0; /* Store timestamp for this frame */
p_mad_adec->i_current_pts = p_mad_adec->p_fifo->p_first->i_pts; p_dec->i_current_pts = p_dec->p_fifo->p_first->i_pts;
} }
/* Fill-in the buffer. If an error occurs print a message /* Fill-in the buffer. If an error occurs print a message and leave
* and leave the decoding loop. If the end of stream is * the decoding loop. If the end of stream is reached we also leave
* reached we also leave the loop but the return status is * the loop but the return status is left untouched. */
* left untouched. if( i_wanted > p_dec->p_data->p_payload_end
*/ - p_dec->p_data->p_payload_start )
if( ReadSize > p_mad_adec->p_data->p_payload_end
- p_mad_adec->p_data->p_payload_start )
{ {
ReadSize = p_mad_adec->p_data->p_payload_end i_wanted = p_dec->p_data->p_payload_end
- p_mad_adec->p_data->p_payload_start; - p_dec->p_data->p_payload_start;
memcpy( ReadStart, p_mad_adec->p_data->p_payload_start, ReadSize ); memcpy( p_dec->buffer + i_left,
NextDataPacket( p_mad_adec->p_fifo, &p_mad_adec->p_data ); p_dec->p_data->p_payload_start, i_wanted );
NextDataPacket( p_dec->p_fifo, &p_dec->p_data );
} }
else else
{ {
memcpy( ReadStart, p_mad_adec->p_data->p_payload_start, ReadSize ); memcpy( p_dec->buffer + i_left,
p_mad_adec->p_data->p_payload_start += ReadSize; p_dec->p_data->p_payload_start, i_wanted );
p_dec->p_data->p_payload_start += i_wanted;
} }
if ( p_mad_adec->p_fifo->b_die == 1 ) if ( p_dec->p_fifo->b_die )
{ {
msg_Dbg( p_mad_adec->p_fifo, "libmad_input stopping libmad decoder" ); msg_Dbg( p_dec->p_fifo, "stopping libmad decoder" );
return MAD_FLOW_STOP; return MAD_FLOW_STOP;
} }
if ( p_mad_adec->p_fifo->b_error == 1 ) if ( p_dec->p_fifo->b_error )
{ {
msg_Warn( p_mad_adec->p_fifo, "libmad_input ignoring current audio frame" ); msg_Warn( p_dec->p_fifo, "ignoring current audio frame" );
return MAD_FLOW_IGNORE; return MAD_FLOW_IGNORE;
} }
/* Pipe the new buffer content to libmad's stream decoder facility. /* Pipe the new buffer content to libmad's stream decoder facility.
* Libmad never copies the buffer, but just references it. So keep it in * Libmad never copies the buffer, but just references it. So keep
* mad_adec_thread_t structure. * it in mad_adec_thread_t structure. */
*/ mad_stream_buffer( p_stream, (unsigned char*) &p_dec->buffer,
mad_stream_buffer(p_libmad_stream,(unsigned char*) &p_mad_adec->buffer, i_left + i_wanted );
Remaining + ReadSize); p_stream->error = 0;
p_libmad_stream->error=0;
} }
return MAD_FLOW_CONTINUE; return MAD_FLOW_CONTINUE;
} }
/***************************************************************************** /*****************************************************************************
* libmad_header: this function is called just after the header of a frame is * libmad_output: this function is called just after the frame is decoded
* decoded
*****************************************************************************/
/*
*enum mad_flow libmad_header(void *data, struct mad_header const *p_libmad_header)
*{
* mad_adec_thread_t *p_mad_adec = (mad_adec_thread_t *) data;
*
* msg_Err( p_mad_adec->p_fifo, "libmad_header samplerate %d", p_libmad_header->samplerate);
*
* PrintFrameInfo(p_limad_mad_header)
* return MAD_FLOW_CONTINUE;
*}
*/
/*****************************************************************************
* lib_mad_filter: this function is called to filter data of a frame
*****************************************************************************/
/* enum mad_flow libmad_filter(void *data, struct mad_stream const *p_libmad_stream, struct mad_frame *p_libmad_frame)
* {
* return MAD_FLOW_CONTINUE;
* }
*/
///*****************************************************************************
// * support routines borrowed from mpg321 (file: mad.c), which is distributed
// * under GPL license
// *
// * mpg321 was written by Joe Drew <drew@debian.org>, and based upon 'plaympeg'
// * from the smpeg sources, which was written by various people from Loki Software
// * (http://www.lokigames.com).
// *
// * It also incorporates some source from mad, written by Robert Leslie
// *****************************************************************************/
//
///* The following two routines and data structure are from the ever-brilliant
// Rob Leslie.
//*/
//
//struct audio_dither {
// mad_fixed_t error[3];
// mad_fixed_t random;
//};
//
///*
//* NAME: prng()
//* DESCRIPTION: 32-bit pseudo-random number generator
//*/
//static inline unsigned long prng(unsigned long state)
//{
// return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
//}
//
///*
//* NAME: mpg321_s24_to_s16_pcm()
//* DESCRIPTION: generic linear sample quantize and dither routine
//*/
//static inline signed int mpg321_s24_to_s16_pcm(unsigned int bits, mad_fixed_t sample,
// struct audio_dither *dither)
//{
// unsigned int scalebits;
// mad_fixed_t output, mask, random;
//
// enum {
// MIN = -MAD_F_ONE,
// MAX = MAD_F_ONE - 1
// };
//
// /* noise shape */
// sample += dither->error[0] - dither->error[1] + dither->error[2];
//
// dither->error[2] = dither->error[1];
// dither->error[1] = dither->error[0] / 2;
//
// /* bias */
// output = sample + (1L << (MAD_F_FRACBITS + 1 - bits - 1));
//
// scalebits = MAD_F_FRACBITS + 1 - bits;
// mask = (1L << scalebits) - 1;
//
// /* dither */
// random = prng(dither->random);
// output += (random & mask) - (dither->random & mask);
//
// dither->random = random;
//
// /* clip */
// if (output > MAX) {
// output = MAX;
//
// if (sample > MAX)
// sample = MAX;
// }
// else if (output < MIN) {
// output = MIN;
//
// if (sample < MIN)
// sample = MIN;
// }
//
// /* quantize */
// output &= ~mask;
//
// /* error feedback */
// dither->error[0] = sample - output;
//
// /* scale */
// return output >> scalebits;
//}
//
///*****************************************************************************
// * s24_to_s16_pcm: Scale a 24 bit pcm sample to a 16 bit pcm sample.
// *****************************************************************************/
//static inline mad_fixed_t s24_to_s16_pcm(mad_fixed_t sample)
//{
// /* round */
// sample += (1L << (MAD_F_FRACBITS - 16));
//
// /* clip */
// if (sample >= MAD_F_ONE)
// sample = MAD_F_ONE - 1;
// else if (sample < -MAD_F_ONE)
// sample = -MAD_F_ONE;
//
// /* quantize */
// return sample >> (MAD_F_FRACBITS + 1 - 16);
//}
//
/*****************************************************************************
* libmad_ouput: this function is called just after the frame is decoded
*****************************************************************************/ *****************************************************************************/
//enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header, struct mad_pcm *p_libmad_pcm) enum mad_flow libmad_output( void *p_data, struct mad_header const *p_header,
//{ struct mad_pcm *p_pcm )
// mad_adec_thread_t *p_mad_adec= (mad_adec_thread_t *) data;
// byte_t *buffer=NULL;
// mad_fixed_t const *left_ch = p_libmad_pcm->samples[0], *right_ch = p_libmad_pcm->samples[1];
// register int nsamples = p_libmad_pcm->length;
// mad_fixed_t sample;
// static struct audio_dither dither;
//
// /* Creating the audio output fifo.
// * Assume the samplerate and nr of channels from the first decoded frame is right for the entire audio track.
// */
// if (p_mad_adec->p_aout_fifo==NULL)
// {
// p_mad_adec->p_aout_fifo = aout_CreateFifo(
// p_mad_adec->p_fifo,
// AOUT_FIFO_PCM, /* fifo type */
// 2, /*p_libmad_pcm->channels,*/ /* nr. of channels */
// p_libmad_pcm->samplerate, /* frame rate in Hz ?*/
// p_libmad_pcm->length*2, /* length of output buffer *2 channels*/
// NULL ); /* buffer */
//
// if ( p_mad_adec->p_aout_fifo == NULL )
// {
// return MAD_FLOW_BREAK;
// }
//
// msg_Dbg( p_mad_adec->p_fifo, "aout fifo created");
// }
//
// if (p_mad_adec->p_aout_fifo->i_rate != p_libmad_pcm->samplerate)
// {
// msg_Warn( p_mad_adec->p_fifo, "samplerate is changing from [%d] Hz "
// "to [%d] Hz, sample size [%d], error_code [%0x]",
// p_mad_adec->p_aout_fifo->i_rate, p_libmad_pcm->samplerate,
// p_libmad_pcm->length,
// p_mad_adec->libmad_decoder->sync->stream.error );
// p_mad_adec->p_aout_fifo->i_rate = p_libmad_pcm->samplerate;
// }
//
// if( p_mad_adec->i_current_pts )
// {
// p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->i_end_frame]
// = p_mad_adec->i_current_pts;
// }
// else
// {
// p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->i_end_frame]
// = LAST_MDATE;
// }
//// mad_timer_add(&p_mad_adec->libmad_timer,p_libmad_header->duration);
//
// buffer = ((byte_t *)p_mad_adec->p_aout_fifo->buffer) + (p_mad_adec->p_aout_fifo->i_end_frame * (p_libmad_pcm->length*4));
//
// while (nsamples--)
// {
// switch (p_mad_adec->audio_scaling)
// {
// case MPG321_SCALING:
// sample = mpg321_s24_to_s16_pcm(16, *left_ch++, &dither);
// break;
// case FAST_SCALING: /* intended fall through */
// default:
// sample = s24_to_s16_pcm(*left_ch++);
// break;
// }
//
// /* left audio channel */
//#ifndef WORDS_BIGENDIAN
// *buffer++ = (byte_t) (sample >> 0);
// *buffer++ = (byte_t) (sample >> 8);
//#else
// *buffer++ = (byte_t) (sample >> 8);
// *buffer++ = (byte_t) (sample >> 0);
//#endif
// if (p_libmad_pcm->channels == 2)
// {
// /* right audio channel */
// switch (p_mad_adec->audio_scaling)
// {
// case MPG321_SCALING:
// sample = mpg321_s24_to_s16_pcm(16, *right_ch++, &dither);
// break;
// case FAST_SCALING: /* intended fall through */
// default:
// sample = s24_to_s16_pcm(*right_ch++);
// break;
// }
// }
// /* else reuse left_ch */
//#ifndef WORDS_BIGENDIAN
// *buffer++ = (byte_t) (sample >> 0);
// *buffer++ = (byte_t) (sample >> 8);
//#else
// *buffer++ = (byte_t) (sample >> 8);
// *buffer++ = (byte_t) (sample >> 0);
//#endif
// }
//
// /* DEBUG */
// /*
// if (p_libmad_pcm->channels == 1) {
// msg_Dbg( p_mad_adec->p_fifo, "libmad_output channels [%d]", p_libmad_pcm->channels);
// }
// */
//
// vlc_mutex_lock (&p_mad_adec->p_aout_fifo->data_lock);
// p_mad_adec->p_aout_fifo->i_end_frame = (p_mad_adec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
// vlc_cond_signal (&p_mad_adec->p_aout_fifo->data_wait);
// vlc_mutex_unlock (&p_mad_adec->p_aout_fifo->data_lock);
//
// return MAD_FLOW_CONTINUE;
//}
/*****************************************************************************
* libmad_ouput3: this function is called just after the frame is decoded
*****************************************************************************/
enum mad_flow libmad_output3(void *data, struct mad_header const *p_libmad_header, struct mad_pcm *p_libmad_pcm)
{ {
mad_adec_thread_t *p_mad_adec= (mad_adec_thread_t *) data; mad_adec_thread_t * p_dec = (mad_adec_thread_t *) p_data;
aout_buffer_t * p_buffer; aout_buffer_t * p_buffer;
mad_fixed_t const *left_ch = p_libmad_pcm->samples[0], *right_ch = p_libmad_pcm->samples[1]; mad_fixed_t const * p_left = p_pcm->samples[0];
register int nsamples = p_libmad_pcm->length; mad_fixed_t const * p_right = p_pcm->samples[1];
mad_fixed_t sample; register int i_samples = p_pcm->length;
mad_fixed_t * p_samples;
/* Creating the audio output fifo.
* Assume the samplerate and nr of channels from the first decoded frame /* Creating the audio output fifo. Assume the samplerate and nr of channels
* is right for the entire audio track. * from the first decoded frame is right for the entire audio track. */
*/ if( (p_dec->p_aout_input != NULL) &&
if( (p_mad_adec->p_aout_input != NULL) && (p_dec->output_format.i_rate != p_pcm->samplerate) )
(p_mad_adec->output_format.i_rate != p_libmad_pcm->samplerate) )
{ {
/* Parameters changed - this should not happen. */ /* Parameters changed - this should not happen. */
aout_InputDelete( p_mad_adec->p_aout, p_mad_adec->p_aout_input ); aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
p_mad_adec->p_aout_input = NULL; p_dec->p_aout_input = NULL;
} }
/* Creating the audio input if not created yet. */ /* Creating the audio input if not created yet. */
if( p_mad_adec->p_aout_input == NULL ) if( p_dec->p_aout_input == NULL )
{ {
p_mad_adec->output_format.i_rate = p_libmad_pcm->samplerate; p_dec->output_format.i_rate = p_pcm->samplerate;
/* p_mad_adec->output_format.i_channels = p_libmad_pcm->channels; */ /* p_dec->output_format.i_channels = p_pcm->channels; */
p_mad_adec->p_aout_input = aout_InputNew( p_mad_adec->p_fifo, aout_DateInit( &p_dec->end_date, p_pcm->samplerate );
&p_mad_adec->p_aout, p_dec->p_aout_input = aout_InputNew( p_dec->p_fifo,
&p_mad_adec->output_format ); &p_dec->p_aout,
&p_dec->output_format );
if ( p_dec->p_aout_input == NULL )
{
p_dec->p_fifo->b_error = VLC_TRUE;
return MAD_FLOW_BREAK;
}
}
if ( p_mad_adec->p_aout_input == NULL ) if( p_dec->i_current_pts )
{
/* Set the Presentation Time Stamp */
if( p_dec->i_current_pts != aout_DateGet( &p_dec->end_date ) )
{ {
p_mad_adec->p_fifo->b_error = 1; aout_DateSet( &p_dec->end_date, p_dec->i_current_pts );
return MAD_FLOW_BREAK;
} }
msg_Dbg( p_mad_adec->p_fifo, "aout3 input created");
p_dec->i_current_pts = 0;
}
else if( p_dec->i_next_pts )
{
/* No PTS this time, but it'll be for next frame */
p_dec->i_current_pts = p_dec->i_next_pts;
p_dec->i_next_pts = 0;
} }
if (p_mad_adec->output_format.i_rate != p_libmad_pcm->samplerate) if( !aout_DateGet( &p_dec->end_date ) )
{ {
msg_Warn( p_mad_adec->p_fifo, "samplerate is changing from [%d] Hz " /* No date available yet, wait for the first PTS. */
"to [%d] Hz, sample size [%d], error_code [%0x]", return MAD_FLOW_CONTINUE;
p_mad_adec->output_format.i_rate, p_libmad_pcm->samplerate,
p_libmad_pcm->length,
p_mad_adec->libmad_decoder->sync->stream.error );
p_mad_adec->output_format.i_rate = p_libmad_pcm->samplerate;
} }
/* Set the Presentation Time Stamp */ p_buffer = aout_BufferNew( p_dec->p_aout, p_dec->p_aout_input, i_samples );
p_buffer = aout_BufferNew( p_mad_adec->p_aout,
p_mad_adec->p_aout_input,
(p_libmad_pcm->length*2) );
if ( p_buffer == NULL ) if ( p_buffer == NULL )
{ {
msg_Dbg( p_mad_adec->p_fifo, "allocating new buffer failed"); msg_Err( p_dec->p_fifo, "allocating new buffer failed" );
return MAD_FLOW_BREAK; return MAD_FLOW_BREAK;
} }
/* Add accurate PTS to buffer. */
if ( p_mad_adec->i_current_pts ) p_buffer->start_date = aout_DateGet( &p_dec->end_date );
{ p_buffer->end_date = aout_DateIncrement( &p_dec->end_date, i_samples );
p_buffer->start_date = p_mad_adec->i_current_pts;
}
else
{
p_buffer->start_date = LAST_MDATE;
}
p_mad_adec->last_date += (mtime_t)(p_libmad_pcm->length*2)
/ p_mad_adec->output_format.i_rate;
p_buffer->end_date = p_mad_adec->last_date;
/* Interleave and keep buffers in mad_fixed_t format */ /* Interleave and keep buffers in mad_fixed_t format */
while (nsamples--) p_samples = (mad_fixed_t *)p_buffer->p_buffer;
switch( p_pcm->channels )
{ {
/* left audio channel */ case 2:
sample = *left_ch++; while( i_samples-- )
#ifndef WORDS_BIGENDIAN {
*(p_buffer->p_buffer)++ = (byte_t) (sample); *p_samples++ = *p_left++;
// *(p_buffer->p_buffer)++ = (byte_t) (sample >> 0); *p_samples++ = *p_right++;
// *(p_buffer->p_buffer)++ = (byte_t) (sample >> 8); }
#else break;
// *(p_buffer->p_buffer)++ = (byte_t) (sample >> 8); case 1:
// *(p_buffer->p_buffer)++ = (byte_t) (sample >> 0); while( i_samples-- )
#endif
/* right audio channel */
if (p_libmad_pcm->channels == 2)
{ {
sample = *right_ch++; *p_samples++ = *p_left;
} /* else reuse left audio channel */ *p_samples++ = *p_left++;
#ifndef WORDS_BIGENDIAN }
*(p_buffer->p_buffer)++ = (byte_t) (sample); break;
// *(p_buffer->p_buffer)++ = (byte_t) (sample >> 0); default:
// *(p_buffer->p_buffer)++ = (byte_t) (sample >> 8); msg_Err( p_dec->p_fifo, "cannot interleave %i channels",
#else p_pcm->channels );
// *(p_buffer->p_buffer)++ = (byte_t) (sample >> 8);
// *(p_buffer->p_buffer)++ = (byte_t) (sample >> 0);
#endif
} }
aout_BufferPlay( p_mad_adec->p_aout, p_mad_adec->p_aout_input, p_buffer ); aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer );
return MAD_FLOW_CONTINUE; return MAD_FLOW_CONTINUE;
} }
...@@ -494,95 +240,97 @@ enum mad_flow libmad_output3(void *data, struct mad_header const *p_libmad_heade ...@@ -494,95 +240,97 @@ enum mad_flow libmad_output3(void *data, struct mad_header const *p_libmad_heade
/***************************************************************************** /*****************************************************************************
* libmad_error: this function is called when an error occurs during decoding * libmad_error: this function is called when an error occurs during decoding
*****************************************************************************/ *****************************************************************************/
enum mad_flow libmad_error(void *data, struct mad_stream *p_libmad_stream, struct mad_frame *p_libmad_frame) enum mad_flow libmad_error( void *data, struct mad_stream *p_libmad_stream,
struct mad_frame *p_libmad_frame )
{ {
mad_adec_thread_t *p_dec = (mad_adec_thread_t *) data;
enum mad_flow result = MAD_FLOW_CONTINUE; enum mad_flow result = MAD_FLOW_CONTINUE;
switch (p_libmad_stream->error) switch (p_libmad_stream->error)
{ {
case MAD_ERROR_BUFLEN: /* input buffer too small (or EOF) */ case MAD_ERROR_BUFLEN: /* input buffer too small (or EOF) */
//X msg_Err("libmad error: input buffer too small (or EOF)"); msg_Err( p_dec->p_fifo, "input buffer too small (or EOF)" );
result = MAD_FLOW_CONTINUE; result = MAD_FLOW_CONTINUE;
break; break;
case MAD_ERROR_BUFPTR: /* invalid (null) buffer pointer */ case MAD_ERROR_BUFPTR: /* invalid (null) buffer pointer */
//X msg_Err("libmad error: invalid (null) buffer pointer"); msg_Err( p_dec->p_fifo, "invalid (null) buffer pointer" );
result = MAD_FLOW_STOP; result = MAD_FLOW_STOP;
break; break;
case MAD_ERROR_NOMEM: /* not enough memory */ case MAD_ERROR_NOMEM: /* not enough memory */
//X msg_Err("libmad error: invalid (null) buffer pointer"); msg_Err( p_dec->p_fifo, "invalid (null) buffer pointer" );
result = MAD_FLOW_STOP; result = MAD_FLOW_STOP;
break; break;
case MAD_ERROR_LOSTSYNC: /* lost synchronization */ case MAD_ERROR_LOSTSYNC: /* lost synchronization */
//X msg_Err("libmad error: lost synchronization"); msg_Err( p_dec->p_fifo, "lost synchronization" );
mad_stream_sync(p_libmad_stream); mad_stream_sync(p_libmad_stream);
result = MAD_FLOW_CONTINUE; result = MAD_FLOW_CONTINUE;
break; break;
case MAD_ERROR_BADLAYER: /* reserved header layer value */ case MAD_ERROR_BADLAYER: /* reserved header layer value */
//X msg_Err("libmad error: reserved header layer value"); msg_Err( p_dec->p_fifo, "reserved header layer value" );
result = MAD_FLOW_CONTINUE; result = MAD_FLOW_CONTINUE;
break; break;
case MAD_ERROR_BADBITRATE: /* forbidden bitrate value */ case MAD_ERROR_BADBITRATE: /* forbidden bitrate value */
//X msg_Err("libmad error: forbidden bitrate value"); msg_Err( p_dec->p_fifo, "forbidden bitrate value" );
result = MAD_FLOW_CONTINUE; result = MAD_FLOW_CONTINUE;
break; break;
case MAD_ERROR_BADSAMPLERATE: /* reserved sample frequency value */ case MAD_ERROR_BADSAMPLERATE: /* reserved sample frequency value */
//X msg_Err("libmad error: reserved sample frequency value"); msg_Err( p_dec->p_fifo, "reserved sample frequency value" );
result = MAD_FLOW_CONTINUE; result = MAD_FLOW_CONTINUE;
break; break;
case MAD_ERROR_BADEMPHASIS: /* reserved emphasis value */ case MAD_ERROR_BADEMPHASIS: /* reserved emphasis value */
//X msg_Err("libmad error: reserverd emphasis value"); msg_Err( p_dec->p_fifo, "reserverd emphasis value" );
result = MAD_FLOW_CONTINUE; result = MAD_FLOW_CONTINUE;
break; break;
case MAD_ERROR_BADCRC: /* CRC check failed */ case MAD_ERROR_BADCRC: /* CRC check failed */
//X msg_Err("libmad error: CRC check failed"); msg_Err( p_dec->p_fifo, "CRC check failed" );
result = MAD_FLOW_CONTINUE; result = MAD_FLOW_CONTINUE;
break; break;
case MAD_ERROR_BADBITALLOC: /* forbidden bit allocation value */ case MAD_ERROR_BADBITALLOC: /* forbidden bit allocation value */
//X msg_Err("libmad error: forbidden bit allocation value"); msg_Err( p_dec->p_fifo, "forbidden bit allocation value" );
result = MAD_FLOW_IGNORE; result = MAD_FLOW_IGNORE;
break; break;
case MAD_ERROR_BADSCALEFACTOR:/* bad scalefactor index */ case MAD_ERROR_BADSCALEFACTOR:/* bad scalefactor index */
//X msg_Err("libmad error: bad scalefactor index"); msg_Err( p_dec->p_fifo, "bad scalefactor index" );
result = MAD_FLOW_CONTINUE; result = MAD_FLOW_CONTINUE;
break; break;
case MAD_ERROR_BADFRAMELEN: /* bad frame length */ case MAD_ERROR_BADFRAMELEN: /* bad frame length */
//X msg_Err("libmad error: bad frame length"); msg_Err( p_dec->p_fifo, "bad frame length" );
result = MAD_FLOW_CONTINUE; result = MAD_FLOW_CONTINUE;
break; break;
case MAD_ERROR_BADBIGVALUES: /* bad big_values count */ case MAD_ERROR_BADBIGVALUES: /* bad big_values count */
//X msg_Err("libmad error: bad big values count"); msg_Err( p_dec->p_fifo, "bad big values count" );
result = MAD_FLOW_IGNORE; result = MAD_FLOW_IGNORE;
break; break;
case MAD_ERROR_BADBLOCKTYPE: /* reserved block_type */ case MAD_ERROR_BADBLOCKTYPE: /* reserved block_type */
//X msg_Err("libmad error: reserverd block_type"); msg_Err( p_dec->p_fifo, "reserverd block_type" );
result = MAD_FLOW_IGNORE; result = MAD_FLOW_IGNORE;
break; break;
case MAD_ERROR_BADSCFSI: /* bad scalefactor selection info */ case MAD_ERROR_BADSCFSI: /* bad scalefactor selection info */
//X msg_Err("libmad error: bad scalefactor selection info"); msg_Err( p_dec->p_fifo, "bad scalefactor selection info" );
result = MAD_FLOW_CONTINUE; result = MAD_FLOW_CONTINUE;
break; break;
case MAD_ERROR_BADDATAPTR: /* bad main_data_begin pointer */ case MAD_ERROR_BADDATAPTR: /* bad main_data_begin pointer */
//X msg_Err("libmad error: bad main_data_begin pointer"); msg_Err( p_dec->p_fifo, "bad main_data_begin pointer" );
result = MAD_FLOW_STOP; result = MAD_FLOW_STOP;
break; break;
case MAD_ERROR_BADPART3LEN: /* bad audio data length */ case MAD_ERROR_BADPART3LEN: /* bad audio data length */
//X msg_Err("libmad error: bad audio data length"); msg_Err( p_dec->p_fifo, "bad audio data length" );
result = MAD_FLOW_IGNORE; result = MAD_FLOW_IGNORE;
break; break;
case MAD_ERROR_BADHUFFTABLE: /* bad Huffman table select */ case MAD_ERROR_BADHUFFTABLE: /* bad Huffman table select */
//X msg_Err("libmad error: bad Huffman table select"); msg_Err( p_dec->p_fifo, "bad Huffman table select" );
result = MAD_FLOW_IGNORE; result = MAD_FLOW_IGNORE;
break; break;
case MAD_ERROR_BADHUFFDATA: /* Huffman data overrun */ case MAD_ERROR_BADHUFFDATA: /* Huffman data overrun */
//X msg_Err("libmad error: Huffman data overrun"); msg_Err( p_dec->p_fifo, "Huffman data overrun" );
result = MAD_FLOW_IGNORE; result = MAD_FLOW_IGNORE;
break; break;
case MAD_ERROR_BADSTEREO: /* incompatible block_type for JS */ case MAD_ERROR_BADSTEREO: /* incompatible block_type for JS */
//X msg_Err("libmad error: incompatible block_type for JS"); msg_Err( p_dec->p_fifo, "incompatible block_type for JS" );
result = MAD_FLOW_IGNORE; result = MAD_FLOW_IGNORE;
break; break;
default: default:
//X msg_Err("libmad error: unknown error occured stopping decoder"); msg_Err( p_dec->p_fifo, "unknown error occured stopping decoder" );
result = MAD_FLOW_STOP; result = MAD_FLOW_STOP;
break; break;
} }
...@@ -611,7 +359,7 @@ static void PrintFrameInfo(struct mad_header *Header) ...@@ -611,7 +359,7 @@ static void PrintFrameInfo(struct mad_header *Header)
*Mode, *Mode,
*Emphasis; *Emphasis;
/* Convert the layer number to it's printed representation. */ /* Convert the layer number to its printed representation. */
switch(Header->layer) switch(Header->layer)
{ {
case MAD_LAYER_I: case MAD_LAYER_I:
...@@ -628,7 +376,7 @@ static void PrintFrameInfo(struct mad_header *Header) ...@@ -628,7 +376,7 @@ static void PrintFrameInfo(struct mad_header *Header)
break; break;
} }
/* Convert the audio mode to it's printed representation. */ /* Convert the audio mode to its printed representation. */
switch(Header->mode) switch(Header->mode)
{ {
case MAD_MODE_SINGLE_CHANNEL: case MAD_MODE_SINGLE_CHANNEL:
...@@ -648,7 +396,7 @@ static void PrintFrameInfo(struct mad_header *Header) ...@@ -648,7 +396,7 @@ static void PrintFrameInfo(struct mad_header *Header)
break; break;
} }
/* Convert the emphasis to it's printed representation. */ /* Convert the emphasis to its printed representation. */
switch(Header->emphasis) switch(Header->emphasis)
{ {
case MAD_EMPHASIS_NONE: case MAD_EMPHASIS_NONE:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment