]> git.sesse.net Git - vlc/commitdiff
* ./modules/audio_filter/converter/fixed32tofloat32.c: fixed conversion.
authorSam Hocevar <sam@videolan.org>
Thu, 22 Aug 2002 17:14:52 +0000 (17:14 +0000)
committerSam Hocevar <sam@videolan.org>
Thu, 22 Aug 2002 17:14:52 +0000 (17:14 +0000)
  * ./modules/codec/mad/libmad.c: ported to the latest aout changes. Still
    doesn't work here, though.

modules/audio_filter/converter/fixed32tofloat32.c
modules/codec/mad/decoder.c
modules/codec/mad/decoder.h
modules/codec/mad/libmad.c

index b9a9f351dbf6d1a1fc46a67e20e3ffaab453030a..d936fd1bca002506302e88903d440d39de3eb8b9 100644 (file)
@@ -2,7 +2,7 @@
  * fixed32float32.c : converter from fixed32 to float32 bits integer
  *****************************************************************************
  * 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>
  *
@@ -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-- ; )
     {
-        /* convert vlc_fixed_t into s32 */
-#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++ = (float)*p_in++ / -(float)FIXED32_MIN;
     }
 
     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
index a9b07f19707591f4dfd54bd4090a6d77f4f9cb8e..e7b25d489eb57ff9ed6d093d52b521da48f3c14b 100644 (file)
  *****************************************************************************/
 static int  OpenDecoder    ( vlc_object_t * );
 static int  RunDecoder     ( decoder_fifo_t * );
-static int  InitThread     ( mad_adec_thread_t * p_mad_adec );
-static void EndThread      ( mad_adec_thread_t * p_mad_adec );
+static int  InitThread     ( mad_adec_thread_t * );
+static void EndThread      ( mad_adec_thread_t * );
 
 /*****************************************************************************
  * 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_( \
     "Specify the mad audio downscale routine you want to use. By default " \
     "the mad plugin will use the fastest routine.")
 
 vlc_module_begin();
-    add_category_hint( N_("Miscellaneous"), NULL );
+    add_category_hint( N_("Libmad"), NULL );
     add_string( "downscale", "fast", NULL, DOWNSCALE_TEXT, DOWNSCALE_LONGTEXT );
     set_description( _("libmad MPEG 1/2/3 audio decoder") );
     set_capability( "decoder", 100 );
@@ -85,68 +85,71 @@ static int OpenDecoder( vlc_object_t *p_this )
  *****************************************************************************/
 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 */
-    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" );
         DecoderError( p_fifo );
-        return( -1 );
+        return VLC_ENOMEM;
     }
 
     /*
      * Initialize the thread properties
      */
-    p_mad_adec->p_fifo = p_fifo;
-    if( InitThread( p_mad_adec ) )
+    p_dec->p_fifo = p_fifo;
+    if( InitThread( p_dec ) )
     {
         msg_Err( p_fifo, "could not initialize thread" );
         DecoderError( p_fifo );
-        free( p_mad_adec );
-        return( -1 );
+        free( p_dec );
+        return VLC_ETHREAD;
     }
 
     /* 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" );
-        if (mad_decoder_run(p_mad_adec->libmad_decoder, MAD_DECODER_MODE_SYNC)==-1)
+        msg_Dbg( p_dec->p_fifo, "starting libmad decoder" );
+        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" );
-            DecoderError( p_mad_adec->p_fifo );
-            EndThread(p_mad_adec);
-            return( -1 );
+            msg_Err( p_dec->p_fifo, "libmad decoder returned abnormally" );
+            DecoderError( p_dec->p_fifo );
+            EndThread(p_dec);
+            return VLC_EGENERIC;
         }
     }
 
     /* 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 */
-    EndThread (p_mad_adec);
+    EndThread (p_dec);
 
-    return( 0 );
+    return VLC_SUCCESS;
 }
 
 /*****************************************************************************
  * 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;
 
     /* Initialize the thread properties */
