lpcm_adec.c 7.86 KB
Newer Older
1
/*****************************************************************************
2
 * lpcm_adec.c: lpcm decoder thread
3
 *****************************************************************************
4
 * Copyright (C) 1999-2001 VideoLAN
5
 * $Id: lpcm_adec.c,v 1.20 2002/07/31 20:56:51 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
 *****************************************************************************/

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

31 32 33
#include <vlc/vlc.h>
#include <vlc/aout.h>
#include <vlc/decoder.h>
Sam Hocevar's avatar
 
Sam Hocevar committed
34 35 36 37

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

Henri Fallon's avatar
 
Henri Fallon committed
39
#include "lpcm_adec.h"
40 41 42 43

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
44 45 46
static int  OpenDecoder    ( vlc_object_t * );
static int  RunDecoder     ( decoder_fifo_t * );

Sam Hocevar's avatar
 
Sam Hocevar committed
47 48 49
       void DecodeFrame    ( lpcmdec_thread_t * );
static int  InitThread     ( lpcmdec_thread_t * );
static void EndThread      ( lpcmdec_thread_t * );
Henri Fallon's avatar
 
Henri Fallon committed
50 51

/*****************************************************************************
52
 * Module descriptor
Henri Fallon's avatar
 
Henri Fallon committed
53
 *****************************************************************************/
54 55 56 57 58
vlc_module_begin();
    set_description( _("linear PCM audio decoder") );
    set_capability( "decoder", 100 );
    set_callbacks( OpenDecoder, NULL );
vlc_module_end();
Henri Fallon's avatar
 
Henri Fallon committed
59 60

/*****************************************************************************
61
 * OpenDecoder: probe the decoder and return score
Henri Fallon's avatar
 
Henri Fallon committed
62
 *****************************************************************************/
63
static int OpenDecoder( vlc_object_t *p_this )
Henri Fallon's avatar
 
Henri Fallon committed
64
{
65 66 67 68 69 70 71 72 73
    decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;

    if( p_fifo->i_fourcc != VLC_FOURCC('l','p','c','m') )
    {   
        return VLC_EGENERIC;
    }
    
    p_fifo->pf_run = RunDecoder;
    return VLC_SUCCESS;
Henri Fallon's avatar
 
Henri Fallon committed
74 75 76
}

/*****************************************************************************
77
 * RunDecoder: the lpcm decoder
Henri Fallon's avatar
 
Henri Fallon committed
78
 *****************************************************************************/
79
static int RunDecoder( decoder_fifo_t * p_fifo )
80 81 82 83
{
    lpcmdec_thread_t *   p_lpcmdec;

    /* Allocate the memory needed to store the thread's structure */
Henri Fallon's avatar
 
Henri Fallon committed
84 85 86
    if( (p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t)) )
            == NULL) 
    {
87 88
        msg_Err( p_fifo, "out of memory" );
        DecoderError( p_fifo );
Henri Fallon's avatar
 
Henri Fallon committed
89
        return( -1 );
90 91 92 93 94
    }

    /*
     * Initialize the thread properties
     */
95
    p_lpcmdec->p_fifo = p_fifo;
96

Sam Hocevar's avatar
 
Sam Hocevar committed
97
    if( InitThread( p_lpcmdec ) )
Henri Fallon's avatar
 
Henri Fallon committed
98
    {
99
        DecoderError( p_fifo );
Sam Hocevar's avatar
 
Sam Hocevar committed
100
        free( p_lpcmdec );
Henri Fallon's avatar
 
Henri Fallon committed
101 102
        return( -1 );
    }
103

Henri Fallon's avatar
 
Henri Fallon committed
104 105
    /* 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
106
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
107
        DecodeFrame(p_lpcmdec);
108 109
    }

Henri Fallon's avatar
 
Henri Fallon committed
110 111 112
    /* 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
113
        DecoderError( p_lpcmdec->p_fifo );
Henri Fallon's avatar
 
Henri Fallon committed
114
    }
115

Henri Fallon's avatar
 
Henri Fallon committed
116
    /* End of the lpcm decoder thread */
Sam Hocevar's avatar
 
Sam Hocevar committed
117
    EndThread (p_lpcmdec);
Henri Fallon's avatar
 
Henri Fallon committed
118 119 120

    return( 0 );
}
121 122

/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
123
 * InitThread : initialize an lpcm decoder thread
