]> git.sesse.net Git - vlc/blob - plugins/lpcm_adec/lpcm_adec.c
* ALL: new module API. Makes a few things a lot simpler, and we gain
[vlc] / plugins / lpcm_adec / lpcm_adec.c
1 /*****************************************************************************
2  * lpcm_adec.c: lpcm decoder thread
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: lpcm_adec.c,v 1.20 2002/07/31 20:56:51 sam 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 <string.h>                                    /* memcpy(), memset() */
29 #include <stdlib.h>                                      /* malloc(), free() */
30
31 #include <vlc/vlc.h>
32 #include <vlc/aout.h>
33 #include <vlc/decoder.h>
34
35 #ifdef HAVE_UNISTD_H
36 #   include <unistd.h>                                           /* getpid() */
37 #endif
38
39 #include "lpcm_adec.h"
40
41 /*****************************************************************************
42  * Local prototypes
43  *****************************************************************************/
44 static int  OpenDecoder    ( vlc_object_t * );
45 static int  RunDecoder     ( decoder_fifo_t * );
46
47        void DecodeFrame    ( lpcmdec_thread_t * );
48 static int  InitThread     ( lpcmdec_thread_t * );
49 static void EndThread      ( lpcmdec_thread_t * );
50
51 /*****************************************************************************
52  * Module descriptor
53  *****************************************************************************/
54 vlc_module_begin();
55     set_description( _("linear PCM audio decoder") );
56     set_capability( "decoder", 100 );
57     set_callbacks( OpenDecoder, NULL );
58 vlc_module_end();
59
60 /*****************************************************************************
61  * OpenDecoder: probe the decoder and return score
62  *****************************************************************************/
63 static int OpenDecoder( vlc_object_t *p_this )
64 {
65     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
66
67     if( p_fifo->i_fourcc != VLC_FOURCC('l','p','c','m') )
68     {   
69         return VLC_EGENERIC;
70     }
71     
72     p_fifo->pf_run = RunDecoder;
73     return VLC_SUCCESS;
74 }
75
76 /*****************************************************************************
77  * RunDecoder: the lpcm decoder
78  *****************************************************************************/
79 static int RunDecoder( decoder_fifo_t * p_fifo )
80 {
81     lpcmdec_thread_t *   p_lpcmdec;
82
83     /* Allocate the memory needed to store the thread's structure */
84     if( (p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t)) )
85             == NULL) 
86     {
87         msg_Err( p_fifo, "out of memory" );
88         DecoderError( p_fifo );
89         return( -1 );
90     }
91
92     /*
93      * Initialize the thread properties
94      */
95     p_lpcmdec->p_fifo = p_fifo;
96
97     if( InitThread( p_lpcmdec ) )
98     {
99         DecoderError( p_fifo );
100         free( p_lpcmdec );
101         return( -1 );
102     }
103
104     /* lpcm decoder thread's main loop */
105     while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
106     {
107         DecodeFrame(p_lpcmdec);
108     }
109
110     /* If b_error is set, the lpcm decoder thread enters the error loop */
111     if (p_lpcmdec->p_fifo->b_error)
112     {
113         DecoderError( p_lpcmdec->p_fifo );
114     }
115
116     /* End of the lpcm decoder thread */
117     EndThread (p_lpcmdec);
118
119     return( 0 );
120 }
121
122 /*****************************************************************************
123  * InitThread : initialize an lpcm decoder thread
124  *****************************************************************************/
125 static int InitThread (lpcmdec_thread_t * p_lpcmdec)
126 {
127
128     /* Init the BitStream */
129     InitBitstream( &p_lpcmdec->bit_stream, p_lpcmdec->p_fifo,
130                    NULL, NULL);
131
132     /* Creating the audio output fifo */
133     p_lpcmdec->p_aout_fifo =
134                 aout_CreateFifo( p_lpcmdec->p_fifo, AOUT_FIFO_PCM,
135                                  2, 48000, LPCMDEC_FRAME_SIZE / 2, NULL  );
136     if ( p_lpcmdec->p_aout_fifo == NULL )
137     {
138         return( -1 );
139     }
140     return( 0 );
141 }
142
143 /*****************************************************************************
144  * DecodeFrame: decodes a frame.
145  *****************************************************************************/
146 void DecodeFrame( lpcmdec_thread_t * p_lpcmdec )
147 {
148     byte_t *    buffer,p_temp[LPCMDEC_FRAME_SIZE];
149     vlc_bool_t  b_sync;
150     int         i_loop;
151
152     CurrentPTS( &p_lpcmdec->bit_stream,
153         &p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame],
154         NULL );
155     if( !p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame] )
156     {
157         p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame] =
158             LAST_MDATE;
159     }
160
161     buffer = ((byte_t *)p_lpcmdec->p_aout_fifo->buffer) + 
162               (p_lpcmdec->p_aout_fifo->i_end_frame * LPCMDEC_FRAME_SIZE);
163
164     RemoveBits32(&p_lpcmdec->bit_stream);
165 #if 0
166     byte1 = GetBits(&p_lpcmdec->bit_stream, 8) ;
167     byte2 = GetBits(&p_lpcmdec->bit_stream, 8) ;
168     
169     /* I only have 2 test streams. As far as I understand
170      * after the RemoveBits and the 2 GetBits, we should be exactly 
171      * where we whant : the sync word : 0x0180.
172      * If not, we got and find it. */
173     while( ( byte1 != 0x01 || byte2 != 0x80 ) && (!p_lpcmdec->p_fifo->b_die)
174                                        && (!p_lpcmdec->p_fifo->b_error) )
175     {
176         byte1 = byte2;
177         byte2 = GetBits(&p_lpcmdec->bit_stream, 8);
178     }
179 #else
180     b_sync = 0;
181     while( ( !p_lpcmdec->p_fifo->b_die ) &&
182            ( !p_lpcmdec->p_fifo->b_error ) &&
183            ( !b_sync ) )
184     {
185         while( ( !p_lpcmdec->p_fifo->b_die ) &&
186                ( !p_lpcmdec->p_fifo->b_error ) &&
187                ( GetBits( &p_lpcmdec->bit_stream, 8 ) != 0x01 ) );
188         b_sync = ( ShowBits( &p_lpcmdec->bit_stream, 8 ) == 0x80 );
189     }
190     RemoveBits( &p_lpcmdec->bit_stream, 8 );
191 #endif
192     
193     GetChunk( &p_lpcmdec->bit_stream, p_temp, LPCMDEC_FRAME_SIZE);
194     if( p_lpcmdec->p_fifo->b_die || p_lpcmdec->p_fifo->b_error ) return;
195
196     for( i_loop = 0; i_loop < LPCMDEC_FRAME_SIZE/2; i_loop++ )
197     {
198         buffer[2*i_loop]=p_temp[2*i_loop+1];
199         buffer[2*i_loop+1]=p_temp[2*i_loop];
200     }
201     
202     vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
203     p_lpcmdec->p_aout_fifo->i_end_frame = 
204         (p_lpcmdec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
205     vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
206     vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
207 }
208
209 /*****************************************************************************
210  * EndThread : lpcm decoder thread destruction
211  *****************************************************************************/
212 static void EndThread( lpcmdec_thread_t * p_lpcmdec )
213 {
214     /* If the audio output fifo was created, we destroy it */
215     if( p_lpcmdec->p_aout_fifo != NULL ) 
216     {
217         aout_DestroyFifo( p_lpcmdec->p_aout_fifo );
218
219         /* Make sure the output thread leaves the NextFrame() function */
220         vlc_mutex_lock( &(p_lpcmdec->p_aout_fifo->data_lock) );
221         vlc_cond_signal( &(p_lpcmdec->p_aout_fifo->data_wait) );
222         vlc_mutex_unlock( &(p_lpcmdec->p_aout_fifo->data_lock) );
223     }
224
225     /* Destroy descriptor */
226     free( p_lpcmdec );
227 }