1 /*****************************************************************************
2 * lpcm.c: lpcm decoder module
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: lpcm.c,v 1.2 2002/09/26 22:40:20 massiot Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
8 * Henri Fallon <henri@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
29 #include <string.h> /* memcpy(), memset() */
33 #include <vlc/decoder.h>
34 #include <input_ext-dec.h>
37 # include <unistd.h> /* getpid() */
40 #define LPCM_FRAME_NB 502
42 /*****************************************************************************
43 * dec_thread_t : lpcm decoder thread descriptor
44 *****************************************************************************/
45 typedef struct dec_thread_t
50 vlc_thread_t thread_id; /* id for thread functions */
55 decoder_fifo_t * p_fifo; /* stores the PES stream data */
56 bit_stream_t bit_stream;
57 int sync_ptr; /* sync ptr from lpcm magic header */
62 aout_instance_t *p_aout;
63 aout_input_t *p_aout_input;
64 audio_sample_format_t output_format;
65 audio_date_t end_date;
68 /*****************************************************************************
70 *****************************************************************************/
71 static int OpenDecoder ( vlc_object_t * );
72 static int RunDecoder ( decoder_fifo_t * );
74 void DecodeFrame ( dec_thread_t * );
75 // static int InitThread ( dec_thread_t * );
76 static void EndThread ( dec_thread_t * );
78 /*****************************************************************************
80 *****************************************************************************/
82 set_description( _("linear PCM audio parser") );
83 set_capability( "decoder", 100 );
84 set_callbacks( OpenDecoder, NULL );
87 /*****************************************************************************
88 * OpenDecoder: probe the decoder and return score
89 *****************************************************************************/
90 static int OpenDecoder( vlc_object_t *p_this )
92 decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
94 if( p_fifo->i_fourcc != VLC_FOURCC('l','p','c','m')
95 && p_fifo->i_fourcc != VLC_FOURCC('l','p','c','b') )
100 p_fifo->pf_run = RunDecoder;
104 /*****************************************************************************
105 * RunDecoder: the lpcm decoder
106 *****************************************************************************/
107 static int RunDecoder( decoder_fifo_t * p_fifo )
109 dec_thread_t * p_dec;
111 /* Allocate the memory needed to store the thread's structure */
112 if( (p_dec = (dec_thread_t *)malloc (sizeof(dec_thread_t)) )
115 msg_Err( p_fifo, "out of memory" );
116 DecoderError( p_fifo );
120 /* Initialize the thread properties */
121 p_dec->p_fifo = p_fifo;
123 /* Init the bitstream */
124 InitBitstream( &p_dec->bit_stream, p_dec->p_fifo,
127 /* FIXME : I suppose the number of channel and sampling rate
128 * are somewhere in the headers */
129 p_dec->output_format.i_format = AOUT_FMT_S16_BE;
130 p_dec->output_format.i_channels = 2;
131 p_dec->output_format.i_rate = 48000;
133 aout_DateInit( &p_dec->end_date, 48000 );
134 p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
136 &p_dec->output_format );
138 if ( p_dec->p_aout_input == NULL )
140 msg_Err( p_dec->p_fifo, "failed to create aout fifo" );
141 p_dec->p_fifo->b_error = 1;
145 /* lpcm decoder thread's main loop */
146 while ( (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) )
151 /* If b_error is set, the lpcm decoder thread enters the error loop */
152 if ( p_dec->p_fifo->b_error )
154 DecoderError( p_dec->p_fifo );
157 /* End of the lpcm decoder thread */
163 /*****************************************************************************
164 * DecodeFrame: decodes a frame.
165 *****************************************************************************/
166 void DecodeFrame( dec_thread_t * p_dec )
168 aout_buffer_t * p_aout_buffer;
171 NextPTS( &p_dec->bit_stream, &i_pts, NULL );
173 if( i_pts != 0 && i_pts != aout_DateGet( &p_dec->end_date ) )
175 aout_DateSet( &p_dec->end_date, i_pts );
178 p_aout_buffer = aout_DecNewBuffer( p_dec->p_aout,
184 msg_Err( p_dec->p_fifo, "cannot get aout buffer" );
185 p_dec->p_fifo->b_error = 1;
189 p_aout_buffer->start_date = aout_DateGet( &p_dec->end_date );
190 p_aout_buffer->end_date = aout_DateIncrement( &p_dec->end_date,
193 /* Look for sync word - should be 0x0180 */
194 RealignBits( &p_dec->bit_stream );
195 while ( (GetBits( &p_dec->bit_stream, 16 ) ) != 0x0180 &&
196 (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error));
198 GetChunk( &p_dec->bit_stream, p_aout_buffer->p_buffer,
201 if( p_dec->p_fifo->b_die )
203 aout_DecDeleteBuffer( p_dec->p_aout, p_dec->p_aout_input,
208 aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input,
212 /*****************************************************************************
213 * EndThread : lpcm decoder thread destruction
214 *****************************************************************************/
215 static void EndThread( dec_thread_t * p_dec )
217 if( p_dec->p_aout_input != NULL )
219 aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );