]> git.sesse.net Git - vlc/blob - modules/codec/lpcm.c
Cosmetics (lpcm).
[vlc] / modules / codec / lpcm.c
1 /*****************************************************************************
2  * lpcm.c: lpcm decoder/packetizer module
3  *****************************************************************************
4  * Copyright (C) 1999-2008 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *          Henri Fallon <henri@videolan.org>
9  *          Christophe Massiot <massiot@via.ecp.fr>
10  *          Gildas Bazin <gbazin@videolan.org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_codec.h>
37 #include <vlc_aout.h>
38
39 /*****************************************************************************
40  * Module descriptor
41  *****************************************************************************/
42 static int  OpenDecoder   ( vlc_object_t * );
43 static int  OpenPacketizer( vlc_object_t * );
44 static void CloseCommon   ( vlc_object_t * );
45
46 vlc_module_begin ()
47
48     set_category( CAT_INPUT )
49     set_subcategory( SUBCAT_INPUT_ACODEC )
50     set_description( N_("Linear PCM audio decoder") )
51     set_capability( "decoder", 100 )
52     set_callbacks( OpenDecoder, CloseCommon )
53
54     add_submodule ()
55     set_description( N_("Linear PCM audio packetizer") )
56     set_capability( "packetizer", 100 )
57     set_callbacks( OpenPacketizer, CloseCommon )
58
59 vlc_module_end ()
60
61
62 /*****************************************************************************
63  * decoder_sys_t : lpcm decoder descriptor
64  *****************************************************************************/
65 struct decoder_sys_t
66 {
67     /* Module mode */
68     bool b_packetizer;
69
70     /*
71      * Output properties
72      */
73     audio_date_t end_date;
74
75     /* */
76     unsigned int i_header_size;
77 };
78
79 /*
80  * LPCM DVD header :
81  * - frame number (8 bits)
82  * - unknown (16 bits) == 0x0003 ?
83  * - unknown (4 bits)
84  * - current frame (4 bits)
85  * - unknown (2 bits)
86  * - frequency (2 bits) 0 == 48 kHz, 1 == 32 kHz, 2 == ?, 3 == ?
87  * - unknown (1 bit)
88  * - number of channels - 1 (3 bits) 1 == 2 channels
89  * - start code (8 bits) == 0x80
90  */
91
92 #define LPCM_DVD_HEADER_LEN (6)
93
94 /*****************************************************************************
95  * Local prototypes
96  *****************************************************************************/
97 static void *DecodeFrame  ( decoder_t *, block_t ** );
98
99 /*****************************************************************************
100  * OpenCommon:
101  *****************************************************************************/
102 static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
103 {
104     decoder_t *p_dec = (decoder_t*)p_this;
105     decoder_sys_t *p_sys;
106
107     switch( p_dec->fmt_in.i_codec )
108     {
109     case VLC_FOURCC('l','p','c','m'):
110     case VLC_FOURCC('l','p','c','b'):
111         break;
112     default:
113         return VLC_EGENERIC;
114     }
115
116     /* Allocate the memory needed to store the decoder's structure */
117     if( ( p_dec->p_sys = p_sys = malloc(sizeof(decoder_sys_t)) ) == NULL )
118         return VLC_ENOMEM;
119
120     /* Misc init */
121     p_sys->b_packetizer = b_packetizer;
122     p_sys->i_header_size = LPCM_DVD_HEADER_LEN;
123     aout_DateSet( &p_sys->end_date, 0 );
124
125     /* Set output properties */
126     p_dec->fmt_out.i_cat = AUDIO_ES;
127
128     if( b_packetizer )
129     {
130         p_dec->fmt_out.i_codec = VLC_FOURCC('l','p','c','m');
131     }
132     else
133     {
134         switch( p_dec->fmt_out.audio.i_bitspersample )
135         {
136         case 24:
137         case 20:
138             p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
139             break;
140         default:
141             p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b');
142             p_dec->fmt_out.audio.i_bitspersample = 16;
143             break;
144         }
145     }
146
147     /* Set callback */
148     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
149         DecodeFrame;
150     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
151         DecodeFrame;
152
153     return VLC_SUCCESS;
154 }
155 static int OpenDecoder( vlc_object_t *p_this )
156 {
157     return OpenCommon( p_this, false );
158 }
159 static int OpenPacketizer( vlc_object_t *p_this )
160 {
161     return OpenCommon( p_this, true );
162 }
163
164 /*****************************************************************************
165  * DecodeFrame: decodes an lpcm frame.
166  ****************************************************************************
167  * Beware, this function must be fed with complete frames (PES packet).
168  *****************************************************************************/
169 static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
170 {
171     decoder_sys_t *p_sys = p_dec->p_sys;
172     block_t       *p_block;
173     unsigned int  i_rate = 0, i_original_channels = 0, i_channels = 0;
174     int           i_frame_length, i_bitspersample;
175     uint8_t       i_header;
176
177     if( !pp_block || !*pp_block ) return NULL;
178
179     p_block = *pp_block;
180     *pp_block = NULL; /* So the packet doesn't get re-sent */
181
182     /* Date management */
183     if( p_block->i_pts > 0 &&
184         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
185     {
186         aout_DateSet( &p_sys->end_date, p_block->i_pts );
187     }
188
189     if( !aout_DateGet( &p_sys->end_date ) )
190     {
191         /* We've just started the stream, wait for the first PTS. */
192         block_Release( p_block );
193         return NULL;
194     }
195
196     if( p_block->i_buffer <= p_sys->i_header_size )
197     {
198         msg_Err(p_dec, "frame is too short");
199         block_Release( p_block );
200         return NULL;
201     }
202
203     i_header = p_block->p_buffer[4];
204     switch ( (i_header >> 4) & 0x3 )
205     {
206     case 0:
207         i_rate = 48000;
208         break;
209     case 1:
210         i_rate = 96000;
211         break;
212     case 2:
213         i_rate = 44100;
214         break;
215     case 3:
216         i_rate = 32000;
217         break;
218     }
219
220     i_channels = (i_header & 0x7);
221     switch ( i_channels )
222     {
223     case 0:
224         i_original_channels = AOUT_CHAN_CENTER;
225         break;
226     case 1:
227         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
228         break;
229     case 2:
230         /* This is unsure. */
231         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE;
232         break;
233     case 3:
234         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
235                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
236         break;
237     case 4:
238         /* This is unsure. */
239         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
240                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
241                                | AOUT_CHAN_LFE;
242         break;
243     case 5:
244         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
245                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
246                                | AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
247         break;
248     case 6:
249         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
250                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
251                                | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
252                                | AOUT_CHAN_MIDDLERIGHT;
253         break;
254     case 7:
255         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
256                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
257                                | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
258                                | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
259         break;
260     }
261
262     switch ( (i_header >> 6) & 0x3 )
263     {
264     case 2:
265         p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
266         p_dec->fmt_out.audio.i_bitspersample = 24;
267         i_bitspersample = 24;
268         break;
269     case 1:
270         p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
271         p_dec->fmt_out.audio.i_bitspersample = 24;
272         i_bitspersample = 20;
273         break;
274     case 0:
275     default:
276         p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b');
277         p_dec->fmt_out.audio.i_bitspersample = 16;
278         i_bitspersample = 16;
279         break;
280     }
281
282     /* Check frame sync and drop it. */
283     if( p_block->p_buffer[5] != 0x80 )
284     {
285         msg_Warn( p_dec, "no frame sync" );
286         block_Release( p_block );
287         return NULL;
288     }
289
290     /* Set output properties */
291     if( p_dec->fmt_out.audio.i_rate != i_rate )
292     {
293         aout_DateInit( &p_sys->end_date, i_rate );
294         aout_DateSet( &p_sys->end_date, p_block->i_pts );
295     }
296     p_dec->fmt_out.audio.i_rate = i_rate;
297     p_dec->fmt_out.audio.i_channels = i_channels + 1;
298     p_dec->fmt_out.audio.i_original_channels = i_original_channels;
299     p_dec->fmt_out.audio.i_physical_channels
300         = i_original_channels & AOUT_CHAN_PHYSMASK;
301
302     i_frame_length = (p_block->i_buffer - p_sys->i_header_size) /
303         p_dec->fmt_out.audio.i_channels * 8 / i_bitspersample;
304
305     if( p_sys->b_packetizer )
306     {
307         p_dec->fmt_out.i_codec = VLC_FOURCC('l','p','c','m');
308         p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
309         p_block->i_length =
310             aout_DateIncrement( &p_sys->end_date, i_frame_length ) -
311             p_block->i_pts;
312
313         /* Just pass on the incoming frame */
314         return p_block;
315     }
316     else
317     {
318         aout_buffer_t *p_aout_buffer;
319         p_aout_buffer = decoder_NewAudioBuffer( p_dec, i_frame_length );
320         if( p_aout_buffer == NULL ) return NULL;
321
322         p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
323         p_aout_buffer->end_date =
324             aout_DateIncrement( &p_sys->end_date, i_frame_length );
325
326         p_block->p_buffer += p_sys->i_header_size;
327         p_block->i_buffer -= p_sys->i_header_size;
328
329         /* 20/24 bits LPCM use special packing */
330         if( i_bitspersample == 24 )
331         {
332             uint8_t *p_out = p_aout_buffer->p_buffer;
333
334             while( p_block->i_buffer / 12 )
335             {
336                 /* Sample 1 */
337                 p_out[0] = p_block->p_buffer[0];
338                 p_out[1] = p_block->p_buffer[1];
339                 p_out[2] = p_block->p_buffer[8];
340                 /* Sample 2 */
341                 p_out[3] = p_block->p_buffer[2];
342                 p_out[4] = p_block->p_buffer[3];
343                 p_out[5] = p_block->p_buffer[9];
344                 /* Sample 3 */
345                 p_out[6] = p_block->p_buffer[4];
346                 p_out[7] = p_block->p_buffer[5];
347                 p_out[8] = p_block->p_buffer[10];
348                 /* Sample 4 */
349                 p_out[9] = p_block->p_buffer[6];
350                 p_out[10] = p_block->p_buffer[7];
351                 p_out[11] = p_block->p_buffer[11];
352
353                 p_block->i_buffer -= 12;
354                 p_block->p_buffer += 12;
355                 p_out += 12;
356             }
357         }
358         else if( i_bitspersample == 20 )
359         {
360             uint8_t *p_out = p_aout_buffer->p_buffer;
361
362             while( p_block->i_buffer / 10 )
363             {
364                 /* Sample 1 */
365                 p_out[0] = p_block->p_buffer[0];
366                 p_out[1] = p_block->p_buffer[1];
367                 p_out[2] = p_block->p_buffer[8] & 0xF0;
368                 /* Sample 2 */
369                 p_out[3] = p_block->p_buffer[2];
370                 p_out[4] = p_block->p_buffer[3];
371                 p_out[5] = p_block->p_buffer[8] << 4;
372                 /* Sample 3 */
373                 p_out[6] = p_block->p_buffer[4];
374                 p_out[7] = p_block->p_buffer[5];
375                 p_out[8] = p_block->p_buffer[9] & 0xF0;
376                 /* Sample 4 */
377                 p_out[9] = p_block->p_buffer[6];
378                 p_out[10] = p_block->p_buffer[7];
379                 p_out[11] = p_block->p_buffer[9] << 4;
380
381                 p_block->i_buffer -= 10;
382                 p_block->p_buffer += 10;
383                 p_out += 12;
384             }
385         }
386         else
387         {
388             memcpy( p_aout_buffer->p_buffer,
389                     p_block->p_buffer, p_block->i_buffer );
390         }
391
392         block_Release( p_block );
393         return p_aout_buffer;
394     }
395 }
396
397 /*****************************************************************************
398  * CloseCommon : lpcm decoder destruction
399  *****************************************************************************/
400 static void CloseCommon( vlc_object_t *p_this )
401 {
402     decoder_t *p_dec = (decoder_t*)p_this;
403     free( p_dec->p_sys );
404 }
405