]> git.sesse.net Git - vlc/blobdiff - plugins/ac3_adec/ac3_adec.c
* ALL: new module API. Makes a few things a lot simpler, and we gain
[vlc] / plugins / ac3_adec / ac3_adec.c
index 38a0dee63dd983e22dbd50d0d82609ea596776b8..81417c6a66694163a951f1345a562063eac71bd3 100644 (file)
@@ -2,7 +2,7 @@
  * ac3_adec.c: ac3 decoder module main file
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: ac3_adec.c,v 1.26 2002/04/21 10:32:20 sam Exp $
+ * $Id: ac3_adec.c,v 1.35 2002/07/31 20:56:50 sam Exp $
  *
  * Authors: Michel Lespinasse <walken@zoy.org>
  *
 #include <stdlib.h>                                      /* malloc(), free() */
 #include <string.h>                                              /* memset() */
 
-#include <videolan/vlc.h>
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/decoder.h>
 
 #ifdef HAVE_UNISTD_H
 #   include <unistd.h>                                           /* getpid() */
 #endif
 
-#include "audio_output.h"
-
-#include "stream_control.h"
-#include "input_ext-dec.h"
-#include "input_ext-intf.h"                                /* MPEG?_AUDIO_ES */
-
 #include "ac3_imdct.h"
 #include "ac3_downmix.h"
-#include "ac3_decoder.h"
 #include "ac3_adec.h"
 
 #define AC3DEC_FRAME_SIZE (2*1536) 
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static int  decoder_Probe     ( u8 * );
-static int  decoder_Run       ( decoder_config_t * );
-static int  InitThread        ( ac3dec_thread_t * p_adec );
-static void EndThread         ( ac3dec_thread_t * p_adec );
+static int  OpenDecoder       ( vlc_object_t * );
+static int  RunDecoder        ( decoder_fifo_t * );
+static int  InitThread        ( ac3dec_t * p_adec );
+static void EndThread         ( ac3dec_t * p_adec );
 static void BitstreamCallback ( bit_stream_t *p_bit_stream,
-                                boolean_t b_new_pes );
-
-/*****************************************************************************
- * Capabilities
- *****************************************************************************/
-void _M( adec_getfunctions )( function_list_t * p_function_list )
-{
-    p_function_list->functions.dec.pf_probe = decoder_Probe;
-    p_function_list->functions.dec.pf_run   = decoder_Run;
-}
+                                vlc_bool_t b_new_pes );
 
 /*****************************************************************************
- * Build configuration tree.
+ * Module descriptor
  *****************************************************************************/
-/* Variable containing the AC3 downmix method */
-#define DOWNMIX_METHOD_VAR              "ac3_downmix"
-/* Variable containing the AC3 IMDCT method */
-#define IMDCT_METHOD_VAR                "ac3_imdct"
-
-MODULE_CONFIG_START
-ADD_CATEGORY_HINT( N_("Miscellaneous"), NULL)
-ADD_PLUGIN  ( DOWNMIX_METHOD_VAR, MODULE_CAPABILITY_DOWNMIX, NULL, NULL,
-              N_("AC3 downmix module"), NULL )
-ADD_PLUGIN  ( IMDCT_METHOD_VAR, MODULE_CAPABILITY_IMDCT, NULL, NULL,
-              N_("AC3 IMDCT module"), NULL )
-MODULE_CONFIG_STOP
-
-MODULE_INIT_START
-    SET_DESCRIPTION( _("software AC3 decoder") )
-    ADD_CAPABILITY( DECODER, 50 )
-    ADD_SHORTCUT( "ac3_adec" )
-    ADD_SHORTCUT( "ac3" )
-MODULE_INIT_STOP
-
-MODULE_ACTIVATE_START
-    _M( adec_getfunctions )( &p_module->p_functions->dec );
-MODULE_ACTIVATE_STOP
-
-MODULE_DEACTIVATE_START
-MODULE_DEACTIVATE_STOP
-
+vlc_module_begin();
+    add_category_hint( N_("Miscellaneous"), NULL );
+    add_module  ( "ac3-downmix", "downmix", NULL, NULL,
+                  N_("AC3 downmix module"), NULL );
+    add_module  ( "ac3-imdct", "imdct", NULL, NULL,
+                  N_("AC3 IMDCT module"), NULL );
+    set_description( _("software AC3 decoder") );
+    set_capability( "decoder", 50 );
+    set_callbacks( OpenDecoder, NULL );
+    add_shortcut( "ac3" );
+vlc_module_end();         
 
 /*****************************************************************************
- * decoder_Probe: probe the decoder and return score
+ * OpenDecoder: probe the decoder and return score
  *****************************************************************************
  * Tries to launch a decoder and return score so that the interface is able 
  * to chose.
  *****************************************************************************/
