lpcm_decoder_thread.c 10 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.5 2000/12/21 13:25:51 massiot Exp $
6 7 8 9 10 11 12
 *
 * Authors:
 *
 * 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.
13
 * 
14 15
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
18
 *
19 20 21
 * 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.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
 *****************************************************************************/

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

#include <unistd.h>                                              /* getpid() */

#include <stdio.h>                                           /* "intf_msg.h" */
#include <stdlib.h>                                      /* malloc(), free() */
#include <sys/types.h>                        /* on BSD, uio.h needs types.h */
#include <sys/uio.h>                                            /* "input.h" */

#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
#include "plugins.h"
#include "debug.h"                                      /* "input_netlist.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 63 64 65

#include "audio_output.h"

#include "lpcm_decoder.h"
#include "lpcm_decoder_thread.h"

#define LPCMDEC_FRAME_SIZE (2*1536)                    /* May not be usefull */

/*****************************************************************************
 * 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
 *****************************************************************************/
66
vlc_thread_t lpcmdec_CreateThread (adec_config_t * p_config)
67 68
{
    lpcmdec_thread_t *   p_lpcmdec;
69
    intf_DbgMsg ( "LPCM Debug: creating lpcm decoder thread\n" );
70 71 72

    /* Allocate the memory needed to store the thread's structure */
    if ((p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t))) == NULL) {
73
        intf_ErrMsg ( "LPCM Error: not enough memory for lpcmdec_CreateThread() to create the new thread\n" );
74
        return 0;
75 76 77 78 79
    }

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


    /* Initialize the lpcm decoder structures */
    lpcm_init (&p_lpcmdec->lpcm_decoder);

    /*
     * Initialize the output properties
     */
90
    p_lpcmdec->p_aout = p_config->p_aout;
91 92 93 94
    p_lpcmdec->p_aout_fifo = NULL;

    /* Spawn the lpcm decoder thread */
    if (vlc_thread_create(&p_lpcmdec->thread_id, "lpcm decoder", (vlc_thread_func_t)RunThread, (void *)p_lpcmdec)) {
95
        intf_ErrMsg  ( "LPCM Error: can't spawn lpcm decoder thread\n" );
96
        free (p_lpcmdec);
97
        return 0;
98 99
    }

100
    intf_DbgMsg ( "LPCM Debug: lpcm decoder thread (%p) created\n", p_lpcmdec );
101
    return p_lpcmdec->thread_id;
102 103 104 105 106 107 108 109 110 111 112 113
}

/* Following functions are local */

/*****************************************************************************
 * InitThread : initialize an lpcm decoder thread
 *****************************************************************************/
static int InitThread (lpcmdec_thread_t * p_lpcmdec)
{
    aout_fifo_t         aout_fifo;
    lpcm_byte_stream_t * byte_stream;

114
    intf_DbgMsg ( "LPCM Debug: initializing lpcm decoder thread %p\n", p_lpcmdec );
115 116 117

    /* Our first job is to initialize the bit stream structure with the
     * beginning of the input stream */
118 119
    vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
    while (DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
120
        if (p_lpcmdec->p_fifo->b_die) {
121
            vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
122 123
            return -1;
        }
124
        vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
125
    }
126
    p_lpcmdec->p_data = DECODER_FIFO_START (*p_lpcmdec->p_fifo)->p_first;
127
    byte_stream = lpcm_byte_stream (&p_lpcmdec->lpcm_decoder);
128 129
    byte_stream->p_byte = p_lpcmdec->p_data->p_payload_start;
    byte_stream->p_end = p_lpcmdec->p_data->p_payload_end;
130
    byte_stream->info = p_lpcmdec;
131
    vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
132 133 134 135 136 137 138 139 140 141 142 143

    aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
    aout_fifo.i_channels = 2;
    aout_fifo.b_stereo = 1;

    aout_fifo.l_frame_size = LPCMDEC_FRAME_SIZE;

    /* Creating the audio output fifo */
    if ((p_lpcmdec->p_aout_fifo = aout_CreateFifo(p_lpcmdec->p_aout, &aout_fifo)) == NULL) {
        return -1;
    }

144
    intf_DbgMsg ( "LPCM Debug: lpcm decoder thread %p initialized\n", p_lpcmdec );
145 146 147 148 149 150 151 152 153 154
    return 0;
}

