]> git.sesse.net Git - vlc/blobdiff - src/audio_decoder/audio_decoder.c
* Mandatory step for video output IV and the audio output quality
[vlc] / src / audio_decoder / audio_decoder.c
index 9e9ee376710cc48b17eb43763a50650cb6026930..763c3aac829147ed700dd8a3697dec787ee7a27b 100644 (file)
-/******************************************************************************
- * audio_decoder.c: MPEG1 Layer I-II audio decoder thread
- * (c)1999 VideoLAN
- ******************************************************************************/
+/*****************************************************************************
+ * audio_decoder.c: MPEG audio decoder thread
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: audio_decoder.c,v 1.50 2001/05/01 04:18:18 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ *          Michel Lespinasse <walken@via.ecp.fr>
+ *          Samuel Hocevar <sam@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
 
 /*
  * TODO :
- * - Optimiser les NeedBits() et les GetBits() du code là où c'est possible
+ *
+ * - optimiser les NeedBits() et les GetBits() du code là où c'est possible ;
+ * - vlc_cond_signal() / vlc_cond_wait() ;
+ *
  */
 
-/******************************************************************************
+/*****************************************************************************
  * Preamble
- ******************************************************************************/
-#include <unistd.h>
+ *****************************************************************************/
+#include "defs.h"
 
-#include <stdio.h>                                            /* "intf_msg.h" */
-#include <stdlib.h>                                       /* malloc(), free() */
-#include <netinet/in.h>                                            /* ntohl() */
-#include <sys/soundcard.h>                                /* "audio_output.h" */
-#include <sys/uio.h>                                             /* "input.h" */
+#include <unistd.h>                                              /* getpid() */
+
+#include <stdio.h>                                           /* "intf_msg.h" */
+#include <string.h>                                    /* memcpy(), memset() */
+#include <stdlib.h>                                      /* malloc(), free() */
 
-#include "common.h"
 #include "config.h"
+#include "common.h"
+#include "threads.h"
 #include "mtime.h"
-#include "vlc_thread.h"
-#include "debug.h"                                       /* "input_netlist.h" */
-
-#include "intf_msg.h"                         /* intf_DbgMsg(), intf_ErrMsg() */
 
-#include "input.h"                                            /* pes_packet_t */
-#include "input_netlist.h"                          /* input_NetlistFreePES() */
-#include "decoder_fifo.h"          /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
+#include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
+#include "stream_control.h"
+#include "input_ext-dec.h"
 
-#include "audio_output.h"
+#include "audio_output.h"               /* aout_fifo_t (for audio_decoder.h) */
 
-#include "audio_constants.h"
+#include "adec_generic.h"
 #include "audio_decoder.h"
-#include "audio_math.h"
+#include "adec_math.h"                                     /* DCT32(), PCM() */
 
