Coverage Report

Created: 2025-08-25 06:17

/src/vlc/modules/codec/araw.c
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
 * araw.c: Pseudo audio decoder; for raw pcm data
3
 *****************************************************************************
4
 * Copyright (C) 2001, 2003 VLC authors and VideoLAN
5
 *
6
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program; if not, write to the Free Software Foundation,
20
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21
 *****************************************************************************/
22
23
/*****************************************************************************
24
 * Preamble
25
 *****************************************************************************/
26
#ifdef HAVE_CONFIG_H
27
# include "config.h"
28
#endif
29
30
#include <math.h>
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
43
#ifdef ENABLE_SOUT
44
static int  EncoderOpen ( vlc_object_t * );
45
#endif
46
47
4
vlc_module_begin ()
48
    /* audio decoder module */
49
2
    set_description( N_("Raw/Log Audio decoder") )
50
2
    set_capability( "audio decoder", 100 )
51
2
    set_subcategory( SUBCAT_INPUT_ACODEC )
52
2
    set_callback( DecoderOpen )
53
54
2
#ifdef ENABLE_SOUT
55
    /* audio encoder submodule */
56
2
    add_submodule ()
57
2
    set_description( N_("Raw audio encoder") )
58
2
    set_capability( "audio encoder", 150 )
59
2
    set_callback( EncoderOpen )
60
2
#endif
61
2
vlc_module_end ()
62
63
/*****************************************************************************
64
 * Local prototypes
65
 *****************************************************************************/
66
static int DecodeBlock( decoder_t *, block_t * );
67
static void Flush( decoder_t * );
68
69
typedef struct
70
{
71
    void (*decode) (void *, const uint8_t *, unsigned);
72
    size_t framebits;
73
    date_t end_date;
74
} decoder_sys_t;
75
76
static void S8Decode( void *, const uint8_t *, unsigned );
77
static void U16BDecode( void *, const uint8_t *, unsigned );
78
static void U16LDecode( void *, const uint8_t *, unsigned );
79
static void S16IDecode( void *, const uint8_t *, unsigned );
80
static void S20BDecode( void *, const uint8_t *, unsigned );
81
static void U24BDecode( void *, const uint8_t *, unsigned );
82
static void U24LDecode( void *, const uint8_t *, unsigned );
83
static void S24BDecode( void *, const uint8_t *, unsigned );
84
static void S24LDecode( void *, const uint8_t *, unsigned );
85
static void S24B32Decode( void *, const uint8_t *, unsigned );
86
static void S24L32Decode( void *, const uint8_t *, unsigned );
87
static void U32BDecode( void *, const uint8_t *, unsigned );
88
static void U32LDecode( void *, const uint8_t *, unsigned );
89
static void S32IDecode( void *, const uint8_t *, unsigned );
90
static void F32NDecode( void *, const uint8_t *, unsigned );
91
static void F32IDecode( void *, const uint8_t *, unsigned );
92
static void F64NDecode( void *, const uint8_t *, unsigned );
93
static void F64IDecode( void *, const uint8_t *, unsigned );
94
static void DAT12Decode( void *, const uint8_t *, unsigned );
95
96
/*****************************************************************************
97
 * DecoderOpen: probe the decoder and return score
98
 *****************************************************************************/
