]> git.sesse.net Git - vlc/blob - plugins/lpcm_adec/lpcm_adec.c
Fixed a bug in the network dialog.
[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.10 2002/01/21 23:57:46 massiot 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  ( probedata_t * );
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->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( probedata_t *p_data )
86 {
87     return ( p_data->i_type == LPCM_AUDIO_ES ) ? 100 : 0;
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     intf_DbgMsg("lpcm_adec debug: thread launched, initializing.");
98     
99     /* Allocate the memory needed to store the thread's structure */
100     if( (p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t)) )
101             == NULL) 
102     {
103         intf_ErrMsg( "LPCM : error : cannot create lpcmdec_thread_t" );
104         DecoderError( p_config->p_decoder_fifo );
105         return( -1 );
106     }
107
108     /*
109      * Initialize the thread properties
110      */
111     p_lpcmdec->p_config = p_config;
112     p_lpcmdec->p_fifo = p_config->p_decoder_fifo;
113
114     if( InitThread( p_lpcmdec ) )
115     {
116         DecoderError( p_config->p_decoder_fifo );
117         free( p_lpcmdec );
118         return( -1 );
119     }
120
121     intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p initialized\n", 
122                  p_lpcmdec );
123     
124     /* lpcm decoder thread's main loop */
125     while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
126     {
127         DecodeFrame(p_lpcmdec);
128     }
129
130     /* If b_error is set, the lpcm decoder thread enters the error loop */
131     if (p_lpcmdec->p_fifo->b_error)
132     {
133         DecoderError( p_lpcmdec->p_fifo );
134     }
135
136     /* End of the lpcm decoder thread */
137     EndThread (p_lpcmdec);
138
139     return( 0 );
140 }
141
142 /*****************************************************************************
143  * InitThread : initialize an lpcm decoder thread
144  *****************************************************************************/
145 static int InitThread (lpcmdec_thread_t * p_lpcmdec)
146 {
147
148     /* Init the BitStream */
149     InitBitstream( &p_lpcmdec->bit_stream, p_lpcmdec->p_config->p_decoder_fifo,
150                    NULL, NULL);
151
152     /* Creating the audio output fifo */
153     p_lpcmdec->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_STEREO_FIFO, 2, 48000,
154                                             0, LPCMDEC_FRAME_SIZE/2, NULL  );
155     if ( p_lpcmdec->p_aout_fifo == NULL )
156     {
157         return( -1 );
158     }
159     return( 0 );
160 }
161
162 /*****************************************************************************
163  * DecodeFrame: decodes a frame.
164  *****************************************************************************/
165 void DecodeFrame( lpcmdec_thread_t * p_lpcmdec )
166 {
167     byte_t * buffer,p_temp[LPCMDEC_FRAME_SIZE];
168     int i_loop;
169     byte_t byte1, byte2;
170
171     CurrentPTS( &p_lpcmdec->bit_stream,
172         &p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame],
173         NULL );
174     if( !p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] )
175     {
176         p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
177             LAST_MDATE;
178     }
179
180     buffer = ((byte_t *)p_lpcmdec->p_aout_fifo->buffer) + 
181               (p_lpcmdec->p_aout_fifo->l_end_frame * LPCMDEC_FRAME_SIZE);
182
183     RemoveBits32(&p_lpcmdec->bit_stream);
184     byte1 = GetBits(&p_lpcmdec->bit_stream, 8) ;
185     byte2 = GetBits(&p_lpcmdec->bit_stream, 8) ;
186     
187     /* I only have 2 test streams. As far as I understand
188      * after the RemoveBits and the 2 GetBits, we should be exactly 
189      * where we whant : the sync word : 0x0180.
190      * If not, we got and find it. */
191     while( ( byte1 != 0x01 || byte2 != 0x80 ) && (!p_lpcmdec->p_fifo->b_die)
192                                        && (!p_lpcmdec->p_fifo->b_error) )
193     {
194         byte1 = byte2;
195         byte2 = GetBits(&p_lpcmdec->bit_stream, 8);
196     }
197     
198     GetChunk( &p_lpcmdec->bit_stream, p_temp, LPCMDEC_FRAME_SIZE);
199     
200     for( i_loop = 0; i_loop < LPCMDEC_FRAME_SIZE/2; i_loop++ )
201     {
202         buffer[2*i_loop]=p_temp[2*i_loop+1];
203         buffer[2*i_loop+1]=p_temp[2*i_loop];
204     }
205     
206     vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
207     p_lpcmdec->p_aout_fifo->l_end_frame = 
208         (p_lpcmdec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
209     vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
210     vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
211     
212     intf_DbgMsg( "LPCM Debug: %x", *buffer );
213
214 }
215
216 /*****************************************************************************
217  * EndThread : lpcm decoder thread destruction
218  *****************************************************************************/
219 static void EndThread( lpcmdec_thread_t * p_lpcmdec )
220 {
221     intf_DbgMsg( "LPCM Debug: destroying lpcm decoder thread %p", p_lpcmdec );
222
223     /* If the audio output fifo was created, we destroy it */
224     if( p_lpcmdec->p_aout_fifo != NULL ) 
225     {
226         aout_DestroyFifo( p_lpcmdec->p_aout_fifo );
227
228         /* Make sure the output thread leaves the NextFrame() function */
229         vlc_mutex_lock( &(p_lpcmdec->p_aout_fifo->data_lock) );
230         vlc_cond_signal( &(p_lpcmdec->p_aout_fifo->data_wait) );
231         vlc_mutex_unlock( &(p_lpcmdec->p_aout_fifo->data_lock) );
232     }
233
234     /* Destroy descriptor */
235     free( p_lpcmdec );
236
237     intf_DbgMsg( "LPCM Debug: lpcm decoder thread %p destroyed", p_lpcmdec );
238 }