-/******************************************************************************
+#define ADEC_FRAME_SIZE (2*1152)
+
+/*****************************************************************************
  * Local prototypes
- ******************************************************************************/
-static int      InitThread              ( adec_thread_t * p_adec );
-static void     RunThread               ( adec_thread_t * p_adec );
-static void     ErrorThread             ( adec_thread_t * p_adec );
-static void     EndThread               ( adec_thread_t * p_adec );
-
-static int      adec_Layer1_Mono        ( adec_thread_t * p_adec );
-static int      adec_Layer1_Stereo      ( adec_thread_t * p_adec );
-static int      adec_Layer2_Mono        ( adec_thread_t * p_adec );
-static int      adec_Layer2_Stereo      ( adec_thread_t * p_adec );
-
-static byte_t   GetByte                 ( bit_stream_t * p_bit_stream );
-static void     NeedBits                ( bit_stream_t * p_bit_stream, int i_bits );
-static void     DumpBits                ( bit_stream_t * p_bit_stream, int i_bits );
-static int      FindHeader              ( adec_thread_t * p_adec );
-
-/******************************************************************************
+ *****************************************************************************/
+static int      InitThread             (adec_thread_t * p_adec);
+static void     RunThread              (adec_thread_t * p_adec);
+static void     ErrorThread            (adec_thread_t * p_adec);
+static void     EndThread              (adec_thread_t * p_adec);
+
+/*****************************************************************************
  * adec_CreateThread: creates an audio decoder thread
- ******************************************************************************
+ *****************************************************************************
  * This function creates a new audio decoder thread, and returns a pointer to
  * its description. On error, it returns NULL.
- ******************************************************************************/
-adec_thread_t * adec_CreateThread( input_thread_t * p_input )
+ *****************************************************************************/
+vlc_thread_t adec_CreateThread ( adec_config_t * p_config )
 {
     adec_thread_t *     p_adec;
 
-    intf_DbgMsg("adec debug: creating audio decoder thread\n");
+    intf_DbgMsg ( "adec debug: creating audio decoder thread" );
 
     /* Allocate the memory needed to store the thread's structure */
-    if ( (p_adec = (adec_thread_t *)malloc( sizeof(adec_thread_t) )) == NULL )
+    if ( (p_adec = (adec_thread_t *)malloc (sizeof(adec_thread_t))) == NULL ) 
     {
-        intf_ErrMsg("adec error: not enough memory for adec_CreateThread() to create the new thread\n");
-        return( NULL );
+        intf_ErrMsg ( "adec error: not enough memory for"
+                      " adec_CreateThread() to create the new thread" );
+        return 0;
     }
 
     /*
      * Initialize the thread properties
      */
-    p_adec->b_die = 0;
-    p_adec->b_error = 0;
-
-    /*
-     * Initialize the input properties
-     */
-    /* Initialize the decoder fifo's data lock and conditional variable and set
-     * its buffer as empty */
-    vlc_mutex_init( &p_adec->fifo.data_lock );
-    vlc_cond_init( &p_adec->fifo.data_wait );
-    p_adec->fifo.i_start = 0;
-    p_adec->fifo.i_end = 0;
-    /* Initialize the bit stream structure */
-    p_adec->bit_stream.p_input = p_input;
-    p_adec->bit_stream.p_decoder_fifo = &p_adec->fifo;
-    p_adec->bit_stream.fifo.buffer = 0;
-    p_adec->bit_stream.fifo.i_available = 0;
+    p_adec->p_config = p_config;
+    p_adec->p_fifo = p_config->decoder_config.p_decoder_fifo;
 
     /*
      * Initialize the decoder properties
      */
-    p_adec->bank_0.actual = p_adec->bank_0.v1;
-    p_adec->bank_0.pos = 0;
-    p_adec->bank_1.actual = p_adec->bank_1.v1;
-    p_adec->bank_1.pos = 0;
+    adec_Init ( p_adec );
 
     /*
      * Initialize the output properties
      */
-    p_adec->p_aout = p_input->p_aout;
     p_adec->p_aout_fifo = NULL;
 
     /* Spawn the audio decoder thread */
-    if ( vlc_thread_create(&p_adec->thread_id, "audio decoder", (vlc_thread_func_t)RunThread, (void *)p_adec) )
-    {
-        intf_ErrMsg("adec error: can't spawn audio decoder thread\n");
-        free( p_adec );
-        return( NULL );
-    }
-
-    intf_DbgMsg("adec debug: audio decoder thread (%p) created\n", p_adec);
-    return( p_adec );
-}
-
-/******************************************************************************
- * adec_DestroyThread: destroys an audio decoder thread
- ******************************************************************************
- * This function asks an audio decoder thread to terminate. This function has
- * not to wait until the decoder thread has really died, because the killer (ie
- * this function's caller) is the input thread, that's why we are sure that no
- * other thread will try to access to this thread's descriptor after its
- * destruction.
- ******************************************************************************/
-void adec_DestroyThread( adec_thread_t * p_adec )
-{
-    intf_DbgMsg("adec debug: requesting termination of audio decoder thread %p\n", p_adec);
-
-    /* Ask thread to kill itself */
-    p_adec->b_die = 1;
-    /* Make sure the decoder thread leaves the GetByte() function */
-    vlc_mutex_lock( &(p_adec->fifo.data_lock) );
-    vlc_cond_signal( &(p_adec->fifo.data_wait) );
-    vlc_mutex_unlock( &(p_adec->fifo.data_lock) );
-
-    /* Waiting for the decoder thread to exit */
-    /* Remove this as soon as the "status" flag is implemented */
-    vlc_thread_join( p_adec->thread_id );
-}
-
-/* Following functions are local */
-
-/******************************************************************************
- * FindHeader : parses an input stream until an audio frame header could be
- *              found
- ******************************************************************************
- * When this function returns successfully, the header can be found in the
- * buffer of the bit stream fifo.
- ******************************************************************************/
-static int FindHeader( adec_thread_t * p_adec )
-{
-    while ( (!p_adec->b_die) && (!p_adec->b_error) )
+    if ( vlc_thread_create(&p_adec->thread_id, "audio decoder",
+         (vlc_thread_func_t)RunThread, (void *)p_adec) ) 
     {
-        NeedBits( &p_adec->bit_stream, 32 );
-        if ( (p_adec->bit_stream.fifo.buffer & ADEC_HEADER_SYNCWORD_MASK) == ADEC_HEADER_SYNCWORD_MASK )
-        {
-            return( 0 );
-        }
-        DumpBits( &p_adec->bit_stream, 8 );
+        intf_ErrMsg ("adec error: can't spawn audio decoder thread");
+        free (p_adec);
+        return 0;
     }
 
-    return( -1 );
-}
-
-/******************************************************************************
- * adec_Layer`L'_`M': decodes an mpeg 1, layer `L', mode `M', audio frame
- ******************************************************************************
- * These functions decode the audio frame which has already its header loaded
- * in the i_header member of the audio decoder thread structure and its first
- * byte of data described by the bit stream structure of the audio decoder
- * thread (there is no bit available in the bit buffer yet)
- ******************************************************************************/
-
-/******************************************************************************
- * adec_Layer1_Mono
- ******************************************************************************/
-static __inline__ int adec_Layer1_Mono( adec_thread_t * p_adec )
-{
-    p_adec->bit_stream.fifo.buffer = 0;
-    p_adec->bit_stream.fifo.i_available = 0;
-    return( 0 );
-}
-
-/******************************************************************************
- * adec_Layer1_Stereo
- ******************************************************************************/
-static __inline__ int adec_Layer1_Stereo( adec_thread_t * p_adec )
-{
-    p_adec->bit_stream.fifo.buffer = 0;
-    p_adec->bit_stream.fifo.i_available = 0;
-    return( 0 );
-}
-
-/******************************************************************************
- * adec_Layer2_Mono
- ******************************************************************************/
-static __inline__ int adec_Layer2_Mono( adec_thread_t * p_adec )
-{
-    p_adec->bit_stream.fifo.buffer = 0;
-    p_adec->bit_stream.fifo.i_available = 0;
-    return( 0 );
+    intf_DbgMsg ("adec debug: audio decoder thread (%p) created", p_adec);
+    return p_adec->thread_id;
 }
 
