lpcm_decoder_thread.c 9.48 KB
Newer Older
1
2
3
4
/*****************************************************************************
 * lpcm_decoder_thread.c: lpcm decoder thread
 *****************************************************************************
 * Copyright (C) 1999, 2000 VideoLAN
5
 * $Id: lpcm_decoder_thread.c,v 1.18 2001/11/06 18:13:21 massiot 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
29
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include "defs.h"

Sam Hocevar's avatar
   
Sam Hocevar committed
30
#ifdef HAVE_UNISTD_H
31
#include <unistd.h>                                              /* getpid() */
Sam Hocevar's avatar
   
Sam Hocevar committed
32
#endif
33
34

#include <stdio.h>                                           /* "intf_msg.h" */
Sam Hocevar's avatar
   
Sam Hocevar committed
35
#include <string.h>                                    /* memcpy(), memset() */
36
37
38
39
40
41
42
43
44
#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() */

45
46
#include "stream_control.h"
#include "input_ext-dec.h"
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

#include "audio_output.h"

#include "lpcm_decoder_thread.h"

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
static int      InitThread              (lpcmdec_thread_t * p_adec);
static void     RunThread               (lpcmdec_thread_t * p_adec);
static void     ErrorThread             (lpcmdec_thread_t * p_adec);
static void     EndThread               (lpcmdec_thread_t * p_adec);

/*****************************************************************************
 * lpcmdec_CreateThread: creates an lpcm decoder thread
 *****************************************************************************/
Henri Fallon's avatar
   
Henri Fallon committed
63
vlc_thread_t lpcmdec_CreateThread( adec_config_t * p_config )
64
65
{
    lpcmdec_thread_t *   p_lpcmdec;
Henri Fallon's avatar
   
Henri Fallon committed
66
    intf_DbgMsg( "LPCM: creating lpcm decoder thread" );
67
68

    /* Allocate the memory needed to store the thread's structure */
Henri Fallon's avatar
   
Henri Fallon committed
69
70
71
72
    if( (p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t)) )
            == NULL) 
    {
        intf_ErrMsg( "LPCM : error : cannot create lpcmdec_thread_t" );
73
        return 0;
74
75
76
77
78
    }

    /*
     * Initialize the thread properties
     */
79
80
    p_lpcmdec->p_config = p_config;
    p_lpcmdec->p_fifo = p_config->decoder_config.p_decoder_fifo;
81
82
83
84
85
86
87

    /*
     * Initialize the output properties
     */
    p_lpcmdec->p_aout_fifo = NULL;

    /* Spawn the lpcm decoder thread */
Henri Fallon's avatar
   
Henri Fallon committed
88
89
90
91
    if( vlc_thread_create( &p_lpcmdec->thread_id, "lpcm decoder", 
                           (vlc_thread_func_t)RunThread, (void *)p_lpcmdec ) )
    {
        intf_ErrMsg( "LPCM : error : cannot spawn thread" );
92
        free (p_lpcmdec);
93
        return 0;
94
95
    }

Henri Fallon's avatar
   
Henri Fallon committed
96
    intf_DbgMsg( "LPCM Debug: lpcm decoder thread (%p) created\n", p_lpcmdec );
97
    return p_lpcmdec->thread_id;
98
99
100
101
102
103
104
105
106
107
}

/* Following functions are local */

/*****************************************************************************
 * InitThread : initialize an lpcm decoder thread
 *****************************************************************************/
static int InitThread (lpcmdec_thread_t * p_lpcmdec)
{

Henri Fallon's avatar
   
Henri Fallon committed
108
109
    intf_DbgMsg ( "lpcm Debug: initializing lpcm decoder thread %p", 
                   p_lpcmdec );
110

Henri Fallon's avatar
   
Henri Fallon committed
111
112
113
114
115
    /* Init the BitStream */
    p_lpcmdec->p_config->decoder_config.pf_init_bit_stream(
            &p_lpcmdec->bit_stream,
            p_lpcmdec->p_config->decoder_config.p_decoder_fifo,
            NULL, NULL);
116
117

    /* Creating the audio output fifo */
Henri Fallon's avatar
   
Henri Fallon committed
118
119
    p_lpcmdec->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_STEREO_FIFO, 2, 48000,
                                            0, LPCMDEC_FRAME_SIZE/2, NULL  );
Sam Hocevar's avatar
   
Sam Hocevar committed
120
121
    if ( p_lpcmdec->p_aout_fifo == NULL )
    {
122
123
        return -1;
    }
124

Henri Fallon's avatar
   
Henri Fallon committed
125
126
127
    intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p initialized\n", 
                 p_lpcmdec );
    return( 0 );
128
129
130
131
132
133
134
}

/*****************************************************************************
 * RunThread : lpcm decoder thread
 *****************************************************************************/
