lpcm_adec.c 7.93 KB
Newer Older
1 2 3
/*****************************************************************************
 * lpcm_decoder_thread.c: lpcm decoder thread
 *****************************************************************************
4
 * Copyright (C) 1999-2001 VideoLAN
Sam Hocevar's avatar
 
Sam Hocevar committed
5
 * $Id: lpcm_adec.c,v 1.14 2002/04/19 13:56:11 sam Exp $
6
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
7
 * Authors: Samuel Hocevar <sam@zoy.org>
Henri Fallon's avatar
 
Henri Fallon committed
8
 *          Henri Fallon <henri@videolan.org>
9 10 11 12 13
 *
 * 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.
14
 * 
15 16
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
19
 *
20 21 22
 * 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.
23 24 25 26 27 28
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdio.h>                                           /* "intf_msg.h" */
Sam Hocevar's avatar
 
Sam Hocevar committed
29
#include <string.h>                                    /* memcpy(), memset() */
30 31
#include <stdlib.h>                                      /* malloc(), free() */

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

#ifdef HAVE_UNISTD_H
#   include <unistd.h>                                           /* getpid() */
#endif
37

Henri Fallon's avatar
 
Henri Fallon committed
38 39
#include "audio_output.h"

40 41
#include "stream_control.h"
#include "input_ext-dec.h"
42

Henri Fallon's avatar
 
Henri Fallon committed
43
#include "lpcm_adec.h"
44 45 46 47

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
48
static int  decoder_Probe  ( u8 * );
Sam Hocevar's avatar
 
Sam Hocevar committed
49 50 51 52
static int  decoder_Run    ( decoder_config_t * );
       void DecodeFrame    ( lpcmdec_thread_t * );
static int  InitThread     ( lpcmdec_thread_t * );
static void EndThread      ( lpcmdec_thread_t * );
Henri Fallon's avatar
 
Henri Fallon committed
53

54 55

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

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

MODULE_INIT_START
Sam Hocevar's avatar
 
Sam Hocevar committed
71
    SET_DESCRIPTION( _("linear PCM audio decoder") )
Sam Hocevar's avatar
 
Sam Hocevar committed
72
    ADD_CAPABILITY( DECODER, 100 )
Henri Fallon's avatar
 
Henri Fallon committed
73 74 75 76 77 78 79 80 81 82
MODULE_INIT_STOP

MODULE_ACTIVATE_START
    _M( adec_getfunctions )( &p_module->p_functions->dec );
MODULE_ACTIVATE_STOP

MODULE_DEACTIVATE_START
MODULE_DEACTIVATE_STOP

/*****************************************************************************
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( u8 *pi_type )
Henri Fallon's avatar
 
Henri Fallon committed
86
{
Sam Hocevar's avatar
 
Sam Hocevar committed
87
    return ( *pi_type == LPCM_AUDIO_ES ) ? 0 : -1;
Henri Fallon's avatar
 
Henri Fallon committed
88 89 90
}

/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
91
 * decoder_Run: the lpcm decoder
Henri Fallon's avatar
 
Henri Fallon committed
92
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
93
static int decoder_Run( decoder_config_t * p_config )
94 95 96 97
{
    lpcmdec_thread_t *   p_lpcmdec;

    /* Allocate the memory needed to store the thread's structure */
Henri Fallon's avatar
 
Henri Fallon committed
98 99 100 101
    if( (p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t)) )
            == NULL) 
    {
        intf_ErrMsg( "LPCM : error : cannot create lpcmdec_thread_t" );
Sam Hocevar's avatar
 
Sam Hocevar committed
102
        DecoderError( p_config->p_decoder_fifo );
Henri Fallon's avatar
 
Henri Fallon committed
103
        return( -1 );
104 105 106 107 108
    }

    /*
     * Initialize the thread properties
     */
109
    p_lpcmdec->p_config = p_config;
Henri Fallon's avatar
 
Henri Fallon committed
110
    p_lpcmdec->p_fifo = p_config->p_decoder_fifo;
111

Sam Hocevar's avatar
 
Sam Hocevar committed
112
    if( InitThread( p_lpcmdec ) )
Henri Fallon's avatar
 
Henri Fallon committed
113
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
114 115
        DecoderError( p_config->p_decoder_fifo );
        free( p_lpcmdec );
Henri Fallon's avatar
 
Henri Fallon committed
116 117
        return( -1 );
    }
118

Henri Fallon's avatar
 
Henri Fallon committed
119 120
    /* lpcm decoder thread's main loop */
    while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
Henri Fallon's avatar
 
Henri Fallon committed
121
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
122
        DecodeFrame(p_lpcmdec);
123 124
    }

Henri Fallon's avatar
 
Henri Fallon committed
125 126 127
    /* If b_error is set, the lpcm decoder thread enters the error loop */
    if (p_lpcmdec->p_fifo->b_error)
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
128
        DecoderError( p_lpcmdec->p_fifo );
Henri Fallon's avatar
 
Henri Fallon committed
129
    }
130

Henri Fallon's avatar
 
Henri Fallon committed
131
    /* End of the lpcm decoder thread */
Sam Hocevar's avatar
 
Sam Hocevar committed
132
    EndThread (p_lpcmdec);
Henri Fallon's avatar
 