-/******************************************************************************
- * adec_Layer2_Stereo
- ******************************************************************************/
-static __inline__ int adec_Layer2_Stereo( adec_thread_t * p_adec )
-{
-    typedef struct requantization_s
-    {
-        byte_t                          i_bits_per_codeword;
-        const float *                   pf_ungroup;
-        float                           f_slope;
-        float                           f_offset;
-    } requantization_t;
-
-    static const float                  pf_scalefactor[64] = ADEC_SCALE_FACTOR;
-
-    static u32                          i_header;
-    static int                          i_sampling_frequency, i_mode, i_bound;
-    static int                          pi_allocation_0[32], pi_allocation_1[32]; /* see ISO/IEC 11172-3 2.4.1.6 */
-    int                                 i_sb, i_nbal;
-    float                               f_scalefactor_0, f_scalefactor_1;
-
-    static const byte_t                 ppi_bitrate_per_channel_index[4][15] = ADEC_LAYER2_BITRATE_PER_CHANNEL_INDEX;
-    static const byte_t                 ppi_sblimit[3][11] = ADEC_LAYER2_SBLIMIT;
-    static const byte_t                 ppi_nbal[2][32] = ADEC_LAYER2_NBAL;
-
-    static const float                  pf_ungroup3[3*3*3 * 3] = ADEC_LAYER2_UNGROUP3;
-    static const float                  pf_ungroup5[5*5*5 * 3] = ADEC_LAYER2_UNGROUP5;
-    static const float                  pf_ungroup9[9*9*9 * 3] = ADEC_LAYER2_UNGROUP9;
-
-    static const requantization_t       p_requantization_cd[16] = ADEC_LAYER2_REQUANTIZATION_CD;
-    static const requantization_t       p_requantization_ab1[16] = ADEC_LAYER2_REQUANTIZATION_AB1;
-    static const requantization_t       p_requantization_ab2[16] = ADEC_LAYER2_REQUANTIZATION_AB2;
-    static const requantization_t       p_requantization_ab3[16] = ADEC_LAYER2_REQUANTIZATION_AB3;
-    static const requantization_t       p_requantization_ab4[16] = ADEC_LAYER2_REQUANTIZATION_AB4;
-    static const requantization_t *     pp_requantization_ab[30] = ADEC_LAYER2_REQUANTIZATION_AB;
-
-    static int                          i_sblimit, i_bitrate_per_channel_index;
-    static int                          pi_scfsi_0[30], pi_scfsi_1[30];
-    static const byte_t *               pi_nbal;
-    static float                        ppf_sample_0[3][32], ppf_sample_1[3][32];
-    static const requantization_t *     pp_requantization_0[30];
-    static const requantization_t *     pp_requantization_1[30];
-    static requantization_t             requantization;
-    static const float *                pf_ungroup;
-
-    static float                        pf_scalefactor_0_0[30], pf_scalefactor_0_1[30], pf_scalefactor_0_2[30];
-    static float                        pf_scalefactor_1_0[30], pf_scalefactor_1_1[30], pf_scalefactor_1_2[30];
-
-    int                                 i_2nbal, i_gr;
-    float                               f_dummy;
-
-    long                                l_end_frame;
-    s16 *                               p_s16;
-
-    int                                 i_need = 0, i_dump = 0;
-//    static const int                    pi_framesize[512] = ADEC_FRAME_SIZE;
-
-    /* Read the audio frame header and flush the bit buffer */
-    i_header = p_adec->bit_stream.fifo.buffer;
-    p_adec->bit_stream.fifo.buffer = 0;
-    p_adec->bit_stream.fifo.i_available = 0;
-    /* Read the sampling frequency (see ISO/IEC 11172-3 2.4.2.3) */
-    i_sampling_frequency = (int)((i_header & ADEC_HEADER_SAMPLING_FREQUENCY_MASK)
-        >> ADEC_HEADER_SAMPLING_FREQUENCY_SHIFT);
-    /* Read the mode (see ISO/IEC 11172-3 2.4.2.3) */
-    i_mode = (int)((i_header & ADEC_HEADER_MODE_MASK) >> ADEC_HEADER_MODE_SHIFT);
-    /* If a CRC can be found in the frame, get rid of it */
-    if ( (i_header & ADEC_HEADER_PROTECTION_BIT_MASK) == 0 )
-    {
-        GetByte( &p_adec->bit_stream );
-        GetByte( &p_adec->bit_stream );
-    }
-
-    /* Find out the bitrate per channel index */
-    i_bitrate_per_channel_index = (int)ppi_bitrate_per_channel_index[i_mode]
-        [(i_header & ADEC_HEADER_BITRATE_INDEX_MASK) >> ADEC_HEADER_BITRATE_INDEX_SHIFT];
-    /* Find out the number of subbands */
-    i_sblimit = (int)ppi_sblimit[i_sampling_frequency][i_bitrate_per_channel_index];
-    /* Check if the frame is valid or not */
-    if ( i_sblimit == 0 )
-    {
-        return( 0 );                                  /* the frame is invalid */
-    }
-    /* Find out the number of bits allocated */
-    pi_nbal = ppi_nbal[ (i_bitrate_per_channel_index <= 2) ? 0 : 1 ];
-
-    /* Find out the `bound' subband (see ISO/IEC 11172-3 2.4.2.3) */
-    if ( i_mode == 1 )
-    {
-        i_bound = (int)(((i_header & ADEC_HEADER_MODE_EXTENSION_MASK) >> (ADEC_HEADER_MODE_EXTENSION_SHIFT - 2)) + 4);
-        if ( i_bound > i_sblimit )
-        {
-            i_bound = i_sblimit;
-        }
-    }
-    else
-    {
-        i_bound = i_sblimit;
-    }
-
-    /* Read the allocation information (see ISO/IEC 11172-3 2.4.1.6) */
-    for ( i_sb = 0; i_sb < i_bound; i_sb++ )
-    {
-        i_2nbal = 2 * (i_nbal = (int)pi_nbal[ i_sb ]);
-        NeedBits( &p_adec->bit_stream, i_2nbal );
-        i_need += i_2nbal;
-        pi_allocation_0[ i_sb ] = (int)(p_adec->bit_stream.fifo.buffer >> (32 - i_nbal));
-        p_adec->bit_stream.fifo.buffer <<= i_nbal;
-        pi_allocation_1[ i_sb ] = (int)(p_adec->bit_stream.fifo.buffer >> (32 - i_nbal));
-        p_adec->bit_stream.fifo.buffer <<= i_nbal;
-        p_adec->bit_stream.fifo.i_available -= i_2nbal;
-        i_dump += i_2nbal;
-    }
-    for ( ; i_sb < i_sblimit; i_sb++ )
-    {
-        i_nbal = (int)pi_nbal[ i_sb ];
-        NeedBits( &p_adec->bit_stream, i_nbal );
-        i_need += i_nbal;
-        pi_allocation_0[ i_sb ] = (int)(p_adec->bit_stream.fifo.buffer >> (32 - i_nbal));
-        DumpBits( &p_adec->bit_stream, i_nbal );
-        i_dump += i_nbal;
-    }
-
-#define MACRO( p_requantization ) \
-    for ( i_sb = 0; i_sb < i_bound; i_sb++ ) \
-    { \
-        if ( pi_allocation_0[i_sb] ) \
-        { \
-            pp_requantization_0[i_sb] = &((p_requantization)[pi_allocation_0[i_sb]]); \
-            NeedBits( &p_adec->bit_stream, 2 ); \
-            i_need += 2; \
-            pi_scfsi_0[i_sb] = (int)(p_adec->bit_stream.fifo.buffer >> (32 - 2)); \
-            DumpBits( &p_adec->bit_stream, 2 ); \
-            i_dump += 2; \
-        } \
-        else \
-        { \
-            ppf_sample_0[0][i_sb] = .0; \
-            ppf_sample_0[1][i_sb] = .0; \
-            ppf_sample_0[2][i_sb] = .0; \
-        } \
-\
-        if ( pi_allocation_1[i_sb] ) \
-        { \
-            pp_requantization_1[i_sb] = &((p_requantization)[pi_allocation_1[i_sb]]); \
-            NeedBits( &p_adec->bit_stream, 2 ); \
-            i_need += 2; \
-            pi_scfsi_1[i_sb] = (int)(p_adec->bit_stream.fifo.buffer >> (32 - 2)); \
-            DumpBits( &p_adec->bit_stream, 2 ); \
-            i_dump += 2; \
-        } \
-        else \
-        { \
-            ppf_sample_1[0][i_sb] = .0; \
-            ppf_sample_1[1][i_sb] = .0; \
-            ppf_sample_1[2][i_sb] = .0; \
-        } \
-    } \
-\
-    for ( ; i_sb < i_sblimit; i_sb++ ) \
-    { \
-        if ( pi_allocation_0[i_sb] ) \
-        { \
-            pp_requantization_0[i_sb] = &((p_requantization)[pi_allocation_0[i_sb]]); \
-            NeedBits( &p_adec->bit_stream, 4 ); \
-            i_need += 4; \
-            pi_scfsi_0[i_sb] = (int)(p_adec->bit_stream.fifo.buffer >> (32 - 2)); \
-            p_adec->bit_stream.fifo.buffer <<= 2; \
-            pi_scfsi_1[i_sb] = (int)(p_adec->bit_stream.fifo.buffer >> (32 - 2)); \
-            p_adec->bit_stream.fifo.buffer <<= 2; \
-            p_adec->bit_stream.fifo.i_available -= 4; \
-            i_dump += 4; \
-        } \
-        else \
-        { \
-            ppf_sample_0[0][i_sb] = .0; \
-            ppf_sample_0[1][i_sb] = .0; \
-            ppf_sample_0[2][i_sb] = .0; \
-            ppf_sample_1[0][i_sb] = .0; \
-            ppf_sample_1[1][i_sb] = .0; \
-            ppf_sample_1[2][i_sb] = .0; \
-        } \
-    }
-/* #define MACRO */
-
-    if ( i_bitrate_per_channel_index <= 2 )
-    {
-        MACRO( p_requantization_cd )
-    }
-    else
-    {
-        MACRO( pp_requantization_ab[i_sb] )
-    }
-
-#define SWITCH( pi_scfsi, pf_scalefactor_0, pf_scalefactor_1, pf_scalefactor_2 ) \
-    switch ( (pi_scfsi)[i_sb] ) \
-    { \
-        case 0: \
-            NeedBits( &p_adec->bit_stream, (3*6) ); \
-            i_need += 18; \
-            (pf_scalefactor_0)[i_sb] = pf_scalefactor[p_adec->bit_stream.fifo.buffer >> (32 - 6)]; \
-            p_adec->bit_stream.fifo.buffer <<= 6; \
-            (pf_scalefactor_1)[i_sb] = pf_scalefactor[p_adec->bit_stream.fifo.buffer >> (32 - 6)]; \
-            p_adec->bit_stream.fifo.buffer <<= 6; \
-            (pf_scalefactor_2)[i_sb] = pf_scalefactor[p_adec->bit_stream.fifo.buffer >> (32 - 6)]; \
-            p_adec->bit_stream.fifo.buffer <<= 6; \
-            p_adec->bit_stream.fifo.i_available -= (3*6); \
-            i_dump += 18; \
-            break; \
-\
-        case 1: \
-            NeedBits( &p_adec->bit_stream, (2*6) ); \
-            i_need += 12; \
-            (pf_scalefactor_0)[i_sb] = \
-                (pf_scalefactor_1)[i_sb] = pf_scalefactor[p_adec->bit_stream.fifo.buffer >> (32 - 6)]; \
-            p_adec->bit_stream.fifo.buffer <<= 6; \
-            (pf_scalefactor_2)[i_sb] = pf_scalefactor[p_adec->bit_stream.fifo.buffer >> (32 - 6)]; \
-            p_adec->bit_stream.fifo.buffer <<= 6; \
-            p_adec->bit_stream.fifo.i_available -= (2*6); \
-            i_dump += 12; \
-            break; \
-\
-        case 2: \
-            NeedBits( &p_adec->bit_stream, (1*6) ); \
-            i_need += 6; \
-            (pf_scalefactor_0)[i_sb] = \
-                (pf_scalefactor_1)[i_sb] = \
-                (pf_scalefactor_2)[i_sb] = pf_scalefactor[p_adec->bit_stream.fifo.buffer >> (32 - 6)]; \
-            DumpBits( &p_adec->bit_stream, (1*6) ); \
-            i_dump += 6; \
-            break; \
-\
-        case 3: \
-            NeedBits( &p_adec->bit_stream, (2*6) ); \
-            i_need += 12; \
-            (pf_scalefactor_0)[i_sb] = pf_scalefactor[p_adec->bit_stream.fifo.buffer >> (32 - 6)]; \
-            p_adec->bit_stream.fifo.buffer <<= 6; \
-            (pf_scalefactor_1)[i_sb] = \
-                (pf_scalefactor_2)[i_sb] = pf_scalefactor[p_adec->bit_stream.fifo.buffer >> (32 - 6)]; \
-            p_adec->bit_stream.fifo.buffer <<= 6; \
-            p_adec->bit_stream.fifo.i_available -= (2*6); \
-            i_dump += 12; \
-            break; \
-    }
-/* #define SWITCH */
-
-    for ( i_sb = 0; i_sb < i_bound; i_sb++ )
-    {
-        if ( pi_allocation_0[i_sb] )
-        {
-            SWITCH( pi_scfsi_0, pf_scalefactor_0_0, pf_scalefactor_0_1, pf_scalefactor_0_2 )
-        }
-        if ( pi_allocation_1[i_sb] )
-        {
-            SWITCH( pi_scfsi_1, pf_scalefactor_1_0, pf_scalefactor_1_1, pf_scalefactor_1_2 )
-        }
-    }
-    for ( ; i_sb < i_sblimit; i_sb++ )
-    {
-        if ( pi_allocation_0[i_sb] )
-        {
-            SWITCH( pi_scfsi_0, pf_scalefactor_0_0, pf_scalefactor_0_1, pf_scalefactor_0_2 )
-            SWITCH( pi_scfsi_1, pf_scalefactor_1_0, pf_scalefactor_1_1, pf_scalefactor_1_2 )
-        }
-    }
-    for ( ; i_sb < 32; i_sb++ )
-    {
-        ppf_sample_0[0][i_sb] = .0;
-        ppf_sample_0[1][i_sb] = .0;
-        ppf_sample_0[2][i_sb] = .0;
-        ppf_sample_1[0][i_sb] = .0;
-        ppf_sample_1[1][i_sb] = .0;
-        ppf_sample_1[2][i_sb] = .0;
-    }
+/* following functions are local */
 
-#define NEXT_BUF \
-/* fprintf(stderr, "%p\n", p_adec->p_aout_fifo->buffer); */ \
-/* fprintf(stderr, "l_end_frame == %li, %p\n", l_end_frame, (aout_frame_t *)p_adec->p_aout_fifo->buffer + l_end_frame); */ \
-    p_s16 = ((aout_frame_t *)p_adec->p_aout_fifo->buffer)[ l_end_frame ]; \
-/* fprintf(stderr, "p_s16 == %p\n", p_s16); */ \
-    l_end_frame += 1; \
-    l_end_frame &= AOUT_FIFO_SIZE;
-/* #define NEXT_BUF */
-
-#define GROUPTEST( pp_requantization, ppf_sample, pf_sf ) \
-    requantization = *((pp_requantization)[i_sb]); \
-    if ( requantization.pf_ungroup == NULL ) \
-    { \
-        NeedBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-        i_need += requantization.i_bits_per_codeword; \
-        (ppf_sample)[0][i_sb] = (f_scalefactor_0 = (pf_sf)[i_sb]) * (requantization.f_slope * \
-            (p_adec->bit_stream.fifo.buffer >> (32 - requantization.i_bits_per_codeword)) + requantization.f_offset); \
-        DumpBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-        i_dump += requantization.i_bits_per_codeword; \
-\
-        NeedBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-        i_need += requantization.i_bits_per_codeword; \
-        (ppf_sample)[1][i_sb] = f_scalefactor_0 * (requantization.f_slope * \
-            (p_adec->bit_stream.fifo.buffer >> (32 - requantization.i_bits_per_codeword)) + requantization.f_offset); \
-        DumpBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-        i_dump += requantization.i_bits_per_codeword; \
-\
-        NeedBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-        i_need += requantization.i_bits_per_codeword; \
-        (ppf_sample)[2][i_sb] = f_scalefactor_0 * (requantization.f_slope * \
-            (p_adec->bit_stream.fifo.buffer >> (32 - requantization.i_bits_per_codeword)) + requantization.f_offset); \
-        DumpBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-        i_dump += requantization.i_bits_per_codeword; \
-    } \
-    else \
-    { \
-        NeedBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-        i_need += requantization.i_bits_per_codeword; \
-        pf_ungroup = requantization.pf_ungroup + 3 * \
-            (p_adec->bit_stream.fifo.buffer >> (32 - requantization.i_bits_per_codeword)); \
-        DumpBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-        i_dump += requantization.i_bits_per_codeword; \
-        (ppf_sample)[0][i_sb] = (f_scalefactor_0 = (pf_sf)[i_sb]) * pf_ungroup[0]; \
-        (ppf_sample)[1][i_sb] = f_scalefactor_0 * pf_ungroup[1]; \
-        (ppf_sample)[2][i_sb] = f_scalefactor_0 * pf_ungroup[2]; \
-    }
-/* #define GROUPTEST */
-
-#define READ_SAMPLE_L2S( pf_scalefactor_0, pf_scalefactor_1, i_grlimit ) \
-    for ( ; i_gr < (i_grlimit); i_gr++ ) \
-    { \
-        for ( i_sb = 0; i_sb < i_bound; i_sb++ ) \
-        { \
-            if ( pi_allocation_0[i_sb] ) \
-            { \
-                GROUPTEST( pp_requantization_0, ppf_sample_0, (pf_scalefactor_0) ) \
-            } \
-            if ( pi_allocation_1[i_sb] ) \
-            { \
-                GROUPTEST( pp_requantization_1, ppf_sample_1, (pf_scalefactor_1) ) \
-            } \
-        } \
-        for ( ; i_sb < i_sblimit; i_sb++ ) \
-        { \
-            if ( pi_allocation_0[i_sb] ) \
-            { \
-                requantization = *(pp_requantization_0[i_sb]); \
-                if ( requantization.pf_ungroup == NULL ) \
-                { \
-                    NeedBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-                    i_need += requantization.i_bits_per_codeword; \
-                    ppf_sample_0[0][i_sb] = (f_scalefactor_0 = (pf_scalefactor_0)[i_sb]) * \
-                        (requantization.f_slope * (f_dummy = \
-                        (float)(p_adec->bit_stream.fifo.buffer >> (32 - requantization.i_bits_per_codeword))) + \
-                        requantization.f_offset); \
-                    DumpBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-                    i_dump += requantization.i_bits_per_codeword; \
-                    ppf_sample_1[0][i_sb] = (f_scalefactor_1 = (pf_scalefactor_1)[i_sb]) * \
-                        (requantization.f_slope * f_dummy + requantization.f_offset); \
-\
-                    NeedBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-                    i_need += requantization.i_bits_per_codeword; \
-                    ppf_sample_0[1][i_sb] = f_scalefactor_0 * \
-                        (requantization.f_slope * (f_dummy = \
-                        (float)(p_adec->bit_stream.fifo.buffer >> (32 - requantization.i_bits_per_codeword))) + \
-                        requantization.f_offset); \
-                    DumpBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-                    i_dump += requantization.i_bits_per_codeword; \
-                    ppf_sample_1[1][i_sb] = f_scalefactor_1 * \
-                        (requantization.f_slope * f_dummy + requantization.f_offset); \
-\
-                    NeedBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-                    i_need += requantization.i_bits_per_codeword; \
-                    ppf_sample_0[2][i_sb] = f_scalefactor_0 * \
-                        (requantization.f_slope * (f_dummy = \
-                        (float)(p_adec->bit_stream.fifo.buffer >> (32 - requantization.i_bits_per_codeword))) + \
-                        requantization.f_offset); \
-                    DumpBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-                    i_dump += requantization.i_bits_per_codeword; \
-                    ppf_sample_1[2][i_sb] = f_scalefactor_1 * \
-                        (requantization.f_slope * f_dummy + requantization.f_offset); \
-                } \
-                else \
-                { \
-                    NeedBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-                    i_need += requantization.i_bits_per_codeword; \
-                    pf_ungroup = requantization.pf_ungroup + 3 * \
-                        (p_adec->bit_stream.fifo.buffer >> (32 - requantization.i_bits_per_codeword)); \
-                    DumpBits( &p_adec->bit_stream, requantization.i_bits_per_codeword ); \
-                    i_dump += requantization.i_bits_per_codeword; \
-\
-                    ppf_sample_0[0][i_sb] = (f_scalefactor_0 = (pf_scalefactor_0)[i_sb]) * pf_ungroup[0]; \
-                    ppf_sample_0[1][i_sb] = f_scalefactor_0 * pf_ungroup[1]; \
-                    ppf_sample_0[2][i_sb] = f_scalefactor_0 * pf_ungroup[2]; \
-\
-                    ppf_sample_1[0][i_sb] = (f_scalefactor_1 = (pf_scalefactor_1)[i_sb]) * pf_ungroup[0]; \
-                    ppf_sample_1[1][i_sb] = f_scalefactor_1 * pf_ungroup[1]; \
-                    ppf_sample_1[2][i_sb] = f_scalefactor_1 * pf_ungroup[2]; \
-                } \
-            } \
-        } \
-\
-/* fprintf(stderr, "%p", p_s16); */ \
-        DCT32( ppf_sample_0[0], &p_adec->bank_0 ); \
-        PCM( &p_adec->bank_0, &p_s16, 2 ); \
-/* fprintf(stderr, " %p", p_s16); */ \
-        p_s16 -= 63; \
-/* fprintf(stderr, " %p\n", p_s16); */ \
-\
-/* fprintf(stderr, "%p", p_s16); */ \
-        DCT32( ppf_sample_1[0], &p_adec->bank_1 ); \
-        PCM( &p_adec->bank_1, &p_s16, 2 ); \
-/* fprintf(stderr, " %p", p_s16); */ \
-        p_s16 -= 1; \
-/* fprintf(stderr, " %p\n", p_s16); */ \
-\
-/* fprintf(stderr, "%p", p_s16); */ \
-        DCT32( ppf_sample_0[1], &p_adec->bank_0 ); \
-        PCM( &p_adec->bank_0, &p_s16, 2 ); \
-/* fprintf(stderr, " %p", p_s16); */ \
-        p_s16 -= 63; \
-/* fprintf(stderr, " %p\n", p_s16); */ \
-\
-/* fprintf(stderr, "%p", p_s16); */ \
-        DCT32( ppf_sample_1[1], &p_adec->bank_1 ); \
-        PCM( &p_adec->bank_1, &p_s16, 2 ); \
-/* fprintf(stderr, " %p", p_s16); */ \
-        p_s16 -= 1; \
-/* fprintf(stderr, " %p\n", p_s16); */ \
-\
-/* fprintf(stderr, "%p", p_s16); */ \
-        DCT32( ppf_sample_0[2], &p_adec->bank_0 ); \
-        PCM( &p_adec->bank_0, &p_s16, 2 ); \
-/* fprintf(stderr, " %p", p_s16); */ \
-        p_s16 -= 63; \
-/* fprintf(stderr, " %p\n", p_s16); */ \
-\
-/* fprintf(stderr, "%p", p_s16); */ \
-        DCT32( ppf_sample_1[2], &p_adec->bank_1 ); \
-        PCM( &p_adec->bank_1, &p_s16, 2 ); \
-/* fprintf(stderr, " %p", p_s16); */ \
-        p_s16 -= 1; \
-/* fprintf(stderr, " %p\n", p_s16); */ \
-    }
-/* #define READ_SAMPLE_L2S */
-
-    l_end_frame = p_adec->p_aout_fifo->l_end_frame;
-    i_gr = 0;
-
-    NEXT_BUF
-    READ_SAMPLE_L2S( pf_scalefactor_0_0, pf_scalefactor_1_0, 2 )
-
-    NEXT_BUF
-    READ_SAMPLE_L2S( pf_scalefactor_0_0, pf_scalefactor_1_0, 4 )
-
-    NEXT_BUF
-    READ_SAMPLE_L2S( pf_scalefactor_0_1, pf_scalefactor_1_1, 6 )
-
-    NEXT_BUF
-    READ_SAMPLE_L2S( pf_scalefactor_0_1, pf_scalefactor_1_1, 8 )
-
-    NEXT_BUF
-    READ_SAMPLE_L2S( pf_scalefactor_0_2, pf_scalefactor_1_2, 10 )
-
-    NEXT_BUF
-    READ_SAMPLE_L2S( pf_scalefactor_0_2, pf_scalefactor_1_2, 12 )
-
-//    fprintf(stderr, "adec debug: layer == %i, padding_bit == %i, sampling_frequency == %i, bitrate_index == %i\n",
-//        (i_header & ADEC_HEADER_LAYER_MASK) >> ADEC_HEADER_LAYER_SHIFT,
-//        (i_header & ADEC_HEADER_PADDING_BIT_MASK) >> ADEC_HEADER_PADDING_BIT_SHIFT,
-//        (i_header & ADEC_HEADER_SAMPLING_FREQUENCY_MASK) >> ADEC_HEADER_SAMPLING_FREQUENCY_SHIFT,
-//        (i_header & ADEC_HEADER_BITRATE_INDEX_MASK) >> ADEC_HEADER_BITRATE_INDEX_SHIFT);
-//    fprintf(stderr, "adec debug: framesize == %i, i_need == %i, i_dump == %i\n",
-//        pi_framesize[ 128 * ((i_header & ADEC_HEADER_LAYER_MASK) >> ADEC_HEADER_LAYER_SHIFT) +
-//            64 * ((i_header & ADEC_HEADER_PADDING_BIT_MASK) >> ADEC_HEADER_PADDING_BIT_SHIFT) +
-//            16 * ((i_header & ADEC_HEADER_SAMPLING_FREQUENCY_MASK) >> ADEC_HEADER_SAMPLING_FREQUENCY_SHIFT) +
-//            1 * ((i_header & ADEC_HEADER_BITRATE_INDEX_MASK) >> ADEC_HEADER_BITRATE_INDEX_SHIFT) ],
-//        i_need,
-//        i_dump);
-    p_adec->bit_stream.fifo.buffer = 0;
-    p_adec->bit_stream.fifo.i_available = 0;
-    return( 6 );
-}
-
-/******************************************************************************
+/*****************************************************************************
  * InitThread : initialize an audio decoder thread
- ******************************************************************************
+ *****************************************************************************
  * This function is called from RunThread and performs the second step of the
  * initialization. It returns 0 on success.
- ******************************************************************************/
-static int InitThread( adec_thread_t * p_adec )
+ *****************************************************************************/
+static int InitThread (adec_thread_t * p_adec)
 {
-    aout_fifo_t         aout_fifo;
-
-    intf_DbgMsg("adec debug: initializing audio decoder thread %p\n", p_adec);
-
-    /* Our first job is to initialize the bit stream structure with the
-     * beginning of the input stream */
-    vlc_mutex_lock( &p_adec->fifo.data_lock );
-    while ( DECODER_FIFO_ISEMPTY(p_adec->fifo) )
-    {
-        vlc_cond_wait( &p_adec->fifo.data_wait, &p_adec->fifo.data_lock );
-    }
-    p_adec->bit_stream.p_ts = DECODER_FIFO_START( p_adec->fifo )->p_first_ts;
-    p_adec->bit_stream.i_byte = p_adec->bit_stream.p_ts->i_payload_start;
-    vlc_mutex_unlock( &p_adec->fifo.data_lock );
-
-    /* Now we look for an audio frame header in the input stream */
-    if ( FindHeader(p_adec) )
-    {
-        return( -1 );                              /* b_die or b_error is set */
-    }
-
-    /*
-     * We have the header and all its informations : we must be able to create
-     * the audio output fifo.
-     */
-
-    /* Is the sound in mono mode or stereo mode ? */
-    if ( (p_adec->bit_stream.fifo.buffer & ADEC_HEADER_MODE_MASK) == ADEC_HEADER_MODE_MASK )
-    {
-        intf_DbgMsg("adec debug: mode == mono\n");
-        aout_fifo.i_type = AOUT_ADEC_MONO_FIFO;
-        aout_fifo.b_stereo = 0;
-    }
-    else
-    {
-        intf_DbgMsg("adec debug: mode == stereo\n");
-        aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
-        aout_fifo.b_stereo = 1;
-    }
-
-    /* Checking the sampling frequency */
-    switch ( (p_adec->bit_stream.fifo.buffer & ADEC_HEADER_SAMPLING_FREQUENCY_MASK) \
-             >> ADEC_HEADER_SAMPLING_FREQUENCY_SHIFT )
-    {
-        case 0:
-            intf_DbgMsg("adec debug: sampling_frequency == 44100 Hz\n");
-            aout_fifo.l_rate = 44100;
-            break;
-
-        case 1:
-            intf_DbgMsg("adec debug: sampling_frequency == 48000 Hz\n");
-            aout_fifo.l_rate = 48000;
-            break;
-
-        case 2:
-            intf_DbgMsg("adec debug: sampling_frequency == 32000 Hz\n");
-            aout_fifo.l_rate = 32000;
-            break;
-
-        case 3:
-            intf_ErrMsg("adec error: can't create audio output fifo (sampling_frequency == `reserved')\n");
-            return( -1 );
-    }
+    intf_DbgMsg ("adec debug: initializing audio decoder thread %p", p_adec);
 
-    aout_fifo.l_frame_size = AOUT_FRAME_SIZE;
+    p_adec->p_config->decoder_config.pf_init_bit_stream( &p_adec->bit_stream,
+        p_adec->p_config->decoder_config.p_decoder_fifo, NULL, NULL );
 
     /* Creating the audio output fifo */
-    if ( (p_adec->p_aout_fifo = aout_CreateFifo(p_adec->p_aout, &aout_fifo)) == NULL )
+    p_adec->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_STEREO_FIFO, 2, 0, 0,
+                                           ADEC_FRAME_SIZE, NULL );
+    if ( p_adec->p_aout_fifo == NULL ) 
     {
-        return( -1 );
+        return -1;
     }
 
