]> git.sesse.net Git - vlc/blobdiff - plugins/ac3_adec/ac3_adec.c
* ./plugins/text/rc.c: added a safety lock.
[vlc] / plugins / ac3_adec / ac3_adec.c
index bd10efc343a4512808233ee0ce60df829619fca5..cb3c63425dcfaa967431578097efd6fbb47eeb3a 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.14 2002/01/14 23:46:35 massiot Exp $
+ * $Id: ac3_adec.c,v 1.30 2002/05/15 19:36:04 sam Exp $
  *
  * Authors: Michel Lespinasse <walken@zoy.org>
  *
@@ -49,7 +49,7 @@
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static int  decoder_Probe     ( probedata_t * );
+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 );
@@ -61,19 +61,31 @@ static void BitstreamCallback ( bit_stream_t *p_bit_stream,
  *****************************************************************************/
 void _M( adec_getfunctions )( function_list_t * p_function_list )
 {
-    p_function_list->pf_probe = decoder_Probe;
-    p_function_list->functions.dec.pf_run = decoder_Run;
+    p_function_list->functions.dec.pf_probe = decoder_Probe;
+    p_function_list->functions.dec.pf_run   = decoder_Run;
 }
 
 /*****************************************************************************
  * Build configuration tree.
  *****************************************************************************/
+/* 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_MODULE  ( DOWNMIX_METHOD_VAR, MODULE_CAPABILITY_DOWNMIX, NULL, NULL,
+              N_("AC3 downmix module"), NULL )
+ADD_MODULE  ( IMDCT_METHOD_VAR, MODULE_CAPABILITY_IMDCT, NULL, NULL,
+              N_("AC3 IMDCT module"), NULL )
 MODULE_CONFIG_STOP
 
 MODULE_INIT_START
-    SET_DESCRIPTION( "software AC3 decoder" )
+    SET_DESCRIPTION( _("software AC3 decoder") )
     ADD_CAPABILITY( DECODER, 50 )
+    ADD_SHORTCUT( "ac3_adec" )
+    ADD_SHORTCUT( "ac3" )
 MODULE_INIT_STOP
 
 MODULE_ACTIVATE_START
@@ -90,9 +102,9 @@ MODULE_DEACTIVATE_STOP
  * Tries to launch a decoder and return score so that the interface is able 
  * to chose.
  *****************************************************************************/
-static int decoder_Probe( probedata_t *p_data )
+static int decoder_Probe( u8 *pi_type )
 {
-    return ( p_data->i_type == AC3_AUDIO_ES ) ? 50 : 0;
+    return ( *pi_type == AC3_AUDIO_ES ) ? 0 : -1;
 }
 
 
@@ -101,24 +113,30 @@ static int decoder_Probe( probedata_t *p_data )
  *****************************************************************************/
 static int InitThread( ac3dec_thread_t * p_ac3thread )
 {
+    char *psz_name;
+
     /*
      * Thread properties 
      */
     p_ac3thread->p_fifo = p_ac3thread->p_config->p_decoder_fifo;
-    p_ac3thread->ac3_decoder = memalign( 16, sizeof(ac3dec_t) );
+
+    p_ac3thread->ac3_decoder =
+        vlc_memalign( &p_ac3thread->ac3_decoder_orig, 16, sizeof(ac3dec_t) );
+    memset( p_ac3thread->ac3_decoder, 0, sizeof( ac3dec_t ) );
 
     /*
      * Choose the best downmix module
      */
 #define DOWNMIX p_ac3thread->ac3_decoder->downmix
-    DOWNMIX.p_module = module_Need( MODULE_CAPABILITY_DOWNMIX,
-                               main_GetPszVariable( DOWNMIX_METHOD_VAR, NULL ),
-                               NULL );
+    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 );
+        free( p_ac3thread->ac3_decoder_orig );
         return( -1 );
     }
 
@@ -136,19 +154,21 @@ static int InitThread( ac3dec_thread_t * p_ac3thread )
     /*
      * Choose the best IMDCT module
      */
-    p_ac3thread->ac3_decoder->imdct = memalign(16, sizeof(imdct_t));
+    p_ac3thread->ac3_decoder->imdct =
+    vlc_memalign( &p_ac3thread->ac3_decoder->imdct_orig, 16, sizeof(imdct_t) );
     
 #define IMDCT p_ac3thread->ac3_decoder->imdct