99
static int DecoderOpen( vlc_object_t *p_this )
100
0
{
101
0
    decoder_t *p_dec = (decoder_t*)p_this;
102
0
    vlc_fourcc_t format = p_dec->fmt_in->i_codec;
103
104
0
    switch( p_dec->fmt_in->i_codec )
105
0
    {
106
0
    case VLC_FOURCC('a','r','a','w'):
107
0
    case VLC_FOURCC('a','f','l','t'):
108
    /* _signed_ big endian samples (mov) */
109
0
    case VLC_FOURCC('t','w','o','s'):
110
    /* _signed_ little endian samples (mov) */
111
0
    case VLC_FOURCC('s','o','w','t'):
112
0
        format =
113
0
            vlc_fourcc_GetCodecAudio( p_dec->fmt_in->i_codec,
114
0
                                      p_dec->fmt_in->audio.i_bitspersample );
115
0
        if( !format )
116
0
        {
117
0
            msg_Err( p_dec, "bad parameters(bits/sample)" );
118
0
            return VLC_EGENERIC;
119
0
        }
120
0
        break;
121
0
    }
122
123
0
    void (*decode) (void *, const uint8_t *, unsigned) = NULL;
124
0
    uint_fast8_t bits;
125
126
0
    switch( format )
127
0
    {
128
#ifdef WORDS_BIGENDIAN
129
    case VLC_CODEC_F64L:
130
#else
131
0
    case VLC_CODEC_F64B:
132
0
#endif
133
0
        format = VLC_CODEC_FL64;
134
0
        decode = F64IDecode;
135
0
        bits = 64;
136
0
        break;
137
0
    case VLC_CODEC_FL64:
138
0
        decode = F64NDecode;
139
0
        bits = 64;
140
0
        break;
141
#ifdef WORDS_BIGENDIAN
142
    case VLC_CODEC_F32L:
143
#else
144
0
    case VLC_CODEC_F32B:
145
0
#endif
146
0
        format = VLC_CODEC_FL32;
147
0
        decode = F32IDecode;
148
0
        bits = 32;
149
0
        break;
150
0
    case VLC_CODEC_FL32:
151
0
        decode = F32NDecode;
152
0
        bits = 32;
153
0
        break;
154
0
    case VLC_CODEC_U32B:
155
0
        format = VLC_CODEC_S32N;
156
0
        decode = U32BDecode;
157
0
        bits = 32;
158
0
        break;
159
0
    case VLC_CODEC_U32L:
160
0
        format = VLC_CODEC_S32N;
161
0
        decode = U32LDecode;
162
0
        bits = 32;
163
0
        break;
164
0
    case VLC_CODEC_S32I:
165
0
        format = VLC_CODEC_S32N;
166
0
        decode = S32IDecode;
167
        /* fall through */
168
0
    case VLC_CODEC_S32N:
169
0
        bits = 32;
170
0
        break;
171
0
    case VLC_CODEC_S24B32:
172
0
        format = VLC_CODEC_S32N;
173
0
        decode = S24B32Decode;
174
0
        bits = 32;
175
0
        break;
176
0
    case VLC_CODEC_S24L32:
177
0
        format = VLC_CODEC_S32N;
178
0
        decode = S24L32Decode;
179
0
        bits = 32;
180
0
        break;
181
0
    case VLC_CODEC_U24B:
182
0
        format = VLC_CODEC_S32N;
183
0
        decode = U24BDecode;
184
0
        bits = 24;
185
0
        break;
186
0
    case VLC_CODEC_U24L:
187
0
        format = VLC_CODEC_S32N;
188
0
        decode = U24LDecode;
189
0
        bits = 24;
190
0
        break;
191
0
    case VLC_CODEC_S24B:
192
0
        format = VLC_CODEC_S32N;
193
0
        decode = S24BDecode;
194
0
        bits = 24;
195
0
        break;
196
0
    case VLC_CODEC_S24L:
197
0
        format = VLC_CODEC_S32N;
198
0
        decode = S24LDecode;
199
0
        bits = 24;
200
0
        break;
201
0
    case VLC_CODEC_S20B:
202
0
        format = VLC_CODEC_S32N;
203
0
        decode = S20BDecode;
204
0
        bits = 20;
205
0
        break;
206
0
    case VLC_CODEC_U16B:
207
0
        format = VLC_CODEC_S16N;
208
0
        decode = U16BDecode;
209
0
        bits = 16;
210
0
        break;
211
0
    case VLC_CODEC_U16L:
212
0
        format = VLC_CODEC_S16N;
213
0
        decode = U16LDecode;
214
0
        bits = 16;
215
0
        break;
216
0
    case VLC_CODEC_S16I:
217
0
        format = VLC_CODEC_S16N;
218
0
        decode = S16IDecode;
219
        /* fall through */
220
0
    case VLC_CODEC_S16N:
221
0
        bits = 16;
222
0
        break;
223
0
    case VLC_CODEC_DAT12:
224
0
        format = VLC_CODEC_S16N;
225
0
        decode = DAT12Decode;
226
0
        bits = 12;
227
0
        break;
228
0
    case VLC_CODEC_S8:
229
0
        decode = S8Decode;
230
0
        format = VLC_CODEC_U8;
231
        /* fall through */
232
0
    case VLC_CODEC_U8:
233
0
        bits = 8;
234
0
        break;
235
0
    default:
236
0
        return VLC_EGENERIC;
237
0
    }
238
239
0
    if( p_dec->fmt_in->audio.i_channels == 0 ||
240
0
        p_dec->fmt_in->audio.i_channels > INPUT_CHAN_MAX )
241
0
    {
242
0
        msg_Err( p_dec, "bad channels count (1-%i): %i",
243
0
                 AOUT_CHAN_MAX, p_dec->fmt_in->audio.i_channels );
244
0
        return VLC_EGENERIC;
245
0
    }
246
247
0
    if( p_dec->fmt_in->audio.i_rate == 0 || p_dec->fmt_in->audio.i_rate > 384000 )
248
0
    {
249
0
        msg_Err( p_dec, "bad samplerate: %d Hz", p_dec->fmt_in->audio.i_rate );
250
0
        return VLC_EGENERIC;
251
0
    }
252
253
0
    msg_Dbg( p_dec, "samplerate:%dHz channels:%d bits/sample:%d",
254
0
             p_dec->fmt_in->audio.i_rate, p_dec->fmt_in->audio.i_channels,
255
0
             p_dec->fmt_in->audio.i_bitspersample );
256
257
    /* Allocate the memory needed to store the decoder's structure */
258
0
    decoder_sys_t *p_sys = vlc_obj_malloc(p_this, sizeof(*p_sys));
259
0
    if( unlikely(p_sys == NULL) )
260
0
        return VLC_ENOMEM;
261
262
    /* Set output properties */
263
0
    p_dec->fmt_out.i_codec = format;
264
0
    p_dec->fmt_out.audio.channel_type = p_dec->fmt_in->audio.channel_type;
265
0
    p_dec->fmt_out.audio.i_format = format;
266
0
    p_dec->fmt_out.audio.i_rate = p_dec->fmt_in->audio.i_rate;
267
0
    if( p_dec->fmt_in->audio.i_channels < ARRAY_SIZE(vlc_chan_maps) )
268
0
    {
269
0
        if( p_dec->fmt_in->audio.i_physical_channels )
270
0
            p_dec->fmt_out.audio.i_physical_channels =
271
0
                                           p_dec->fmt_in->audio.i_physical_channels;
272
0
        else
273
0
            p_dec->fmt_out.audio.i_physical_channels =
274
0
                vlc_chan_maps[p_dec->fmt_in->audio.i_channels];
275
0
    }
276
0
    else
277
0
    {
278
        /* Unknown channel map, let the aout/filters decide what to do */
279
0
        p_dec->fmt_out.audio.i_channels = p_dec->fmt_in->audio.i_channels;
280
0
        p_dec->fmt_out.audio.i_physical_channels = 0;
281
0
    }
282
0
    aout_FormatPrepare( &p_dec->fmt_out.audio );
283
284
0
    p_sys->decode = decode;
285
0
    p_sys->framebits = bits * p_dec->fmt_out.audio.i_channels;
286
0
    assert( p_sys->framebits );
287
288
0
    date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
289
290
0
    p_dec->pf_decode = DecodeBlock;
291
0
    p_dec->pf_flush  = Flush;
292
0
    p_dec->p_sys = p_sys;
293
294
0
    return VLC_SUCCESS;
295
0
}
296
297
/*****************************************************************************
298
 * Flush:
299
 *****************************************************************************/