124
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
125
static int InitThread (lpcmdec_thread_t * p_lpcmdec)
126 127
{

Henri Fallon's avatar
 
Henri Fallon committed
128
    /* Init the BitStream */
129
    InitBitstream( &p_lpcmdec->bit_stream, p_lpcmdec->p_fifo,
130
                   NULL, NULL);
131 132

    /* Creating the audio output fifo */
133
    p_lpcmdec->p_aout_fifo =
134
                aout_CreateFifo( p_lpcmdec->p_fifo, AOUT_FIFO_PCM,
135
                                 2, 48000, LPCMDEC_FRAME_SIZE / 2, NULL  );
Sam Hocevar's avatar
 
Sam Hocevar committed
136 137
    if ( p_lpcmdec->p_aout_fifo == NULL )
    {
Henri Fallon's avatar
 
Henri Fallon committed
138
        return( -1 );
139
    }
Henri Fallon's avatar
 
Henri Fallon committed
140
    return( 0 );
141 142 143
}

/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
144
 * DecodeFrame: decodes a frame.
145
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
146
void DecodeFrame( lpcmdec_thread_t * p_lpcmdec )
147
{
148 149 150
    byte_t *    buffer,p_temp[LPCMDEC_FRAME_SIZE];
    vlc_bool_t  b_sync;
    int         i_loop;
151

152
    CurrentPTS( &p_lpcmdec->bit_stream,
Sam Hocevar's avatar
 
Sam Hocevar committed
153
        &p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame],
154
        NULL );
Sam Hocevar's avatar
 
Sam Hocevar committed
155
    if( !p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame] )
156
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
157
        p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame] =
Henri Fallon's avatar
 
Henri Fallon committed
158
            LAST_MDATE;
159 160
    }

Henri Fallon's avatar
 
Henri Fallon committed
161
    buffer = ((byte_t *)p_lpcmdec->p_aout_fifo->buffer) + 
Sam Hocevar's avatar
 
Sam Hocevar committed
162
              (p_lpcmdec->p_aout_fifo->i_end_frame * LPCMDEC_FRAME_SIZE);
163

Henri Fallon's avatar
 
Henri Fallon committed
164
    RemoveBits32(&p_lpcmdec->bit_stream);
165
#if 0
Henri Fallon's avatar
 
Henri Fallon committed
166 167
    byte1 = GetBits(&p_lpcmdec->bit_stream, 8) ;
    byte2 = GetBits(&p_lpcmdec->bit_stream, 8) ;
Henri Fallon's avatar
 
Henri Fallon committed
168
    
Henri Fallon's avatar
 
Henri Fallon committed
169 170 171 172 173 174 175 176 177
    /* 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);
178
    }
179 180 181 182 183 184 185 186 187 188 189 190 191
#else
    b_sync = 0;
    while( ( !p_lpcmdec->p_fifo->b_die ) &&
           ( !p_lpcmdec->p_fifo->b_error ) &&
           ( !b_sync ) )
    {
        while( ( !p_lpcmdec->p_fifo->b_die ) &&
               ( !p_lpcmdec->p_fifo->b_error ) &&
               ( GetBits( &p_lpcmdec->bit_stream, 8 ) != 0x01 ) );
        b_sync = ( ShowBits( &p_lpcmdec->bit_stream, 8 ) == 0x80 );
    }
    RemoveBits( &p_lpcmdec->bit_stream, 8 );
#endif
Henri Fallon's avatar
 
Henri Fallon committed
192 193
    
    GetChunk( &p_lpcmdec->bit_stream, p_temp, LPCMDEC_FRAME_SIZE);
194
    if( p_lpcmdec->p_fifo->b_die || p_lpcmdec->p_fifo->b_error ) return;
Gildas Bazin's avatar
 
Gildas Bazin committed
195

Henri Fallon's avatar
 
Henri Fallon committed
196
    for( i_loop = 0; i_loop < LPCMDEC_FRAME_SIZE/2; i_loop++ )
197
    {
Henri Fallon's avatar
 
Henri Fallon committed
198 199
        buffer[2*i_loop]=p_temp[2*i_loop+1];
        buffer[2*i_loop+1]=p_temp[2*i_loop];
200
    }
Henri Fallon's avatar
 
Henri Fallon committed
201 202
    
    vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
Sam Hocevar's avatar
 
Sam Hocevar committed
203 204
    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
205 206
    vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
    vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
207 208 209
}

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

        /* Make sure the output thread leaves the NextFrame() function */
Henri Fallon's avatar
 
Henri Fallon committed
220 221 222
        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) );
223 224 225
    }

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