/*****************************************************************************
 * RunThread : lpcm decoder thread
 *****************************************************************************/
static void RunThread (lpcmdec_thread_t * p_lpcmdec)
{
    int sync;

155
    intf_DbgMsg( "LPCM Debug: running lpcm decoder thread (%p) (pid== %i)\n", p_lpcmdec, getpid() );
156

157 158
    /* Fucking holy piece of shit ! */
    //msleep (INPUT_PTS_DELAY);
159 160 161 162

    /* Initializing the lpcm decoder thread */
    if (InitThread (p_lpcmdec)) 
    {
163
        p_lpcmdec->p_fifo->b_error = 1;
164 165 166 167 168 169 170 171
    }

    sync = 0;
    p_lpcmdec->sync_ptr = 0;

    /* lpcm decoder thread's main loop */
    /* FIXME : do we have enough room to store the decoded frames ?? */
   
172
    while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
173 174 175 176 177 178 179 180 181
    {
	    s16 * buffer;
	    lpcm_sync_info_t sync_info;

	    if (!sync)
        {
            /* have to find a synchro point */
        }
    
182
        if (DECODER_FIFO_START(*p_lpcmdec->p_fifo)->b_has_pts)
183
        {
184 185
	        p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts;
	        DECODER_FIFO_START(*p_lpcmdec->p_fifo)->b_has_pts = 0;
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
        }
        else
        {
	        p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = LAST_MDATE;
        }

    	p_lpcmdec->p_aout_fifo->l_rate = sync_info.sample_rate;

	    buffer = ((s16 *)p_lpcmdec->p_aout_fifo->buffer) + (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);

	    if (lpcm_decode_frame (&p_lpcmdec->lpcm_decoder, buffer))
        {
	        sync = 0;
	        goto bad_frame;
	    }

	    vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
	    p_lpcmdec->p_aout_fifo->l_end_frame = (p_lpcmdec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
	    vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
	    vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);

207
        intf_DbgMsg( "LPCM Debug: %x\n", *buffer );
208 209 210 211
        bad_frame:
    }

    /* If b_error is set, the lpcm decoder thread enters the error loop */
212
    if (p_lpcmdec->p_fifo->b_error)
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
    {
        ErrorThread (p_lpcmdec);
    }

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

/*****************************************************************************
 * ErrorThread : lpcm decoder's RunThread() error loop
 *****************************************************************************/
static void ErrorThread (lpcmdec_thread_t * p_lpcmdec)
{
    /* We take the lock, because we are going to read/write the start/end
     * indexes of the decoder fifo */
228
    vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
229 230

    /* Wait until a `die' order is sent */
231
    while (!p_lpcmdec->p_fifo->b_die) {
232
        /* Trash all received PES packets */
233 234 235 236
        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);
237 238 239
        }

        /* Waiting for the input thread to put new PES packets in the fifo */
240
        vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
241 242 243
    }

    /* We can release the lock before leaving */
244
    vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
245 246 247 248 249 250 251
}

/*****************************************************************************
 * EndThread : lpcm decoder thread destruction
 *****************************************************************************/
static void EndThread (lpcmdec_thread_t * p_lpcmdec)
{
252
    intf_DbgMsg( "LPCM Debug: destroying lpcm decoder thread %p\n", p_lpcmdec );
253 254 255 256 257 258 259 260 261 262 263 264 265 266

    /* If the audio output fifo was created, we destroy it */
    if (p_lpcmdec->p_aout_fifo != NULL) {
        aout_DestroyFifo (p_lpcmdec->p_aout_fifo);

        /* Make sure the output thread leaves the NextFrame() function */
        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));
    }

    /* Destroy descriptor */
    free (p_lpcmdec);

267
    intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p destroyed\n", p_lpcmdec );
268 269 270 271 272 273 274 275 276
}

void lpcm_byte_stream_next (lpcm_byte_stream_t * p_byte_stream)
{
//    lpcmdec_thread_t * p_lpcmdec = p_byte_stream->info;

    /* We are looking for the next TS packet that contains real data,
     * and not just a PES header */
}