static void RunThread (lpcmdec_thread_t * p_lpcmdec)
{
Henri Fallon's avatar
   
Henri Fallon committed
135
136
    intf_DbgMsg( "LPCM Debug: running lpcm decoder thread (%p) (pid== %i)", 
                 p_lpcmdec, getpid() );
137
138
139
140

    /* Initializing the lpcm decoder thread */
    if (InitThread (p_lpcmdec)) 
    {
141
        p_lpcmdec->p_fifo->b_error = 1;
142
143
144
145
    }

    /* lpcm decoder thread's main loop */
   
146
    while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
147
    {
Henri Fallon's avatar
   
Henri Fallon committed
148
149
150
        byte_t * buffer,p_temp[LPCMDEC_FRAME_SIZE];
        int i_loop;
        byte_t byte1, byte2;
151
    
Henri Fallon's avatar
   
Henri Fallon committed
152
        if( DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts )
153
        {
Henri Fallon's avatar
   
Henri Fallon committed
154
155
            p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
                DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts;
Sam Hocevar's avatar
   
Sam Hocevar committed
156
            DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts = 0;
157
158
        }
        else
Henri Fallon's avatar
   
Henri Fallon committed
159
160
161
        { 
            p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
                LAST_MDATE;
162
163
        }

Henri Fallon's avatar
   
Henri Fallon committed
164
165
166
        buffer = ((byte_t *)p_lpcmdec->p_aout_fifo->buffer) + 
                  (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);
    
167
168
169
        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
170
        
171
172
173
174
        /* 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. */
Henri Fallon's avatar
   
Henri Fallon committed
175
176
        while( ( byte1 != 0x01 || byte2 != 0x80 ) && (!p_lpcmdec->p_fifo->b_die)
                                           && (!p_lpcmdec->p_fifo->b_error) )
177
        {
Henri Fallon's avatar
   
Henri Fallon committed
178
179
            byte1 = byte2;
            byte2 = GetBits(&p_lpcmdec->bit_stream, 8);
Sam Hocevar's avatar
   
Sam Hocevar committed
180
        }
Henri Fallon's avatar
   
Henri Fallon committed
181
182
183
184
185
186
187
188
189
        
        GetChunk( &p_lpcmdec->bit_stream, p_temp, LPCMDEC_FRAME_SIZE);
        
        for( i_loop = 0; i_loop < LPCMDEC_FRAME_SIZE/2; i_loop++ )
        {
            buffer[2*i_loop]=p_temp[2*i_loop+1];
            buffer[2*i_loop+1]=p_temp[2*i_loop];
        }
        
Sam Hocevar's avatar
   
Sam Hocevar committed
190
        vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
Henri Fallon's avatar
   
Henri Fallon committed
191
192
        p_lpcmdec->p_aout_fifo->l_end_frame = 
            (p_lpcmdec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
Sam Hocevar's avatar
   
Sam Hocevar committed
193
194
        vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
        vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
Henri Fallon's avatar
   
Henri Fallon committed
195
        
Sam Hocevar's avatar
   
Sam Hocevar committed
196
        intf_DbgMsg( "LPCM Debug: %x", *buffer );
Sam Hocevar's avatar
   
Sam Hocevar committed
197

198
199
200
    }

    /* If b_error is set, the lpcm decoder thread enters the error loop */
201
    if (p_lpcmdec->p_fifo->b_error)
202
203
204
205
206
207
208
209
210
211
212
    {
        ErrorThread (p_lpcmdec);
    }

    /* End of the lpcm decoder thread */
    EndThread (p_lpcmdec);
}

/*****************************************************************************
 * ErrorThread : lpcm decoder's RunThread() error loop
 *****************************************************************************/
Henri Fallon's avatar
   
Henri Fallon committed
213
static void ErrorThread( lpcmdec_thread_t * p_lpcmdec )
214
215
216
{
    /* We take the lock, because we are going to read/write the start/end
     * indexes of the decoder fifo */
Henri Fallon's avatar
   
Henri Fallon committed
217
    vlc_mutex_lock( &p_lpcmdec->p_fifo->data_lock );
218
219

    /* Wait until a `die' order is sent */
Henri Fallon's avatar
   
Henri Fallon committed
220
221
    while( !p_lpcmdec->p_fifo->b_die ) 
    {
222
        /* Trash all received PES packets */
Henri Fallon's avatar
   
Henri Fallon committed
223
224
225
226
227
        while( !DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo) ) 
        {
            p_lpcmdec->p_fifo->pf_delete_pes( p_lpcmdec->p_fifo->p_packets_mgt,
                    DECODER_FIFO_START(*p_lpcmdec->p_fifo ));
            DECODER_FIFO_INCSTART( *p_lpcmdec->p_fifo );
228
229
230
        }

        /* Waiting for the input thread to put new PES packets in the fifo */
Henri Fallon's avatar
   
Henri Fallon committed
231
232
        vlc_cond_wait ( &p_lpcmdec->p_fifo->data_wait, 
                        &p_lpcmdec->p_fifo->data_lock );
233
234
235
    }

    /* We can release the lock before leaving */
Henri Fallon's avatar
   
Henri Fallon committed
236
    vlc_mutex_unlock( &p_lpcmdec->p_fifo->data_lock );
237
238
239
240
241
}

/*****************************************************************************
 * EndThread : lpcm decoder thread destruction
 *****************************************************************************/
Henri Fallon's avatar
   
Henri Fallon committed
242
static void EndThread( lpcmdec_thread_t * p_lpcmdec )
243
{
Sam Hocevar's avatar
   
Sam Hocevar committed
244
    intf_DbgMsg( "LPCM Debug: destroying lpcm decoder thread %p", p_lpcmdec );
245
246

    /* If the audio output fifo was created, we destroy it */
Henri Fallon's avatar
   
Henri Fallon committed
247
248
249
    if( p_lpcmdec->p_aout_fifo != NULL ) 
    {
        aout_DestroyFifo( p_lpcmdec->p_aout_fifo );
250
251

        /* Make sure the output thread leaves the NextFrame() function */
Henri Fallon's avatar
   
Henri Fallon committed
252
253
254
        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) );
255
256
257
    }

    /* Destroy descriptor */
Henri Fallon's avatar
   
Henri Fallon committed
258
    free( p_lpcmdec );
259

Sam Hocevar's avatar
   
Sam Hocevar committed
260
    intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p destroyed", p_lpcmdec );
261
}