#include <stdlib.h> /* malloc(), free() */
#include <string.h> /* strdup() */
-#include <videolan/vlc.h>
-
-#include "audio_output.h"
-
-#include "stream_control.h"
-#include "input_ext-dec.h"
-
-#include "debug.h"
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/decoder.h>
/*****************************************************************************
* Libmad includes files
#include "mad_adec.h"
#include "mad_libmad.h"
+static void PrintFrameInfo(struct mad_header *Header);
+
/*****************************************************************************
* libmad_input: this function is called by libmad when the input buffer needs
* to be filled.
unsigned char *ReadStart;
if ( p_mad_adec->p_fifo->b_die == 1 ) {
- intf_ErrMsg( "mad_adec error: libmad_input stopping libmad decoder" );
+ msg_Err( p_mad_adec->p_fifo, "libmad_input stopping libmad decoder" );
return MAD_FLOW_STOP;
}
if ( p_mad_adec->p_fifo->b_error == 1 ) {
- intf_ErrMsg( "mad_adec error: libmad_input ignoring current audio frame" );
+ msg_Err( p_mad_adec->p_fifo, "libmad_input ignoring current audio frame" );
return MAD_FLOW_IGNORE;
}
Remaining=p_libmad_stream->bufend-p_libmad_stream->next_frame;
if( p_mad_adec->buffer != p_libmad_stream->next_frame )
{
- FAST_MEMCPY( p_mad_adec->buffer, p_libmad_stream->next_frame,
- Remaining );
+ p_mad_adec->p_fifo->p_vlc->pf_memcpy( p_mad_adec->buffer,
+ p_libmad_stream->next_frame, Remaining );
}
ReadStart=p_mad_adec->buffer+Remaining;
- ReadSize=(MAD_BUFFER_SIZE)-Remaining;
+ ReadSize=(MAD_BUFFER_MDLEN)-Remaining;
/* Store time stamp of next frame */
p_mad_adec->i_current_pts = p_mad_adec->i_next_pts;
}
else
{
- ReadSize=(MAD_BUFFER_SIZE);
+ ReadSize=(MAD_BUFFER_MDLEN);
ReadStart=p_mad_adec->buffer;
Remaining=0;
p_mad_adec->i_next_pts = 0;
{
ReadSize = p_mad_adec->p_data->p_payload_end
- p_mad_adec->p_data->p_payload_start;
- FAST_MEMCPY( ReadStart, p_mad_adec->p_data->p_payload_start,
- ReadSize );
+ p_mad_adec->p_fifo->p_vlc->pf_memcpy( ReadStart,
+ p_mad_adec->p_data->p_payload_start, ReadSize );
NextDataPacket( p_mad_adec->p_fifo, &p_mad_adec->p_data );
}
else
{
- FAST_MEMCPY( ReadStart, p_mad_adec->p_data->p_payload_start,
- ReadSize );
+ p_mad_adec->p_fifo->p_vlc->pf_memcpy( ReadStart,
+ p_mad_adec->p_data->p_payload_start, ReadSize );
p_mad_adec->p_data->p_payload_start += ReadSize;
}
if ( p_mad_adec->p_fifo->b_die == 1 )
{
- intf_ErrMsg( "mad_adec error: libmad_input stopping libmad decoder" );
+ msg_Dbg( p_mad_adec->p_fifo, "libmad_input stopping libmad decoder" );
return MAD_FLOW_STOP;
}
if ( p_mad_adec->p_fifo->b_error == 1 )
{
- intf_ErrMsg( "mad_adec error: libmad_input ignoring current audio frame" );
+ msg_Err( p_mad_adec->p_fifo, "libmad_input ignoring current audio frame" );
return MAD_FLOW_IGNORE;
}
*{
* mad_adec_thread_t *p_mad_adec = (mad_adec_thread_t *) data;
*
- * intf_ErrMsg( "mad_adec: libmad_header samplerate %d", p_libmad_header->samplerate);
- *
- * p_mad_adec->p_aout_fifo->i_rate = p_libmad_header->samplerate;
- * mad_timer_add(&p_mad_adec->libmad_timer,p_libmad_header->duration);
+ * msg_Err( p_mad_adec->p_fifo, "libmad_header samplerate %d", p_libmad_header->samplerate);
*
+ * PrintFrameInfo(p_limad_mad_header)
* return MAD_FLOW_CONTINUE;
*}
*/
* }
*/
-//#define MPG321_ROUTINES 1
-#ifdef MPG321_ROUTINES
/*****************************************************************************
* support routines borrowed from mpg321 (file: mad.c), which is distributed
* under GPL license
* NAME: prng()
* DESCRIPTION: 32-bit pseudo-random number generator
*/
-static __inline__ unsigned long prng(unsigned long state)
+static inline unsigned long prng(unsigned long state)
{
return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
}
/*
-* NAME: audio_linear_dither()
+* NAME: mpg321_s24_to_s16_pcm()
* DESCRIPTION: generic linear sample quantize and dither routine
*/
-static __inline__ signed int audio_linear_dither(unsigned int bits, mad_fixed_t sample,
+static inline signed int mpg321_s24_to_s16_pcm(unsigned int bits, mad_fixed_t sample,
struct audio_dither *dither)
{
unsigned int scalebits;
/* scale */
return output >> scalebits;
}
-#else
/*****************************************************************************
* 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)
+static inline mad_fixed_t s24_to_s16_pcm(mad_fixed_t sample)
{
/* round */
sample += (1L << (MAD_F_FRACBITS - 16));
/* quantize */
return sample >> (MAD_F_FRACBITS + 1 - 16);
}
-#endif
/*****************************************************************************
* libmad_ouput: this function is called just after the frame is decoded
{
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;
-#ifdef MPG321_ROUTINES
static struct audio_dither dither;
-#endif
/* 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 */
- p_libmad_pcm->channels, /* nr. of channels */
+ 2, /*p_libmad_pcm->channels,*/ /* nr. of channels */
p_libmad_pcm->samplerate, /* frame rate in Hz ?*/
- ADEC_FRAME_SIZE, /* frame size */
+ p_libmad_pcm->length*2, /* length of output buffer *2 channels*/
NULL ); /* buffer */
if ( p_mad_adec->p_aout_fifo == NULL )
return( -1 );
}
- intf_ErrMsg("mad_adec debug: in libmad_output aout fifo created");
+ msg_Dbg( p_mad_adec->p_fifo, "aout fifo created");
}
if (p_mad_adec->p_aout_fifo->i_rate != p_libmad_pcm->samplerate)
{
- intf_ErrMsg( "mad_adec: libmad_output 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);
+ 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;
}
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);
+// 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 * MAD_OUTPUT_SIZE);
+ 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--)
{
-#ifdef MPG321_ROUTINES
- sample = audio_linear_dither(16, *left_ch++, &dither);
-#else
- sample = s24_to_s16_pcm(*left_ch++);
-#endif
-
+ 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);
+ *buffer++ = (byte_t) (sample >> 8);
+ *buffer++ = (byte_t) (sample >> 0);
#endif
- if (p_libmad_pcm->channels == 2) {
-
- /* right audio channel */
-#ifdef MPG321_ROUTINES
- sample = audio_linear_dither(16, *right_ch++, &dither);
-#else
- sample = s24_to_s16_pcm(*right_ch++);
-#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);
+ *buffer++ = (byte_t) (sample >> 0);
+ *buffer++ = (byte_t) (sample >> 8);
#else
- *buffer++ = (byte_t) (sample >> 8);
- *buffer++ = (byte_t) (sample >> 0);
+ *buffer++ = (byte_t) (sample >> 8);
+ *buffer++ = (byte_t) (sample >> 0);
#endif
- }
- else {
- /* Somethimes a single channel frame is found, while the rest of the movie are
- * stereo channel frames. How to deal with this ??
- * One solution is to silence the second channel.
- */
- *buffer++ = (byte_t) (0);
- *buffer++ = (byte_t) (0);
- }
}
+
/* DEBUG */
+ /*
if (p_libmad_pcm->channels == 1) {
- intf_ErrMsg( "mad debug: libmad_output channels [%d]", p_libmad_pcm->channels);
+ 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;
switch (p_libmad_stream->error)
{
case MAD_ERROR_BUFLEN: /* input buffer too small (or EOF) */
- intf_ErrMsg("libmad error: input buffer too small (or EOF)");
+//X intf_ErrMsg("libmad error: input buffer too small (or EOF)");
result = MAD_FLOW_CONTINUE;
break;
case MAD_ERROR_BUFPTR: /* invalid (null) buffer pointer */
- intf_ErrMsg("libmad error: invalid (null) buffer pointer");
+//X intf_ErrMsg("libmad error: invalid (null) buffer pointer");
result = MAD_FLOW_STOP;
break;
case MAD_ERROR_NOMEM: /* not enough memory */
- intf_ErrMsg("libmad error: invalid (null) buffer pointer");
+//X intf_ErrMsg("libmad error: invalid (null) buffer pointer");
result = MAD_FLOW_STOP;
break;
case MAD_ERROR_LOSTSYNC: /* lost synchronization */
- intf_ErrMsg("libmad error: lost synchronization");
+//X intf_ErrMsg("libmad error: lost synchronization");
mad_stream_sync(p_libmad_stream);
result = MAD_FLOW_CONTINUE;
break;
case MAD_ERROR_BADLAYER: /* reserved header layer value */
- intf_ErrMsg("libmad error: reserved header layer value");
+//X intf_ErrMsg("libmad error: reserved header layer value");
result = MAD_FLOW_CONTINUE;
break;
case MAD_ERROR_BADBITRATE: /* forbidden bitrate value */
- intf_ErrMsg("libmad error: forbidden bitrate value");
+//X intf_ErrMsg("libmad error: forbidden bitrate value");
result = MAD_FLOW_CONTINUE;
break;
case MAD_ERROR_BADSAMPLERATE: /* reserved sample frequency value */
- intf_ErrMsg("libmad error: reserved sample frequency value");
+//X intf_ErrMsg("libmad error: reserved sample frequency value");
result = MAD_FLOW_CONTINUE;
break;
case MAD_ERROR_BADEMPHASIS: /* reserved emphasis value */
- intf_ErrMsg("libmad error: reserverd emphasis value");
+//X intf_ErrMsg("libmad error: reserverd emphasis value");
result = MAD_FLOW_CONTINUE;
break;
case MAD_ERROR_BADCRC: /* CRC check failed */
- intf_ErrMsg("libmad error: CRC check failed");
+//X intf_ErrMsg("libmad error: CRC check failed");
result = MAD_FLOW_CONTINUE;
break;
case MAD_ERROR_BADBITALLOC: /* forbidden bit allocation value */
- intf_ErrMsg("libmad error: forbidden bit allocation value");
+//X intf_ErrMsg("libmad error: forbidden bit allocation value");
result = MAD_FLOW_IGNORE;
break;
case MAD_ERROR_BADSCALEFACTOR:/* bad scalefactor index */
- intf_ErrMsg("libmad error: bad scalefactor index");
+//X intf_ErrMsg("libmad error: bad scalefactor index");
result = MAD_FLOW_CONTINUE;
break;
case MAD_ERROR_BADFRAMELEN: /* bad frame length */
- intf_ErrMsg("libmad error: bad frame length");
+//X intf_ErrMsg("libmad error: bad frame length");
result = MAD_FLOW_CONTINUE;
break;
case MAD_ERROR_BADBIGVALUES: /* bad big_values count */
- intf_ErrMsg("libmad error: bad big values count");
+//X intf_ErrMsg("libmad error: bad big values count");
result = MAD_FLOW_IGNORE;
break;
case MAD_ERROR_BADBLOCKTYPE: /* reserved block_type */
- intf_ErrMsg("libmad error: reserverd block_type");
+//X intf_ErrMsg("libmad error: reserverd block_type");
result = MAD_FLOW_IGNORE;
break;
case MAD_ERROR_BADSCFSI: /* bad scalefactor selection info */
- intf_ErrMsg("libmad error: bad scalefactor selection info");
+//X intf_ErrMsg("libmad error: bad scalefactor selection info");
result = MAD_FLOW_CONTINUE;
break;
case MAD_ERROR_BADDATAPTR: /* bad main_data_begin pointer */
- intf_ErrMsg("libmad error: bad main_data_begin pointer");
+//X intf_ErrMsg("libmad error: bad main_data_begin pointer");
result = MAD_FLOW_STOP;
break;
case MAD_ERROR_BADPART3LEN: /* bad audio data length */
- intf_ErrMsg("libmad error: bad audio data length");
+//X intf_ErrMsg("libmad error: bad audio data length");
result = MAD_FLOW_IGNORE;
break;
case MAD_ERROR_BADHUFFTABLE: /* bad Huffman table select */
- intf_ErrMsg("libmad error: bad Huffman table select");
+//X intf_ErrMsg("libmad error: bad Huffman table select");
result = MAD_FLOW_IGNORE;
break;
case MAD_ERROR_BADHUFFDATA: /* Huffman data overrun */
- intf_ErrMsg("libmad error: Huffman data overrun");
+//X intf_ErrMsg("libmad error: Huffman data overrun");
result = MAD_FLOW_IGNORE;
break;
case MAD_ERROR_BADSTEREO: /* incompatible block_type for JS */
- intf_ErrMsg("libmad error: incompatible block_type for JS");
+//X intf_ErrMsg("libmad error: incompatible block_type for JS");
result = MAD_FLOW_IGNORE;
break;
default:
- intf_ErrMsg("libmad error: unknown error occured stopping decoder");
+//X intf_ErrMsg("libmad error: unknown error occured stopping decoder");
result = MAD_FLOW_STOP;
break;
}
*/
+
+/****************************************************************************
+ * Print human readable informations about an audio MPEG frame. *
+ ****************************************************************************/
+static void PrintFrameInfo(struct mad_header *Header)
+{
+ const char *Layer,
+ *Mode,
+ *Emphasis;
+
+ /* Convert the layer number to it's printed representation. */
+ switch(Header->layer)
+ {
+ case MAD_LAYER_I:
+ Layer="I";
+ break;
+ case MAD_LAYER_II:
+ Layer="II";
+ break;
+ case MAD_LAYER_III:
+ Layer="III";
+ break;
+ default:
+ Layer="(unexpected layer value)";
+ break;
+ }
+
+ /* Convert the audio mode to it's printed representation. */
+ switch(Header->mode)
+ {
+ case MAD_MODE_SINGLE_CHANNEL:
+ Mode="single channel";
+ break;
+ case MAD_MODE_DUAL_CHANNEL:
+ Mode="dual channel";
+ break;
+ case MAD_MODE_JOINT_STEREO:
+ Mode="joint (MS/intensity) stereo";
+ break;
+ case MAD_MODE_STEREO:
+ Mode="normal LR stereo";
+ break;
+ default:
+ Mode="(unexpected mode value)";
+ break;
+ }
+
+ /* Convert the emphasis to it's printed representation. */
+ switch(Header->emphasis)
+ {
+ case MAD_EMPHASIS_NONE:
+ Emphasis="no";
+ break;
+ case MAD_EMPHASIS_50_15_US:
+ Emphasis="50/15 us";
+ break;
+ case MAD_EMPHASIS_CCITT_J_17:
+ Emphasis="CCITT J.17";
+ break;
+ default:
+ Emphasis="(unexpected emphasis value)";
+ break;
+ }
+
+//X intf_ErrMsg("statistics: %lu kb/s audio mpeg layer %s stream %s crc, "
+//X "%s with %s emphasis at %d Hz sample rate\n",
+//X Header->bitrate,Layer,
+//X Header->flags&MAD_FLAG_PROTECTION?"with":"without",
+//X Mode,Emphasis,Header->samplerate);
+}