mpeg_adec.c 8.55 KB
Newer Older
1
/*****************************************************************************
Henri Fallon's avatar
 
Henri Fallon committed
2
 * mpeg_adec.c: MPEG audio decoder thread
3
 *****************************************************************************
4
 * Copyright (C) 1999-2001 VideoLAN
5
 * $Id: mpeg_adec.c,v 1.16 2002/01/22 23:14:26 massiot Exp $
6
 *
7 8 9
 * Authors: Michel Kaempf <maxx@via.ecp.fr>
 *          Michel Lespinasse <walken@via.ecp.fr>
 *          Samuel Hocevar <sam@via.ecp.fr>
10
 *          Cyril Deguet <asmax@via.ecp.fr>
11 12 13 14 15
 *
 * 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.
Sam Hocevar's avatar
 
Sam Hocevar committed
16
 * 
17 18
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
21
 *
22 23 24
 * 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.
25
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
26

Sam Hocevar's avatar
 
Sam Hocevar committed
27 28 29 30
/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>                                      /* malloc(), free() */
31
#include <string.h>
Michel Kaempf's avatar
Michel Kaempf committed
32

Sam Hocevar's avatar
 
Sam Hocevar committed
33
#include <videolan/vlc.h>
Henri Fallon's avatar
 
Henri Fallon committed
34 35 36

#include "audio_output.h"               /* aout_fifo_t (for audio_decoder.h) */

Sam Hocevar's avatar
 
Sam Hocevar committed
37 38
#include "stream_control.h"
#include "input_ext-dec.h"
Michel Kaempf's avatar
Michel Kaempf committed
39

Henri Fallon's avatar
 
Henri Fallon committed
40 41
#include "mpeg_adec_generic.h"
#include "mpeg_adec.h"
Michel Kaempf's avatar
Michel Kaempf committed
42

Sam Hocevar's avatar
 
Sam Hocevar committed
43
#define ADEC_FRAME_SIZE (2*1152)
44

Sam Hocevar's avatar
 
Sam Hocevar committed
45
/*****************************************************************************
Henri Fallon's avatar
 
Henri Fallon committed
46
 * Local Prototypes
Sam Hocevar's avatar
 
Sam Hocevar committed
47
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
48 49 50 51
static int   decoder_Probe ( probedata_t * );
static int   decoder_Run   ( decoder_config_t * );
static void  EndThread     ( adec_thread_t * );
static void  DecodeThread  ( adec_thread_t * );
Henri Fallon's avatar
 
Henri Fallon committed
52

Sam Hocevar's avatar
 
Sam Hocevar committed
53
/*****************************************************************************
Henri Fallon's avatar
 
Henri Fallon committed
54
 * Capabilities
Sam Hocevar's avatar
 
Sam Hocevar committed
55
 *****************************************************************************/
Henri Fallon's avatar
 
Henri Fallon committed
56
void _M( adec_getfunctions )( function_list_t * p_function_list )
Michel Kaempf's avatar
Michel Kaempf committed
57
{
Sam Hocevar's avatar
 
Sam Hocevar committed
58 59
    p_function_list->pf_probe = decoder_Probe;
    p_function_list->functions.dec.pf_run = decoder_Run;
Henri Fallon's avatar
 
Henri Fallon committed
60 61 62 63 64 65 66 67 68
}

/*****************************************************************************
 * Build configuration tree.
 *****************************************************************************/
MODULE_CONFIG_START
MODULE_CONFIG_STOP

MODULE_INIT_START
Sam Hocevar's avatar
 
Sam Hocevar committed
69 70 71 72
    SET_DESCRIPTION( "Mpeg I layer 1/2 audio decoder" )
    ADD_CAPABILITY( DECODER, 100 )
    ADD_REQUIREMENT( FPU )
    ADD_SHORTCUT( "builtin" )
Henri Fallon's avatar
 
Henri Fallon committed
73 74 75 76 77
MODULE_INIT_STOP

MODULE_ACTIVATE_START
    _M( adec_getfunctions )( &p_module->p_functions->dec );
MODULE_ACTIVATE_STOP
Michel Kaempf's avatar
Michel Kaempf committed
78

Henri Fallon's avatar
 
Henri Fallon committed
79 80
MODULE_DEACTIVATE_START
MODULE_DEACTIVATE_STOP
81

Henri Fallon's avatar
 
Henri Fallon committed
82
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
83
 * decoder_Probe: probe the decoder and return score
Henri Fallon's avatar
 
