]> git.sesse.net Git - vlc/blob - modules/codec/araw.c
araw: remove G.711 and fix leak of p_enc->p_sys
[vlc] / modules / codec / araw.c
1 /*****************************************************************************
2  * araw.c: Pseudo audio decoder; for raw pcm data
3  *****************************************************************************
4  * Copyright (C) 2001, 2003 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <assert.h>
32
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
36 #include <vlc_aout.h>
37
38 /*****************************************************************************
39  * Module descriptor
40  *****************************************************************************/
41 static int  DecoderOpen ( vlc_object_t * );
42 static void DecoderClose( vlc_object_t * );
43
44 #ifdef ENABLE_SOUT
45 static int  EncoderOpen ( vlc_object_t * );
46 #endif
47
48 vlc_module_begin ()
49     /* audio decoder module */
50     set_description( N_("Raw/Log Audio decoder") )
51     set_capability( "decoder", 100 )
52     set_category( CAT_INPUT )
53     set_subcategory( SUBCAT_INPUT_ACODEC )
54     set_callbacks( DecoderOpen, DecoderClose )
55
56 #ifdef ENABLE_SOUT
57     /* audio encoder submodule */
58     add_submodule ()
59     set_description( N_("Raw audio encoder") )
60     set_capability( "encoder", 150 )
61     set_callbacks( EncoderOpen, NULL )
62 #endif
63 vlc_module_end ()
64
65 /*****************************************************************************
66  * Local prototypes
67  *****************************************************************************/
68 static block_t *DecodeBlock( decoder_t *, block_t ** );
69 #ifdef ENABLE_SOUT
70 static block_t *EncoderEncode( encoder_t *, block_t * );
71 #endif
72
73 struct decoder_sys_t
74 {
75     void (*decode) (void *, const uint8_t *, unsigned);
76     size_t framebits;
77     date_t end_date;
78 };
79
80 static const uint16_t pi_channels_maps[] =
81 {
82     0,
83     AOUT_CHAN_CENTER, AOUT_CHANS_2_0, AOUT_CHANS_3_0,
84     AOUT_CHANS_4_0,   AOUT_CHANS_5_0, AOUT_CHANS_5_1,
85     AOUT_CHANS_7_0,   AOUT_CHANS_7_1, AOUT_CHANS_8_1,
86 };
87
88 static void DecodeS20B( void *, const uint8_t *, unsigned );
89 static void DecodeDAT12( void *, const uint8_t *, unsigned );
90
91 /*****************************************************************************
92  * DecoderOpen: probe the decoder and return score
93  *****************************************************************************/
94 static int DecoderOpen( vlc_object_t *p_this )
95 {
96     decoder_t *p_dec = (decoder_t*)p_this;
97     vlc_fourcc_t format = p_dec->fmt_in.i_codec;
98
99     switch( p_dec->fmt_in.i_codec )
100     {
101     case VLC_FOURCC('a','r','a','w'):
102     case VLC_FOURCC('p','c','m',' '):
103     case VLC_FOURCC('a','f','l','t'):
104     /* _signed_ big endian samples (mov) */
105     case VLC_FOURCC('t','w','o','s'):
106     /* _signed_ little endian samples (mov) */
107     case VLC_FOURCC('s','o','w','t'):
108         format =
109             vlc_fourcc_GetCodecAudio( p_dec->fmt_in.i_codec,
110                                       p_dec->fmt_in.audio.i_bitspersample );
111         if( !format )
112         {
113             msg_Err( p_dec, "bad parameters(bits/sample)" );
114             return VLC_EGENERIC;
115         }
116         break;
117     }
118
119     void (*decode) (void *, const uint8_t *, unsigned) = NULL;
120     uint_fast8_t bits;
121
122     switch( format )
123     {
124     case VLC_CODEC_F64L:
125     case VLC_CODEC_F64B:
126         bits = 64;
127         break;
128     case VLC_CODEC_F32L:
129     case VLC_CODEC_F32B:
130     case VLC_CODEC_S32L:
131     case VLC_CODEC_S32B:
132         bits = 32;
133         break;
134     case VLC_CODEC_S24L:
135     case VLC_CODEC_S24B:
136         bits = 24;
137         break;
138     case VLC_CODEC_S20B:
139         format = VLC_CODEC_S32N;
140         decode = DecodeS20B;
141         bits = 20;
142         break;
143     case VLC_CODEC_S16L:
144     case VLC_CODEC_S16B:
145         bits = 16;
146         break;
147     case VLC_CODEC_DAT12:
148         format = VLC_CODEC_S16N;
149         decode = DecodeDAT12;
150         bits = 12;
151         break;
152     case VLC_CODEC_S8:
153     case VLC_CODEC_U8:
154         bits = 8;
155         break;
156     default:
157         return VLC_EGENERIC;
158     }
159
160     if( p_dec->fmt_in.audio.i_channels <= 0 ||
161         p_dec->fmt_in.audio.i_channels > AOUT_CHAN_MAX )
162     {
163         msg_Err( p_dec, "bad channels count (1-9): %i",
164                  p_dec->fmt_in.audio.i_channels );
165         return VLC_EGENERIC;
166     }
167
168     if( p_dec->fmt_in.audio.i_rate <= 0 )
169     {
170         msg_Err( p_dec, "bad samplerate: %d Hz", p_dec->fmt_in.audio.i_rate );
171         return VLC_EGENERIC;
172     }
173
174     msg_Dbg( p_dec, "samplerate:%dHz channels:%d bits/sample:%d",
175              p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels,
176              p_dec->fmt_in.audio.i_bitspersample );
177
178     /* Allocate the memory needed to store the decoder's structure */
179     decoder_sys_t *p_sys = malloc(sizeof(*p_sys));
180     if( unlikely(p_sys == NULL) )
181         return VLC_ENOMEM;
182
183     /* Set output properties */
184     p_dec->fmt_out.i_cat = AUDIO_ES;
185     p_dec->fmt_out.i_codec = format;
186     p_dec->fmt_out.audio.i_format = format;
187     p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
188     if( p_dec->fmt_in.audio.i_physical_channels )
189         p_dec->fmt_out.audio.i_physical_channels =
190                                        p_dec->fmt_in.audio.i_physical_channels;
191     else
192         p_dec->fmt_out.audio.i_physical_channels =
193                               pi_channels_maps[p_dec->fmt_in.audio.i_channels];
194     if( p_dec->fmt_in.audio.i_original_channels )
195         p_dec->fmt_out.audio.i_original_channels =
196                                        p_dec->fmt_in.audio.i_original_channels;
197     else
198         p_dec->fmt_out.audio.i_original_channels =
199                                       p_dec->fmt_out.audio.i_physical_channels;
200     aout_FormatPrepare( &p_dec->fmt_out.audio );
201
202     p_sys->decode = decode;
203     p_sys->framebits = bits * p_dec->fmt_out.audio.i_channels;
204     assert( p_sys->framebits );
205
206     date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
207     date_Set( &p_sys->end_date, 0 );
208
209     p_dec->pf_decode_audio = DecodeBlock;
210     p_dec->p_sys = p_sys;
211
212     return VLC_SUCCESS;
213 }
214
215 /****************************************************************************
216  * DecodeBlock: the whole thing
217  ****************************************************************************
218  * This function must be fed with whole samples (see nBlockAlign).
219  ****************************************************************************/
220 static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
221 {
222     decoder_sys_t *p_sys = p_dec->p_sys;
223
224     if( !pp_block || !*pp_block ) return NULL;
225
226     block_t *p_block = *pp_block;
227
228     if( p_block->i_pts > VLC_TS_INVALID &&
229         p_block->i_pts != date_Get( &p_sys->end_date ) )
230     {
231         date_Set( &p_sys->end_date, p_block->i_pts );
232     }
233     else if( !date_Get( &p_sys->end_date ) )
234     {
235         /* We've just started the stream, wait for the first PTS. */
236         block_Release( p_block );
237         return NULL;
238     }
239
240     /* Don't re-use the same pts twice */
241     p_block->i_pts = VLC_TS_INVALID;
242
243     unsigned samples = (8 * p_block->i_buffer) / p_sys->framebits;
244     if( samples == 0 )
245     {
246         block_Release( p_block );
247         return NULL;
248     }
249
250     /* Create chunks of max 1024 samples */
251     if( samples > 1024 ) samples = 1024;
252
253     block_t *p_out = decoder_NewAudioBuffer( p_dec, samples );
254     if( p_out == NULL )
255     {
256         block_Release( p_block );
257         return NULL;
258     }
259
260     p_out->i_pts = date_Get( &p_sys->end_date );
261     p_out->i_length = date_Increment( &p_sys->end_date, samples )
262                       - p_out->i_pts;
263
264     if( p_sys->decode != NULL )
265         p_sys->decode( p_out->p_buffer, p_block->p_buffer,
266                        samples * p_dec->fmt_in.audio.i_channels );
267     else
268         memcpy( p_out->p_buffer, p_block->p_buffer, p_out->i_buffer );
269
270     samples = (samples * p_sys->framebits) / 8;
271     p_block->p_buffer += samples;
272     p_block->i_buffer -= samples;
273
274     return p_out;
275 }
276
277 static void DecodeS20B( void *outp, const uint8_t *in, unsigned samples )
278 {
279     int32_t *out = outp;
280
281     while( samples >= 2 )
282     {
283         uint32_t dw = U32_AT(in);
284         in += 4;
285         *(out++) = dw & ~0xFFF;
286         *(out++) = (dw << 20) | (*in << 12);
287         in++;
288         samples -= 2;
289     }
290
291     /* No U32_AT() for the last odd sample: avoid off-by-one overflow! */
292     if( samples )
293         *(out++) = (U16_AT(in) << 16) | ((in[2] & 0xF0) << 8);
294 }
295
296 static int16_t dat12tos16( uint16_t y )
297 {
298     static const uint16_t diff[16] = {
299        0x0000, 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600,
300        0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, 0x0F00, 0x1000, 0x1000 };
301     static const uint8_t shift[16] = {
302         0, 0, 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 0, 0 };
303
304     int d = y >> 8;
305     return (y - diff[d]) << shift[d];
306 }
307
308 static void DecodeDAT12( void *outp, const uint8_t *in, unsigned samples )
309 {
310     int32_t *out = outp;
311
312     while( samples >= 2 )
313     {
314         *(out++) = dat12tos16(U16_AT(in) >> 4);
315         *(out++) = dat12tos16(U16_AT(in + 1) & ~0xF000);
316         in += 3;
317         samples -= 2;
318     }
319
320     if( samples )
321         *(out++) = dat12tos16(U16_AT(in) >> 4);
322 }
323
324 /*****************************************************************************
325  * DecoderClose: decoder destruction
326  *****************************************************************************/
327 static void DecoderClose( vlc_object_t *p_this )
328 {
329     decoder_t *p_dec = (decoder_t *)p_this;
330
331     free( p_dec->p_sys );
332 }
333
334 #ifdef ENABLE_SOUT
335 /*****************************************************************************
336  * EncoderOpen:
337  *****************************************************************************/
338 static int EncoderOpen( vlc_object_t *p_this )
339 {
340     encoder_t *p_enc = (encoder_t *)p_this;
341
342     if( p_enc->fmt_out.i_codec == VLC_CODEC_U8 ||
343         p_enc->fmt_out.i_codec == VLC_CODEC_S8 )
344     {
345         p_enc->fmt_out.audio.i_bitspersample = 8;
346     }
347     else if( p_enc->fmt_out.i_codec == VLC_CODEC_U16L ||
348              p_enc->fmt_out.i_codec == VLC_CODEC_U16B ||
349              p_enc->fmt_out.i_codec == VLC_CODEC_S16L ||
350              p_enc->fmt_out.i_codec == VLC_CODEC_S16B )
351     {
352         p_enc->fmt_out.audio.i_bitspersample = 16;
353     }
354     else if( p_enc->fmt_out.i_codec == VLC_CODEC_U24L ||
355              p_enc->fmt_out.i_codec == VLC_CODEC_U24B ||
356              p_enc->fmt_out.i_codec == VLC_CODEC_S24L ||
357              p_enc->fmt_out.i_codec == VLC_CODEC_S24B )
358     {
359         p_enc->fmt_out.audio.i_bitspersample = 24;
360     }
361     else if( p_enc->fmt_out.i_codec == VLC_CODEC_U32L ||
362              p_enc->fmt_out.i_codec == VLC_CODEC_U32B ||
363              p_enc->fmt_out.i_codec == VLC_CODEC_S32L ||
364              p_enc->fmt_out.i_codec == VLC_CODEC_S32B ||
365              p_enc->fmt_out.i_codec == VLC_CODEC_FL32 )
366     {
367         p_enc->fmt_out.audio.i_bitspersample = 32;
368     }
369     else if( p_enc->fmt_out.i_codec == VLC_CODEC_FL64 )
370     {
371         p_enc->fmt_out.audio.i_bitspersample = 64;
372     }
373     else
374     {
375         return VLC_EGENERIC;
376     }
377
378     p_enc->pf_encode_audio = EncoderEncode;
379     p_enc->fmt_in.i_codec = p_enc->fmt_out.i_codec;
380     p_enc->fmt_out.i_bitrate =
381         p_enc->fmt_in.audio.i_channels *
382         p_enc->fmt_in.audio.i_rate *
383         p_enc->fmt_in.audio.i_bitspersample;
384
385     msg_Dbg( p_enc, "samplerate:%dHz channels:%d bits/sample:%d",
386              p_enc->fmt_out.audio.i_rate, p_enc->fmt_out.audio.i_channels,
387              p_enc->fmt_out.audio.i_bitspersample );
388
389     return VLC_SUCCESS;
390 }
391
392 /*****************************************************************************
393  * EncoderEncode:
394  *****************************************************************************/
395 static block_t *EncoderEncode( encoder_t *p_enc, block_t *p_aout_buf )
396 {
397     (void) p_enc;
398     return block_Duplicate(p_aout_buf);
399 }
400 #endif /* ENABLE_SOUT */