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