300
static void Flush( decoder_t *p_dec )
301
0
{
302
0
    decoder_sys_t *p_sys = p_dec->p_sys;
303
304
0
    date_Set( &p_sys->end_date, VLC_TICK_INVALID );
305
0
}
306
307
/****************************************************************************
308
 * DecodeBlock: the whole thing
309
 ****************************************************************************
310
 * This function must be fed with whole samples (see nBlockAlign).
311
 ****************************************************************************/
312
static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
313
0
{
314
0
    decoder_sys_t *p_sys = p_dec->p_sys;
315
0
    if( p_block == NULL ) /* No Drain */
316
0
        return VLCDEC_SUCCESS;
317
318
0
    if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED|BLOCK_FLAG_DISCONTINUITY) )
319
0
    {
320
0
        Flush( p_dec );
321
0
        if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
322
0
            goto skip;
323
0
    }
324
325
0
    if( p_block->i_pts != VLC_TICK_INVALID &&
326
0
        p_block->i_pts != date_Get( &p_sys->end_date ) )
327
0
    {
328
0
        date_Set( &p_sys->end_date, p_block->i_pts );
329
0
    }
330
0
    else if( date_Get( &p_sys->end_date ) == VLC_TICK_INVALID )
331
        /* We've just started the stream, wait for the first PTS. */
332
0
        goto skip;
333
334
0
    unsigned samples = (8 * p_block->i_buffer) / p_sys->framebits;
335
0
    if( samples == 0 )
336
0
        goto skip;
337
338
0
    if( p_sys->decode != NULL )
