]> git.sesse.net Git - vlc/blob - modules/codec/lpcm.c
* ALL: Introduction of a new api for decoders.
[vlc] / modules / codec / lpcm.c
1 /*****************************************************************************
2  * lpcm.c: lpcm decoder module
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: lpcm.c,v 1.17 2003/09/02 20:19:25 gbazin Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *          Henri Fallon <henri@videolan.org>
9  *          Christophe Massiot <massiot@via.ecp.fr>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdlib.h>                                      /* malloc(), free() */
30 #include <string.h>                                    /* memcpy(), memset() */
31
32 #include <vlc/vlc.h>
33 #include <vlc/aout.h>
34 #include <vlc/decoder.h>
35 #include <input_ext-dec.h>
36
37 #ifdef HAVE_UNISTD_H
38 #   include <unistd.h>                                           /* getpid() */
39 #endif
40
41 /*****************************************************************************
42  * dec_thread_t : lpcm decoder thread descriptor
43  *****************************************************************************/
44 typedef struct dec_thread_t
45 {
46     /*
47      * Input properties
48      */
49     decoder_fifo_t *    p_fifo;                /* stores the PES stream data */
50     /* Some filters don't handle well too small buffers (coreaudio resampler).
51      * Thus an aout buffer will be two PES packets. */
52     pes_packet_t *      p_buffered_pes;
53     data_packet_t *     p_buffered_data;
54     size_t              i_buffered_size;
55
56     /*
57      * Output properties
58      */
59     aout_instance_t        *p_aout;
60     aout_input_t           *p_aout_input;
61     audio_sample_format_t   output_format;
62     audio_date_t            end_date;
63 } dec_thread_t;
64
65 /*
66  * LPCM header :
67  * - PES header
68  * - private stream ID (16 bits) == 0xA0 -> not in the bitstream
69  * - frame number (8 bits)
70  * - unknown (16 bits) == 0x0003 ?
71  * - unknown (4 bits)
72  * - current frame (4 bits)
73  * - unknown (2 bits)
74  * - frequency (2 bits) 0 == 48 kHz, 1 == 32 kHz, 2 == ?, 3 == ?
75  * - unknown (1 bit)
76  * - number of channels - 1 (3 bits) 1 == 2 channels
77  * - start code (8 bits) == 0x80
78  */
79
80 #define LPCM_HEADER_LEN 6
81
82 /*****************************************************************************
83  * Local prototypes
84  *****************************************************************************/
85 static int  OpenDecoder    ( vlc_object_t * );
86 static int  RunDecoder     ( decoder_fifo_t * );
87
88 static void DecodeFrame    ( dec_thread_t * );
89 static void EndThread      ( dec_thread_t * );
90
91 /*****************************************************************************
92  * Module descriptor
93  *****************************************************************************/
94 vlc_module_begin();
95     set_description( _("linear PCM audio parser") );
96     set_capability( "decoder", 100 );
97     set_callbacks( OpenDecoder, NULL );
98 vlc_module_end();
99
100 /*****************************************************************************
101  * OpenDecoder: probe the decoder and return score
102  *****************************************************************************/
103 static int OpenDecoder( vlc_object_t *p_this )
104 {
105     decoder_t *p_dec = (decoder_t*)p_this;
106
107     if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('l','p','c','m')
108          && p_dec->p_fifo->i_fourcc != VLC_FOURCC('l','p','c','b') )
109     {   
110         return VLC_EGENERIC;
111     }
112     
113     p_dec->pf_run = RunDecoder;
114     return VLC_SUCCESS;
115 }
116
117 /*****************************************************************************
118  * RunDecoder: the lpcm decoder
119  *****************************************************************************/
120 static int RunDecoder( decoder_fifo_t * p_fifo )
121 {
122     dec_thread_t *   p_dec;
123
124     /* Allocate the memory needed to store the thread's structure */
125     if( (p_dec = (dec_thread_t *)malloc( sizeof(dec_thread_t)) )
126             == NULL) 
127     {
128         msg_Err( p_fifo, "out of memory" );
129         DecoderError( p_fifo );
130         return -1;
131     }
132
133     /* Initialize the thread properties */
134     p_dec->p_fifo = p_fifo;
135     p_dec->i_buffered_size = 0;
136
137     p_dec->output_format.i_format = VLC_FOURCC('s','1','6','b');
138     p_dec->p_aout = NULL;
139     p_dec->p_aout_input = NULL;
140
141     /* LPCM decoder thread's main loop */
142     while ( (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) )
143     {
144         DecodeFrame(p_dec);
145     }
146
147     /* If b_error is set, the lpcm decoder thread enters the error loop */
148     if ( p_dec->p_fifo->b_error )
149     {
150         DecoderError( p_dec->p_fifo );
151     }
152
153     /* End of the lpcm decoder thread */
154     EndThread( p_dec );
155
156     return 0;
157 }
158
159 /*****************************************************************************
160  * DecodeFrame: decodes a frame.
161  *****************************************************************************/
162 static void DecodeFrame( dec_thread_t * p_dec )
163 {
164     pes_packet_t *     p_pes;
165     data_packet_t *    p_data;
166     aout_buffer_t *    p_buffer;
167     void *             p_dest;
168     mtime_t            i_pts;
169     uint8_t            i_header;
170     unsigned int       i_rate = 0, i_original_channels = 0, i_size;
171     int                i;
172
173     input_ExtractPES( p_dec->p_fifo, &p_pes );
174     if ( !p_pes )
175     {
176         p_dec->p_fifo->b_error = 1;
177         return;
178     }
179
180     /* Compute the size of the PES - i_pes_size includes the PES header. */
181     p_data = p_pes->p_first;
182     i_size = 0;
183     while ( p_data != NULL )
184     {
185         i_size += p_data->p_payload_end - p_data->p_payload_start;
186         p_data = p_data->p_next;
187     }
188     if ( i_size < LPCM_HEADER_LEN )
189     {
190         msg_Err(p_dec->p_fifo, "PES packet is too short");
191         input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
192         return;
193     }
194
195     i_pts = p_pes->i_pts;
196     if( i_pts != 0 && i_pts != aout_DateGet( &p_dec->end_date ) )
197     {
198         aout_DateSet( &p_dec->end_date, i_pts );
199     }
200
201     p_data = p_pes->p_first;
202     /* It necessarily contains one byte. */
203     /* Get LPCM header. */
204
205     /* Drop the first four bytes. */
206     for ( i = 0; i < 4; i++ )
207     {
208         if ( p_data->p_payload_end == p_data->p_payload_start )
209         {
210             p_data = p_data->p_next;
211         }
212         p_data->p_payload_start++;
213     }
214
215     i_header = p_data->p_payload_start[0];
216     p_data->p_payload_start++;
217
218     switch ( (i_header >> 4) & 0x3 )
219     {
220     case 0:
221         i_rate = 48000;
222         break;
223     case 1:
224         i_rate = 96000;
225         break;
226     case 2:
227         i_rate = 44100;
228         break;
229     case 3:
230         i_rate = 32000;
231         break;
232     }
233
234     switch ( i_header & 0x7 )
235     {
236     case 0:
237         i_original_channels = AOUT_CHAN_CENTER;
238         break;
239     case 1:
240         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
241         break;
242     case 2:
243         /* This is unsure. */
244         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE;
245         break;
246     case 3:
247         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
248                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
249         break;
250     case 4:
251         /* This is unsure. */
252         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
253                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
254                                | AOUT_CHAN_LFE;
255         break;
256     case 5:
257         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
258                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
259                                | AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
260         break;
261     case 6:
262         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
263                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
264                                | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
265                                | AOUT_CHAN_MIDDLERIGHT;
266         break;
267     case 7:
268         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
269                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
270                                | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
271                                | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
272         break;
273     }
274
275     /* Check frame sync and drop it. */
276     if ( p_data->p_payload_end == p_data->p_payload_start )
277     {
278         p_data = p_data->p_next;
279     }
280     if ( p_data->p_payload_start[0] != 0x80 )
281     {
282         msg_Warn(p_dec->p_fifo, "no frame sync");
283         input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
284         return;
285     }
286     p_data->p_payload_start++;
287
288     if( (p_dec->p_aout_input != NULL) &&
289         ( (p_dec->output_format.i_rate != i_rate)
290             || (p_dec->output_format.i_original_channels
291                   != i_original_channels) ) )
292     {
293         /* Parameters changed - this should not happen. */
294         aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
295         p_dec->p_aout_input = NULL;
296     }
297
298     /* Creating the audio input if not created yet. */
299     if( p_dec->p_aout_input == NULL )
300     {
301         p_dec->output_format.i_rate = i_rate;
302         p_dec->output_format.i_original_channels = i_original_channels;
303         p_dec->output_format.i_physical_channels
304                    = i_original_channels & AOUT_CHAN_PHYSMASK;
305         aout_DateInit( &p_dec->end_date, i_rate );
306         aout_DateSet( &p_dec->end_date, i_pts );
307         p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
308                                            &p_dec->p_aout,
309                                            &p_dec->output_format );
310
311         if ( p_dec->p_aout_input == NULL )
312         {
313             p_dec->p_fifo->b_error = 1;
314             input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
315             return;
316         }
317
318         if ( p_dec->i_buffered_size )
319         {
320             input_DeletePES( p_dec->p_fifo->p_packets_mgt,
321                              p_dec->p_buffered_pes );
322             p_dec->i_buffered_size = 0;
323         }
324     }
325
326     if ( !aout_DateGet( &p_dec->end_date ) )
327     {
328         /* We've just started the stream, wait for the first PTS. */
329         input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
330         return;
331     }
332
333     if ( p_dec->i_buffered_size != 0 )
334     {
335         p_buffer = aout_DecNewBuffer( p_dec->p_aout, p_dec->p_aout_input,
336                 (i_size - LPCM_HEADER_LEN + p_dec->i_buffered_size)
337                     / p_dec->output_format.i_bytes_per_frame );
338
339         if( p_buffer == NULL )
340         {
341             msg_Err( p_dec->p_fifo, "cannot get aout buffer" );
342             p_dec->p_fifo->b_error = 1;
343             input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
344             return;
345         }
346         p_buffer->start_date = aout_DateGet( &p_dec->end_date );
347         p_buffer->end_date = aout_DateIncrement( &p_dec->end_date,
348                 (i_size - LPCM_HEADER_LEN + p_dec->i_buffered_size)
349                     / p_dec->output_format.i_bytes_per_frame );
350
351         /* Get the whole frame. */
352         p_dest = p_buffer->p_buffer;
353
354         while ( p_dec->p_buffered_data != NULL )
355         {
356             p_dec->p_fifo->p_vlc->pf_memcpy( p_dest,
357                     p_dec->p_buffered_data->p_payload_start,
358                     p_dec->p_buffered_data->p_payload_end
359                      - p_dec->p_buffered_data->p_payload_start );
360             p_dest += p_dec->p_buffered_data->p_payload_end
361                          - p_dec->p_buffered_data->p_payload_start;
362             p_dec->p_buffered_data = p_dec->p_buffered_data->p_next;
363         }
364         input_DeletePES( p_dec->p_fifo->p_packets_mgt,
365                          p_dec->p_buffered_pes );
366
367         p_dest = p_buffer->p_buffer + p_dec->i_buffered_size;
368
369         while ( p_data != NULL )
370         {
371             p_dec->p_fifo->p_vlc->pf_memcpy( p_dest, p_data->p_payload_start,
372                     p_data->p_payload_end - p_data->p_payload_start );
373             p_dest += p_data->p_payload_end - p_data->p_payload_start;
374             p_data = p_data->p_next;
375         }
376         input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
377
378         /* Send the buffer to the aout core. */
379         aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer );
380
381         p_dec->i_buffered_size = 0;
382     }
383     else
384     {
385         p_dec->i_buffered_size = i_size - LPCM_HEADER_LEN;
386         p_dec->p_buffered_pes = p_pes;
387         p_dec->p_buffered_data = p_data;
388     }
389 }
390
391 /*****************************************************************************
392  * EndThread : lpcm decoder thread destruction
393  *****************************************************************************/
394 static void EndThread( dec_thread_t * p_dec )
395 {
396     if( p_dec->p_aout_input != NULL )
397     {
398         aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
399     }
400
401     if ( p_dec->i_buffered_size )
402     {
403         input_DeletePES( p_dec->p_fifo->p_packets_mgt,
404                          p_dec->p_buffered_pes );
405         p_dec->i_buffered_size = 0;
406     }
407
408     free( p_dec );
409 }