-    intf_DbgMsg("adec debug: audio decoder thread %p initialized\n", p_adec);
-    return( 0 );
+    intf_DbgMsg ( "adec debug: audio decoder thread %p initialized", p_adec );
+    return 0;
 }
 
-/******************************************************************************
+/*****************************************************************************
  * RunThread : audio decoder thread
- ******************************************************************************
+ *****************************************************************************
  * Audio decoder thread. This function does only returns when the thread is
  * terminated.
- ******************************************************************************/
-static void RunThread( adec_thread_t * p_adec )
+ *****************************************************************************/
+static void RunThread (adec_thread_t * p_adec)
 {
-//    static const int    pi_framesize[512] = ADEC_FRAME_SIZE;
-//    int                 i_header;
-//    int                 i_framesize;
-//    int                 i_dummy;
+    int sync;
 
-    intf_DbgMsg("adec debug: running audio decoder thread (%p) (pid == %i)\n", p_adec, getpid());
+    intf_DbgMsg ( "adec debug: running audio decoder thread (%p) (pid == %i)",
+                  p_adec, getpid() );
 
     /* Initializing the audio decoder thread */
-    if ( InitThread(p_adec) )
-    {
-        p_adec->b_error = 1;
-    }
+    p_adec->p_fifo->b_error = InitThread (p_adec);
+
+    sync = 0;
 
     /* Audio decoder thread's main loop */
-    while ( (!p_adec->b_die) && (!p_adec->b_error) )
+    while( (!p_adec->p_fifo->b_die) && (!p_adec->p_fifo->b_error) )
     {
-        switch ( (p_adec->bit_stream.fifo.buffer & ADEC_HEADER_LAYER_MASK) >> ADEC_HEADER_LAYER_SHIFT )
+        s16 * buffer;
+        adec_sync_info_t sync_info;
+
+        if( DECODER_FIFO_START( *p_adec->p_fifo)->i_pts )
         {
-            /* Reserved */
-            case 0:
-                intf_DbgMsg("adec debug: layer == 0 (reserved)\n");
-                p_adec->bit_stream.fifo.buffer = 0;
-                p_adec->bit_stream.fifo.i_available = 0;
-                break;
-
-            /* Layer III */
-            case 1:
-                p_adec->bit_stream.fifo.buffer = 0;
-                p_adec->bit_stream.fifo.i_available = 0;
-                break;
-
-            /* Layer II */
-            case 2:
-                if ( (p_adec->bit_stream.fifo.buffer & ADEC_HEADER_MODE_MASK) == ADEC_HEADER_MODE_MASK )
-                {
-                    adec_Layer2_Mono( p_adec );
-                }
-                else
-                {
-                    /* Waiting until there is enough free space in the audio output fifo
-                     * in order to store the new decoded frames */
-                    vlc_mutex_lock( &p_adec->p_aout_fifo->data_lock );
-                   /* adec_Layer2_Stereo() produces 6 output frames (2*1152/384)...
-                     * If these 6 frames were recorded in the audio output fifo, the
-                     * l_end_frame index would be incremented 6 times. But, if after
-                     * this operation the audio output fifo contains less than 6 frames,
-                     * it would mean that we had not enough room to store the 6 frames :-P */
-                    while ( (((p_adec->p_aout_fifo->l_end_frame + 6) - p_adec->p_aout_fifo->l_start_frame) & AOUT_FIFO_SIZE) < 6 ) /* !! */
-                    {
-                        vlc_cond_wait( &p_adec->p_aout_fifo->data_wait, &p_adec->p_aout_fifo->data_lock );
-                    }
-                   if ( DECODER_FIFO_START(p_adec->fifo)->b_has_pts )
-                   {
-                        p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(p_adec->fifo)->i_pts;
-                        DECODER_FIFO_START(p_adec->fifo)->b_has_pts = 0;
-                   }
-                   else
-                   {
-                        p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] = LAST_MDATE;
-                   }
-                    vlc_mutex_unlock( &p_adec->p_aout_fifo->data_lock );
-
-                   /* Decoding the frames */
-                    if ( adec_Layer2_Stereo(p_adec) )
-                    {
-                        vlc_mutex_lock( &p_adec->p_aout_fifo->data_lock );
-                        /* Frame 1 */
-                        p_adec->p_aout_fifo->l_end_frame = (p_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
-                        /* Frame 2 */
-                        p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] = LAST_MDATE;
-                        p_adec->p_aout_fifo->l_end_frame = (p_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
-                        /* Frame 3 */
-                        p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] = LAST_MDATE;
-                        p_adec->p_aout_fifo->l_end_frame = (p_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
-                        /* Frame 4 */
-                        p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] = LAST_MDATE;
-                        p_adec->p_aout_fifo->l_end_frame = (p_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
-                        /* Frame 5 */
-                        p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] = LAST_MDATE;
-                        p_adec->p_aout_fifo->l_end_frame = (p_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
-                        /* Frame 6 */
-                        p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] = LAST_MDATE;
-                        p_adec->p_aout_fifo->l_end_frame = (p_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
-                        vlc_mutex_unlock( &p_adec->p_aout_fifo->data_lock );
-                    }
-                }
-                break;
-
-            /* Layer I */
-            case 3:
-                if ( (p_adec->bit_stream.fifo.buffer & ADEC_HEADER_MODE_MASK) == ADEC_HEADER_MODE_MASK )
-                {
-                    adec_Layer1_Mono( p_adec );
-                }
-                else
-                {
-                    adec_Layer1_Stereo( p_adec );
-                }
-                break;
-
-            default:
-                intf_DbgMsg("adec debug: layer == %i (unknown)\n",
-                    (p_adec->bit_stream.fifo.buffer & ADEC_HEADER_LAYER_MASK) >> ADEC_HEADER_LAYER_SHIFT);
-                p_adec->bit_stream.fifo.buffer = 0;
-                p_adec->bit_stream.fifo.i_available = 0;
-                break;
+            p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
+                DECODER_FIFO_START( *p_adec->p_fifo )->i_pts;
+            DECODER_FIFO_START(*p_adec->p_fifo)->i_pts = 0;
+        }
+        else
+        {
+            p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
+                LAST_MDATE;
+        }
+
+        if( ! adec_SyncFrame (p_adec, &sync_info) )
+        {
+            sync = 1;
+
+            p_adec->p_aout_fifo->l_rate = sync_info.sample_rate;
+
+            buffer = ((s16 *)p_adec->p_aout_fifo->buffer)
+                        + (p_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE);
+
+            if( adec_DecodeFrame (p_adec, buffer) )
+            {
+                /* Ouch, failed decoding... We'll have to resync */
+                sync = 0;
+            }
+            else
+            {
+                vlc_mutex_lock (&p_adec->p_aout_fifo->data_lock);
+    
+                p_adec->p_aout_fifo->l_end_frame =
+                    (p_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
+                vlc_cond_signal (&p_adec->p_aout_fifo->data_wait);
+                vlc_mutex_unlock (&p_adec->p_aout_fifo->data_lock);
+            }
         }
-        FindHeader( p_adec );
     }
 
     /* If b_error is set, the audio decoder thread enters the error loop */
-    if ( p_adec->b_error )
+    if( p_adec->p_fifo->b_error ) 
     {
         ErrorThread( p_adec );
     }
@@ -900,54 +216,62 @@ static void RunThread( adec_thread_t * p_adec )
     EndThread( p_adec );
 }
 
-/******************************************************************************
+/*****************************************************************************
  * ErrorThread : audio decoder's RunThread() error loop
- ******************************************************************************
+ *****************************************************************************
  * This function is called when an error occured during thread main's loop. The
  * thread can still receive feed, but must be ready to terminate as soon as
  * possible.
- ******************************************************************************/
-static void ErrorThread( adec_thread_t *p_adec )
+ *****************************************************************************/
+static void ErrorThread ( adec_thread_t *p_adec )
 {
     /* We take the lock, because we are going to read/write the start/end
      * indexes of the decoder fifo */
-    vlc_mutex_lock( &p_adec->fifo.data_lock );
+    vlc_mutex_lock ( &p_adec->p_fifo->data_lock );
 
     /* Wait until a `die' order is sent */
-    while( !p_adec->b_die )
+    while ( !p_adec->p_fifo->b_die ) 
     {
         /* Trash all received PES packets */
-        while( !DECODER_FIFO_ISEMPTY(p_adec->fifo) )
+        while ( !DECODER_FIFO_ISEMPTY(*p_adec->p_fifo) ) 
         {
-            input_NetlistFreePES( p_adec->bit_stream.p_input, DECODER_FIFO_START(p_adec->fifo) );
-           DECODER_FIFO_INCSTART( p_adec->fifo );
+            p_adec->p_fifo->pf_delete_pes ( p_adec->p_fifo->p_packets_mgt,
+                                   DECODER_FIFO_START(*p_adec->p_fifo) );
+            DECODER_FIFO_INCSTART ( *p_adec->p_fifo );
         }
 
         /* Waiting for the input thread to put new PES packets in the fifo */
-        vlc_cond_wait( &p_adec->fifo.data_wait, &p_adec->fifo.data_lock );
+        vlc_cond_wait ( &p_adec->p_fifo->data_wait, &p_adec->p_fifo->data_lock );
     }
 
     /* We can release the lock before leaving */
-    vlc_mutex_unlock( &p_adec->fifo.data_lock );
+    vlc_mutex_unlock ( &p_adec->p_fifo->data_lock );
 }
 
-/******************************************************************************
+/*****************************************************************************
  * EndThread : audio decoder thread destruction
- ******************************************************************************
- * This function is called when the thread ends after a sucessful
+ *****************************************************************************
+ * This function is called when the thread ends after a sucessful
  * initialization.
- ******************************************************************************/
-static void EndThread( adec_thread_t *p_adec )
+ *****************************************************************************/
+static void EndThread ( adec_thread_t *p_adec )
 {
-    intf_DbgMsg("adec debug: destroying audio decoder thread %p\n", p_adec);
+    intf_DbgMsg ( "adec debug: destroying audio decoder thread %p", p_adec );
 
     /* If the audio output fifo was created, we destroy it */
-    if ( p_adec->p_aout_fifo != NULL )
+    if ( p_adec->p_aout_fifo != NULL ) 
     {
-        aout_DestroyFifo( p_adec->p_aout_fifo );
+        aout_DestroyFifo ( p_adec->p_aout_fifo );
+
+        /* Make sure the output thread leaves the NextFrame() function */
+        vlc_mutex_lock (&(p_adec->p_aout_fifo->data_lock));
+        vlc_cond_signal (&(p_adec->p_aout_fifo->data_wait));
+        vlc_mutex_unlock (&(p_adec->p_aout_fifo->data_lock));
     }
     /* Destroy descriptor */
+    free( p_adec->p_config );
     free( p_adec );
 
-    intf_DbgMsg("adec debug: audio decoder thread %p destroyed\n", p_adec);
+    intf_DbgMsg ("adec debug: audio decoder thread %p destroyed", p_adec);
 }
+