]> git.sesse.net Git - vlc/blob - modules/codec/lpcm/lpcm.c
1d0059397a602a173f393253cb10eb555c6c9bb1
[vlc] / modules / codec / lpcm / lpcm.c
1 /*****************************************************************************
2  * lpcm.c: lpcm decoder module
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: lpcm.c,v 1.4 2002/09/18 01:28:05 henri 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 <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>                                    /* memcpy(), memset() */
30
31 #include <vlc/vlc.h>
32 #include <vlc/aout.h>
33 #include <vlc/decoder.h>
34 #include <input_ext-dec.h>
35
36 #ifdef HAVE_UNISTD_H
37 #   include <unistd.h>                                           /* getpid() */
38 #endif
39
40 #include "lpcm.h"
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          && p_fifo->i_fourcc != VLC_FOURCC('l','p','c','b') )
69     {   
70         return VLC_EGENERIC;
71     }
72     
73     p_fifo->pf_run = RunDecoder;
74     return VLC_SUCCESS;
75 }
76
77 /*****************************************************************************
78  * RunDecoder: the lpcm decoder
79  *****************************************************************************/
80 static int RunDecoder( decoder_fifo_t * p_fifo )
81 {
82     lpcmdec_thread_t *   p_lpcmdec;
83
84     /* Allocate the memory needed to store the thread's structure */
85     if( (p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t)) )
86             == NULL) 
87     {
88         msg_Err( p_fifo, "out of memory" );
89         DecoderError( p_fifo );
90         return( -1 );
91     }
92
93     /*
94      * Initialize the thread properties
95      */
96     p_lpcmdec->p_fifo = p_fifo;
97
98     /* Init the BitStream */
99     InitBitstream( &p_lpcmdec->bit_stream, p_lpcmdec->p_fifo,
100                    NULL, NULL );
101    
102     /* FIXME : I suppose the number of channel ans sampling rate 
103      * are someway in the headers */
104     p_lpcmdec->output_format.i_format = AOUT_FMT_S16_BE;
105     p_lpcmdec->output_format.i_channels = 2;
106     p_lpcmdec->output_format.i_rate = 48000;
107     
108     aout_DateInit( &p_lpcmdec->end_date, 48000 );
109     p_lpcmdec->p_aout_input = aout_InputNew( p_lpcmdec->p_fifo,
110                                          &p_lpcmdec->p_aout,
111                                          &p_lpcmdec->output_format );
112
113     if( p_lpcmdec->p_aout_input == NULL )
114     {
115         msg_Err( p_lpcmdec->p_fifo, "failed to create aout fifo" );
116         p_lpcmdec->p_fifo->b_error = 1;
117         return( -1 );
118     }
119
120     /* lpcm decoder thread's main loop */
121     while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
122     {
123         DecodeFrame(p_lpcmdec);
124     }
125
126     /* If b_error is set, the lpcm decoder thread enters the error loop */
127     if (p_lpcmdec->p_fifo->b_error)
128     {
129         DecoderError( p_lpcmdec->p_fifo );
130     }
131
132     /* End of the lpcm decoder thread */
133     EndThread (p_lpcmdec);
134
135     return( 0 );
136 }
137
138 /*****************************************************************************
139  * DecodeFrame: decodes a frame.
140  *****************************************************************************/
141 void DecodeFrame( lpcmdec_thread_t * p_lpcmdec )
142 {
143     byte_t     buffer[LPCMDEC_FRAME_SIZE];
144     
145     aout_buffer_t *    p_aout_buffer;
146     mtime_t     i_pts;
147     vlc_bool_t  b_sync;
148     int         i_loop;
149
150     NextPTS( &p_lpcmdec->bit_stream, &i_pts, NULL );
151     
152     if( i_pts != 0 && i_pts != aout_DateGet( &p_lpcmdec->end_date ) )
153     {
154         aout_DateSet( &p_lpcmdec->end_date, i_pts );
155     }
156     
157     p_aout_buffer = aout_BufferNew( p_lpcmdec->p_aout,
158                                   p_lpcmdec->p_aout_input,
159                                   LPCMDEC_FRAME_SIZE/4 );
160     
161     if( !p_aout_buffer )
162     {
163         msg_Err( p_lpcmdec->p_fifo, "cannot get aout buffer" );
164         p_lpcmdec->p_fifo->b_error = 1;
165         return;
166     }
167     
168     p_aout_buffer->start_date = aout_DateGet( &p_lpcmdec->end_date );
169    
170     p_aout_buffer->end_date = aout_DateIncrement( &p_lpcmdec->end_date,
171                                                    LPCMDEC_FRAME_SIZE/4 );
172
173     b_sync = 0;
174     while( ( !p_lpcmdec->p_fifo->b_die ) &&
175            ( !p_lpcmdec->p_fifo->b_error ) &&
176            ( !b_sync ) )
177     {
178         while( ( !p_lpcmdec->p_fifo->b_die ) &&
179                ( !p_lpcmdec->p_fifo->b_error ) &&
180                ( GetBits( &p_lpcmdec->bit_stream, 8 ) != 0x01 ) );
181         b_sync = ( ShowBits( &p_lpcmdec->bit_stream, 8 ) == 0x80 );
182     }
183     
184     RemoveBits( &p_lpcmdec->bit_stream, 8 );
185     
186     GetChunk( &p_lpcmdec->bit_stream, p_aout_buffer->p_buffer, 
187               LPCMDEC_FRAME_SIZE);
188
189     if( p_lpcmdec->p_fifo->b_die || p_lpcmdec->p_fifo->b_error ) 
190         return;
191
192     aout_BufferPlay( p_lpcmdec->p_aout, p_lpcmdec->p_aout_input, 
193                      p_aout_buffer );
194
195 }
196
197 /*****************************************************************************
198  * EndThread : lpcm decoder thread destruction
199  *****************************************************************************/
200 static void EndThread( lpcmdec_thread_t * p_lpcmdec )
201 {
202     /* If the audio output fifo was created, we destroy it */
203     if( p_lpcmdec->p_aout_input )
204     {
205         aout_InputDelete( p_lpcmdec->p_aout, p_lpcmdec->p_aout_input );
206         
207     }
208
209     /* Destroy descriptor */
210     free( p_lpcmdec );
211 }