Henri Fallon committed
84
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
85
static int decoder_Probe( probedata_t *p_data )
Henri Fallon's avatar
 
Henri Fallon committed
86
{
Sam Hocevar's avatar
 
Sam Hocevar committed
87 88
    return( ( p_data->i_type == MPEG1_AUDIO_ES
               || p_data->i_type == MPEG2_AUDIO_ES ) ? 100 : 0 );
Henri Fallon's avatar
 
Henri Fallon committed
89 90 91
}

/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
92
 * decoder_Run: initialize, go inside main loop, detroy
Henri Fallon's avatar
 
Henri Fallon committed
93
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
94
static int decoder_Run ( decoder_config_t * p_config )
Henri Fallon's avatar
 
Henri Fallon committed
95 96 97 98 99
{
    adec_thread_t   * p_adec;
    
    intf_DbgMsg("mpeg_adec debug: thread launched, initializing.");
    
Sam Hocevar's avatar
 
Sam Hocevar committed
100 101
    /* Allocate the memory needed to store the thread's structure */
    if ( (p_adec = (adec_thread_t *)malloc (sizeof(adec_thread_t))) == NULL ) 
Henri Fallon's avatar
 
Henri Fallon committed
102
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
103 104
        intf_ErrMsg ( "adec error: not enough memory for"
                      " adec_CreateThread() to create the new thread" );
Sam Hocevar's avatar
 
Sam Hocevar committed
105
        DecoderError( p_config->p_decoder_fifo );
Sam Hocevar's avatar
 
Sam Hocevar committed
106
        return 0;
Michel Kaempf's avatar
Michel Kaempf committed
107
    }
Henri Fallon's avatar
 
Henri Fallon committed
108
    
Sam Hocevar's avatar
 
Sam Hocevar committed
109 110 111 112
    /*
     * Initialize the thread properties
     */
    p_adec->p_config = p_config;
Henri Fallon's avatar
 
Henri Fallon committed
113
    p_adec->p_fifo = p_config->p_decoder_fifo;
114

Henri Fallon's avatar
 
Henri Fallon committed
115 116
    /* 
     * Initilize the banks
Sam Hocevar's avatar
 
Sam Hocevar committed
117
     */
Henri Fallon's avatar
 
Henri Fallon committed
118 119 120 121 122
    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;
    
Sam Hocevar's avatar
 
Sam Hocevar committed
123
    /*
Henri Fallon's avatar
 
Henri Fallon committed
124
     * Initialize bit stream 
Sam Hocevar's avatar
 
Sam Hocevar committed
125
     */
126 127
    InitBitstream( &p_adec->bit_stream, p_adec->p_config->p_decoder_fifo,
                   NULL, NULL );
Sam Hocevar's avatar
Sam Hocevar committed
128

129 130 131
    /* We do not create the audio output fifo now, but
       it will be created when the first frame is received */
    p_adec->p_aout_fifo = NULL;
132

Henri Fallon's avatar
 
Henri Fallon committed
133
    intf_DbgMsg("mpeg_adec debug: thread initialized, decoding begins.");
Sam Hocevar's avatar
 
Sam Hocevar committed
134

Henri Fallon's avatar
 
Henri Fallon committed
135
    p_adec->i_sync = 0;
Michel Kaempf's avatar
Michel Kaempf committed
136

Henri Fallon's avatar
 
Henri Fallon committed
137 138
    /* Audio decoder thread's main loop */
    while( (!p_adec->p_fifo->b_die) && (!p_adec->p_fifo->b_error) )
Henri Fallon's avatar
 
Henri Fallon committed
139
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
140
        DecodeThread( p_adec );
Henri Fallon's avatar
 
Henri Fallon committed
141 142 143 144 145
    }
    
    /* If b_error is set, the audio decoder thread enters the error loop */
    if( p_adec->p_fifo->b_error ) 
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
146
        DecoderError( p_adec->p_fifo );
Michel Kaempf's avatar
Michel Kaempf committed
147 148
    }

Henri Fallon's avatar
 
Henri Fallon committed
149
    /* End of the audio decoder thread */
Sam Hocevar's avatar
 
Sam Hocevar committed
150
    EndThread( p_adec );
Henri Fallon's avatar
 
Henri Fallon committed
151 152

    return( 0 );
153 154
}

Henri Fallon's avatar
 
Henri Fallon committed
155
/*
156
 * Following functions are local to this module
Henri Fallon's avatar
 
Henri Fallon committed
157 158
 */

Sam Hocevar's avatar
 
Sam Hocevar committed
159
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
160
 * DecodeThread: decodes a mpeg frame
