]> git.sesse.net Git - vlc/blob - plugins/lpcm_adec/lpcm_adec.c
* plugins/lpcm_adec/lpcm_adec.c: fix for broken lpcm plugin on little endian
[vlc] / plugins / lpcm_adec / lpcm_adec.c
1 /*****************************************************************************
2  * lpcm_decoder_thread.c: lpcm decoder thread
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: lpcm_adec.c,v 1.15.2.3 2002/10/14 16:27:44 gbazin Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *          Henri Fallon <henri@videolan.org>
9  *
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.
14  * 
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.
19  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdio.h>                                           /* "intf_msg.h" */
29 #include <string.h>                                    /* memcpy(), memset() */
30 #include <stdlib.h>                                      /* malloc(), free() */
31
32 #include <videolan/vlc.h>
33
34 #ifdef HAVE_UNISTD_H
35 #   include <unistd.h>                                           /* getpid() */
36 #endif
37
38 #include "audio_output.h"
39
40 #include "stream_control.h"
41 #include "input_ext-dec.h"
42
43 #include "lpcm_adec.h"
44
45 /*****************************************************************************
46  * Local prototypes
47  *****************************************************************************/
48 static int  decoder_Probe  ( u8 * );
49 static int  decoder_Run    ( decoder_config_t * );
50        void DecodeFrame    ( lpcmdec_thread_t * );
51 static int  InitThread     ( lpcmdec_thread_t * );
52 static void EndThread      ( lpcmdec_thread_t * );
53
54
55 /*****************************************************************************
56  * Capabilities
57  *****************************************************************************/
58 void _M( adec_getfunctions )( function_list_t * p_function_list )
59 {
60     p_function_list->functions.dec.pf_probe = decoder_Probe;
61     p_function_list->functions.dec.pf_run   = decoder_Run;
62 }
63
64 /*****************************************************************************
65  * Build configuration tree.
66  *****************************************************************************/
67 MODULE_CONFIG_START
68 MODULE_CONFIG_STOP
69
70 MODULE_INIT_START
71     SET_DESCRIPTION( _("linear PCM audio decoder") )
72     ADD_CAPABILITY( DECODER, 100 )
73 MODULE_INIT_STOP
74
75 MODULE_ACTIVATE_START
76     _M( adec_getfunctions )( &p_module->p_functions->dec );
77 MODULE_ACTIVATE_STOP
78
79 MODULE_DEACTIVATE_START
80 MODULE_DEACTIVATE_STOP
81
82 /*****************************************************************************
83  * decoder_Probe: probe the decoder and return score
84  *****************************************************************************/
85 static int decoder_Probe( u8 *pi_type )
86 {
87     return ( (*pi_type == LPCM_AUDIO_ES || *pi_type == LPCMB_AUDIO_ES) ? 0 : -1 );
88 }
89
90 /*****************************************************************************
91  * decoder_Run: the lpcm decoder
92  *****************************************************************************/
93 static int decoder_Run( decoder_config_t * p_config )
94 {
95     lpcmdec_thread_t *   p_lpcmdec;
96
97     /* Allocate the memory needed to store the thread's structure */
98     if( (p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t)) )
99             == NULL) 
100     {
101         intf_ErrMsg( "LPCM : error : cannot create lpcmdec_thread_t" );
102         DecoderError( p_config->p_decoder_fifo );
103         return( -1 );
104     }
105
106     /*
107      * Initialize the thread properties
108      */
109     p_lpcmdec->p_config = p_config;
110     p_lpcmdec->p_fifo = p_config->p_decoder_fifo;
111
112     if( InitThread( p_lpcmdec ) )
113     {
114         DecoderError( p_config->p_decoder_fifo );
115         free( p_lpcmdec );
116         return( -1 );
117     }
118
119     /* lpcm decoder thread's main loop */
120     while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
121     {
122         DecodeFrame(p_lpcmdec);
123     }
124
125     /* If b_error is set, the lpcm decoder thread enters the error loop */
126     if (p_lpcmdec->p_fifo->b_error)
127     {
128         DecoderError( p_lpcmdec->p_fifo );
129     }
130
131     /* End of the lpcm decoder thread */
132     EndThread (p_lpcmdec);
133
134     return( 0 );
135 }
136
137 /*****************************************************************************
138  * InitThread : initialize an lpcm decoder thread
139  *****************************************************************************/
140 static int InitThread (lpcmdec_thread_t * p_lpcmdec)
141 {
142
143     /* Init the BitStream */
144     InitBitstream( &p_lpcmdec->bit_stream, p_lpcmdec->p_config->p_decoder_fifo,
145                    NULL, NULL);
146
147     /* Creating the audio output fifo */
148     p_lpcmdec->p_aout_fifo = aout_CreateFifo( AOUT_FIFO_PCM, 2, 48000,
149                                               LPCMDEC_FRAME_SIZE/2, NULL  );
150     if ( p_lpcmdec->p_aout_fifo == NULL )
151     {
152         return( -1 );
153     }
154     return( 0 );
155 }
156
157 /*****************************************************************************
158  * DecodeFrame: decodes a frame.
159  *****************************************************************************/
160 void DecodeFrame( lpcmdec_thread_t * p_lpcmdec )
161 {
162     byte_t * buffer;
163 #ifndef WORDS_BIGENDIAN
164     byte_t p_temp[LPCMDEC_FRAME_SIZE];
165 #endif
166     int i_loop;
167     byte_t byte1, byte2;
168
169     CurrentPTS( &p_lpcmdec->bit_stream,
170         &p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame],
171         NULL );
172     if( !p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame] )
173     {
174         p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame] =
175             LAST_MDATE;
176     }
177
178     buffer = ((byte_t *)p_lpcmdec->p_aout_fifo->buffer) + 
179               (p_lpcmdec->p_aout_fifo->i_end_frame * LPCMDEC_FRAME_SIZE);
180
181     RemoveBits32(&p_lpcmdec->bit_stream);
182     byte1 = GetBits(&p_lpcmdec->bit_stream, 8) ;
183     byte2 = GetBits(&p_lpcmdec->bit_stream, 8) ;
184     
185     /* I only have 2 test streams. As far as I understand
186      * after the RemoveBits and the 2 GetBits, we should be exactly 
187      * where we want : the sync word : 0x0180.
188      * If not, we go and find it. */
189     while( ( byte1 != 0x01 || byte2 != 0x80 ) && (!p_lpcmdec->p_fifo->b_die)
190                                        && (!p_lpcmdec->p_fifo->b_error) )
191     {
192         byte1 = byte2;
193         byte2 = GetBits(&p_lpcmdec->bit_stream, 8);
194     }
195     
196 #ifndef WORDS_BIGENDIAN
197     GetChunk( &p_lpcmdec->bit_stream, p_temp, LPCMDEC_FRAME_SIZE);
198     if( p_lpcmdec->p_fifo->b_die ) return;
199
200 #   ifdef HAVE_SWAB
201     swab( p_temp, buffer, LPCMDEC_FRAME_SIZE );
202 #   else
203     for( i_loop = 0; i_loop < LPCMDEC_FRAME_SIZE/2; i_loop++ )
204     {
205         buffer[2*i_loop]=p_temp[2*i_loop+1];
206         buffer[2*i_loop+1]=p_temp[2*i_loop];
207     }
208 #   endif
209
210 #else
211     GetChunk( &p_lpcmdec->bit_stream, buffer, LPCMDEC_FRAME_SIZE);
212     if( p_lpcmdec->p_fifo->b_die ) return;
213 #endif
214     
215     vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
216     p_lpcmdec->p_aout_fifo->i_end_frame = 
217         (p_lpcmdec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
218     vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
219     vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
220 }
221
222 /*****************************************************************************
223  * EndThread : lpcm decoder thread destruction
224  *****************************************************************************/
225 static void EndThread( lpcmdec_thread_t * p_lpcmdec )
226 {
227     /* If the audio output fifo was created, we destroy it */
228     if( p_lpcmdec->p_aout_fifo != NULL ) 
229     {
230         aout_DestroyFifo( p_lpcmdec->p_aout_fifo );
231
232         /* Make sure the output thread leaves the NextFrame() function */
233         vlc_mutex_lock( &(p_lpcmdec->p_aout_fifo->data_lock) );
234         vlc_cond_signal( &(p_lpcmdec->p_aout_fifo->data_wait) );
235         vlc_mutex_unlock( &(p_lpcmdec->p_aout_fifo->data_lock) );
236     }
237
238     /* Destroy descriptor */
239     free( p_lpcmdec );
240 }