-static int decoder_Probe( u8 *pi_type )
-{
-    return ( *pi_type == AC3_AUDIO_ES ) ? 0 : -1;
-}
-
-
-/*****************************************************************************
- * InitThread: initialize data before entering main loop
- *****************************************************************************/
-static int InitThread( ac3dec_thread_t * p_ac3thread )
+static int OpenDecoder( vlc_object_t *p_this )
 {
-    char *psz_name;
-
-    /*
-     * Thread properties 
-     */
-    p_ac3thread->p_fifo = p_ac3thread->p_config->p_decoder_fifo;
-    p_ac3thread->ac3_decoder =
-        vlc_memalign( 16, sizeof(ac3dec_t), &p_ac3thread->ac3_decoder_orig );
-
-    /*
-     * Choose the best downmix module
-     */
-#define DOWNMIX p_ac3thread->ac3_decoder->downmix
-    psz_name = config_GetPszVariable( DOWNMIX_METHOD_VAR );
-    DOWNMIX.p_module = module_Need( MODULE_CAPABILITY_DOWNMIX, psz_name,
-                                    NULL );
-    if( psz_name ) free( psz_name );
-
-    if( DOWNMIX.p_module == NULL )
-    {
-        intf_ErrMsg( "ac3dec error: no suitable downmix module" );
-        free( p_ac3thread->ac3_decoder_orig );
-        return( -1 );
-    }
-
-#define F DOWNMIX.p_module->p_functions->downmix.functions.downmix
-    DOWNMIX.pf_downmix_3f_2r_to_2ch     = F.pf_downmix_3f_2r_to_2ch;
-    DOWNMIX.pf_downmix_2f_2r_to_2ch     = F.pf_downmix_2f_2r_to_2ch;
-    DOWNMIX.pf_downmix_3f_1r_to_2ch     = F.pf_downmix_3f_1r_to_2ch;
-    DOWNMIX.pf_downmix_2f_1r_to_2ch     = F.pf_downmix_2f_1r_to_2ch;
-    DOWNMIX.pf_downmix_3f_0r_to_2ch     = F.pf_downmix_3f_0r_to_2ch;
-    DOWNMIX.pf_stream_sample_2ch_to_s16 = F.pf_stream_sample_2ch_to_s16;
-    DOWNMIX.pf_stream_sample_1ch_to_s16 = F.pf_stream_sample_1ch_to_s16;
-#undef F
-#undef DOWNMIX
-
-    /*
-     * Choose the best IMDCT module
-     */
-    p_ac3thread->ac3_decoder->imdct =
-    vlc_memalign( 16, sizeof(imdct_t), &p_ac3thread->ac3_decoder->imdct_orig );
+    decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
     
-#define IMDCT p_ac3thread->ac3_decoder->imdct
-    psz_name = config_GetPszVariable( IMDCT_METHOD_VAR );
-    IMDCT->p_module = module_Need( MODULE_CAPABILITY_IMDCT, psz_name,
-                                   NULL );
-    if( psz_name ) free( psz_name );
-
-    if( IMDCT->p_module == NULL )
-    {
-        intf_ErrMsg( "ac3dec error: no suitable IMDCT module" );
-        module_Unneed( p_ac3thread->ac3_decoder->downmix.p_module );
-        free( p_ac3thread->ac3_decoder->imdct_orig );
-        free( p_ac3thread->ac3_decoder_orig );
-        return( -1 );
+    if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') )
+    {   
+        return VLC_EGENERIC;
     }
 
-#define F IMDCT->p_module->p_functions->imdct.functions.imdct
-    IMDCT->pf_imdct_init    = F.pf_imdct_init;
-    IMDCT->pf_imdct_256     = F.pf_imdct_256;
-    IMDCT->pf_imdct_256_nol = F.pf_imdct_256_nol;
-    IMDCT->pf_imdct_512     = F.pf_imdct_512;
-    IMDCT->pf_imdct_512_nol = F.pf_imdct_512_nol;
-#undef F
-
-    /* Initialize the ac3 decoder structures */
-    p_ac3thread->ac3_decoder->samples =
-        vlc_memalign( 16, 6 * 256 * sizeof(float),
-                      &p_ac3thread->ac3_decoder->samples_orig );
-
-    IMDCT->buf    = vlc_memalign( 16, N/4 * sizeof(complex_t),
-                                  &IMDCT->buf_orig );
-    IMDCT->delay  = vlc_memalign( 16, 6 * 256 * sizeof(float),
-                                  &IMDCT->delay_orig );
-    IMDCT->delay1 = vlc_memalign( 16, 6 * 256 * sizeof(float),
-                                  &IMDCT->delay1_orig );
-    IMDCT->xcos1  = vlc_memalign( 16, N/4 * sizeof(float),
-                                  &IMDCT->xcos1_orig );
-    IMDCT->xsin1  = vlc_memalign( 16, N/4 * sizeof(float),
-                                  &IMDCT->xsin1_orig );
-    IMDCT->xcos2  = vlc_memalign( 16, N/8 * sizeof(float),
-                                  &IMDCT->xcos2_orig );
-    IMDCT->xsin2  = vlc_memalign( 16, N/8 * sizeof(float),
-                                  &IMDCT->xsin2_orig );
-    IMDCT->xcos_sin_sse = vlc_memalign( 16, 128 * 4 * sizeof(float),
-                                        &IMDCT->xcos_sin_sse_orig );
-    IMDCT->w_1    = vlc_memalign( 16, 1  * sizeof(complex_t),
-                                  &IMDCT->w_1_orig );
-    IMDCT->w_2    = vlc_memalign( 16, 2  * sizeof(complex_t),
-                                  &IMDCT->w_2_orig );
-    IMDCT->w_4    = vlc_memalign( 16, 4  * sizeof(complex_t),
-                                  &IMDCT->w_4_orig );
-    IMDCT->w_8    = vlc_memalign( 16, 8  * sizeof(complex_t),
-                                  &IMDCT->w_8_orig );
-    IMDCT->w_16   = vlc_memalign( 16, 16 * sizeof(complex_t),
-                                  &IMDCT->w_16_orig );
-    IMDCT->w_32   = vlc_memalign( 16, 32 * sizeof(complex_t),
-                                  &IMDCT->w_32_orig );
-    IMDCT->w_64   = vlc_memalign( 16, 64 * sizeof(complex_t),
-                                  &IMDCT->w_64_orig );
-
-    ac3_init( p_ac3thread->ac3_decoder );
-
-    /*
-     * Initialize the output properties
-     */
-    p_ac3thread->p_aout_fifo = NULL;
-
-    /*
-     * Bit stream
-     */
-    InitBitstream(&p_ac3thread->ac3_decoder->bit_stream,
-            p_ac3thread->p_config->p_decoder_fifo,
-            BitstreamCallback, (void *) p_ac3thread );
-    
-    return( 0 );
+    p_fifo->pf_run = RunDecoder;
+    return VLC_SUCCESS;
 }
 
 /*****************************************************************************
- * decoder_Run: this function is called just after the thread is created
+ * RunDecoder: this function is called just after the thread is created
  *****************************************************************************/
-static int decoder_Run ( decoder_config_t * p_config )
+static int RunDecoder( decoder_fifo_t *p_fifo )
 {
-    ac3dec_thread_t *   p_ac3thread;
-    void *              p_ac3thread_orig;         /* pointer before memalign */
-    boolean_t           b_sync = 0;
+    ac3dec_t *   p_ac3dec;
+    void *       p_orig;                          /* pointer before memalign */
+    vlc_bool_t   b_sync = 0;
 
     /* Allocate the memory needed to store the thread's structure */
-    p_ac3thread = (ac3dec_thread_t *)vlc_memalign( 16,
-                      sizeof(ac3dec_thread_t), &p_ac3thread_orig );
+    p_ac3dec = (ac3dec_t *)vlc_memalign( &p_orig, 16, sizeof(ac3dec_t) );
+    memset( p_ac3dec, 0, sizeof( ac3dec_t ) );
 
-    if( p_ac3thread == NULL )
+    if( p_ac3dec == NULL )
     {
-        intf_ErrMsg ( "ac3_adec error: not enough memory "
-                      "for decoder_Run() to allocate p_ac3thread" );
-        DecoderError( p_config->p_decoder_fifo );
+        msg_Err( p_fifo, "out of memory" );
+        DecoderError( p_fifo );
         return( -1 );
     }
 
     /*
      * Initialize the thread properties
      */
-    p_ac3thread->p_config = p_config;
-    if( InitThread( p_ac3thread ) )
+    p_ac3dec->p_fifo = p_fifo;
+    if( InitThread( p_ac3dec ) )
     {
-        intf_ErrMsg( "ac3_adec error: could not initialize thread" );
-        DecoderError( p_config->p_decoder_fifo );
-        free( p_ac3thread_orig );
+        msg_Err( p_fifo, "could not initialize thread" );
+        DecoderError( p_fifo );
+        free( p_orig );
         return( -1 );
     }
 
     /* ac3 decoder thread's main loop */
     /* FIXME : do we have enough room to store the decoded frames ?? */
-    while ((!p_ac3thread->p_fifo->b_die) && (!p_ac3thread->p_fifo->b_error))
+    while ((!p_ac3dec->p_fifo->b_die) && (!p_ac3dec->p_fifo->b_error))
     {
         s16 * buffer;
         ac3_sync_info_t sync_info;
@@ -274,7 +127,7 @@ static int decoder_Run ( decoder_config_t * p_config )
         if( !b_sync )
         {
              int i_sync_ptr;
-#define p_bit_stream (&p_ac3thread->ac3_decoder->bit_stream)
+#define p_bit_stream (&p_ac3dec->bit_stream)
 
              /* Go to the next PES packet and jump to sync_ptr */
              do {
@@ -295,120 +148,195 @@ static int decoder_Run ( decoder_config_t * p_config )
 #undef p_bit_stream
         }
 
-        if (ac3_sync_frame (p_ac3thread->ac3_decoder, &sync_info))
+        if (ac3_sync_frame (p_ac3dec, &sync_info))
         {
             b_sync = 0;
             continue;
         }
 
-        if( ( p_ac3thread->p_aout_fifo != NULL ) &&
-            ( p_ac3thread->p_aout_fifo->i_rate != sync_info.sample_rate ) )
+        if( ( p_ac3dec->p_aout_fifo != NULL ) &&
+            ( p_ac3dec->p_aout_fifo->i_rate != sync_info.sample_rate ) )
         {
             /* Make sure the output thread leaves the NextFrame() function */
-            vlc_mutex_lock (&(p_ac3thread->p_aout_fifo->data_lock));
-            aout_DestroyFifo (p_ac3thread->p_aout_fifo);
-            vlc_cond_signal (&(p_ac3thread->p_aout_fifo->data_wait));
-            vlc_mutex_unlock (&(p_ac3thread->p_aout_fifo->data_lock));
+            vlc_mutex_lock (&(p_ac3dec->p_aout_fifo->data_lock));
+            aout_DestroyFifo (p_ac3dec->p_aout_fifo);
+            vlc_cond_signal (&(p_ac3dec->p_aout_fifo->data_wait));
+            vlc_mutex_unlock (&(p_ac3dec->p_aout_fifo->data_lock));
 
-            p_ac3thread->p_aout_fifo = NULL;
+            p_ac3dec->p_aout_fifo = NULL;
         }
 
         /* Creating the audio output fifo if not created yet */
-        if (p_ac3thread->p_aout_fifo == NULL ) {
-            p_ac3thread->p_aout_fifo = aout_CreateFifo( AOUT_FIFO_PCM, 2,
-                           sync_info.sample_rate, AC3DEC_FRAME_SIZE, NULL  );
-            if ( p_ac3thread->p_aout_fifo == NULL )
+        if (p_ac3dec->p_aout_fifo == NULL ) {
+            p_ac3dec->p_aout_fifo =
+                aout_CreateFifo( p_ac3dec->p_fifo, AOUT_FIFO_PCM, 2,
+                         sync_info.sample_rate, AC3DEC_FRAME_SIZE, NULL  );
+            if ( p_ac3dec->p_aout_fifo == NULL )
             {
-                free( IMDCT->w_1_orig );
-                free( IMDCT->w_64_orig );
-                free( IMDCT->w_32_orig );
-                free( IMDCT->w_16_orig );
-                free( IMDCT->w_8_orig );
-                free( IMDCT->w_4_orig );
-                free( IMDCT->w_2_orig );
-                free( IMDCT->xcos_sin_sse_orig );
-                free( IMDCT->xsin2_orig );
-                free( IMDCT->xcos2_orig );
-                free( IMDCT->xsin1_orig );
-                free( IMDCT->xcos1_orig );
-                free( IMDCT->delay1_orig );
-                free( IMDCT->delay_orig );
-                free( IMDCT->buf_orig );
-        #undef IMDCT
-
-                free( p_ac3thread->ac3_decoder->samples_orig );
-        
-                module_Unneed( p_ac3thread->ac3_decoder->imdct->p_module );
-                module_Unneed( p_ac3thread->ac3_decoder->downmix.p_module );
-        
-                free( p_ac3thread->ac3_decoder->imdct_orig );
-                free( p_ac3thread->ac3_decoder_orig );
-        
-                return( -1 );
+                p_ac3dec->p_fifo->b_error = 1;
+                break;
             }
         }
 
-        CurrentPTS( &p_ac3thread->ac3_decoder->bit_stream,
-            &p_ac3thread->p_aout_fifo->date[p_ac3thread->p_aout_fifo->i_end_frame],
+        CurrentPTS( &p_ac3dec->bit_stream,
+            &p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->i_end_frame],
             NULL );
-        if( !p_ac3thread->p_aout_fifo->date[p_ac3thread->p_aout_fifo->i_end_frame] )
+        if( !p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->i_end_frame] )
         {
-            p_ac3thread->p_aout_fifo->date[
-                p_ac3thread->p_aout_fifo->i_end_frame] =
+            p_ac3dec->p_aout_fifo->date[
+                p_ac3dec->p_aout_fifo->i_end_frame] =
                 LAST_MDATE;
         }
     
-        buffer = ((s16 *)p_ac3thread->p_aout_fifo->buffer) + 
-            (p_ac3thread->p_aout_fifo->i_end_frame * AC3DEC_FRAME_SIZE);
+        buffer = ((s16 *)p_ac3dec->p_aout_fifo->buffer) + 
+            (p_ac3dec->p_aout_fifo->i_end_frame * AC3DEC_FRAME_SIZE);
 
-        if (ac3_decode_frame (p_ac3thread->ac3_decoder, buffer))
+        if (ac3_decode_frame (p_ac3dec, buffer))
         {
             b_sync = 0;
             continue;
         }
         
-        vlc_mutex_lock (&p_ac3thread->p_aout_fifo->data_lock);
-        p_ac3thread->p_aout_fifo->i_end_frame = 
-            (p_ac3thread->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
-        vlc_cond_signal (&p_ac3thread->p_aout_fifo->data_wait);
-        vlc_mutex_unlock (&p_ac3thread->p_aout_fifo->data_lock);
+        vlc_mutex_lock (&p_ac3dec->p_aout_fifo->data_lock);
+        p_ac3dec->p_aout_fifo->i_end_frame = 
+            (p_ac3dec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
+        vlc_cond_signal (&p_ac3dec->p_aout_fifo->data_wait);
+        vlc_mutex_unlock (&p_ac3dec->p_aout_fifo->data_lock);
 
-        RealignBits(&p_ac3thread->ac3_decoder->bit_stream);
+        RealignBits(&p_ac3dec->bit_stream);
     }
 
     /* If b_error is set, the ac3 decoder thread enters the error loop */
-    if (p_ac3thread->p_fifo->b_error)
+    if (p_ac3dec->p_fifo->b_error)
     {
-        DecoderError( p_ac3thread->p_fifo );
+        DecoderError( p_ac3dec->p_fifo );
     }
 
     /* End of the ac3 decoder thread */
-    EndThread (p_ac3thread);
+    EndThread (p_ac3dec);
 
-    free( p_ac3thread_orig );
+    free( p_orig );
 
     return( 0 );
 }
 
+/*****************************************************************************
+ * InitThread: initialize data before entering main loop
+ *****************************************************************************/
+static int InitThread( ac3dec_t * p_ac3dec )
+{
+    char *psz_name;
+
+    /*
+     * Choose the best downmix module
+     */
+    p_ac3dec->p_downmix = vlc_object_create( p_ac3dec->p_fifo,
+                                             sizeof( downmix_t ) );
+    p_ac3dec->p_downmix->psz_object_name = "downmix";
+
+    psz_name = config_GetPsz( p_ac3dec->p_downmix, "ac3-downmix" );
+    p_ac3dec->p_downmix->p_module =
+                    module_Need( p_ac3dec->p_downmix, "downmix", psz_name );
+    if( psz_name ) free( psz_name );
+
+    if( p_ac3dec->p_downmix->p_module == NULL )
+    {
+        msg_Err( p_ac3dec->p_fifo, "no suitable downmix module" );
+        vlc_object_destroy( p_ac3dec->p_downmix );
+        return( -1 );
+    }
+
+    /*
+     * Choose the best IMDCT module
+     */
+    p_ac3dec->p_imdct = vlc_object_create( p_ac3dec->p_fifo,
+                                           sizeof( imdct_t ) );
+    
+#define IMDCT p_ac3dec->p_imdct
+    psz_name = config_GetPsz( p_ac3dec->p_fifo, "ac3-imdct" );
+    p_ac3dec->p_imdct->p_module =
+                   module_Need( p_ac3dec->p_imdct, "imdct", psz_name );
+    if( psz_name ) free( psz_name );
+
+    if( p_ac3dec->p_imdct->p_module == NULL )
+    {
+        msg_Err( p_ac3dec->p_fifo, "no suitable IMDCT module" );
+        vlc_object_destroy( p_ac3dec->p_imdct );
+        module_Unneed( p_ac3dec->p_downmix, p_ac3dec->p_downmix->p_module );
+        vlc_object_destroy( p_ac3dec->p_downmix );
+        return( -1 );
+    }
+
+    /* Initialize the ac3 decoder structures */
+    p_ac3dec->samples = vlc_memalign( &p_ac3dec->samples_orig,
+                                      16, 6 * 256 * sizeof(float) );
+
+    IMDCT->buf    = vlc_memalign( &IMDCT->buf_orig,
+                                  16, N/4 * sizeof(complex_t) );
+    IMDCT->delay  = vlc_memalign( &IMDCT->delay_orig,
+                                  16, 6 * 256 * sizeof(float) );
+    IMDCT->delay1 = vlc_memalign( &IMDCT->delay1_orig,
+                                  16, 6 * 256 * sizeof(float) );
+    IMDCT->xcos1  = vlc_memalign( &IMDCT->xcos1_orig,
+                                  16, N/4 * sizeof(float) );
+    IMDCT->xsin1  = vlc_memalign( &IMDCT->xsin1_orig,
+                                  16, N/4 * sizeof(float) );
+    IMDCT->xcos2  = vlc_memalign( &IMDCT->xcos2_orig,
+                                  16, N/8 * sizeof(float) );
+    IMDCT->xsin2  = vlc_memalign( &IMDCT->xsin2_orig,
+                                  16, N/8 * sizeof(float) );
+    IMDCT->xcos_sin_sse = vlc_memalign( &IMDCT->xcos_sin_sse_orig,
+                                        16, 128 * 4 * sizeof(float) );
+    IMDCT->w_1    = vlc_memalign( &IMDCT->w_1_orig,
+                                  16, 1  * sizeof(complex_t) );
+    IMDCT->w_2    = vlc_memalign( &IMDCT->w_2_orig,
+                                  16, 2  * sizeof(complex_t) );
+    IMDCT->w_4    = vlc_memalign( &IMDCT->w_4_orig,
+                                  16, 4  * sizeof(complex_t) );
+    IMDCT->w_8    = vlc_memalign( &IMDCT->w_8_orig,
+                                  16, 8  * sizeof(complex_t) );
+    IMDCT->w_16   = vlc_memalign( &IMDCT->w_16_orig,
+                                  16, 16 * sizeof(complex_t) );
+    IMDCT->w_32   = vlc_memalign( &IMDCT->w_32_orig,
+                                  16, 32 * sizeof(complex_t) );
+    IMDCT->w_64   = vlc_memalign( &IMDCT->w_64_orig,
+                                  16, 64 * sizeof(complex_t) );
+#undef IMDCT
+
+    E_( ac3_init )( p_ac3dec );
+
+    /*
+     * Initialize the output properties
+     */
+    p_ac3dec->p_aout_fifo = NULL;
+
+    /*
+     * Bit stream
+     */
+    InitBitstream( &p_ac3dec->bit_stream, p_ac3dec->p_fifo,
+                   BitstreamCallback, (void *) p_ac3dec );
+    
+    return( 0 );
+}
 
 /*****************************************************************************
  * EndThread : ac3 decoder thread destruction
  *****************************************************************************/
-static void EndThread (ac3dec_thread_t * p_ac3thread)
+static void EndThread (ac3dec_t * p_ac3dec)
 {
     /* If the audio output fifo was created, we destroy it */
-    if (p_ac3thread->p_aout_fifo != NULL)
+    if (p_ac3dec->p_aout_fifo != NULL)
     {
-        aout_DestroyFifo (p_ac3thread->p_aout_fifo);
+        aout_DestroyFifo (p_ac3dec->p_aout_fifo);
 
         /* Make sure the output thread leaves the NextFrame() function */
-        vlc_mutex_lock (&(p_ac3thread->p_aout_fifo->data_lock));
-        vlc_cond_signal (&(p_ac3thread->p_aout_fifo->data_wait));
-        vlc_mutex_unlock (&(p_ac3thread->p_aout_fifo->data_lock));
+        vlc_mutex_lock (&(p_ac3dec->p_aout_fifo->data_lock));
+        vlc_cond_signal (&(p_ac3dec->p_aout_fifo->data_wait));
+        vlc_mutex_unlock (&(p_ac3dec->p_aout_fifo->data_lock));
     }
 
     /* Free allocated structures */
-#define IMDCT p_ac3thread->ac3_decoder->imdct
+#define IMDCT p_ac3dec->p_imdct
     free( IMDCT->w_1_orig );
     free( IMDCT->w_64_orig );
     free( IMDCT->w_32_orig );
@@ -426,15 +354,17 @@ static void EndThread (ac3dec_thread_t * p_ac3thread)
     free( IMDCT->buf_orig );
 #undef IMDCT
 
-    free( p_ac3thread->ac3_decoder->samples_orig );
+    free( p_ac3dec->samples_orig );
 
     /* Unlock the modules */
-    module_Unneed( p_ac3thread->ac3_decoder->downmix.p_module );
-    module_Unneed( p_ac3thread->ac3_decoder->imdct->p_module );
+    module_Unneed( p_ac3dec->p_downmix, p_ac3dec->p_downmix->p_module );
+    vlc_object_destroy( p_ac3dec->p_downmix );
+
+    module_Unneed( p_ac3dec->p_imdct, p_ac3dec->p_imdct->p_module );
+    vlc_object_destroy( p_ac3dec->p_imdct );
 
     /* Free what's left of the decoder */
-    free( p_ac3thread->ac3_decoder->imdct_orig );
-    free( p_ac3thread->ac3_decoder_orig );
+    free( p_ac3dec->imdct_orig );
 }
 
 /*****************************************************************************
@@ -443,12 +373,12 @@ static void EndThread (ac3dec_thread_t * p_ac3thread)
  * This function is called by input's NextDataPacket.
  *****************************************************************************/
 static void BitstreamCallback ( bit_stream_t * p_bit_stream,
-                                boolean_t b_new_pes )
+                                vlc_bool_t b_new_pes )
 {
     if( b_new_pes )
     {
         /* Drop special AC3 header */
-        p_bit_stream->p_byte += 3;
+/*        p_bit_stream->p_byte += 3; */
     }
 }