-    p_mad_adec->p_aout = NULL;
-    p_mad_adec->p_aout_input = NULL;
-    p_mad_adec->output_format.i_format = AOUT_FMT_FIXED32;
-    p_mad_adec->output_format.i_channels = 2; /* FIXME ! */
+    p_dec->p_aout = NULL;
+    p_dec->p_aout_input = NULL;
+    p_dec->output_format.i_format = AOUT_FMT_FIXED32;
+    p_dec->output_format.i_channels = 2; /* FIXME ! */
 
     /*
      * Properties of audio for libmad
@@ -157,45 +160,43 @@ static int InitThread( mad_adec_thread_t * p_mad_adec )
 
     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" );
     }
     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" );
     }
     else
     {
-        p_mad_adec->audio_scaling = FAST_SCALING;
+        p_dec->audio_scaling = FAST_SCALING;
         msg_Dbg( p_fifo, "downscale default fast selected" );
     }
 
     if (psz_downscale) free(psz_downscale);
 
     /* Initialize the libmad decoder structures */
-    p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
-    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;
+    p_dec->i_current_pts = p_dec->i_next_pts = 0;
 
-    mad_decoder_init( p_mad_adec->libmad_decoder,
-                      p_mad_adec,       /* vlc's thread structure and p_fifo playbuffer */
-                      libmad_input,     /* input_func */
-                      0,                /* header_func */
-                      0,                /* filter */
-                      libmad_output3,   /* output_func */
-                      0,                /* error */
-                      0);               /* message */
+    mad_decoder_init( &p_dec->libmad_decoder,
+                      p_dec, /* vlc's thread structure and p_fifo playbuffer */
+                      libmad_input,    /* input_func */
+                      NULL,           /* header_func */
+                      NULL,                /* filter */
+                      libmad_output,  /* output_func */
+                      NULL,                 /* error */
+                      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
      */
+
+    /* Init the Bitstream */
+    InitBitstream( &p_dec->bit_stream, p_dec->p_fifo, NULL, NULL );
+
     /* Get the first data packet. */
     vlc_mutex_lock( &p_fifo->data_lock );
     while ( p_fifo->p_first == NULL )
@@ -203,32 +204,30 @@ static int InitThread( mad_adec_thread_t * p_mad_adec )
         if ( p_fifo->b_die )
         {
             vlc_mutex_unlock( &p_fifo->data_lock );
-            return( -1 );
+            return VLC_EGENERIC;
         }
         vlc_cond_wait( &p_fifo->data_wait, &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
  *****************************************************************************/
-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 (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( 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_mad_adec->libmad_decoder );
-    free( p_mad_adec );
+    free( p_dec );
 }
 
index 84944d9e14155074cb46c53f7b017ee991c195b0..825d7397637e527dc5d8f53b14c8324660af3ceb 100644 (file)
@@ -29,7 +29,7 @@ typedef struct mad_adec_thread_s
     /*
      * Decoder properties
      */
-    struct mad_decoder *libmad_decoder;
+    struct mad_decoder  libmad_decoder;
     mad_timer_t         libmad_timer;  
     byte_t              buffer[MAD_BUFFER_MDLEN];
    
@@ -38,6 +38,9 @@ typedef struct mad_adec_thread_s
      */
     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
      */
@@ -47,19 +50,14 @@ typedef struct mad_adec_thread_s
     /* Store i_pts for syncing audio frames */
     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
      */
     aout_instance_t *   p_aout; /* opaque */
     aout_input_t *      p_aout_input; /* opaque */
     audio_sample_format_t output_format;
+    audio_date_t        end_date;
 
-    mtime_t             last_date;
     enum mad_scaling   audio_scaling;
 
 } mad_adec_thread_t;
index 4ed0d888d861512dd3ee601c1612a6429a68b0a3..7575224b18a71650ec4c01f130e21928109fbe64 100644 (file)
@@ -41,452 +41,198 @@ static void PrintFrameInfo(struct mad_header *Header);
  * libmad_input: this function is called by libmad when the input buffer needs
  * 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;
-    size_t             ReadSize, Remaining;
-    unsigned char     *ReadStart;
+    mad_adec_thread_t * p_dec = (mad_adec_thread_t *) p_data;
+    size_t   i_wanted, i_left;
 
-    if ( p_mad_adec->p_fifo->b_die == 1 ) {
-        msg_Dbg( p_mad_adec->p_fifo, "libmad_input stopping libmad decoder" );
+    if ( p_dec->p_fifo->b_die )
+    {
+        msg_Dbg( p_dec->p_fifo, "stopping libmad decoder" );
         return MAD_FLOW_STOP;
     }
 
-    if ( p_mad_adec->p_fifo->b_error == 1 ) {
-        msg_Warn( p_mad_adec->p_fifo, "libmad_input ignoring current audio frame" );
+    if ( p_dec->p_fifo->b_error )
+    {
+        msg_Warn( p_dec->p_fifo, "ignoring current audio frame" );
         return MAD_FLOW_IGNORE;
     }
 
-    /* libmad_stream_buffer does not consume the total buffer, it consumes 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))
+    /* libmad_stream_buffer does not consume the total buffer, it consumes
+     * only data for one frame only. So all data left in the buffer should
+     * be put back in front. */
+    if ( !p_stream->buffer || p_stream->error == MAD_ERROR_BUFLEN )
     {
-        /* libmad does not consume all the buffer it's given. Some
-         * datas, part of a truncated frame, is left unused at the
-         * end of the buffer. Those datas must be put back at the
-         * beginning of the buffer and taken in account for
-         * refilling the buffer. This means that the input buffer
-         * must be large enough to hold a complete frame at the
-         * highest observable bit-rate (currently 448 kb/s). XXX=XXX
-         * Is 2016 bytes the size of the largest frame?
-         * (448000*(1152/32000))/8
-         */
-        if(p_libmad_stream->next_frame!=NULL)
+       /* libmad does not consume all the buffer it's given. Some data,
+        * part of a truncated frame, is left unused at the end of the
+        * buffer. Those datas must be put back at the beginning of the
+        * buffer and taken in account for refilling the buffer. This
+        * means that the input buffer must be large enough to hold a
+        * complete frame at the highest observable bit-rate (currently
+        * 448 kb/s). XXX=XXX Is 2016 bytes the size of the largest frame?
+        * (448000*(1152/32000))/8 */
+        if( p_stream->next_frame )
         {
-            Remaining=p_libmad_stream->bufend-p_libmad_stream->next_frame;
-            if( p_mad_adec->buffer != p_libmad_stream->next_frame )
+            i_left = p_stream->bufend - p_stream->next_frame;
+            if( p_dec->buffer != p_stream->next_frame )
             {
-                memcpy( p_mad_adec->buffer,
-                        p_libmad_stream->next_frame, Remaining );
+                memcpy( p_dec->buffer, p_stream->next_frame, i_left );
             }
-            ReadStart=p_mad_adec->buffer+Remaining;
-            ReadSize=(MAD_BUFFER_MDLEN)-Remaining;
+            i_wanted = MAD_BUFFER_MDLEN - i_left;
 
-            /* Store time stamp of next frame */
-            p_mad_adec->i_current_pts = p_mad_adec->i_next_pts;
-            p_mad_adec->i_next_pts = p_mad_adec->p_fifo->p_first->i_pts;
+            /* Store timestamp for next frame */
+            p_dec->i_next_pts = p_dec->p_fifo->p_first->i_pts;
         }
         else
         {
-            ReadSize=(MAD_BUFFER_MDLEN);
-            ReadStart=p_mad_adec->buffer;
-            Remaining=0;
-            p_mad_adec->i_next_pts = 0;
-            p_mad_adec->i_current_pts = p_mad_adec->p_fifo->p_first->i_pts;
+            i_wanted = MAD_BUFFER_MDLEN;
+            i_left = 0;
+
+            /* Store timestamp for this frame */
+            p_dec->i_current_pts = p_dec->p_fifo->p_first->i_pts;
         }
 
-        /* Fill-in the buffer. If an error occurs print a message
-         * and leave the decoding loop. If the end of stream is
-         * reached we also leave the loop but the return status is
-         * left untouched.
-         */
-        if( ReadSize > p_mad_adec->p_data->p_payload_end
-                        - p_mad_adec->p_data->p_payload_start )
+        /* Fill-in the buffer. If an error occurs print a message and leave
+         * the decoding loop. If the end of stream is reached we also leave
+         * the loop but the return status is left untouched. */
+        if( i_wanted > p_dec->p_data->p_payload_end
+                        - p_dec->p_data->p_payload_start )
         {
-            ReadSize = p_mad_adec->p_data->p_payload_end
-                        - p_mad_adec->p_data->p_payload_start;
-            memcpy( ReadStart, p_mad_adec->p_data->p_payload_start, ReadSize );
-            NextDataPacket( p_mad_adec->p_fifo, &p_mad_adec->p_data );
+            i_wanted = p_dec->p_data->p_payload_end
+                        - p_dec->p_data->p_payload_start;
+            memcpy( p_dec->buffer + i_left,
+                    p_dec->p_data->p_payload_start, i_wanted );
+            NextDataPacket( p_dec->p_fifo, &p_dec->p_data );
         }
         else
         {
-            memcpy( ReadStart, p_mad_adec->p_data->p_payload_start, ReadSize );
-            p_mad_adec->p_data->p_payload_start += ReadSize;
+            memcpy( p_dec->buffer + i_left,
+                    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;
         }
 
-        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;
         }
 
         /* Pipe the new buffer content to libmad's stream decoder facility.
-         * Libmad never copies the buffer, but just references it. So keep it in
-         * mad_adec_thread_t structure.
-         */
-        mad_stream_buffer(p_libmad_stream,(unsigned char*) &p_mad_adec->buffer,
-                          Remaining + ReadSize);
-        p_libmad_stream->error=0;
+         * Libmad never copies the buffer, but just references it. So keep
+         * it in mad_adec_thread_t structure. */
+        mad_stream_buffer( p_stream, (unsigned char*) &p_dec->buffer,
+                           i_left + i_wanted );
+        p_stream->error = 0;
     }
 
     return MAD_FLOW_CONTINUE;
 }
 
 /*****************************************************************************
- * libmad_header: this function is called just after the header of a frame is
- * 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
+ * libmad_output: 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)
-//{
-//    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)
+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;
-    aout_buffer_t * p_buffer;
-    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;
-
-    /* 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_input != NULL) &&
-        (p_mad_adec->output_format.i_rate != p_libmad_pcm->samplerate) )
+    mad_adec_thread_t * p_dec = (mad_adec_thread_t *) p_data;
+    aout_buffer_t *     p_buffer;
+    mad_fixed_t const * p_left = p_pcm->samples[0];
+    mad_fixed_t const * p_right = p_pcm->samples[1];
+    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 is right for the entire audio track. */
+    if( (p_dec->p_aout_input != NULL) &&
+        (p_dec->output_format.i_rate != p_pcm->samplerate) )
     {
         /* Parameters changed - this should not happen. */
-        aout_InputDelete( p_mad_adec->p_aout, p_mad_adec->p_aout_input );
-        p_mad_adec->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_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_mad_adec->output_format.i_channels = p_libmad_pcm->channels; */
-        p_mad_adec->p_aout_input = aout_InputNew( p_mad_adec->p_fifo,
-                                               &p_mad_adec->p_aout,
-                                               &p_mad_adec->output_format );
+        p_dec->output_format.i_rate = p_pcm->samplerate;
+        /* p_dec->output_format.i_channels = p_pcm->channels; */
+        aout_DateInit( &p_dec->end_date, p_pcm->samplerate );
+        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 = 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;
-           return MAD_FLOW_BREAK;
+            aout_DateSet( &p_dec->end_date, p_dec->i_current_pts );
         }
-        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 "
-                  "to [%d] Hz, sample size [%d], error_code [%0x]",
-                  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;
+        /* No date available yet, wait for the first PTS. */
+        return MAD_FLOW_CONTINUE;
     }
 
-    /* Set the Presentation Time Stamp */
-    p_buffer = aout_BufferNew( p_mad_adec->p_aout,
-                               p_mad_adec->p_aout_input,
-                               (p_libmad_pcm->length*2) );
+    p_buffer = aout_BufferNew( p_dec->p_aout, p_dec->p_aout_input, i_samples );
 
     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;
     }
