]> git.sesse.net Git - vlc/blob - modules/codec/araw.c
Qt: ToolbarEditDialog: show tooltip on widgets list
[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
301     if( !pp_block || !*pp_block ) return NULL;
302
303     block_t *p_block = *pp_block;
304
305     if( p_block->i_pts > VLC_TS_INVALID &&
306         p_block->i_pts != date_Get( &p_sys->end_date ) )
307     {
308         date_Set( &p_sys->end_date, p_block->i_pts );
309     }
310     else if( !date_Get( &p_sys->end_date ) )
311     {
312         /* We've just started the stream, wait for the first PTS. */
313         block_Release( p_block );
314         return NULL;
315     }
316
317     /* Don't re-use the same pts twice */
318     p_block->i_pts = VLC_TS_INVALID;
319
320     unsigned samples = (8 * p_block->i_buffer) / p_sys->framebits;
321     if( samples == 0 )
322     {
323         block_Release( p_block );
324         return NULL;
325     }
326
327     /* Create chunks of max 1024 samples */
328     if( samples > 1024 ) samples = 1024;
329
330     block_t *p_out = decoder_NewAudioBuffer( p_dec, samples );
331     if( p_out == NULL )
332     {
333         block_Release( p_block );
334         return NULL;
335     }
336
337     p_out->i_pts = date_Get( &p_sys->end_date );
338     p_out->i_length = date_Increment( &p_sys->end_date, samples )
339                       - p_out->i_pts;
340
341     if( p_sys->decode != NULL )
342         p_sys->decode( p_out->p_buffer, p_block->p_buffer,
343                        samples * p_dec->fmt_in.audio.i_channels );
344     else
345         memcpy( p_out->p_buffer, p_block->p_buffer, p_out->i_buffer );
346
347     samples = (samples * p_sys->framebits) / 8;
348     p_block->p_buffer += samples;
349     p_block->i_buffer -= samples;
350
351     return p_out;
352 }
353
354 static void S8Decode( void *outp, const uint8_t *in, unsigned samples )
355 {
356     uint8_t *out = outp;
357
358     for( size_t i = 0; i < samples; i++ )
359         out[i] = in[i] ^ 0x80;
360 }
361
362 static void U16BDecode( void *outp, const uint8_t *in, unsigned samples )
363 {
364     uint16_t *out = outp;
365
366     for( size_t i = 0; i < samples; i++ )
367     {
368         *(out++) = GetWBE( in ) - 0x8000;
369         in += 2;
370     }
371 }
372
373 static void U16LDecode( void *outp, const uint8_t *in, unsigned samples )
374 {
375     uint16_t *out = outp;
376
377     for( size_t i = 0; i < samples; i++ )
378     {
379         *(out++) = GetWLE( in ) - 0x8000;
380         in += 2;
381     }
382 }
383
384 static void S16IDecode( void *out, const uint8_t *in, unsigned samples )
385 {
386     swab( in, out, samples * 2 );
387 }
388
389 static void S20BDecode( void *outp, const uint8_t *in, unsigned samples )
390 {
391     int32_t *out = outp;
392
393     while( samples >= 2 )
394     {
395         uint32_t dw = U32_AT(in);
396         in += 4;
397         *(out++) = dw & ~0xFFF;
398         *(out++) = (dw << 20) | (*in << 12);
399         in++;
400         samples -= 2;
401     }
402
403     /* No U32_AT() for the last odd sample: avoid off-by-one overflow! */
404     if( samples )
405         *(out++) = (U16_AT(in) << 16) | ((in[2] & 0xF0) << 8);
406 }
407
408 static void U24BDecode( void *outp, const uint8_t *in, unsigned samples )
409 {
410     uint32_t *out = outp;
411
412     for( size_t i = 0; i < samples; i++ )
413     {
414         uint32_t s = ((in[0] << 24) | (in[1] << 16) | (in[2] << 8)) - 0x80000000;
415         *(out++) = s;
416         in += 3;
417     }
418 }
419
420 static void U24LDecode( void *outp, const uint8_t *in, unsigned samples )
421 {
422     uint32_t *out = outp;
423
424     for( size_t i = 0; i < samples; i++ )
425     {
426         uint32_t s = ((in[2] << 24) | (in[1] << 16) | (in[0] << 8)) - 0x80000000;
427         *(out++) = s;
428         in += 3;
429     }
430 }
431
432 static void S24BDecode( void *outp, const uint8_t *in, unsigned samples )
433 {
434     uint32_t *out = outp;
435
436     for( size_t i = 0; i < samples; i++ )
437     {
438         uint32_t s = ((in[0] << 24) | (in[1] << 16) | (in[2] << 8));
439         *(out++) = s;
440         in += 3;
441     }
442 }
443
444 static void S24LDecode( void *outp, const uint8_t *in, unsigned samples )
445 {
446     uint32_t *out = outp;
447
448     for( size_t i = 0; i < samples; i++ )
449     {
450         uint32_t s = ((in[2] << 24) | (in[1] << 16) | (in[0] << 8));
451         *(out++) = s;
452         in += 3;
453     }
454 }
455
456 static void S24B32Decode( void *outp, const uint8_t *in, unsigned samples )
457 {
458     uint32_t *out = outp;
459
460     for( size_t i = 0; i < samples; i++ )
461     {
462         *(out++) = GetDWBE( in ) << 8;
463         in += 4;
464     }
465 }
466
467 static void S24L32Decode( void *outp, const uint8_t *in, unsigned samples )
468 {
469     uint32_t *out = outp;
470
471     for( size_t i = 0; i < samples; i++ )
472     {
473         *(out++) = GetDWLE( in ) << 8;
474         in += 4;
475     }
476 }
477
478 static void U32BDecode( void *outp, const uint8_t *in, unsigned samples )
479 {
480     uint32_t *out = outp;
481
482     for( size_t i = 0; i < samples; i++ )
483     {
484         *(out++) = GetDWBE( in ) - 0x80000000;
485         in += 4;
486     }
487 }
488
489 static void U32LDecode( void *outp, const uint8_t *in, unsigned samples )
490 {
491     uint32_t *out = outp;
492
493     for( size_t i = 0; i < samples; i++ )
494     {
495         *(out++) = GetDWLE( in ) - 0x80000000;
496         in += 4;
497     }
498 }
499
500 static void S32IDecode( void *outp, const uint8_t *in, unsigned samples )
501 {
502     int32_t *out = outp;
503
504     for( size_t i = 0; i < samples; i++ )
505     {
506 #ifdef WORDS_BIGENDIAN
507         *(out++) = GetDWLE( in );
508 #else
509         *(out++) = GetDWBE( in );
510 #endif
511         in += 4;
512     }
513 }
514
515 static void F32IDecode( void *outp, const uint8_t *in, unsigned samples )
516 {
517     float *out = outp;
518
519     for( size_t i = 0; i < samples; i++ )
520     {
521         union { float f; uint32_t u; } s;
522
523 #ifdef WORDS_BIGENDIAN
524         s.u = GetDWLE( in );
525 #else
526         s.u = GetDWBE( in );
527 #endif
528         *(out++) = s.f;
529         in += 4;
530     }
531 }
532
533 static void F64IDecode( void *outp, const uint8_t *in, unsigned samples )
534 {
535     double *out = outp;
536
537     for( size_t i = 0; i < samples; i++ )
538     {
539         union { double d; uint64_t u; } s;
540
541 #ifdef WORDS_BIGENDIAN
542         s.u = GetQWLE( in );
543 #else
544         s.u = GetQWBE( in );
545 #endif
546         *(out++) = s.d;
547         in += 8;
548     }
549 }
550
551 static int16_t dat12tos16( uint16_t y )
552 {
553     static const uint16_t diff[16] = {
554        0x0000, 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600,
555        0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, 0x0F00, 0x1000, 0x1000 };
556     static const uint8_t shift[16] = {
557         0, 0, 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 0, 0 };
558
559     int d = y >> 8;
560     return (y - diff[d]) << shift[d];
561 }
562
563 static void DAT12Decode( void *outp, const uint8_t *in, unsigned samples )
564 {
565     int32_t *out = outp;
566
567     while( samples >= 2 )
568     {
569         *(out++) = dat12tos16(U16_AT(in) >> 4);
570         *(out++) = dat12tos16(U16_AT(in + 1) & ~0xF000);
571         in += 3;
572         samples -= 2;
573     }
574
575     if( samples )
576         *(out++) = dat12tos16(U16_AT(in) >> 4);
577 }
578
579 /*****************************************************************************
580  * DecoderClose: decoder destruction
581  *****************************************************************************/
582 static void DecoderClose( vlc_object_t *p_this )
583 {
584     decoder_t *p_dec = (decoder_t *)p_this;
585
586     free( p_dec->p_sys );
587 }
588
589 #ifdef ENABLE_SOUT
590 /* NOTE: Output buffers are always aligned since they are allocated by the araw plugin.
591  * Contrary to the decoder, the encoder can also assume that input buffers are aligned,
592  * since decoded audio blocks must always be aligned. */
593
594 static void U16IEncode( void *outp, const uint8_t *inp, unsigned samples )
595 {
596     const uint16_t *in = (const uint16_t *)inp;
597     uint16_t *out = outp;
598
599     for( size_t i = 0; i < samples; i++ )
600         *(out++) =  bswap16( *(in++) + 0x8000 );
601 }
602
603 static void U16NEncode( void *outp, const uint8_t *inp, unsigned samples )
604 {
605     const uint16_t *in = (const uint16_t *)inp;
606     uint16_t *out = outp;
607
608     for( size_t i = 0; i < samples; i++ )
609         *(out++) =  *(in++) + 0x8000;
610 }
611
612 static void U24BEncode( void *outp, const uint8_t *inp, unsigned samples )
613 {
614     const uint32_t *in = (const uint32_t *)inp;
615     uint8_t *out = outp;
616
617     for( size_t i = 0; i < samples; i++ )
618     {
619         uint32_t s = *(in++);
620         *(out++) = (s >> 24) + 0x80;
621         *(out++) = (s >> 16);
622         *(out++) = (s >>  8);
623     }
624 }
625
626 static void U24LEncode( void *outp, const uint8_t *inp, unsigned samples )
627 {
628     const uint32_t *in = (const uint32_t *)inp;
629     uint8_t *out = outp;
630
631     for( size_t i = 0; i < samples; i++ )
632     {
633         uint32_t s = *(in++);
634         *(out++) = (s >>  8);
635         *(out++) = (s >> 16);
636         *(out++) = (s >> 24) + 0x80;
637     }
638 }
639
640 static void S24BEncode( void *outp, const uint8_t *inp, unsigned samples )
641 {
642     const uint32_t *in = (const uint32_t *)inp;
643     uint8_t *out = outp;
644
645     for( size_t i = 0; i < samples; i++ )
646     {
647         uint32_t s = *(in++);
648         *(out++) = (s >> 24);
649         *(out++) = (s >> 16);
650         *(out++) = (s >>  8);
651     }
652 }
653
654 static void S24LEncode( void *outp, const uint8_t *inp, unsigned samples )
655 {
656     const uint32_t *in = (const uint32_t *)inp;
657     uint8_t *out = outp;
658
659     for( size_t i = 0; i < samples; i++ )
660     {
661         uint32_t s = *(in++);
662         *(out++) = (s >>  8);
663         *(out++) = (s >> 16);
664         *(out++) = (s >> 24);
665     }
666 }
667
668 static void U32IEncode( void *outp, const uint8_t *inp, unsigned samples )
669 {
670     const uint32_t *in = (const uint32_t *)inp;
671     uint32_t *out = outp;
672
673     for( size_t i = 0; i < samples; i++ )
674         *(out++) =  bswap32( *(in++) + 0x80000000 );
675 }
676
677 static void U32NEncode( void *outp, const uint8_t *inp, unsigned samples )
678 {
679     const uint32_t *in = (const uint32_t *)inp;
680     uint32_t *out = outp;
681
682     for( size_t i = 0; i < samples; i++ )
683         *(out++) =  *(in++) + 0x80000000;
684 }
685
686 static void S32IEncode( void *outp, const uint8_t *inp, unsigned samples )
687 {
688     const int32_t *in = (const int32_t *)inp;
689     int32_t *out = outp;
690
691     for( size_t i = 0; i < samples; i++ )
692         *(out++) = bswap32( *(in++) );
693 }
694
695 static void F32IEncode( void *outp, const uint8_t *inp, unsigned samples )
696 {
697     const float *in = (const float *)inp;
698     uint8_t *out = outp;
699
700     for( size_t i = 0; i < samples; i++ )
701     {
702         union { float f; uint32_t u; char b[4]; } s;
703
704         s.f = *(in++);
705         s.u = bswap32( s.u );
706         memcpy( out, s.b, 4 );
707         out += 4;
708     }
709 }
710
711 static void F64IEncode( void *outp, const uint8_t *inp, unsigned samples )
712 {
713     const double *in = (const double *)inp;
714     uint8_t *out = outp;
715
716     for( size_t i = 0; i < samples; i++ )
717     {
718         union { double d; uint64_t u; char b[8]; } s;
719
720         s.d = *(in++);
721         s.u = bswap64( s.u );
722         memcpy( out, s.b, 8 );
723         out += 8;
724     }
725 }
726
727 static block_t *Encode( encoder_t *enc, block_t *in )
728 {
729     if( in == NULL )
730         return NULL;
731
732     block_t *out = block_Alloc( in->i_nb_samples
733                                 * enc->fmt_out.audio.i_bytes_per_frame );
734     if( unlikely(out == NULL) )
735         return NULL;
736
737     out->i_flags      = in->i_flags;
738     out->i_nb_samples = in->i_nb_samples;
739     out->i_dts        = in->i_dts;
740     out->i_pts        = in->i_pts;
741     out->i_length     = in->i_length;
742     out->i_nb_samples = in->i_nb_samples;
743
744     void (*encode)(void *, const uint8_t *, unsigned) = (void *)enc->p_sys;
745     if( encode != NULL )
746         encode( out->p_buffer, in->p_buffer, in->i_nb_samples
747                                              * enc->fmt_out.audio.i_channels );
748     else
749         memcpy( out->p_buffer, in->p_buffer, in->i_buffer );
750     return out;
751 }
752
753 /**
754  * Probes the PCM audio encoder.
755  */
756 static int EncoderOpen( vlc_object_t *p_this )
757 {
758     encoder_t *p_enc = (encoder_t *)p_this;
759     void (*encode)(void *, const uint8_t *, unsigned) = NULL;
760
761     switch( p_enc->fmt_out.i_codec )
762     {
763     case VLC_CODEC_S8:
764         encode = S8Decode;
765     case VLC_CODEC_U8:
766         p_enc->fmt_in.i_codec = VLC_CODEC_U8;
767         p_enc->fmt_out.audio.i_bitspersample = 8;
768         break;
769     case VLC_CODEC_U16I:
770         encode = U16IEncode;
771         p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
772         p_enc->fmt_out.audio.i_bitspersample = 16;
773         break;
774     case VLC_CODEC_U16N:
775         encode = U16NEncode;
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_S16I:
780         encode = S16IDecode;
781     case VLC_CODEC_S16N:
782         p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
783         p_enc->fmt_out.audio.i_bitspersample = 16;
784         break;
785     case VLC_CODEC_U24B:
786         encode = U24BEncode;
787         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
788         p_enc->fmt_out.audio.i_bitspersample = 24;
789         break;
790     case VLC_CODEC_U24L:
791         encode = U24LEncode;
792         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
793         p_enc->fmt_out.audio.i_bitspersample = 24;
794         break;
795     case VLC_CODEC_S24B:
796         encode = S24BEncode;
797         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
798         p_enc->fmt_out.audio.i_bitspersample = 24;
799         break;
800     case VLC_CODEC_S24L:
801         encode = S24LEncode;
802         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
803         p_enc->fmt_out.audio.i_bitspersample = 24;
804         break;
805     case VLC_CODEC_U32I:
806         encode = U32IEncode;
807         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
808         p_enc->fmt_out.audio.i_bitspersample = 32;
809         break;
810     case VLC_CODEC_U32N:
811         encode = U32NEncode;
812         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
813         p_enc->fmt_out.audio.i_bitspersample = 32;
814         break;
815     case VLC_CODEC_S32I:
816         encode = S32IEncode;
817     case VLC_CODEC_S32N:
818         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
819         p_enc->fmt_out.audio.i_bitspersample = 32;
820         break;
821 #ifdef WORDS_BIGENDIAN
822     case VLC_CODEC_F32L:
823 #else
824     case VLC_CODEC_F32B:
825 #endif
826         encode = F32IEncode;
827     case VLC_CODEC_FL32:
828         p_enc->fmt_in.i_codec = VLC_CODEC_FL32;
829         p_enc->fmt_out.audio.i_bitspersample = 32;
830         break;
831 #ifdef WORDS_BIGENDIAN
832     case VLC_CODEC_F64L:
833 #else
834     case VLC_CODEC_F64B:
835 #endif
836         encode = F64IEncode;
837     case VLC_CODEC_FL64:
838         p_enc->fmt_in.i_codec = VLC_CODEC_FL64;
839         p_enc->fmt_out.audio.i_bitspersample = 64;
840         break;
841     default:
842         return VLC_EGENERIC;
843     }
844
845     p_enc->p_sys = (void *)encode;
846     p_enc->pf_encode_audio = Encode;
847     p_enc->fmt_out.audio.i_bytes_per_frame =
848         (p_enc->fmt_out.audio.i_bitspersample / 8) *
849         p_enc->fmt_in.audio.i_channels;
850     p_enc->fmt_out.i_bitrate =
851         p_enc->fmt_in.audio.i_channels *
852         p_enc->fmt_in.audio.i_rate *
853         p_enc->fmt_out.audio.i_bitspersample;
854
855     msg_Dbg( p_enc, "samplerate:%dHz channels:%d bits/sample:%d",
856              p_enc->fmt_out.audio.i_rate, p_enc->fmt_out.audio.i_channels,
857              p_enc->fmt_out.audio.i_bitspersample );
858
859     return VLC_SUCCESS;
860 }
861 #endif /* ENABLE_SOUT */