Henri Fallon committed
133 134 135

    return( 0 );
}
136 137

/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
138
 * InitThread : initialize an lpcm decoder thread
139
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
140
static int InitThread (lpcmdec_thread_t * p_lpcmdec)
141 142
{

Henri Fallon's avatar
 
Henri Fallon committed
143
    /* Init the BitStream */
144 145
    InitBitstream( &p_lpcmdec->bit_stream, p_lpcmdec->p_config->p_decoder_fifo,
                   NULL, NULL);
146 147

    /* Creating the audio output fifo */
Sam Hocevar's avatar
 
Sam Hocevar committed
148 149
    p_lpcmdec->p_aout_fifo = aout_CreateFifo( AOUT_FIFO_PCM, 2, 48000,
                                              LPCMDEC_FRAME_SIZE/2, NULL  );
Sam Hocevar's avatar
 
Sam Hocevar committed
150 151
    if ( p_lpcmdec->p_aout_fifo == NULL )
    {
Henri Fallon's avatar
 
Henri Fallon committed
152
        return( -1 );
153
    }
Henri Fallon's avatar
 
Henri Fallon committed
154
    return( 0 );
155 156 157
}

/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
158
 * DecodeFrame: decodes a frame.
159
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
160
void DecodeFrame( lpcmdec_thread_t * p_lpcmdec )
161
{
Henri Fallon's avatar
 
Henri Fallon committed
162 163 164
    byte_t * buffer,p_temp[LPCMDEC_FRAME_SIZE];
    int i_loop;
    byte_t byte1, byte2;
165

166
    CurrentPTS( &p_lpcmdec->bit_stream,
Sam Hocevar's avatar
 
Sam Hocevar committed
167
        &p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame],
168
        NULL );
Sam Hocevar's avatar
 
Sam Hocevar committed
169
    if( !p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame] )
170
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
171
        p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame] =
Henri Fallon's avatar
 
Henri Fallon committed
172
            LAST_MDATE;
173 174
    }

Henri Fallon's avatar
 
Henri Fallon committed
175
    buffer = ((byte_t *)p_lpcmdec->p_aout_fifo->buffer) + 
Sam Hocevar's avatar
 
Sam Hocevar committed
176
              (p_lpcmdec->p_aout_fifo->i_end_frame * LPCMDEC_FRAME_SIZE);
177

Henri Fallon's avatar
 
Henri Fallon committed
178 179 180
    RemoveBits32(&p_lpcmdec->bit_stream);
    byte1 = GetBits(&p_lpcmdec->bit_stream, 8) ;
    byte2 = GetBits(&p_lpcmdec->bit_stream, 8) ;
Henri Fallon's avatar
 
Henri Fallon committed
181
    
Henri Fallon's avatar
 
Henri Fallon committed
182 183 184 185 186 187 188 189 190
    /* I only have 2 test streams. As far as I understand
     * after the RemoveBits and the 2 GetBits, we should be exactly 
     * where we whant : the sync word : 0x0180.
     * If not, we got and find it. */
    while( ( byte1 != 0x01 || byte2 != 0x80 ) && (!p_lpcmdec->p_fifo->b_die)
                                       && (!p_lpcmdec->p_fifo->b_error) )
    {
        byte1 = byte2;
        byte2 = GetBits(&p_lpcmdec->bit_stream, 8);
191
    }
Henri Fallon's avatar
 
Henri Fallon committed
192 193 194 195
    
    GetChunk( &p_lpcmdec->bit_stream, p_temp, LPCMDEC_FRAME_SIZE);
    
    for( i_loop = 0; i_loop < LPCMDEC_FRAME_SIZE/2; i_loop++ )
196
    {
Henri Fallon's avatar
 
Henri Fallon committed
197 198
        buffer[2*i_loop]=p_temp[2*i_loop+1];
        buffer[2*i_loop+1]=p_temp[2*i_loop];
199
    }
Henri Fallon's avatar
 
Henri Fallon committed
200 201
    
    vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
Sam Hocevar's avatar
 
Sam Hocevar committed
202 203
    p_lpcmdec->p_aout_fifo->i_end_frame = 
        (p_lpcmdec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
Henri Fallon's avatar
 
Henri Fallon committed
204 205
    vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
    vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
206 207 208
}

/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
209
 * EndThread : lpcm decoder thread destruction
210
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
211
static void EndThread( lpcmdec_thread_t * p_lpcmdec )
212 213
{
    /* If the audio output fifo was created, we destroy it */
Henri Fallon's avatar
 
Henri Fallon committed
214 215 216
    if( p_lpcmdec->p_aout_fifo != NULL ) 
    {
        aout_DestroyFifo( p_lpcmdec->p_aout_fifo );
217 218

        /* Make sure the output thread leaves the NextFrame() function */
Henri Fallon's avatar
 
Henri Fallon committed
219 220 221
        vlc_mutex_lock( &(p_lpcmdec->p_aout_fifo->data_lock) );
        vlc_cond_signal( &(p_lpcmdec->p_aout_fifo->data_wait) );
        vlc_mutex_unlock( &(p_lpcmdec->p_aout_fifo->data_lock) );
222 223 224
    }

    /* Destroy descriptor */
Henri Fallon's avatar
 
Henri Fallon committed
225
    free( p_lpcmdec );
226
}