339
0
    {
340
0
        if( decoder_UpdateAudioFormat( p_dec ) )
341
0
            goto skip;
342
0
        block_t *p_out = decoder_NewAudioBuffer( p_dec, samples );
343
0
        if( p_out == NULL )
344
0
            goto skip;
345
346
0
        p_sys->decode( p_out->p_buffer, p_block->p_buffer,
347
0
                       samples * p_dec->fmt_in->audio.i_channels );
348
0
        block_Release( p_block );
349
0
        p_block = p_out;
350
0
    }
351
0
    else
352
0
    {
353
0
        if( decoder_UpdateAudioFormat( p_dec ) )
354
0
            goto skip;
355
0
        p_block->i_nb_samples = samples;
356
0
        p_block->i_buffer = samples * (p_sys->framebits / 8);
357
0
    }
358
359
0
    p_block->i_pts = date_Get( &p_sys->end_date );
360
0
    p_block->i_length = date_Increment( &p_sys->end_date, samples )
361
0
                      - p_block->i_pts;
362
0
    decoder_QueueAudio( p_dec, p_block );
363
0
    return VLCDEC_SUCCESS;
364
0
skip:
365
0
    block_Release( p_block );
366
0
    return VLCDEC_SUCCESS;
367
0
}
368
369
static void S8Decode( void *outp, const uint8_t *in, unsigned samples )
370
0
{
371
0
    uint8_t *out = outp;
372
373
0
    for( size_t i = 0; i < samples; i++ )
374
0
        out[i] = in[i] ^ 0x80;
375
0
}
376
377
static void U16BDecode( void *outp, const uint8_t *in, unsigned samples )
378
0
{
379
0
    uint16_t *out = outp;
380
381
0
    for( size_t i = 0; i < samples; i++ )
382
0
    {
383
0
        *(out++) = GetWBE( in ) - 0x8000;
384
0
        in += 2;
385
0
    }
386
0
}
387
388
static void U16LDecode( void *outp, const uint8_t *in, unsigned samples )
389
0
{
390
0
    uint16_t *out = outp;
391
392
0
    for( size_t i = 0; i < samples; i++ )
393
0
    {
394
0
        *(out++) = GetWLE( in ) - 0x8000;
395
0
        in += 2;
396
0
    }
397
0
}
398
399
static void S16IDecode( void *out, const uint8_t *in, unsigned samples )
400
0
{
401
0
    swab( in, out, samples * 2 );
402
0
}
403
404
static void S20BDecode( void *outp, const uint8_t *in, unsigned samples )
405
0
{
406
0
    int32_t *out = outp;
407
408
0
    while( samples >= 2 )
409
0
    {
410
0
        uint32_t dw = U32_AT(in);
411
0
        in += 4;
412
0
        *(out++) = dw & ~0xFFF;
413
0
        *(out++) = (dw << 20) | (*in << 12);
414
0
        in++;
415
0
        samples -= 2;
416
0
    }
417
418
    /* No U32_AT() for the last odd sample: avoid off-by-one overflow! */
419
0
    if( samples )
420
0
        *(out++) = (U16_AT(in) << 16) | ((in[2] & 0xF0) << 8);
421
0
}
422
423
static void U24BDecode( void *outp, const uint8_t *in, unsigned samples )
424
0
{
425
0
    int32_t *out = outp;
426
0
    union { int32_t s; uint32_t u; } u;
427
428
0
    for( size_t i = 0; i < samples; i++ )
429
0
    {
430
0
        uint_fast32_t hi = in[0], mid = in[1], lo = in[2];
431
432
0
        u.u = ((hi << 24) | (mid << 16) | (lo << 8)) - UINT32_C(0x80000000);
433
0
        *(out++) = u.s;
434
0
        in += 3;
435
0
    }
436
0
}
437
438
static void U24LDecode( void *outp, const uint8_t *in, unsigned samples )
439
0
{
440
0
    int32_t *out = outp;
441
0
    union { int32_t s; uint32_t u; } u;
442
443
0
    for( size_t i = 0; i < samples; i++ )
444
0
    {
445
0
        uint_fast32_t hi = in[2], mid = in[1], lo = in[0];
446
447
0
        u.u = ((hi << 24) | (mid << 16) | (lo << 8)) - UINT32_C(0x80000000);
448
0
        *(out++) = u.s;
449
0
        in += 3;
450
0
    }
451
0
}
452
453
static void S24BDecode( void *outp, const uint8_t *in, unsigned samples )
454
0
{
455
0
    int32_t *out = outp;
456
0
    union { int32_t s; uint32_t u; } u;
457
458
0
    for( size_t i = 0; i < samples; i++ )
459
0
    {
460
0
        uint_fast32_t hi = in[0], mid = in[1], lo = in[2];
461
462
0
        u.u = (hi << 24) | (mid << 16) | (lo << 8);
463
0
        *(out++) = u.s;
464
0
        in += 3;
465
0
    }
466
0
}
467
468
static void S24LDecode( void *outp, const uint8_t *in, unsigned samples )
469
0
{
470
0
    uint32_t *out = outp;
471
0
    union { int32_t s; uint32_t u; } u;
472
473
0
    for( size_t i = 0; i < samples; i++ )
474
0
    {
475
0
        uint_fast32_t hi = in[2], mid = in[1], lo = in[0];
476
477
0
        u.u = (hi << 24) | (mid << 16) | (lo << 8);
478
0
        *(out++) = u.s;
479
0
        in += 3;
480
0
    }
481
0
}
482
483
static void S24B32Decode( void *outp, const uint8_t *in, unsigned samples )
484
0
{
485
0
    uint32_t *out = outp;
486
487
0
    for( size_t i = 0; i < samples; i++ )
488
0
    {
489
0
        *(out++) = GetDWBE( in ) << 8;
490
0
        in += 4;
491
0
    }
492
0
}
493
494
static void S24L32Decode( void *outp, const uint8_t *in, unsigned samples )
495
0
{
496
0
    uint32_t *out = outp;
497
498
0
    for( size_t i = 0; i < samples; i++ )
499
0
    {
500
0
        *(out++) = GetDWLE( in ) << 8;
501
0
        in += 4;
502
0
    }
503
0
}
504
505
static void U32BDecode( void *outp, const uint8_t *in, unsigned samples )
506
0
{
507
0
    uint32_t *out = outp;
508
509
0
    for( size_t i = 0; i < samples; i++ )
510
0
    {
511
0
        *(out++) = GetDWBE( in ) - 0x80000000;
512
0
        in += 4;
513
0
    }
514
0
}
515
516
static void U32LDecode( void *outp, const uint8_t *in, unsigned samples )
517
0
{
518
0
    uint32_t *out = outp;
519
520
0
    for( size_t i = 0; i < samples; i++ )
521
0
    {
522
0
        *(out++) = GetDWLE( in ) - 0x80000000;
523
0
        in += 4;
524
0
    }
525
0
}
526
527
static void S32IDecode( void *outp, const uint8_t *in, unsigned samples )
528
0
{
529
0
    int32_t *out = outp;
530
531
0
    for( size_t i = 0; i < samples; i++ )
532
0
    {
533
#ifdef WORDS_BIGENDIAN
534
        *(out++) = GetDWLE( in );
535
#else
536
0
        *(out++) = GetDWBE( in );
537
0
#endif
538
0
        in += 4;
539
0
    }
540
0
}
541
542
static void F32NDecode( void *outp, const uint8_t *in, unsigned samples )
543
0
{
544
0
    float *out = outp;
545
546
0
    for( size_t i = 0; i < samples; i++ )
547
0
    {
548
0
        memcpy( out, in, sizeof(float) );
549
0
        if( unlikely(!isfinite(*out)) )
550
0
            *out = 0.f;
551
0
        out++;
552
0
        in += sizeof(float);
553
0
    }
554
0
}
555
556
static void F32IDecode( void *outp, const uint8_t *in, unsigned samples )
557
0
{
558
0
    float *out = outp;
559
560
0
    for( size_t i = 0; i < samples; i++ )
561
0
    {
562
0
        union { float f; uint32_t u; } s;
563
564
#ifdef WORDS_BIGENDIAN
565
        s.u = GetDWLE( in );
566
#else
567
0
        s.u = GetDWBE( in );
568
0
#endif
569
0
        if( unlikely(!isfinite(s.f)) )
570
0
            s.f = 0.f;
571
0
        *(out++) = s.f;
572
0
        in += 4;
573
0
    }
574
0
}
575
576
static void F64NDecode( void *outp, const uint8_t *in, unsigned samples )
577
0
{
578
0
    double *out = outp;
579
580
0
    for( size_t i = 0; i < samples; i++ )
581
0
    {
582
0
        memcpy( out, in, sizeof(double) );
583
0
        if( unlikely(!isfinite( *out )) )
584
0
            *out = 0.;
585
0
        out++;
586
0
        in += sizeof(double);
587
0
    }
588
0
}
589
590
static void F64IDecode( void *outp, const uint8_t *in, unsigned samples )
591
0
{
592
0
    double *out = outp;
593
594
0
    for( size_t i = 0; i < samples; i++ )
595
0
    {
596
0
        union { double d; uint64_t u; } s;
597
598
#ifdef WORDS_BIGENDIAN
599
        s.u = GetQWLE( in );
600
#else
601
0
        s.u = GetQWBE( in );
602
0
#endif
603
0
        if( unlikely(!isfinite( s.d )) )
604
0
            s.d = 0.;
605
0
        *(out++) = s.d;
606
0
        in += 8;
607
0
    }
608
0
}
609
610
static int_fast16_t dat12tos16( uint_fast16_t y )
611
0
{
612
0
    static const int16_t diff[16] = {
613
0
       0x0000, 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600,
614
0
       0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, 0x0F00, 0x1000, 0x1000,
615
0
    };
616
0
    static const uint8_t shift[16] = {
617
0
        0, 0, 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 0, 0
618
0
    };
619
620
0
    assert(y < 0x1000);
621
622
0
    int d = y >> 8;
623
0
    return ((int)y - diff[d]) << shift[d];
624
0
}
625
626
static void DAT12Decode( void *outp, const uint8_t *in, unsigned samples )
627
0
{
628
0
    int16_t *out = outp;
629
630
0
    while( samples >= 2 )
631
0
    {
632
0
        *(out++) = dat12tos16(U16_AT(in) >> 4);
633
0
        *(out++) = dat12tos16(U16_AT(in + 1) & ~0xF000);
634
0
        in += 3;
635
0
        samples -= 2;
636
0
    }
637
638
0
    if( samples )
639
0
        *(out++) = dat12tos16(U16_AT(in) >> 4);
640
0
}
641
642
#ifdef ENABLE_SOUT
643
/* NOTE: Output buffers are always aligned since they are allocated by the araw plugin.
644
 * Contrary to the decoder, the encoder can also assume that input buffers are aligned,
645
 * since decoded audio blocks must always be aligned. */