-    /* Add accurate PTS to buffer. */
-    if ( p_mad_adec->i_current_pts )
-    {
-        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;
+
+    p_buffer->start_date = aout_DateGet( &p_dec->end_date );
+    p_buffer->end_date = aout_DateIncrement( &p_dec->end_date, i_samples );
 
     /* 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 */
-        sample = *left_ch++;
-#ifndef WORDS_BIGENDIAN
-        *(p_buffer->p_buffer)++ = (byte_t) (sample);
-//        *(p_buffer->p_buffer)++ = (byte_t) (sample >> 0);
-//        *(p_buffer->p_buffer)++ = (byte_t) (sample >> 8);
-#else
-//        *(p_buffer->p_buffer)++ = (byte_t) (sample >> 8);
-//        *(p_buffer->p_buffer)++ = (byte_t) (sample >> 0);
-#endif
-        /* right audio channel */
-        if (p_libmad_pcm->channels == 2)
+    case 2:
+        while( i_samples-- )
+        {
+            *p_samples++ = *p_left++;
+            *p_samples++ = *p_right++;
+        }
+        break;
+    case 1:
+        while( i_samples-- )
         {
-           sample = *right_ch++;
-        } /* else reuse left audio channel */
-#ifndef WORDS_BIGENDIAN
-        *(p_buffer->p_buffer)++ = (byte_t) (sample);
-//        *(p_buffer->p_buffer)++ = (byte_t) (sample >> 0);
-//        *(p_buffer->p_buffer)++ = (byte_t) (sample >> 8);
-#else
-//        *(p_buffer->p_buffer)++ = (byte_t) (sample >> 8);
-//        *(p_buffer->p_buffer)++ = (byte_t) (sample >> 0);
-#endif
+            *p_samples++ = *p_left;
+            *p_samples++ = *p_left++;
+        }
+        break;
+    default:
+        msg_Err( p_dec->p_fifo, "cannot interleave %i channels",
+                                p_pcm->channels );
     }
 
-    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;
 }
@@ -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
  *****************************************************************************/
-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;
 
     switch (p_libmad_stream->error)
     {             
     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;
         break;
     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;
         break;
     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;
         break;
     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);
         result = MAD_FLOW_CONTINUE;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     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;
         break;
     }
@@ -611,7 +359,7 @@ static void PrintFrameInfo(struct mad_header *Header)
                        *Mode,
                        *Emphasis;
 
-       /* Convert the layer number to it's printed representation. */
+       /* Convert the layer number to its printed representation. */
        switch(Header->layer)
        {
                case MAD_LAYER_I:
@@ -628,7 +376,7 @@ static void PrintFrameInfo(struct mad_header *Header)
                        break;
        }
 
-       /* Convert the audio mode to it's printed representation. */
+       /* Convert the audio mode to its printed representation. */
        switch(Header->mode)
        {
                case MAD_MODE_SINGLE_CHANNEL:
@@ -648,7 +396,7 @@ static void PrintFrameInfo(struct mad_header *Header)
                        break;
        }
 
-       /* Convert the emphasis to it's printed representation. */
+       /* Convert the emphasis to its printed representation. */
        switch(Header->emphasis)
        {
                case MAD_EMPHASIS_NONE: