/*****************************************************************************
- * audio_decoder.c: MPEG1 Layer I-II audio decoder
+ * 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:
+ * 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.
+ * 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-1307, USA.
+ * 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 ;
+ * - vlc_cond_signal() / vlc_cond_wait() ;
*
*/
-#include "int_types.h"
-#include "audio_constants.h"
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "defs.h"
+
+#include <unistd.h> /* getpid() */
+
+#include <stdio.h> /* "intf_msg.h" */
+#include <string.h> /* memcpy(), memset() */
+#include <stdlib.h> /* malloc(), free() */
+
+#include "config.h"
+#include "common.h"
+#include "threads.h"
+#include "mtime.h"
+
+#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
+
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
+#include "audio_output.h" /* aout_fifo_t (for audio_decoder.h) */
+
+#include "adec_generic.h"
#include "audio_decoder.h"
-#include "audio_math.h" /* DCT32(), PCM() */
-#include "audio_bit_stream.h"
+#include "adec_math.h" /* DCT32(), PCM() */
-#define NULL ((void *)0)
+#define ADEC_FRAME_SIZE (2*1152)
/*****************************************************************************
- * 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)
+ * 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);
/*****************************************************************************
- * adec_Layer1_Mono
+ * 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.
*****************************************************************************/
-static __inline__ int adec_Layer1_Mono (audiodec_t * p_adec)
+vlc_thread_t adec_CreateThread ( adec_config_t * p_config )
{
- p_adec->bit_stream.buffer = 0;
- p_adec->bit_stream.i_available = 0;
- return (0);
-}
+ adec_thread_t * p_adec;
-/*****************************************************************************
- * adec_Layer1_Stereo
- *****************************************************************************/
-static __inline__ int adec_Layer1_Stereo (audiodec_t * p_adec)
-{
- p_adec->bit_stream.buffer = 0;
- p_adec->bit_stream.i_available = 0;
- return (0);
-}
+ intf_DbgMsg ( "adec debug: creating audio decoder thread" );
-/*****************************************************************************
- * adec_Layer2_Mono
- *****************************************************************************/
-static __inline__ int adec_Layer2_Mono (audiodec_t * p_adec)
-{
- p_adec->bit_stream.buffer = 0;
- p_adec->bit_stream.i_available = 0;
- return (0);
+ /* Allocate the memory needed to store the thread's structure */
+ 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" );
+ return 0;
+ }
+
+ /*
+ * Initialize the thread properties
+ */
+ p_adec->p_config = p_config;
+ p_adec->p_fifo = p_config->decoder_config.p_decoder_fifo;
+
+ /*
+ * Initialize the decoder properties
+ */
+ adec_Init ( p_adec );
+
+ /*
+ * Initialize the output properties
+ */
+ 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");
+ free (p_adec);
+ return 0;
+ }
+
+ intf_DbgMsg ("adec debug: audio decoder thread (%p) created", p_adec);
+ return p_adec->thread_id;
}
+/* following functions are local */
+
/*****************************************************************************
- * adec_Layer2_Stereo
+ * 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 __inline__ int adec_Layer2_Stereo (audiodec_t * p_adec, s16 * buffer)
+static int InitThread (adec_thread_t * p_adec)
{
- typedef struct requantization_s
- {
- u8 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 u8 ppi_bitrate_per_channel_index[4][15] = ADEC_LAYER2_BITRATE_PER_CHANNEL_INDEX;
- static const u8 ppi_sblimit[3][11] = ADEC_LAYER2_SBLIMIT;
- static const u8 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 u8 * 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;
-
- s16 * p_s16;
-
- int i_need = 0, i_dump = 0;
-#if 0
- static const int pi_framesize[512] = ADEC_FRAME_SIZE;
-#endif
-
- /* Read the audio frame header and flush the bit buffer */
- i_header = p_adec->header;
- /* 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)
- {
- NeedBits (&p_adec->bit_stream, 16);
- DumpBits (&p_adec->bit_stream, 16);
- }
+ intf_DbgMsg ("adec debug: initializing audio decoder thread %p", p_adec);
- /* 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 ];
+ 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 );
- /* Find out the `bound' subband (see ISO/IEC 11172-3 2.4.2.3) */
- if (i_mode == 1)
+ /* Creating the audio output fifo */
+ 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 )
{
- 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;
+ return -1;
}
- /* 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.buffer >> (32 - i_nbal));
- p_adec->bit_stream.buffer <<= i_nbal;
- pi_allocation_1[ i_sb ] = (int)(p_adec->bit_stream.buffer >> (32 - i_nbal));
- p_adec->bit_stream.buffer <<= i_nbal;
- p_adec->bit_stream.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.buffer >> (32 - i_nbal));
- DumpBits (&p_adec->bit_stream, i_nbal);
- i_dump += i_nbal;
- }
+ intf_DbgMsg ( "adec debug: audio decoder thread %p initialized", p_adec );
+ return 0;
+}
-#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.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.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.buffer >> (32 - 2)); \
- p_adec->bit_stream.buffer <<= 2; \
- pi_scfsi_1[i_sb] = (int)(p_adec->bit_stream.buffer >> (32 - 2)); \
- p_adec->bit_stream.buffer <<= 2; \
- p_adec->bit_stream.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 */
+/*****************************************************************************
+ * 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)
+{
+ int sync;
- if (i_bitrate_per_channel_index <= 2)
- {
- MACRO (p_requantization_cd)
- }
- else
- {
- MACRO (pp_requantization_ab[i_sb])
- }
+ intf_DbgMsg ( "adec debug: running audio decoder thread (%p) (pid == %i)",
+ p_adec, getpid() );
-#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.buffer >> (32 - 6)]; \
- p_adec->bit_stream.buffer <<= 6; \
- (pf_scalefactor_1)[i_sb] = pf_scalefactor[p_adec->bit_stream.buffer >> (32 - 6)]; \
- p_adec->bit_stream.buffer <<= 6; \
- (pf_scalefactor_2)[i_sb] = pf_scalefactor[p_adec->bit_stream.buffer >> (32 - 6)]; \
- p_adec->bit_stream.buffer <<= 6; \
- p_adec->bit_stream.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.buffer >> (32 - 6)]; \
- p_adec->bit_stream.buffer <<= 6; \
- (pf_scalefactor_2)[i_sb] = pf_scalefactor[p_adec->bit_stream.buffer >> (32 - 6)]; \
- p_adec->bit_stream.buffer <<= 6; \
- p_adec->bit_stream.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.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.buffer >> (32 - 6)]; \
- p_adec->bit_stream.buffer <<= 6; \
- (pf_scalefactor_1)[i_sb] = \
- (pf_scalefactor_2)[i_sb] = pf_scalefactor[p_adec->bit_stream.buffer >> (32 - 6)]; \
- p_adec->bit_stream.buffer <<= 6; \
- p_adec->bit_stream.i_available -= (2*6); \
- i_dump += 12; \
- break; \
- }
-/* #define SWITCH */
+ /* Initializing the audio decoder thread */
+ p_adec->p_fifo->b_error = InitThread (p_adec);
+
+ sync = 0;
- for (i_sb = 0; i_sb < i_bound; i_sb++)
+ /* Audio decoder thread's main loop */
+ while( (!p_adec->p_fifo->b_die) && (!p_adec->p_fifo->b_error) )
{
- if (pi_allocation_0[i_sb])
+ s16 * buffer;
+ adec_sync_info_t sync_info;
+
+ if( DECODER_FIFO_START( *p_adec->p_fifo)->i_pts )
{
- SWITCH (pi_scfsi_0, pf_scalefactor_0_0, pf_scalefactor_0_1, pf_scalefactor_0_2)
+ 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;
}
- if (pi_allocation_1[i_sb])
+ else
{
- SWITCH (pi_scfsi_1, pf_scalefactor_1_0, pf_scalefactor_1_1, pf_scalefactor_1_2)
+ p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
+ LAST_MDATE;
}
- }
- for (; i_sb < i_sblimit; i_sb++)
- {
- if (pi_allocation_0[i_sb])
+
+ if( ! adec_SyncFrame (p_adec, &sync_info) )
{
- 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)
+ 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);
+ }
}
}
- 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;
- }
-#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.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.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.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.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.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.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.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.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]; \
- } \
- } \
- } \
-\
- DCT32 (ppf_sample_0[0], &p_adec->bank_0); \
- PCM (&p_adec->bank_0, &p_s16, 2); \
- p_s16 -= 63; \
-\
- DCT32 (ppf_sample_1[0], &p_adec->bank_1); \
- PCM (&p_adec->bank_1, &p_s16, 2); \
- p_s16 -= 1; \
-\
- DCT32 (ppf_sample_0[1], &p_adec->bank_0); \
- PCM (&p_adec->bank_0, &p_s16, 2); \
- p_s16 -= 63; \
-\
- DCT32 (ppf_sample_1[1], &p_adec->bank_1); \
- PCM (&p_adec->bank_1, &p_s16, 2); \
- p_s16 -= 1; \
-\
- DCT32 (ppf_sample_0[2], &p_adec->bank_0); \
- PCM (&p_adec->bank_0, &p_s16, 2); \
- p_s16 -= 63; \
-\
- DCT32 (ppf_sample_1[2], &p_adec->bank_1); \
- PCM (&p_adec->bank_1, &p_s16, 2); \
- p_s16 -= 1; \
+ /* If b_error is set, the audio decoder thread enters the error loop */
+ if( p_adec->p_fifo->b_error )
+ {
+ ErrorThread( p_adec );
}
-/* #define READ_SAMPLE_L2S */
-
- i_gr = 0;
- p_s16 = buffer;
-
- READ_SAMPLE_L2S (pf_scalefactor_0_0, pf_scalefactor_1_0, 4)
- READ_SAMPLE_L2S (pf_scalefactor_0_1, pf_scalefactor_1_1, 8)
- READ_SAMPLE_L2S (pf_scalefactor_0_2, pf_scalefactor_1_2, 12)
- p_adec->bit_stream.buffer = 0;
- p_adec->bit_stream.i_available = 0;
- return (6);
+ /* End of the audio decoder thread */
+ EndThread( p_adec );
}
-/**** wkn ****/
-
-int adec_init (audiodec_t * 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 )
{
- 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;
- return 0;
-}
+ /* We take the lock, because we are going to read/write the start/end
+ * indexes of the decoder fifo */
+ vlc_mutex_lock ( &p_adec->p_fifo->data_lock );
-int adec_sync_frame (audiodec_t * p_adec, adec_sync_info_t * p_sync_info)
-{
- static int mpeg1_sample_rate[3] = {44100, 48000, 32000};
- static int mpeg1_layer1_bit_rate[15] = {
- 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448
- };
- static int mpeg1_layer2_bit_rate[15] = {
- 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384
- };
- static int mpeg2_layer1_bit_rate[15] = {
- 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256
- };
- static int mpeg2_layer2_bit_rate[15] = {
- 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160
- };
- u32 header;
- int index;
- int * bit_rate_table;
- int sample_rate;
- int bit_rate;
- int frame_size;
-
- p_adec->bit_stream.total_bytes_read = 0;
- header = GetByte (&p_adec->bit_stream) << 24;
- header |= GetByte (&p_adec->bit_stream) << 16;
- header |= GetByte (&p_adec->bit_stream) << 8;
- header |= GetByte (&p_adec->bit_stream);
-
- p_adec->header = header;
-
- /* basic header check : sync word, no emphasis */
- if ((header & 0xfff00003) != 0xfff00000)
- return 1;
-
- index = (header >> 10) & 3; /* sample rate index */
- if (index > 2)
- return 1;
- sample_rate = mpeg1_sample_rate[index];
-
- switch ((header >> 17) & 7) {
- case 2: /* mpeg 2, layer 2 */
- sample_rate >>= 1; /* half sample rate for mpeg2 */
- bit_rate_table = mpeg2_layer2_bit_rate;
- break;
- case 3: /* mpeg 2, layer 1 */
- sample_rate >>= 1; /* half sample rate for mpeg2 */
- bit_rate_table = mpeg2_layer1_bit_rate;
- break;
- case 6: /* mpeg1, layer 2 */
- bit_rate_table = mpeg1_layer2_bit_rate;
- break;
- case 7: /* mpeg1, layer 1 */
- bit_rate_table = mpeg1_layer1_bit_rate;
- break;
- default: /* invalid layer */
- return 1;
- }
+ /* Wait until a `die' order is sent */
+ while ( !p_adec->p_fifo->b_die )
+ {
+ /* Trash all received PES packets */
+ while ( !DECODER_FIFO_ISEMPTY(*p_adec->p_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 );
+ }
- index = (header >> 12) & 15; /* bit rate index */
- if (index > 14)
- return 1;
- bit_rate = bit_rate_table[index];
-
- p_sync_info->sample_rate = sample_rate;
- p_sync_info->bit_rate = bit_rate;
-
- if ((header & 0x60000) == 0x60000) { /* layer 1 */
- frame_size = 48000 * bit_rate / sample_rate;
- if (header & 0x200) /* padding */
- frame_size += 4;
- } else { /* layer >1 */
- frame_size = 144000 * bit_rate / sample_rate;
- if (header & 0x200) /* padding */
- frame_size ++;
+ /* Waiting for the input thread to put new PES packets in the fifo */
+ vlc_cond_wait ( &p_adec->p_fifo->data_wait, &p_adec->p_fifo->data_lock );
}
- p_sync_info->frame_size = frame_size;
- p_adec->frame_size = frame_size;
-
- return 0;
+ /* We can release the lock before leaving */
+ vlc_mutex_unlock ( &p_adec->p_fifo->data_lock );
}
-int adec_decode_frame (audiodec_t * p_adec, s16 * buffer)
+/*****************************************************************************
+ * EndThread : audio decoder thread destruction
+ *****************************************************************************
+ * This function is called when the thread ends after a sucessful
+ * initialization.
+ *****************************************************************************/
+static void EndThread ( adec_thread_t *p_adec )
{
- p_adec->bit_stream.i_available = 0;
+ intf_DbgMsg ( "adec debug: destroying audio decoder thread %p", p_adec );
- adec_Layer2_Stereo (p_adec, buffer);
-
- if (p_adec->bit_stream.total_bytes_read > p_adec->frame_size)
- return 1;
+ /* If the audio output fifo was created, we destroy it */
+ if ( p_adec->p_aout_fifo != NULL )
+ {
+ aout_DestroyFifo ( p_adec->p_aout_fifo );
- while (p_adec->bit_stream.total_bytes_read < p_adec->frame_size)
- GetByte (&p_adec->bit_stream);
+ /* 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 );
- return 0;
+ intf_DbgMsg ("adec debug: audio decoder thread %p destroyed", p_adec);
}
+