-    IMDCT->p_module = module_Need( MODULE_CAPABILITY_IMDCT,
-                               main_GetPszVariable( IMDCT_METHOD_VAR, NULL ),
-                               NULL );
+    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 );
-        free( p_ac3thread->ac3_decoder );
+        free( p_ac3thread->ac3_decoder->imdct_orig );
+        free( p_ac3thread->ac3_decoder_orig );
         return( -1 );
     }
 
@@ -161,52 +181,56 @@ static int InitThread( ac3dec_thread_t * p_ac3thread )
 #undef F
 
     /* Initialize the ac3 decoder structures */
-#define p_dec p_ac3thread->ac3_decoder
-#if defined( __MINGW32__ )
-    p_dec->samples_back = memalign( 16, 6 * 256 * sizeof(float) + 15 );
-    p_dec->samples = (float *)
-                     (((unsigned long) p_dec->samples_back + 15 ) & ~0xFUL);
-#else
-    p_dec->samples = memalign( 16, 6 * 256 * sizeof(float) );
-#endif
-#undef p_dec
-
-    IMDCT->buf    = memalign( 16, N/4 * sizeof(complex_t) );
-    IMDCT->delay  = memalign( 16, 6 * 256 * sizeof(float) );
-    IMDCT->delay1 = memalign( 16, 6 * 256 * sizeof(float) );
-    IMDCT->xcos1  = memalign( 16, N/4 * sizeof(float) );
-    IMDCT->xsin1  = memalign( 16, N/4 * sizeof(float) );
-    IMDCT->xcos2  = memalign( 16, N/8 * sizeof(float) );
-    IMDCT->xsin2  = memalign( 16, N/8 * sizeof(float) );
-    IMDCT->xcos_sin_sse = memalign( 16, 128 * 4 * sizeof(float) );
-    IMDCT->w_1    = memalign( 16, 1  * sizeof(complex_t) );
-    IMDCT->w_2    = memalign( 16, 2  * sizeof(complex_t) );
-    IMDCT->w_4    = memalign( 16, 4  * sizeof(complex_t) );
-    IMDCT->w_8    = memalign( 16, 8  * sizeof(complex_t) );
-    IMDCT->w_16   = memalign( 16, 16 * sizeof(complex_t) );
-    IMDCT->w_32   = memalign( 16, 32 * sizeof(complex_t) );
-    IMDCT->w_64   = memalign( 16, 64 * sizeof(complex_t) );
-
-    ac3_init( p_ac3thread->ac3_decoder );
+    p_ac3thread->ac3_decoder->samples =
+        vlc_memalign( &p_ac3thread->ac3_decoder->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
+
+    _M( ac3_init )( p_ac3thread->ac3_decoder );
 
     /*
      * Initialize the output properties
      */
     p_ac3thread->p_aout_fifo = NULL;
 
-    intf_DbgMsg ( "ac3_adec debug: ac3_adec thread (%p) initialized", 
-                  p_ac3thread );
-
     /*
      * Bit stream
      */
-    p_ac3thread->p_config->pf_init_bit_stream(
-            &p_ac3thread->ac3_decoder->bit_stream,
+    InitBitstream(&p_ac3thread->ac3_decoder->bit_stream,
             p_ac3thread->p_config->p_decoder_fifo,
             BitstreamCallback, (void *) p_ac3thread );
     
-    intf_DbgMsg("ac3dec debug: ac3 decoder thread %p initialized", p_ac3thread);
-    
     return( 0 );
 }
 
@@ -216,12 +240,12 @@ static int InitThread( ac3dec_thread_t * p_ac3thread )
 static int decoder_Run ( decoder_config_t * p_config )
 {
     ac3dec_thread_t *   p_ac3thread;
-    int sync;
-
-    intf_DbgMsg( "ac3_adec debug: ac3_adec thread launched, initializing" );
+    void *              p_ac3thread_orig;         /* pointer before memalign */
+    boolean_t           b_sync = 0;
 
     /* Allocate the memory needed to store the thread's structure */
-    p_ac3thread = (ac3dec_thread_t *)memalign(16, sizeof(ac3dec_thread_t));
+    p_ac3thread = (ac3dec_thread_t *)vlc_memalign( &p_ac3thread_orig, 16,
+                                                   sizeof(ac3dec_thread_t) );
 
     if( p_ac3thread == NULL )
     {
@@ -230,7 +254,7 @@ static int decoder_Run ( decoder_config_t * p_config )
         DecoderError( p_config->p_decoder_fifo );
         return( -1 );
     }
-   
+
     /*
      * Initialize the thread properties
      */
@@ -239,111 +263,97 @@ static int decoder_Run ( decoder_config_t * p_config )
     {
         intf_ErrMsg( "ac3_adec error: could not initialize thread" );
         DecoderError( p_config->p_decoder_fifo );
-        free( p_ac3thread );
+        free( p_ac3thread_orig );
         return( -1 );
     }
 
-    sync = 0;
-    p_ac3thread->sync_ptr = 0;
-
     /* 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))
     {
         s16 * buffer;
         ac3_sync_info_t sync_info;
-        int ptr;
-
-        if (!sync) {
-            do {
-                GetBits(&p_ac3thread->ac3_decoder->bit_stream,8);
-            } while ((!p_ac3thread->sync_ptr) && (!p_ac3thread->p_fifo->b_die)
-                    && (!p_ac3thread->p_fifo->b_error));
-            
-            ptr = p_ac3thread->sync_ptr;
-
-            while(ptr-- && (!p_ac3thread->p_fifo->b_die)
-                && (!p_ac3thread->p_fifo->b_error))
-            {
-                p_ac3thread->ac3_decoder->bit_stream.p_byte++;
-            }
-                        
-            /* we are in sync now */
-            sync = 1;
+
+        if( !b_sync )
+        {
+             int i_sync_ptr;
+#define p_bit_stream (&p_ac3thread->ac3_decoder->bit_stream)
+
+             /* Go to the next PES packet and jump to sync_ptr */
+             do {
+                BitstreamNextDataPacket( p_bit_stream );
+             } while( !p_bit_stream->p_decoder_fifo->b_die
+                       && !p_bit_stream->p_decoder_fifo->b_error
+                       && p_bit_stream->p_data !=
+                          p_bit_stream->p_decoder_fifo->p_first->p_first );
+             i_sync_ptr = *(p_bit_stream->p_byte - 2) << 8
+                            | *(p_bit_stream->p_byte - 1);
+             p_bit_stream->p_byte += i_sync_ptr;
+
+             /* Empty the bit FIFO and realign the bit stream */
+             p_bit_stream->fifo.buffer = 0;
+             p_bit_stream->fifo.i_available = 0;
+             AlignWord( p_bit_stream );
+             b_sync = 1;
+#undef p_bit_stream
         }
 
         if (ac3_sync_frame (p_ac3thread->ac3_decoder, &sync_info))
         {
-            sync = 0;
-            goto bad_frame;
+            b_sync = 0;
+            continue;
         }
-        
+
+        if( ( p_ac3thread->p_aout_fifo != NULL ) &&
+            ( p_ac3thread->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));
+
+            p_ac3thread->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_ADEC_STEREO_FIFO, 
-                    2, sync_info.sample_rate, 0, AC3DEC_FRAME_SIZE, NULL  );
+        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 )
             {
-                free( IMDCT->w_1 );
-                free( IMDCT->w_64 );
-                free( IMDCT->w_32 );
-                free( IMDCT->w_16 );
-                free( IMDCT->w_8 );
-                free( IMDCT->w_4 );
-                free( IMDCT->w_2 );
-                free( IMDCT->xcos_sin_sse );
-                free( IMDCT->xsin2 );
-                free( IMDCT->xcos2 );
-                free( IMDCT->xsin1 );
-                free( IMDCT->xcos1 );
-                free( IMDCT->delay1 );
-                free( IMDCT->delay );
-                free( IMDCT->buf );
-        #undef IMDCT
-        
-        #if defined( __MINGW32__ )
-                free( p_ac3thread->ac3_decoder->samples_back );
-        #else
-                free( p_ac3thread->ac3_decoder->samples );
-        #endif
-        
-                module_Unneed( p_ac3thread->ac3_decoder->imdct->p_module );
-                module_Unneed( p_ac3thread->ac3_decoder->downmix.p_module );
-        
-                free( p_ac3thread->ac3_decoder->imdct );
-                free( p_ac3thread->ac3_decoder );
-        
-                return( -1 );
+                p_ac3thread->p_fifo->b_error = 1;
+                break;
             }
         }
 
         CurrentPTS( &p_ac3thread->ac3_decoder->bit_stream,
-            &p_ac3thread->p_aout_fifo->date[p_ac3thread->p_aout_fifo->l_end_frame],
+            &p_ac3thread->p_aout_fifo->date[p_ac3thread->p_aout_fifo->i_end_frame],
             NULL );