646
647
static void U16IEncode( void *outp, const uint8_t *inp, unsigned samples )
648
0
{
649
0
    const uint16_t *in = (const uint16_t *)inp;
650
0
    uint16_t *out = outp;
651
652
0
    for( size_t i = 0; i < samples; i++ )
653
0
        *(out++) =  vlc_bswap16( *(in++) + 0x8000 );
654
0
}
655
656
static void U16NEncode( void *outp, const uint8_t *inp, unsigned samples )
657
0
{
658
0
    const uint16_t *in = (const uint16_t *)inp;
659
0
    uint16_t *out = outp;
660
661
0
    for( size_t i = 0; i < samples; i++ )
662
0
        *(out++) =  *(in++) + 0x8000;
663
0
}
664
665
static void U24BEncode( void *outp, const uint8_t *inp, unsigned samples )
666
0
{
667
0
    const uint32_t *in = (const uint32_t *)inp;
668
0
    uint8_t *out = outp;
669
670
0
    for( size_t i = 0; i < samples; i++ )
671
0
    {
672
0
        uint32_t s = *(in++);
673
0
        *(out++) = (s >> 24) + 0x80;
674
0
        *(out++) = (s >> 16);
675
0
        *(out++) = (s >>  8);
676
0
    }
677
0
}
678
679
static void U24LEncode( void *outp, const uint8_t *inp, unsigned samples )
680
0
{
681
0
    const uint32_t *in = (const uint32_t *)inp;
682
0
    uint8_t *out = outp;
683
684
0
    for( size_t i = 0; i < samples; i++ )
685
0
    {
686
0
        uint32_t s = *(in++);
687
0
        *(out++) = (s >>  8);
688
0
        *(out++) = (s >> 16);
689
0
        *(out++) = (s >> 24) + 0x80;
690
0
    }
691
0
}
692
693
static void S24BEncode( void *outp, const uint8_t *inp, unsigned samples )
694
0
{
695
0
    const uint32_t *in = (const uint32_t *)inp;
696
0
    uint8_t *out = outp;
697
698
0
    for( size_t i = 0; i < samples; i++ )
699
0
    {
700
0
        uint32_t s = *(in++);
701
0
        *(out++) = (s >> 24);
702
0
        *(out++) = (s >> 16);
703
0
        *(out++) = (s >>  8);
704
0
    }
705
0
}
706
707
static void S24LEncode( void *outp, const uint8_t *inp, unsigned samples )
708
0
{
709
0
    const uint32_t *in = (const uint32_t *)inp;
710
0
    uint8_t *out = outp;
711
712
0
    for( size_t i = 0; i < samples; i++ )
713
0
    {
714
0
        uint32_t s = *(in++);
715
0
        *(out++) = (s >>  8);
716
0
        *(out++) = (s >> 16);
717
0
        *(out++) = (s >> 24);
718
0
    }
719
0
}
720
721
static void U32IEncode( void *outp, const uint8_t *inp, unsigned samples )
722
0
{
723
0
    const uint32_t *in = (const uint32_t *)inp;
724
0
    uint32_t *out = outp;
725
726
0
    for( size_t i = 0; i < samples; i++ )
727
0
        *(out++) =  vlc_bswap32( *(in++) + 0x80000000 );
728
0
}
729
730
static void U32NEncode( void *outp, const uint8_t *inp, unsigned samples )
731
0
{
732
0
    const uint32_t *in = (const uint32_t *)inp;
733
0
    uint32_t *out = outp;
734
735
0
    for( size_t i = 0; i < samples; i++ )
736
0
        *(out++) =  *(in++) + 0x80000000;
737
0
}
738
739
static void S32IEncode( void *outp, const uint8_t *inp, unsigned samples )
740
0
{
741
0
    const int32_t *in = (const int32_t *)inp;
742
0
    int32_t *out = outp;
743
744
0
    for( size_t i = 0; i < samples; i++ )
745
0
        *(out++) = vlc_bswap32( *(in++) );
746
0
}
747
748
static void F32IEncode( void *outp, const uint8_t *inp, unsigned samples )
749
0
{
750
0
    const float *in = (const float *)inp;
751
0
    uint8_t *out = outp;
752
753
0
    for( size_t i = 0; i < samples; i++ )
754
0
    {
755
0
        union { float f; uint32_t u; char b[4]; } s;
756
757
0
        s.f = *(in++);
758
0
        s.u = vlc_bswap32( s.u );
759
0
        memcpy( out, s.b, 4 );
760
0
        out += 4;
761
0
    }
762
0
}
763
764
static void F64IEncode( void *outp, const uint8_t *inp, unsigned samples )
765
0
{
766
0
    const double *in = (const double *)inp;
767
0
    uint8_t *out = outp;
768
769
0
    for( size_t i = 0; i < samples; i++ )
770
0
    {
771
0
        union { double d; uint64_t u; char b[8]; } s;
772
773
0
        s.d = *(in++);
774
0
        s.u = vlc_bswap64( s.u );
775
0
        memcpy( out, s.b, 8 );
776
0
        out += 8;
777
0
    }
778
0
}
779
780
static block_t *Encode( encoder_t *enc, block_t *in )
781
0
{
782
0
    if( in == NULL )
783
0
        return NULL;
784
785
0
    block_t *out = block_Alloc( in->i_nb_samples
786
0
                                * enc->fmt_out.audio.i_bytes_per_frame );
787
0
    if( unlikely(out == NULL) )
788
0
        return NULL;
789
790
0
    out->i_flags      = in->i_flags;
791
0
    out->i_nb_samples = in->i_nb_samples;
792
0
    out->i_dts        = in->i_dts;
793
0
    out->i_pts        = in->i_pts;
794
0
    out->i_length     = in->i_length;
795
796
0
    void (*encode)(void *, const uint8_t *, unsigned) = (void *)enc->p_sys;
797
0
    if( encode != NULL )
798
0
        encode( out->p_buffer, in->p_buffer, in->i_nb_samples
799
0
                                             * enc->fmt_out.audio.i_channels );
800
0
    else {
801
0
        assert( out->i_buffer >= in->i_buffer );
802
0
        memcpy( out->p_buffer, in->p_buffer, in->i_buffer );
803
0
    }
804
0
    return out;
805
0
}
806
807
/**
808
 * Probes the PCM audio encoder.
809
 */
