]> git.sesse.net Git - vlc/blob - modules/codec/lpcm.c
Dbus control module: * Add the MprisVersion Method. * The MPRIS 1.0 implementation...
[vlc] / modules / codec / lpcm.c
1 /*****************************************************************************
2  * lpcm.c: lpcm decoder/packetizer module
3  *****************************************************************************
4  * Copyright (C) 1999-2005 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/vlc.h>
35 #include <vlc_codec.h>
36 #include <vlc_aout.h>
37
38 /*****************************************************************************
39  * decoder_sys_t : lpcm decoder descriptor
40  *****************************************************************************/
41 struct decoder_sys_t
42 {
43     /* Module mode */
44     vlc_bool_t b_packetizer;
45
46     /*
47      * Output properties
48      */
49     audio_date_t end_date;
50
51 };
52
53 /*
54  * LPCM header :
55  * - PES header
56  * - private stream ID (16 bits) == 0xA0 -> not in the bitstream
57  *
58  * - frame number (8 bits)
59  * - unknown (16 bits) == 0x0003 ?
60  * - unknown (4 bits)
61  * - current frame (4 bits)
62  * - unknown (2 bits)
63  * - frequency (2 bits) 0 == 48 kHz, 1 == 32 kHz, 2 == ?, 3 == ?
64  * - unknown (1 bit)
65  * - number of channels - 1 (3 bits) 1 == 2 channels
66  * - start code (8 bits) == 0x80
67  */
68
69 #define LPCM_HEADER_LEN 6
70
71 /*****************************************************************************
72  * Local prototypes
73  *****************************************************************************/
74 static int  OpenDecoder   ( vlc_object_t * );
75 static int  OpenPacketizer( vlc_object_t * );
76 static void CloseDecoder  ( vlc_object_t * );
77
78 static void *DecodeFrame  ( decoder_t *, block_t ** );
79
80 /*****************************************************************************
81  * Module descriptor
82  *****************************************************************************/
83 vlc_module_begin();
84
85     set_category( CAT_INPUT );
86     set_subcategory( SUBCAT_INPUT_ACODEC );
87     set_description( _("Linear PCM audio decoder") );
88     set_capability( "decoder", 100 );
89     set_callbacks( OpenDecoder, CloseDecoder );
90
91     add_submodule();
92     set_description( _("Linear PCM audio packetizer") );
93     set_capability( "packetizer", 100 );
94     set_callbacks( OpenPacketizer, CloseDecoder );
95
96 vlc_module_end();
97
98 /*****************************************************************************
99  * OpenDecoder: probe the decoder and return score
100  *****************************************************************************/
101 static int OpenDecoder( vlc_object_t *p_this )
102 {
103     decoder_t *p_dec = (decoder_t*)p_this;
104     decoder_sys_t *p_sys;
105
106     if( p_dec->fmt_in.i_codec != VLC_FOURCC('l','p','c','m')
107          && p_dec->fmt_in.i_codec != VLC_FOURCC('l','p','c','b') )
108     {
109         return VLC_EGENERIC;
110     }
111
112     /* Allocate the memory needed to store the decoder's structure */
113     if( ( p_dec->p_sys = p_sys =
114           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
115     {
116         msg_Err( p_dec, "out of memory" );
117         return VLC_EGENERIC;
118     }
119
120     /* Misc init */
121     p_sys->b_packetizer = VLC_FALSE;
122     aout_DateSet( &p_sys->end_date, 0 );
123
124     /* Set output properties */
125     p_dec->fmt_out.i_cat = AUDIO_ES;
126
127     if( p_dec->fmt_out.audio.i_bitspersample == 24 )
128     {
129         p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
130     }
131     else
132     {
133         p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b');
134         p_dec->fmt_out.audio.i_bitspersample = 16;
135     }
136
137     /* Set callback */
138     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
139         DecodeFrame;
140     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
141         DecodeFrame;
142
143     return VLC_SUCCESS;
144 }
145
146 static int OpenPacketizer( vlc_object_t *p_this )
147 {
148     decoder_t *p_dec = (decoder_t*)p_this;
149
150     int i_ret = OpenDecoder( p_this );
151
152     if( i_ret != VLC_SUCCESS ) return i_ret;
153
154     p_dec->p_sys->b_packetizer = VLC_TRUE;
155
156     p_dec->fmt_out.i_codec = VLC_FOURCC('l','p','c','m');
157
158     return i_ret;
159 }
160
161 /*****************************************************************************
162  * DecodeFrame: decodes an lpcm frame.
163  ****************************************************************************
164  * Beware, this function must be fed with complete frames (PES packet).
165  *****************************************************************************/
166 static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
167 {
168     decoder_sys_t *p_sys = p_dec->p_sys;
169     block_t       *p_block;
170     unsigned int  i_rate = 0, i_original_channels = 0, i_channels = 0;
171     int           i_frame_length, i_bitspersample;
172     uint8_t       i_header;
173
174     if( !pp_block || !*pp_block ) return NULL;
175
176     p_block = *pp_block;
177     *pp_block = NULL; /* So the packet doesn't get re-sent */
178
179     /* Date management */
180     if( p_block->i_pts > 0 &&
181         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
182     {
183         aout_DateSet( &p_sys->end_date, p_block->i_pts );
184     }
185
186     if( !aout_DateGet( &p_sys->end_date ) )
187     {
188         /* We've just started the stream, wait for the first PTS. */
189         block_Release( p_block );
190         return NULL;
191     }
192
193     if( p_block->i_buffer <= LPCM_HEADER_LEN )
194     {
195         msg_Err(p_dec, "frame is too short");
196         block_Release( p_block );
197         return NULL;
198     }
199
200     i_header = p_block->p_buffer[4];
201     switch ( (i_header >> 4) & 0x3 )
202     {
203     case 0:
204         i_rate = 48000;
205         break;
206     case 1:
207         i_rate = 96000;
208         break;
209     case 2:
210         i_rate = 44100;
211         break;
212     case 3:
213         i_rate = 32000;
214         break;
215     }
216
217     i_channels = (i_header & 0x7);
218     switch ( i_channels )
219     {
220     case 0:
221         i_original_channels = AOUT_CHAN_CENTER;
222         break;
223     case 1:
224         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
225         break;
226     case 2:
227         /* This is unsure. */
228         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE;
229         break;
230     case 3:
231         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
232                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
233         break;
234     case 4:
235         /* This is unsure. */
236         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
237                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
238                                | AOUT_CHAN_LFE;
239         break;
240     case 5:
241         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
242                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
243                                | AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
244         break;
245     case 6:
246         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
247                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
248                                | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
249                                | AOUT_CHAN_MIDDLERIGHT;
250         break;
251     case 7:
252         i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
253                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
254                                | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
255                                | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
256         break;
257     }
258
259     switch ( (i_header >> 6) & 0x3 )
260     {
261     case 2:
262         p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
263         p_dec->fmt_out.audio.i_bitspersample = 24;
264         i_bitspersample = 24;
265         break;
266     case 1:
267         p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
268         p_dec->fmt_out.audio.i_bitspersample = 24;
269         i_bitspersample = 20;
270         break;
271     case 0:
272     default:
273         p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b');
274         p_dec->fmt_out.audio.i_bitspersample = 16;
275         i_bitspersample = 16;
276         break;
277     }
278
279     /* Check frame sync and drop it. */
280     if( p_block->p_buffer[5] != 0x80 )
281     {
282         msg_Warn( p_dec, "no frame sync" );
283         block_Release( p_block );
284         return NULL;
285     }
286
287     /* Set output properties */
288     if( p_dec->fmt_out.audio.i_rate != i_rate )
289     {
290         aout_DateInit( &p_sys->end_date, i_rate );
291         aout_DateSet( &p_sys->end_date, p_block->i_pts );
292     }
293     p_dec->fmt_out.audio.i_rate = i_rate;
294     p_dec->fmt_out.audio.i_channels = i_channels + 1;
295     p_dec->fmt_out.audio.i_original_channels = i_original_channels;
296     p_dec->fmt_out.audio.i_physical_channels
297         = i_original_channels & AOUT_CHAN_PHYSMASK;
298
299     i_frame_length = (p_block->i_buffer - LPCM_HEADER_LEN) /
300         p_dec->fmt_out.audio.i_channels * 8 / i_bitspersample;
301
302     if( p_sys->b_packetizer )
303     {
304         p_dec->fmt_out.i_codec = VLC_FOURCC('l','p','c','m');
305         p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
306         p_block->i_length =
307             aout_DateIncrement( &p_sys->end_date, i_frame_length ) -
308             p_block->i_pts;
309
310         /* Just pass on the incoming frame */
311         return p_block;
312     }
313     else
314     {
315         aout_buffer_t *p_aout_buffer;
316         p_aout_buffer = p_dec->pf_aout_buffer_new( p_dec, i_frame_length );
317         if( p_aout_buffer == NULL ) return NULL;
318
319         p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
320         p_aout_buffer->end_date =
321             aout_DateIncrement( &p_sys->end_date, i_frame_length );
322
323         p_block->p_buffer += LPCM_HEADER_LEN;
324         p_block->i_buffer -= LPCM_HEADER_LEN;
325
326         /* 20/24 bits LPCM use special packing */
327         if( i_bitspersample == 24 )
328         {
329             uint8_t *p_out = p_aout_buffer->p_buffer;
330
331             while( p_block->i_buffer / 12 )
332             {
333                 /* Sample 1 */
334                 p_out[0] = p_block->p_buffer[0];
335                 p_out[1] = p_block->p_buffer[1];
336                 p_out[2] = p_block->p_buffer[8];
337                 /* Sample 2 */
338                 p_out[3] = p_block->p_buffer[2];
339                 p_out[4] = p_block->p_buffer[3];
340                 p_out[5] = p_block->p_buffer[9];
341                 /* Sample 3 */
342                 p_out[6] = p_block->p_buffer[4];
343                 p_out[7] = p_block->p_buffer[5];
344                 p_out[8] = p_block->p_buffer[10];
345                 /* Sample 4 */
346                 p_out[9] = p_block->p_buffer[6];
347                 p_out[10] = p_block->p_buffer[7];
348                 p_out[11] = p_block->p_buffer[11];
349
350                 p_block->i_buffer -= 12;
351                 p_block->p_buffer += 12;
352                 p_out += 12;
353             }
354         }
355         else if( i_bitspersample == 20 )
356         {
357             uint8_t *p_out = p_aout_buffer->p_buffer;
358
359             while( p_block->i_buffer / 10 )
360             {
361                 /* Sample 1 */
362                 p_out[0] = p_block->p_buffer[0];
363                 p_out[1] = p_block->p_buffer[1];
364                 p_out[2] = p_block->p_buffer[8] & 0xF0;
365                 /* Sample 2 */
366                 p_out[3] = p_block->p_buffer[2];
367                 p_out[4] = p_block->p_buffer[3];
368                 p_out[5] = p_block->p_buffer[8] << 4;
369                 /* Sample 3 */
370                 p_out[6] = p_block->p_buffer[4];
371                 p_out[7] = p_block->p_buffer[5];
372                 p_out[8] = p_block->p_buffer[9] & 0xF0;
373                 /* Sample 4 */
374                 p_out[9] = p_block->p_buffer[6];
375                 p_out[10] = p_block->p_buffer[7];
376                 p_out[11] = p_block->p_buffer[9] << 4;
377
378                 p_block->i_buffer -= 10;
379                 p_block->p_buffer += 10;
380                 p_out += 12;
381             }
382         }
383         else
384         {
385             memcpy( p_aout_buffer->p_buffer,
386                     p_block->p_buffer, p_block->i_buffer );
387         }
388
389         block_Release( p_block );
390         return p_aout_buffer;
391     }
392 }
393
394 /*****************************************************************************
395  * CloseDecoder : lpcm decoder destruction
396  *****************************************************************************/
397 static void CloseDecoder( vlc_object_t *p_this )
398 {
399     decoder_t *p_dec = (decoder_t*)p_this;
400     free( p_dec->p_sys );
401 }