-        if( !p_ac3thread->p_aout_fifo->date[p_ac3thread->p_aout_fifo->l_end_frame] )
+        if( !p_ac3thread->p_aout_fifo->date[p_ac3thread->p_aout_fifo->i_end_frame] )
         {
             p_ac3thread->p_aout_fifo->date[
-                p_ac3thread->p_aout_fifo->l_end_frame] =
+                p_ac3thread->p_aout_fifo->i_end_frame] =
                 LAST_MDATE;
         }
     
         buffer = ((s16 *)p_ac3thread->p_aout_fifo->buffer) + 
-            (p_ac3thread->p_aout_fifo->l_end_frame * AC3DEC_FRAME_SIZE);
+            (p_ac3thread->p_aout_fifo->i_end_frame * AC3DEC_FRAME_SIZE);
 
         if (ac3_decode_frame (p_ac3thread->ac3_decoder, buffer))
         {
-            sync = 0;
-            goto bad_frame;
+            b_sync = 0;
+            continue;
         }
         
         vlc_mutex_lock (&p_ac3thread->p_aout_fifo->data_lock);
-        p_ac3thread->p_aout_fifo->l_end_frame = 
-            (p_ac3thread->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
+        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);
 
-        bad_frame:
-            RealignBits(&p_ac3thread->ac3_decoder->bit_stream);
+        RealignBits(&p_ac3thread->ac3_decoder->bit_stream);
     }
 
     /* If b_error is set, the ac3 decoder thread enters the error loop */
