]> git.sesse.net Git - vlc/blob - modules/codec/araw.c
1a99c7f4ec10bd1ef8160626acde01211d5b2146
[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
70 struct decoder_sys_t
71 {
72     void (*decode) (void *, const uint8_t *, unsigned);
73     size_t framebits;
74     date_t end_date;
75 };
76
77 static const uint16_t pi_channels_maps[] =
78 {
79     0,
80     AOUT_CHAN_CENTER, AOUT_CHANS_2_0, AOUT_CHANS_3_0,
81     AOUT_CHANS_4_0,   AOUT_CHANS_5_0, AOUT_CHANS_5_1,
82     AOUT_CHANS_7_0,   AOUT_CHANS_7_1, AOUT_CHANS_8_1,
83 };
84
85 static void S8Decode( void *, const uint8_t *, unsigned );
86 static void U16BDecode( void *, const uint8_t *, unsigned );
87 static void U16LDecode( void *, const uint8_t *, unsigned );
88 static void S16IDecode( void *, const uint8_t *, unsigned );
89 static void S20BDecode( void *, const uint8_t *, unsigned );
90 static void U24BDecode( void *, const uint8_t *, unsigned );
91 static void U24LDecode( void *, const uint8_t *, unsigned );
92 static void S24BDecode( void *, const uint8_t *, unsigned );
93 static void S24LDecode( void *, const uint8_t *, unsigned );
94 static void S24B32Decode( void *, const uint8_t *, unsigned );
95 static void S24L32Decode( void *, const uint8_t *, unsigned );
96 static void U32BDecode( void *, const uint8_t *, unsigned );
97 static void U32LDecode( void *, const uint8_t *, unsigned );
98 static void S32IDecode( void *, const uint8_t *, unsigned );
99 static void F32IDecode( void *, const uint8_t *, unsigned );
100 static void F64IDecode( void *, const uint8_t *, unsigned );
101 static void DAT12Decode( void *, const uint8_t *, unsigned );
102
103 /*****************************************************************************
104  * DecoderOpen: probe the decoder and return score
105  *****************************************************************************/
106 static int DecoderOpen( vlc_object_t *p_this )
107 {
108     decoder_t *p_dec = (decoder_t*)p_this;
109     vlc_fourcc_t format = p_dec->fmt_in.i_codec;
110
111     switch( p_dec->fmt_in.i_codec )
112     {
113     case VLC_FOURCC('a','r','a','w'):
114     case VLC_FOURCC('a','f','l','t'):
115     /* _signed_ big endian samples (mov) */
116     case VLC_FOURCC('t','w','o','s'):
117     /* _signed_ little endian samples (mov) */
118     case VLC_FOURCC('s','o','w','t'):
119         format =
120             vlc_fourcc_GetCodecAudio( p_dec->fmt_in.i_codec,
121                                       p_dec->fmt_in.audio.i_bitspersample );
122         if( !format )
123         {
124             msg_Err( p_dec, "bad parameters(bits/sample)" );
125             return VLC_EGENERIC;
126         }
127         break;
128     }
129
130     void (*decode) (void *, const uint8_t *, unsigned) = NULL;
131     uint_fast8_t bits;
132
133     switch( format )
134     {
135 #ifdef WORDS_BIGENDIAN
136     case VLC_CODEC_F64L:
137 #else
138     case VLC_CODEC_F64B:
139 #endif
140         format = VLC_CODEC_FL64;
141         decode = F64IDecode;
142     case VLC_CODEC_FL64:
143         bits = 64;
144         break;
145 #ifdef WORDS_BIGENDIAN
146     case VLC_CODEC_F32L:
147 #else
148     case VLC_CODEC_F32B:
149 #endif
150         format = VLC_CODEC_FL32;
151         decode = F32IDecode;
152     case VLC_CODEC_FL32:
153         bits = 32;
154         break;
155     case VLC_CODEC_U32B:
156         format = VLC_CODEC_S32N;
157         decode = U32BDecode;
158         bits = 32;
159         break;
160     case VLC_CODEC_U32L:
161         format = VLC_CODEC_S32N;
162         decode = U32LDecode;
163         bits = 32;
164         break;
165     case VLC_CODEC_S32I:
166         format = VLC_CODEC_S32N;
167         decode = S32IDecode;
168     case VLC_CODEC_S32N:
169         bits = 32;
170         break;
171     case VLC_CODEC_S24B32:
172         format = VLC_CODEC_S32N;
173         decode = S24B32Decode;
174         bits = 32;
175         break;
176     case VLC_CODEC_S24L32:
177         format = VLC_CODEC_S32N;
178         decode = S24L32Decode;
179         bits = 32;
180         break;
181     case VLC_CODEC_U24B:
182         format = VLC_CODEC_S32N;
183         decode = U24BDecode;
184         bits = 24;
185         break;
186     case VLC_CODEC_U24L:
187         format = VLC_CODEC_S32N;
188         decode = U24LDecode;
189         bits = 24;
190         break;
191     case VLC_CODEC_S24B:
192         format = VLC_CODEC_S32N;
193         decode = S24BDecode;
194         bits = 24;
195         break;
196     case VLC_CODEC_S24L:
197         format = VLC_CODEC_S32N;
198         decode = S24LDecode;
199         bits = 24;
200         break;
201     case VLC_CODEC_S20B:
202         format = VLC_CODEC_S32N;
203         decode = S20BDecode;
204         bits = 20;
205         break;
206     case VLC_CODEC_U16B:
207         format = VLC_CODEC_S16N;
208         decode = U16BDecode;
209         bits = 16;
210         break;
211     case VLC_CODEC_U16L:
212         format = VLC_CODEC_S16N;
213         decode = U16LDecode;
214         bits = 16;
215         break;
216     case VLC_CODEC_S16I:
217         format = VLC_CODEC_S16N;
218         decode = S16IDecode;
219     case VLC_CODEC_S16N:
220         bits = 16;
221         break;
222     case VLC_CODEC_DAT12:
223         format = VLC_CODEC_S16N;
224         decode = DAT12Decode;
225         bits = 12;
226         break;
227     case VLC_CODEC_S8:
228         decode = S8Decode;
229         format = VLC_CODEC_U8;
230     case VLC_CODEC_U8:
231         bits = 8;
232         break;
233     default:
234         return VLC_EGENERIC;
235     }
236
237     if( p_dec->fmt_in.audio.i_channels <= 0 ||
238         p_dec->fmt_in.audio.i_channels > AOUT_CHAN_MAX )
239     {
240         msg_Err( p_dec, "bad channels count (1-9): %i",
241                  p_dec->fmt_in.audio.i_channels );
242         return VLC_EGENERIC;
243     }
244
245     if( p_dec->fmt_in.audio.i_rate <= 0 )
246     {
247         msg_Err( p_dec, "bad samplerate: %d Hz", p_dec->fmt_in.audio.i_rate );
248         return VLC_EGENERIC;
249     }
250
251     msg_Dbg( p_dec, "samplerate:%dHz channels:%d bits/sample:%d",
252              p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels,
253              p_dec->fmt_in.audio.i_bitspersample );
254
255     /* Allocate the memory needed to store the decoder's structure */
256     decoder_sys_t *p_sys = malloc(sizeof(*p_sys));
257     if( unlikely(p_sys == NULL) )
258         return VLC_ENOMEM;
259
260     /* Set output properties */
261     p_dec->fmt_out.i_cat = AUDIO_ES;
262     p_dec->fmt_out.i_codec = format;
263     p_dec->fmt_out.audio.i_format = format;
264     p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
265     if( p_dec->fmt_in.audio.i_physical_channels )
266         p_dec->fmt_out.audio.i_physical_channels =
267                                        p_dec->fmt_in.audio.i_physical_channels;
268     else
269         p_dec->fmt_out.audio.i_physical_channels =
270                               pi_channels_maps[p_dec->fmt_in.audio.i_channels];
271     if( p_dec->fmt_in.audio.i_original_channels )
272         p_dec->fmt_out.audio.i_original_channels =
273                                        p_dec->fmt_in.audio.i_original_channels;
274     else
275         p_dec->fmt_out.audio.i_original_channels =
276                                       p_dec->fmt_out.audio.i_physical_channels;
277     aout_FormatPrepare( &p_dec->fmt_out.audio );
278
279     p_sys->decode = decode;
280     p_sys->framebits = bits * p_dec->fmt_out.audio.i_channels;
281     assert( p_sys->framebits );
282
283     date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
284     date_Set( &p_sys->end_date, 0 );
285
286     p_dec->pf_decode_audio = DecodeBlock;
287     p_dec->p_sys = p_sys;
288
289     return VLC_SUCCESS;
290 }
291
292 /****************************************************************************
293  * DecodeBlock: the whole thing
294  ****************************************************************************
295  * This function must be fed with whole samples (see nBlockAlign).
296  ****************************************************************************/
297 static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
298 {
299     decoder_sys_t *p_sys = p_dec->p_sys;
300     if( pp_block == NULL )
301         return NULL;
302
303     block_t *p_block = *pp_block;
304     if( p_block == NULL )
305         return NULL;
306     *pp_block = NULL;
307
308     if( p_block->i_pts > VLC_TS_INVALID &&
309         p_block->i_pts != date_Get( &p_sys->end_date ) )
310     {
311         date_Set( &p_sys->end_date, p_block->i_pts );
312     }
313     else if( !date_Get( &p_sys->end_date ) )
314         /* We've just started the stream, wait for the first PTS. */
315         goto skip;
316
317     unsigned samples = (8 * p_block->i_buffer) / p_sys->framebits;
318     if( samples == 0 )
319         goto skip;
320
321     if( p_sys->decode != NULL )
322     {
323         block_t *p_out = decoder_NewAudioBuffer( p_dec, samples );
324         if( p_out == NULL )
325             goto skip;
326
327         p_sys->decode( p_out->p_buffer, p_block->p_buffer,
328                        samples * p_dec->fmt_in.audio.i_channels );
329         block_Release( p_block );
330         p_block = p_out;
331     }
332     else
333     {
334         decoder_UpdateAudioFormat( p_dec );
335         p_block->i_nb_samples = samples;
336         p_block->i_buffer = samples * (p_sys->framebits / 8);
337     }
338
339     p_block->i_pts = date_Get( &p_sys->end_date );
340     p_block->i_length = date_Increment( &p_sys->end_date, samples )
341                       - p_block->i_pts;
342     return p_block;
343 skip:
344     block_Release( p_block );
345     return NULL;
346 }
347
348 static void S8Decode( void *outp, const uint8_t *in, unsigned samples )
349 {
350     uint8_t *out = outp;
351
352     for( size_t i = 0; i < samples; i++ )
353         out[i] = in[i] ^ 0x80;
354 }
355
356 static void U16BDecode( void *outp, const uint8_t *in, unsigned samples )
357 {
358     uint16_t *out = outp;
359
360     for( size_t i = 0; i < samples; i++ )
361     {
362         *(out++) = GetWBE( in ) - 0x8000;
363         in += 2;
364     }
365 }
366
367 static void U16LDecode( void *outp, const uint8_t *in, unsigned samples )
368 {
369     uint16_t *out = outp;
370
371     for( size_t i = 0; i < samples; i++ )
372     {
373         *(out++) = GetWLE( in ) - 0x8000;
374         in += 2;
375     }
376 }
377
378 static void S16IDecode( void *out, const uint8_t *in, unsigned samples )
379 {
380     swab( in, out, samples * 2 );
381 }
382
383 static void S20BDecode( void *outp, const uint8_t *in, unsigned samples )
384 {
385     int32_t *out = outp;
386
387     while( samples >= 2 )
388     {
389         uint32_t dw = U32_AT(in);
390         in += 4;
391         *(out++) = dw & ~0xFFF;
392         *(out++) = (dw << 20) | (*in << 12);
393         in++;
394         samples -= 2;
395     }
396
397     /* No U32_AT() for the last odd sample: avoid off-by-one overflow! */
398     if( samples )
399         *(out++) = (U16_AT(in) << 16) | ((in[2] & 0xF0) << 8);
400 }
401
402 static void U24BDecode( void *outp, const uint8_t *in, unsigned samples )
403 {
404     uint32_t *out = outp;
405
406     for( size_t i = 0; i < samples; i++ )
407     {
408         uint32_t s = ((in[0] << 24) | (in[1] << 16) | (in[2] << 8)) - 0x80000000;
409         *(out++) = s;
410         in += 3;
411     }
412 }
413
414 static void U24LDecode( void *outp, const uint8_t *in, unsigned samples )
415 {
416     uint32_t *out = outp;
417
418     for( size_t i = 0; i < samples; i++ )
419     {
420         uint32_t s = ((in[2] << 24) | (in[1] << 16) | (in[0] << 8)) - 0x80000000;
421         *(out++) = s;
422         in += 3;
423     }
424 }
425
426 static void S24BDecode( void *outp, const uint8_t *in, unsigned samples )
427 {
428     uint32_t *out = outp;
429
430     for( size_t i = 0; i < samples; i++ )
431     {
432         uint32_t s = ((in[0] << 24) | (in[1] << 16) | (in[2] << 8));
433         *(out++) = s;
434         in += 3;
435     }
436 }
437
438 static void S24LDecode( void *outp, const uint8_t *in, unsigned samples )
439 {
440     uint32_t *out = outp;
441
442     for( size_t i = 0; i < samples; i++ )
443     {
444         uint32_t s = ((in[2] << 24) | (in[1] << 16) | (in[0] << 8));
445         *(out++) = s;
446         in += 3;
447     }
448 }
449
450 static void S24B32Decode( void *outp, const uint8_t *in, unsigned samples )
451 {
452     uint32_t *out = outp;
453
454     for( size_t i = 0; i < samples; i++ )
455     {
456         *(out++) = GetDWBE( in ) << 8;
457         in += 4;
458     }
459 }
460
461 static void S24L32Decode( void *outp, const uint8_t *in, unsigned samples )
462 {
463     uint32_t *out = outp;
464
465     for( size_t i = 0; i < samples; i++ )
466     {
467         *(out++) = GetDWLE( in ) << 8;
468         in += 4;
469     }
470 }
471
472 static void U32BDecode( void *outp, const uint8_t *in, unsigned samples )
473 {
474     uint32_t *out = outp;
475
476     for( size_t i = 0; i < samples; i++ )
477     {
478         *(out++) = GetDWBE( in ) - 0x80000000;
479         in += 4;
480     }
481 }
482
483 static void U32LDecode( void *outp, const uint8_t *in, unsigned samples )
484 {
485     uint32_t *out = outp;
486
487     for( size_t i = 0; i < samples; i++ )
488     {
489         *(out++) = GetDWLE( in ) - 0x80000000;
490         in += 4;
491     }
492 }
493
494 static void S32IDecode( void *outp, const uint8_t *in, unsigned samples )
495 {
496     int32_t *out = outp;
497
498     for( size_t i = 0; i < samples; i++ )
499     {
500 #ifdef WORDS_BIGENDIAN
501         *(out++) = GetDWLE( in );
502 #else
503         *(out++) = GetDWBE( in );
504 #endif
505         in += 4;
506     }
507 }
508
509 static void F32IDecode( void *outp, const uint8_t *in, unsigned samples )
510 {
511     float *out = outp;
512
513     for( size_t i = 0; i < samples; i++ )
514     {
515         union { float f; uint32_t u; } s;
516
517 #ifdef WORDS_BIGENDIAN
518         s.u = GetDWLE( in );
519 #else
520         s.u = GetDWBE( in );
521 #endif
522         *(out++) = s.f;
523         in += 4;
524     }
525 }
526
527 static void F64IDecode( void *outp, const uint8_t *in, unsigned samples )
528 {
529     double *out = outp;
530
531     for( size_t i = 0; i < samples; i++ )
532     {
533         union { double d; uint64_t u; } s;
534
535 #ifdef WORDS_BIGENDIAN
536         s.u = GetQWLE( in );
537 #else
538         s.u = GetQWBE( in );
539 #endif
540         *(out++) = s.d;
541         in += 8;
542     }
543 }
544
545 static int16_t dat12tos16( uint16_t y )
546 {
547     static const uint16_t diff[16] = {
548        0x0000, 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600,
549        0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, 0x0F00, 0x1000, 0x1000 };
550     static const uint8_t shift[16] = {
551         0, 0, 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 0, 0 };
552
553     int d = y >> 8;
554     return (y - diff[d]) << shift[d];
555 }
556
557 static void DAT12Decode( void *outp, const uint8_t *in, unsigned samples )
558 {
559     int32_t *out = outp;
560
561     while( samples >= 2 )
562     {
563         *(out++) = dat12tos16(U16_AT(in) >> 4);
564         *(out++) = dat12tos16(U16_AT(in + 1) & ~0xF000);
565         in += 3;
566         samples -= 2;
567     }
568
569     if( samples )
570         *(out++) = dat12tos16(U16_AT(in) >> 4);
571 }
572
573 /*****************************************************************************
574  * DecoderClose: decoder destruction
575  *****************************************************************************/
576 static void DecoderClose( vlc_object_t *p_this )
577 {
578     decoder_t *p_dec = (decoder_t *)p_this;
579
580     free( p_dec->p_sys );
581 }
582
583 #ifdef ENABLE_SOUT
584 /* NOTE: Output buffers are always aligned since they are allocated by the araw plugin.
585  * Contrary to the decoder, the encoder can also assume that input buffers are aligned,
586  * since decoded audio blocks must always be aligned. */
587
588 static void U16IEncode( void *outp, const uint8_t *inp, unsigned samples )
589 {
590     const uint16_t *in = (const uint16_t *)inp;
591     uint16_t *out = outp;
592
593     for( size_t i = 0; i < samples; i++ )
594         *(out++) =  bswap16( *(in++) + 0x8000 );
595 }
596
597 static void U16NEncode( void *outp, const uint8_t *inp, unsigned samples )
598 {
599     const uint16_t *in = (const uint16_t *)inp;
600     uint16_t *out = outp;
601
602     for( size_t i = 0; i < samples; i++ )
603         *(out++) =  *(in++) + 0x8000;
604 }
605
606 static void U24BEncode( void *outp, const uint8_t *inp, unsigned samples )
607 {
608     const uint32_t *in = (const uint32_t *)inp;
609     uint8_t *out = outp;
610
611     for( size_t i = 0; i < samples; i++ )
612     {
613         uint32_t s = *(in++);
614         *(out++) = (s >> 24) + 0x80;
615         *(out++) = (s >> 16);
616         *(out++) = (s >>  8);
617     }
618 }
619
620 static void U24LEncode( void *outp, const uint8_t *inp, unsigned samples )
621 {
622     const uint32_t *in = (const uint32_t *)inp;
623     uint8_t *out = outp;
624
625     for( size_t i = 0; i < samples; i++ )
626     {
627         uint32_t s = *(in++);
628         *(out++) = (s >>  8);
629         *(out++) = (s >> 16);
630         *(out++) = (s >> 24) + 0x80;
631     }
632 }
633
634 static void S24BEncode( void *outp, const uint8_t *inp, unsigned samples )
635 {
636     const uint32_t *in = (const uint32_t *)inp;
637     uint8_t *out = outp;
638
639     for( size_t i = 0; i < samples; i++ )
640     {
641         uint32_t s = *(in++);
642         *(out++) = (s >> 24);
643         *(out++) = (s >> 16);
644         *(out++) = (s >>  8);
645     }
646 }
647
648 static void S24LEncode( void *outp, const uint8_t *inp, unsigned samples )
649 {
650     const uint32_t *in = (const uint32_t *)inp;
651     uint8_t *out = outp;
652
653     for( size_t i = 0; i < samples; i++ )
654     {
655         uint32_t s = *(in++);
656         *(out++) = (s >>  8);
657         *(out++) = (s >> 16);
658         *(out++) = (s >> 24);
659     }
660 }
661
662 static void U32IEncode( void *outp, const uint8_t *inp, unsigned samples )
663 {
664     const uint32_t *in = (const uint32_t *)inp;
665     uint32_t *out = outp;
666
667     for( size_t i = 0; i < samples; i++ )
668         *(out++) =  bswap32( *(in++) + 0x80000000 );
669 }
670
671 static void U32NEncode( void *outp, const uint8_t *inp, unsigned samples )
672 {
673     const uint32_t *in = (const uint32_t *)inp;
674     uint32_t *out = outp;
675
676     for( size_t i = 0; i < samples; i++ )
677         *(out++) =  *(in++) + 0x80000000;
678 }
679
680 static void S32IEncode( void *outp, const uint8_t *inp, unsigned samples )
681 {
682     const int32_t *in = (const int32_t *)inp;
683     int32_t *out = outp;
684
685     for( size_t i = 0; i < samples; i++ )
686         *(out++) = bswap32( *(in++) );
687 }
688
689 static void F32IEncode( void *outp, const uint8_t *inp, unsigned samples )
690 {
691     const float *in = (const float *)inp;
692     uint8_t *out = outp;
693
694     for( size_t i = 0; i < samples; i++ )
695     {
696         union { float f; uint32_t u; char b[4]; } s;
697
698         s.f = *(in++);
699         s.u = bswap32( s.u );
700         memcpy( out, s.b, 4 );
701         out += 4;
702     }
703 }
704
705 static void F64IEncode( void *outp, const uint8_t *inp, unsigned samples )
706 {
707     const double *in = (const double *)inp;
708     uint8_t *out = outp;
709
710     for( size_t i = 0; i < samples; i++ )
711     {
712         union { double d; uint64_t u; char b[8]; } s;
713
714         s.d = *(in++);
715         s.u = bswap64( s.u );
716         memcpy( out, s.b, 8 );
717         out += 8;
718     }
719 }
720
721 static block_t *Encode( encoder_t *enc, block_t *in )
722 {
723     if( in == NULL )
724         return NULL;
725
726     block_t *out = block_Alloc( in->i_nb_samples
727                                 * enc->fmt_out.audio.i_bytes_per_frame );
728     if( unlikely(out == NULL) )
729         return NULL;
730
731     out->i_flags      = in->i_flags;
732     out->i_nb_samples = in->i_nb_samples;
733     out->i_dts        = in->i_dts;
734     out->i_pts        = in->i_pts;
735     out->i_length     = in->i_length;
736     out->i_nb_samples = in->i_nb_samples;
737
738     void (*encode)(void *, const uint8_t *, unsigned) = (void *)enc->p_sys;
739     if( encode != NULL )
740         encode( out->p_buffer, in->p_buffer, in->i_nb_samples
741                                              * enc->fmt_out.audio.i_channels );
742     else
743         memcpy( out->p_buffer, in->p_buffer, in->i_buffer );
744     return out;
745 }
746
747 /**
748  * Probes the PCM audio encoder.
749  */
750 static int EncoderOpen( vlc_object_t *p_this )
751 {
752     encoder_t *p_enc = (encoder_t *)p_this;
753     void (*encode)(void *, const uint8_t *, unsigned) = NULL;
754
755     switch( p_enc->fmt_out.i_codec )
756     {
757     case VLC_CODEC_S8:
758         encode = S8Decode;
759     case VLC_CODEC_U8:
760         p_enc->fmt_in.i_codec = VLC_CODEC_U8;
761         p_enc->fmt_out.audio.i_bitspersample = 8;
762         break;
763     case VLC_CODEC_U16I:
764         encode = U16IEncode;
765         p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
766         p_enc->fmt_out.audio.i_bitspersample = 16;
767         break;
768     case VLC_CODEC_U16N:
769         encode = U16NEncode;
770         p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
771         p_enc->fmt_out.audio.i_bitspersample = 16;
772         break;
773     case VLC_CODEC_S16I:
774         encode = S16IDecode;
775     case VLC_CODEC_S16N:
776         p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
777         p_enc->fmt_out.audio.i_bitspersample = 16;
778         break;
779     case VLC_CODEC_U24B:
780         encode = U24BEncode;
781         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
782         p_enc->fmt_out.audio.i_bitspersample = 24;
783         break;
784     case VLC_CODEC_U24L:
785         encode = U24LEncode;
786         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
787         p_enc->fmt_out.audio.i_bitspersample = 24;
788         break;
789     case VLC_CODEC_S24B:
790         encode = S24BEncode;
791         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
792         p_enc->fmt_out.audio.i_bitspersample = 24;
793         break;
794     case VLC_CODEC_S24L:
795         encode = S24LEncode;
796         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
797         p_enc->fmt_out.audio.i_bitspersample = 24;
798         break;
799     case VLC_CODEC_U32I:
800         encode = U32IEncode;
801         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
802         p_enc->fmt_out.audio.i_bitspersample = 32;
803         break;
804     case VLC_CODEC_U32N:
805         encode = U32NEncode;
806         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
807         p_enc->fmt_out.audio.i_bitspersample = 32;
808         break;
809     case VLC_CODEC_S32I:
810         encode = S32IEncode;
811     case VLC_CODEC_S32N:
812         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
813         p_enc->fmt_out.audio.i_bitspersample = 32;
814         break;
815 #ifdef WORDS_BIGENDIAN
816     case VLC_CODEC_F32L:
817 #else
818     case VLC_CODEC_F32B:
819 #endif
820         encode = F32IEncode;
821     case VLC_CODEC_FL32:
822         p_enc->fmt_in.i_codec = VLC_CODEC_FL32;
823         p_enc->fmt_out.audio.i_bitspersample = 32;
824         break;
825 #ifdef WORDS_BIGENDIAN
826     case VLC_CODEC_F64L:
827 #else
828     case VLC_CODEC_F64B:
829 #endif
830         encode = F64IEncode;
831     case VLC_CODEC_FL64:
832         p_enc->fmt_in.i_codec = VLC_CODEC_FL64;
833         p_enc->fmt_out.audio.i_bitspersample = 64;
834         break;
835     default:
836         return VLC_EGENERIC;
837     }
838
839     p_enc->p_sys = (void *)encode;
840     p_enc->pf_encode_audio = Encode;
841     p_enc->fmt_out.audio.i_bytes_per_frame =
842         (p_enc->fmt_out.audio.i_bitspersample / 8) *
843         p_enc->fmt_in.audio.i_channels;
844     p_enc->fmt_out.i_bitrate =
845         p_enc->fmt_in.audio.i_channels *
846         p_enc->fmt_in.audio.i_rate *
847         p_enc->fmt_out.audio.i_bitspersample;
848
849     msg_Dbg( p_enc, "samplerate:%dHz channels:%d bits/sample:%d",
850              p_enc->fmt_out.audio.i_rate, p_enc->fmt_out.audio.i_channels,
851              p_enc->fmt_out.audio.i_bitspersample );
852
853     return VLC_SUCCESS;
854 }
855 #endif /* ENABLE_SOUT */