810
static int EncoderOpen( vlc_object_t *p_this )
811
0
{
812
0
    encoder_t *p_enc = (encoder_t *)p_this;
813
0
    void (*encode)(void *, const uint8_t *, unsigned) = NULL;
814
815
0
    switch( p_enc->fmt_out.i_codec )
816
0
    {
817
0
    case VLC_CODEC_S8:
818
0
        encode = S8Decode;
819
        /* fall through */
820
0
    case VLC_CODEC_U8:
821
0
        p_enc->fmt_in.i_codec = VLC_CODEC_U8;
822
0
        p_enc->fmt_out.audio.i_bitspersample = 8;
823
0
        break;
824
0
    case VLC_CODEC_U16I:
825
0
        encode = U16IEncode;
826
0
        p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
827
0
        p_enc->fmt_out.audio.i_bitspersample = 16;
828
0
        break;
829
0
    case VLC_CODEC_U16N:
830
0
        encode = U16NEncode;
831
0
        p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
832
0
        p_enc->fmt_out.audio.i_bitspersample = 16;
833
0
        break;
834
0
    case VLC_CODEC_S16I:
835
0
        encode = S16IDecode;
836
        /* fall through */
837
0
    case VLC_CODEC_S16N:
838
0
        p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
839
0
        p_enc->fmt_out.audio.i_bitspersample = 16;
840
0
        break;
841
0
    case VLC_CODEC_U24B:
842
0
        encode = U24BEncode;
843
0
        p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
844
0
        p_enc->fmt_out.audio.i_bitspersample = 24;
845
0
        break;
846
0
    case VLC_CODEC_U24L:
847
0
        encode = U24LEncode;
848
0
        p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
849
0
        p_enc->fmt_out.audio.i_bitspersample = 24;
850
0
        break;
851
0
    case VLC_CODEC_S24B:
852
0
        encode = S24BEncode;
853
0
        p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
854
0
        p_enc->fmt_out.audio.i_bitspersample = 24;
855
0
        break;
856
0
    case VLC_CODEC_S24L:
857
0
        encode = S24LEncode;
858
0
        p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
859
0
        p_enc->fmt_out.audio.i_bitspersample = 24;
860
0
        break;
861
0
    case VLC_CODEC_U32I:
862
0
        encode = U32IEncode;
863
0
        p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
864
0
        p_enc->fmt_out.audio.i_bitspersample = 32;
865
0
        break;
866
0
    case VLC_CODEC_U32N:
867
0
        encode = U32NEncode;
868
0
        p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
869
0
        p_enc->fmt_out.audio.i_bitspersample = 32;
870
0
        break;
871
0
    case VLC_CODEC_S32I:
872
0
        encode = S32IEncode;
873
        /* fall through */
874
0
    case VLC_CODEC_S32N:
875
0
        p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
876
0
        p_enc->fmt_out.audio.i_bitspersample = 32;
877
0
        break;
878
#ifdef WORDS_BIGENDIAN
879
    case VLC_CODEC_F32L:
880
#else
881
0
    case VLC_CODEC_F32B:
882
0
#endif
883
0
        encode = F32IEncode;
884
        /* fall through */
885
0
    case VLC_CODEC_FL32:
886
0
        p_enc->fmt_in.i_codec = VLC_CODEC_FL32;
887
0
        p_enc->fmt_out.audio.i_bitspersample = 32;
888
0
        break;
889
#ifdef WORDS_BIGENDIAN
890
    case VLC_CODEC_F64L:
891
#else
892
0
    case VLC_CODEC_F64B:
893
0
#endif
894
0
        encode = F64IEncode;
895
        /* fall through */
896
0
    case VLC_CODEC_FL64:
897
0
        p_enc->fmt_in.i_codec = VLC_CODEC_FL64;
898
0
        p_enc->fmt_out.audio.i_bitspersample = 64;
899
0
        break;
900
0
    default:
901
0
        return VLC_EGENERIC;
902
0
    }
903
904
0
    p_enc->p_sys = (void *)encode;
905
0
    p_enc->fmt_out.audio.i_bytes_per_frame =
906
0
        (p_enc->fmt_out.audio.i_bitspersample / 8) *
907
0
        p_enc->fmt_in.audio.i_channels;
908
0
    p_enc->fmt_out.i_bitrate =
909
0
        p_enc->fmt_in.audio.i_channels *
910
0
        p_enc->fmt_in.audio.i_rate *
911
0
        p_enc->fmt_out.audio.i_bitspersample;
912
913
0
    msg_Dbg( p_enc, "samplerate:%dHz channels:%d bits/sample:%d",
914
0
             p_enc->fmt_out.audio.i_rate, p_enc->fmt_out.audio.i_channels,
915
0
             p_enc->fmt_out.audio.i_bitspersample );
916
917
0
    static const struct vlc_encoder_operations ops =
918
0
        { .encode_audio = Encode };
919
0
    p_enc->ops = &ops;
920
921
0
    return VLC_SUCCESS;
922
0
}
923
#endif /* ENABLE_SOUT */