@@ -355,7 +365,7 @@ static int decoder_Run ( decoder_config_t * p_config )
     /* End of the ac3 decoder thread */
     EndThread (p_ac3thread);
 
-    free( p_ac3thread );
+    free( p_ac3thread_orig );
 
     return( 0 );
 }
@@ -366,8 +376,6 @@ static int decoder_Run ( decoder_config_t * p_config )
  *****************************************************************************/
 static void EndThread (ac3dec_thread_t * p_ac3thread)
 {
-    intf_DbgMsg ("ac3dec debug: destroying ac3 decoder thread %p", p_ac3thread);
-
     /* If the audio output fifo was created, we destroy it */
     if (p_ac3thread->p_aout_fifo != NULL)
     {
@@ -381,38 +389,32 @@ static void EndThread (ac3dec_thread_t * p_ac3thread)
 
     /* Free allocated structures */
 #define IMDCT p_ac3thread->ac3_decoder->imdct
-    free( IMDCT->w_1 );
-    free( IMDCT->w_64 );
-    free( IMDCT->w_32 );
-    free( IMDCT->w_16 );
-    free( IMDCT->w_8 );
-    free( IMDCT->w_4 );
-    free( IMDCT->w_2 );
-    free( IMDCT->xcos_sin_sse );
-    free( IMDCT->xsin2 );
-    free( IMDCT->xcos2 );
-    free( IMDCT->xsin1 );
-    free( IMDCT->xcos1 );
-    free( IMDCT->delay1 );
-    free( IMDCT->delay );
-    free( IMDCT->buf );
+    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
 
-#if defined( __MINGW32__ )
-    free( p_ac3thread->ac3_decoder->samples_back );
-#else
-    free( p_ac3thread->ac3_decoder->samples );
-#endif
+    free( p_ac3thread->ac3_decoder->samples_orig );
 
     /* Unlock the modules */
     module_Unneed( p_ac3thread->ac3_decoder->downmix.p_module );
     module_Unneed( p_ac3thread->ac3_decoder->imdct->p_module );
 
     /* Free what's left of the decoder */
-    free( p_ac3thread->ac3_decoder->imdct );
-    free( p_ac3thread->ac3_decoder );
-
-    intf_DbgMsg( "ac3dec debug: ac3 decoder thread %p destroyed", p_ac3thread );
+    free( p_ac3thread->ac3_decoder->imdct_orig );
+    free( p_ac3thread->ac3_decoder_orig );
 }
 
 /*****************************************************************************
@@ -421,20 +423,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)
+                                boolean_t b_new_pes )
 {
-
-    ac3dec_thread_t *p_ac3thread=(ac3dec_thread_t *)p_bit_stream->p_callback_arg;
-
     if( b_new_pes )
     {
-        int ptr;
-        
-        ptr = *(p_bit_stream->p_byte + 1);
-        ptr <<= 8;
-        ptr |= *(p_bit_stream->p_byte + 2);
-        p_ac3thread->sync_ptr = ptr;
-        p_bit_stream->p_byte += 3;                                                            
+        /* Drop special AC3 header */
+        p_bit_stream->p_byte += 3;
     }
 }