Sam Hocevar's avatar
 
Sam Hocevar committed
161
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
162
static void DecodeThread( adec_thread_t * p_adec )
163
{
Henri Fallon's avatar
 
Henri Fallon committed
164 165
    s16 * buffer;
    adec_sync_info_t sync_info;
Henri Fallon's avatar
 
Henri Fallon committed
166

Henri Fallon's avatar
 
Henri Fallon committed
167 168
    if( ! adec_SyncFrame (p_adec, &sync_info) )
    {
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
        
        /* TODO: check if audio type has changed */
        
        /* Create the output fifo if it doesn't exist yet */
        if( p_adec->p_aout_fifo == NULL )
        {
            int fifo_type;
            int channels;
            
            if( sync_info.b_stereo )
            {
                fifo_type = AOUT_ADEC_STEREO_FIFO;
                channels = 2;
            }
            else
            {
                fifo_type = AOUT_ADEC_MONO_FIFO;
                channels = 1;
            }
            p_adec->p_aout_fifo = aout_CreateFifo( fifo_type, channels,
                    sync_info.sample_rate, 0, ADEC_FRAME_SIZE, NULL );
            if( p_adec->p_aout_fifo == NULL)
            {
                intf_ErrMsg( "adec error: failed to create Audio Output "
                        "Fifo." );
Sam Hocevar's avatar
 
Sam Hocevar committed
194 195
                p_adec->p_fifo->b_error = 1;
                return;
196 197 198
            }
        }

Henri Fallon's avatar
 
Henri Fallon committed
199
        p_adec->i_sync = 1;
Henri Fallon's avatar
 
Henri Fallon committed
200

Henri Fallon's avatar
 
Henri Fallon committed
201 202
        buffer = ((s16 *)p_adec->p_aout_fifo->buffer)
                    + (p_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE);
Henri Fallon's avatar
 
Henri Fallon committed
203

204 205 206 207
        CurrentPTS( &p_adec->bit_stream,
            &p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame],
            NULL );
        if( !p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] )
Henri Fallon's avatar
 
Henri Fallon committed
208 209 210 211
        {
            p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
                LAST_MDATE;
        }
Henri Fallon's avatar
 
Henri Fallon committed
212

Henri Fallon's avatar
 
Henri Fallon committed
213
        if( adec_DecodeFrame (p_adec, buffer) )
Sam Hocevar's avatar
Sam Hocevar committed
214
        {
Henri Fallon's avatar
 
Henri Fallon committed
215 216
            /* Ouch, failed decoding... We'll have to resync */
            p_adec->i_sync = 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
217
        }
Henri Fallon's avatar
 
Henri Fallon committed
218 219 220 221 222 223 224 225
        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);
        }
Sam Hocevar's avatar
Sam Hocevar committed
226
    }
227
}
Michel Kaempf's avatar
Michel Kaempf committed
228

Sam Hocevar's avatar
 
Sam Hocevar committed
229
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
230
 * EndThread : audio decoder thread destruction
Sam Hocevar's avatar
 
Sam Hocevar committed
231 232 233 234
 *****************************************************************************
 * This function is called when the thread ends after a sucessful
 * initialization.
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
235
static void EndThread ( adec_thread_t *p_adec )
Sam Hocevar's avatar
 
Sam Hocevar committed
236
{
Sam Hocevar's avatar
 
Sam Hocevar committed
237
    intf_DbgMsg ( "adec debug: destroying audio decoder thread %p", p_adec );
Sam Hocevar's avatar
Sam Hocevar committed
238

Sam Hocevar's avatar
 
Sam Hocevar committed
239 240
    /* If the audio output fifo was created, we destroy it */
    if ( p_adec->p_aout_fifo != NULL ) 
Sam Hocevar's avatar
Sam Hocevar committed
241
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
242
        aout_DestroyFifo ( p_adec->p_aout_fifo );
Michel Lespinasse's avatar
 
Michel Lespinasse committed
243

Sam Hocevar's avatar
 
Sam Hocevar committed
244 245 246 247
        /* 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));
Sam Hocevar's avatar
Sam Hocevar committed
248
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
249
    /* Destroy descriptor */
250
    free( p_adec );
Michel Kaempf's avatar
Michel Kaempf committed
251

Sam Hocevar's avatar
 
Sam Hocevar committed
252
    intf_DbgMsg ("adec debug: audio decoder thread %p destroyed", p_adec);
Michel Kaempf's avatar
Michel Kaempf committed
253 254
}