Coverage Report

Created: 2026-02-26 08:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/codec/lpcm.c
Line
Count
Source
1
/*****************************************************************************
2
 * lpcm.c: lpcm decoder/packetizer module
3
 *****************************************************************************
4
 * Copyright (C) 1999-2008 VLC authors and VideoLAN
5
 *
6
 * Authors: Samuel Hocevar <sam@zoy.org>
7
 *          Henri Fallon <henri@videolan.org>
8
 *          Christophe Massiot <massiot@via.ecp.fr>
9
 *          Gildas Bazin <gbazin@videolan.org>
10
 *          Lauren Aimar <fenrir _AT_ videolan _DOT_ org >
11
 *          Steinar H. Gunderson <steinar+vlc@gunderson.no>
12
 *
13
 * This program is free software; you can redistribute it and/or modify it
14
 * under the terms of the GNU Lesser General Public License as published by
15
 * the Free Software Foundation; either version 2.1 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
 * GNU Lesser General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Lesser General Public License
24
 * along with this program; if not, write to the Free Software Foundation,
25
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26
 *****************************************************************************/
27
28
/*****************************************************************************
29
 * Preamble
30
 *****************************************************************************/
31
#ifdef HAVE_CONFIG_H
32
# include "config.h"
33
#endif
34
35
#include <vlc_common.h>
36
#include <vlc_plugin.h>
37
#include <vlc_codec.h>
38
#include <vlc_aout.h>
39
#include <unistd.h>
40
#include <assert.h>
41
42
/*****************************************************************************
43
 * Module descriptor
44
 *****************************************************************************/
45
static int  OpenDecoder   ( vlc_object_t * );
46
static int  OpenPacketizer( vlc_object_t * );
47
48
#ifdef ENABLE_SOUT
49
static int  OpenEncoder   ( vlc_object_t * );
50
static void CloseEncoder  ( encoder_t * );
51
static block_t *EncodeFrames( encoder_t *, block_t * );
52
#endif
53
54
104
vlc_module_begin ()
55
56
52
    set_subcategory( SUBCAT_INPUT_ACODEC )
57
52
    set_description( N_("Linear PCM audio decoder") )
58
52
    set_capability( "audio decoder", 100 )
59
52
    set_callback( OpenDecoder )
60
61
52
    add_submodule ()
62
52
    set_description( N_("Linear PCM audio packetizer") )
63
52
    set_capability( "audio packetizer", 100 )
64
52
    set_callback( OpenPacketizer )
65
66
52
#ifdef ENABLE_SOUT
67
52
    add_submodule ()
68
52
    set_description( N_("Linear PCM audio encoder") )
69
52
    set_capability( "audio encoder", 100 )
70
52
    set_callback( OpenEncoder )
71
52
    add_shortcut( "lpcm" )
72
52
#endif
73
74
52
vlc_module_end ()
75
76
77
/*****************************************************************************
78
 * decoder_sys_t : lpcm decoder descriptor
79
 *****************************************************************************/
80
typedef struct
81
{
82
    /* Module mode */
83
    bool b_packetizer;
84
85
    /*
86
     * Output properties
87
     */
88
    date_t   end_date;
89
90
    /* */
91
    unsigned i_header_size;
92
    int      i_type;
93
    uint8_t  i_chans_to_reorder;
94
    uint8_t  pi_chan_table[AOUT_CHAN_MAX];
95
} decoder_sys_t;
96
97
#ifdef ENABLE_SOUT
98
typedef struct
99
{
100
    int     i_channels;
101
    int     i_rate;
102
103
    int     i_frame_samples;
104
    uint8_t *p_buffer;
105
    int     i_buffer_used;
106
    int     i_frame_num;
107
} encoder_sys_t;
108
#endif
109
110
/*
111
 * LPCM DVD header :
112
 * - number of frames in this packet (8 bits)
113
 * - first access unit (16 bits) == 0x0003 ?
114
 * - emphasis (1 bit)
115
 * - mute (1 bit)
116
 * - reserved (1 bit)
117
 * - current frame (5 bits)
118
 * - quantisation (2 bits) 0 == 16bps, 1 == 20bps, 2 == 24bps, 3 == illegal
119
 * - frequency (2 bits) 0 == 48 kHz, 1 == 96 kHz, 2 == 44.1 kHz, 3 == 32 kHz
120
 * - reserved (1 bit)
121
 * - number of channels - 1 (3 bits) 1 == 2 channels
122
 * - dynamic range (8 bits) 0x80 == neutral
123
 *
124
 * LPCM DVD-A header (http://dvd-audio.sourceforge.net/spec/aob.shtml)
125
 * - continuity counter (8 bits, clipped to 0x00-0x1f)
126
 * - header size (16 bits)
127
 * - byte pointer to start of first audio frame.
128
 * - unknown (8bits, 0x10 for stereo, 0x00 for surround)
129
 * - sample size (4+4 bits)
130
 * - samplerate (4+4 bits)
131
 * - unknown (8 bits)
132
 * - group assignment (8 bits)
133
 * - unknown (8 bits)
134
 * - padding(variable)
135
 *
136
 * LPCM BD header :
137
 * - unknown (16 bits)
138
 * - number of channels (4 bits)
139
 * - frequency (4 bits)
140
 * - bits per sample (2 bits)
141
 * - unknown (6 bits)
142
 *
143
 * LPCM WIDI header
144
 * refers http://www.dvdforum.org/images/Guideline1394V10R0_20020911.pdf
145
  * - sub stream id (8 bits) = 0xa0
146
 * - frame header count (8 bits) = 0x06
147
 * [ 0b0000000 (7 bits)
148
 * - audio emphasis (1 bit) ] (8 bits)
149
 * [ qz word length (2 bits) 0x00 == 16bits
150
 * - sampling freq (3 bits) 0b001 == 44.1K, 0b010 == 48K Hz
151
 * - channels count(3 bits) ] (8 bits) 0b000 == dual mono, 0b001 == stereo
152
 * follows: LPCM data (15360 bits/1920 bytes)
153
 */
154
155
457
#define LPCM_VOB_HEADER_LEN (6)
156
70.2k
#define LPCM_AOB_HEADER_LEN (11)
157
6.10k
#define LPCM_BD_HEADER_LEN (4)
158
19
#define LPCM_WIDI_HEADER_LEN (4)
159
160
enum
161
{
162
    LPCM_VOB,
163
    LPCM_AOB,
164
    LPCM_BD,
165
    LPCM_WIDI,
166
};
167
168
typedef struct
169
{
170
    unsigned i_channels;
171
    unsigned i_bits;
172
    unsigned pi_position[6];
173
} aob_group_t;
174
175
/*****************************************************************************
176
 * Local prototypes
177
 *****************************************************************************/
178
static int DecodeFrame    ( decoder_t *, block_t * );
179
static block_t *Packetize ( decoder_t *, block_t ** );
180
static void Flush( decoder_t * );
181
182
/* */
183
static int VobHeader( unsigned *pi_rate,
184
                      unsigned *pi_channels, unsigned *pi_original_channels,
185
                      unsigned *pi_bits,
186
                      const uint8_t *p_header );
187
static void VobExtract( block_t *, block_t *, unsigned i_bits );
188
/* */
189
static int AobHeader( unsigned *pi_rate,
190
                      unsigned *pi_channels, unsigned *pi_layout,
191
                      unsigned *pi_bits,
192
                      unsigned *pi_padding,
193
                      aob_group_t g[2],
194
                      const uint8_t *p_header );
195
static void AobExtract( block_t *, block_t *, unsigned i_bits, aob_group_t p_group[2] );
196
/* */
197
static int BdHeader( decoder_sys_t *p_sys,
198
                     unsigned *pi_rate,
199
                     unsigned *pi_channels,
200
                     unsigned *pi_channels_padding,
201
                     unsigned *pi_original_channels,
202
                     unsigned *pi_bits,
203
                     const uint8_t *p_header );
204
static void BdExtract( block_t *, block_t *, unsigned, unsigned, unsigned, unsigned );
205
/* */
206
static int WidiHeader( unsigned *pi_rate,
207
                       unsigned *pi_channels, unsigned *pi_original_channels,
208
                       unsigned *pi_bits,
209
                       const uint8_t *p_header );
210
211
/*****************************************************************************
212
 * OpenCommon:
213
 *****************************************************************************/
214
static int OpenCommon( decoder_t *p_dec, bool b_packetizer )
215
2.37M
{
216
2.37M
    decoder_sys_t *p_sys;
217
2.37M
    int i_type;
218
2.37M
    int i_header_size;
219
220
2.37M
    switch( p_dec->fmt_in->i_codec )
221
2.37M
    {
222
    /* DVD LPCM */
223
457
    case VLC_CODEC_DVD_LPCM:
224
457
        i_type = LPCM_VOB;
225
457
        i_header_size = LPCM_VOB_HEADER_LEN;
226
457
        break;
227
    /* DVD-Audio LPCM */
228
878
    case VLC_CODEC_DVDA_LPCM:
229
878
        i_type = LPCM_AOB;
230
878
        i_header_size = LPCM_AOB_HEADER_LEN;
231
878
        break;
232
    /* BD LPCM */
233
6.10k
    case VLC_CODEC_BD_LPCM:
234
6.10k
        i_type = LPCM_BD;
235
6.10k
        i_header_size = LPCM_BD_HEADER_LEN;
236
6.10k
        break;
237
    /* WIDI LPCM */
238
19
    case VLC_CODEC_WIDI_LPCM:
239
19
        i_type = LPCM_WIDI;
240
19
        i_header_size = LPCM_WIDI_HEADER_LEN;
241
19
        break;
242
2.36M
    default:
243
2.36M
        return VLC_EGENERIC;
244
2.37M
    }
245
246
    /* Allocate the memory needed to store the decoder's structure */
247
7.45k
    p_sys = vlc_obj_malloc(VLC_OBJECT(p_dec), sizeof (*p_sys));
248
7.45k
    if (unlikely(p_sys == NULL))
249
0
        return VLC_ENOMEM;
250
251
    /* Misc init */
252
7.45k
    p_sys->b_packetizer = b_packetizer;
253
7.45k
    date_Set( &p_sys->end_date, VLC_TICK_INVALID );
254
7.45k
    p_sys->i_type = i_type;
255
7.45k
    p_sys->i_header_size = i_header_size;
256
7.45k
    p_sys->i_chans_to_reorder = 0;
257
258
    /* Set output properties */
259
7.45k
    if( b_packetizer )
260
237
    {
261
237
        switch( i_type )
262
237
        {
263
105
        case LPCM_VOB:
264
105
            p_dec->fmt_out.i_codec = VLC_CODEC_DVD_LPCM;
265
105
            break;
266
95
        case LPCM_AOB:
267
95
            p_dec->fmt_out.i_codec = VLC_CODEC_DVDA_LPCM;
268
95
            break;
269
9
        case LPCM_WIDI:
270
9
            p_dec->fmt_out.i_codec = VLC_CODEC_WIDI_LPCM;
271
9
            break;
272
0
        default:
273
0
            vlc_assert_unreachable();
274
28
        case LPCM_BD:
275
28
            p_dec->fmt_out.i_codec = VLC_CODEC_BD_LPCM;
276
28
            break;
277
237
        }
278
237
    }
279
7.21k
    else
280
7.21k
    {
281
7.21k
        switch( p_dec->fmt_out.audio.i_bitspersample )
282
7.21k
        {
283
0
        case 24:
284
0
        case 20:
285
0
            p_dec->fmt_out.i_codec = VLC_CODEC_S32N;
286
0
            p_dec->fmt_out.audio.i_bitspersample = 32;
287
0
            break;
288
7.21k
        default:
289
7.21k
            p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
290
7.21k
            p_dec->fmt_out.audio.i_bitspersample = 16;
291
7.21k
            break;
292
7.21k
        }
293
7.21k
    }
294
295
    /* Set callback */
296
7.45k
    if( !b_packetizer )
297
7.21k
        p_dec->pf_decode    = DecodeFrame;
298
237
    else
299
237
        p_dec->pf_packetize = Packetize;
300
7.45k
    p_dec->pf_flush     = Flush;
301
7.45k
    p_dec->p_sys = p_sys;
302
7.45k
    return VLC_SUCCESS;
303
7.45k
}
304
static int OpenDecoder( vlc_object_t *p_this )
305
486k
{
306
486k
    return OpenCommon( (decoder_t*) p_this, false );
307
486k
}
308
static int OpenPacketizer( vlc_object_t *p_this )
309
1.88M
{
310
1.88M
    return OpenCommon( (decoder_t*) p_this, true );
311
1.88M
}
312
313
/*****************************************************************************
314
 * Flush:
315
 *****************************************************************************/
316
static void Flush( decoder_t *p_dec )
317
1.56k
{
318
1.56k
    decoder_sys_t *p_sys = p_dec->p_sys;
319
320
1.56k
    date_Set( &p_sys->end_date, VLC_TICK_INVALID );
321
1.56k
}
322
323
/*****************************************************************************
324
 * DecodeFrame: decodes an lpcm frame.
325
 ****************************************************************************
326
 * Beware, this function must be fed with complete frames (PES packet).
327
 *****************************************************************************/
328
static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
329
310k
{
330
310k
    decoder_sys_t *p_sys = p_dec->p_sys;
331
310k
    block_t       *p_block;
332
310k
    unsigned int  i_rate = 0, i_original_channels = 0, i_channels = 0, i_bits = 0;
333
310k
    int           i_frame_length;
334
335
310k
    if( !pp_block || !*pp_block ) return NULL;
336
337
151k
    p_block = *pp_block;
338
151k
    *pp_block = NULL; /* So the packet doesn't get re-sent */
339
340
151k
    if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED|BLOCK_FLAG_DISCONTINUITY) )
341
1.56k
    {
342
1.56k
        Flush( p_dec );
343
1.56k
        if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
344
0
        {
345
0
            block_Release( p_block );
346
0
            *pp_block = NULL;
347
0
            return NULL;
348
0
        }
349
1.56k
    }
350
351
    /* Date management */
352
151k
    if( p_block->i_pts != VLC_TICK_INVALID &&
353
151k
        p_block->i_pts != date_Get( &p_sys->end_date ) )
354
61.0k
    {
355
61.0k
        date_Set( &p_sys->end_date, p_block->i_pts );
356
61.0k
    }
357
358
151k
    if( date_Get( &p_sys->end_date ) == VLC_TICK_INVALID )
359
77
    {
360
        /* We've just started the stream, wait for the first PTS. */
361
77
        block_Release( p_block );
362
77
        return NULL;
363
77
    }
364
365
151k
    if( p_block->i_buffer <= p_sys->i_header_size )
366
84
    {
367
84
        msg_Err(p_dec, "frame is too short");
368
84
        block_Release( p_block );
369
84
        return NULL;
370
84
    }
371
372
151k
    int i_ret;
373
151k
    unsigned i_channels_padding = 0;
374
151k
    unsigned i_padding = 0; /* only for AOB */
375
151k
    aob_group_t p_aob_group[2];
376
377
151k
    switch( p_sys->i_type )
378
151k
    {
379
3.93k
    case LPCM_VOB:
380
3.93k
        i_ret = VobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits,
381
3.93k
                           p_block->p_buffer );
382
3.93k
        break;
383
41.9k
    case LPCM_AOB:
384
41.9k
        i_ret = AobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits, &i_padding,
385
41.9k
                           p_aob_group,
386
41.9k
                           p_block->p_buffer );
387
41.9k
        break;
388
80.5k
    case LPCM_BD:
389
80.5k
        i_ret = BdHeader( p_sys, &i_rate, &i_channels, &i_channels_padding, &i_original_channels, &i_bits,
390
80.5k
                          p_block->p_buffer );
391
80.5k
        break;
392
24.9k
    case LPCM_WIDI:
393
24.9k
        i_ret = WidiHeader( &i_rate, &i_channels, &i_original_channels, &i_bits,
394
24.9k
                            p_block->p_buffer );
395
24.9k
        break;
396
0
    default:
397
0
        abort();
398
151k
    }
399
400
151k
    if( i_ret || p_block->i_buffer <= p_sys->i_header_size + i_padding )
401
130k
    {
402
130k
        msg_Warn( p_dec, "no frame sync or too small frame" );
403
130k
        block_Release( p_block );
404
130k
        return NULL;
405
130k
    }
406
407
    /* Set output properties */
408
21.1k
    if( p_dec->fmt_out.audio.i_rate != i_rate )
409
12.1k
    {
410
12.1k
        date_Init( &p_sys->end_date, i_rate, 1 );
411
12.1k
        date_Set( &p_sys->end_date, p_block->i_pts );
412
12.1k
    }
413
21.1k
    p_dec->fmt_out.audio.i_rate = i_rate;
414
21.1k
    p_dec->fmt_out.audio.i_channels = i_channels;
415
21.1k
    p_dec->fmt_out.audio.i_physical_channels = i_original_channels;
416
417
21.1k
    if ( p_sys->i_type == LPCM_AOB )
418
3.37k
    {
419
3.37k
        i_frame_length = (p_block->i_buffer - p_sys->i_header_size - i_padding) /
420
3.37k
                         (
421
3.37k
                            ( (p_aob_group[0].i_bits / 8) * p_aob_group[0].i_channels ) +
422
3.37k
                            ( (p_aob_group[1].i_bits / 8) * p_aob_group[1].i_channels )
423
3.37k
                         );
424
3.37k
    }
425
17.7k
    else
426
17.7k
    {
427
17.7k
        i_frame_length = (p_block->i_buffer - p_sys->i_header_size - i_padding) /
428
17.7k
                         (i_channels + i_channels_padding) * 8 / i_bits;
429
17.7k
    }
430
431
21.1k
    if( p_sys->b_packetizer )
432
10.5k
    {
433
10.5k
        p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date );
434
10.5k
        p_block->i_length =
435
10.5k
            date_Increment( &p_sys->end_date, i_frame_length ) -
436
10.5k
            p_block->i_pts;
437
438
        /* Just pass on the incoming frame */
439
10.5k
        return p_block;
440
10.5k
    }
441
10.5k
    else
442
10.5k
    {
443
        /* */
444
10.5k
        if( i_bits == 16 )
445
6.88k
        {
446
6.88k
            p_dec->fmt_out.audio.i_format =
447
6.88k
            p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
448
6.88k
            p_dec->fmt_out.audio.i_bitspersample = 16;
449
6.88k
        }
450
3.69k
        else
451
3.69k
        {
452
3.69k
            p_dec->fmt_out.audio.i_format =
453
3.69k
            p_dec->fmt_out.i_codec = VLC_CODEC_S32N;
454
3.69k
            p_dec->fmt_out.audio.i_bitspersample = 32;
455
3.69k
        }
456
10.5k
        aout_FormatPrepare(&p_dec->fmt_out.audio);
457
458
        /* */
459
10.5k
        block_t *p_aout_buffer;
460
10.5k
        if( decoder_UpdateAudioFormat( p_dec ) != VLC_SUCCESS ||
461
0
           !(p_aout_buffer = decoder_NewAudioBuffer( p_dec, i_frame_length )) )
462
10.5k
        {
463
10.5k
            block_Release( p_block );
464
10.5k
            return NULL;
465
10.5k
        }
466
467
0
        p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
468
0
        p_aout_buffer->i_length =
469
0
            date_Increment( &p_sys->end_date, i_frame_length )
470
0
            - p_aout_buffer->i_pts;
471
472
0
        p_block->p_buffer += p_sys->i_header_size + i_padding;
473
0
        p_block->i_buffer -= p_sys->i_header_size + i_padding;
474
475
0
        switch( p_sys->i_type )
476
0
        {
477
0
        case LPCM_WIDI:
478
0
        case LPCM_VOB:
479
0
            VobExtract( p_aout_buffer, p_block, i_bits );
480
0
            break;
481
0
        case LPCM_AOB:
482
0
            AobExtract( p_aout_buffer, p_block, i_bits, p_aob_group );
483
0
            break;
484
0
        default:
485
0
            vlc_assert_unreachable();
486
0
        case LPCM_BD:
487
0
            BdExtract( p_aout_buffer, p_block, i_frame_length, i_channels, i_channels_padding, i_bits );
488
0
            break;
489
0
        }
490
491
0
        if( p_sys->i_chans_to_reorder )
492
0
        {
493
0
            aout_ChannelReorder( p_aout_buffer->p_buffer, p_aout_buffer->i_buffer,
494
0
                                 p_sys->i_chans_to_reorder, p_sys->pi_chan_table,
495
0
                                 p_dec->fmt_out.i_codec );
496
0
        }
497
498
0
        block_Release( p_block );
499
0
        return p_aout_buffer;
500
0
    }
501
21.1k
}
502
503
static int DecodeFrame( decoder_t *p_dec, block_t *p_block )
504
158k
{
505
158k
    block_t *p_out = Packetize( p_dec, &p_block );
506
158k
    if( p_out != NULL )
507
0
        decoder_QueueAudio( p_dec, p_out );
508
158k
    return VLCDEC_SUCCESS;
509
158k
}
510
511
#ifdef ENABLE_SOUT
512
/*****************************************************************************
513
 * OpenEncoder: lpcm encoder construction
514
 *****************************************************************************/
515
static int OpenEncoder( vlc_object_t *p_this )
516
0
{
517
0
    encoder_t *p_enc = (encoder_t *)p_this;
518
0
    encoder_sys_t *p_sys;
519
520
    /* We only support DVD LPCM yet. */
521
0
    if( p_enc->fmt_out.i_codec != VLC_CODEC_DVD_LPCM )
522
0
        return VLC_EGENERIC;
523
524
0
    if( p_enc->fmt_in.audio.i_rate != 48000 &&
525
0
        p_enc->fmt_in.audio.i_rate != 96000 &&
526
0
        p_enc->fmt_in.audio.i_rate != 44100 &&
527
0
        p_enc->fmt_in.audio.i_rate != 32000 )
528
0
    {
529
0
        msg_Err( p_enc, "DVD LPCM supports only sample rates of 48, 96, 44.1 or 32 kHz" );
530
0
        return VLC_EGENERIC;
531
0
    }
532
533
0
    if( p_enc->fmt_in.audio.i_channels > 8 )
534
0
    {
535
0
        msg_Err( p_enc, "DVD LPCM supports a maximum of eight channels" );
536
0
        return VLC_EGENERIC;
537
0
    }
538
539
    /* Allocate the memory needed to store the encoder's structure */
540
0
    if( ( p_sys =
541
0
          (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
542
0
        return VLC_ENOMEM;
543
544
    /* In DVD LCPM, a frame is always 150 PTS ticks. */
545
0
    p_sys->i_frame_samples = p_enc->fmt_in.audio.i_rate * 150 / 90000;
546
0
    p_sys->p_buffer = xmalloc(p_sys->i_frame_samples
547
0
                            * p_enc->fmt_in.audio.i_channels * 16);
548
0
    p_sys->i_buffer_used = 0;
549
0
    p_sys->i_frame_num = 0;
550
551
0
    p_sys->i_channels = p_enc->fmt_in.audio.i_channels;
552
0
    p_sys->i_rate = p_enc->fmt_in.audio.i_rate;
553
554
0
    p_enc->fmt_in.i_codec = p_enc->fmt_out.i_codec;
555
556
0
    p_enc->fmt_in.audio.i_bitspersample = 16;
557
0
    p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
558
559
0
    p_enc->fmt_out.i_bitrate =
560
0
        p_enc->fmt_in.audio.i_channels *
561
0
        p_enc->fmt_in.audio.i_rate *
562
0
        p_enc->fmt_in.audio.i_bitspersample *
563
0
        (p_sys->i_frame_samples + LPCM_VOB_HEADER_LEN) /
564
0
        p_sys->i_frame_samples;
565
566
0
    static const struct vlc_encoder_operations ops =
567
0
    {
568
0
        .close = CloseEncoder,
569
0
        .encode_audio = EncodeFrames,
570
0
    };
571
572
0
    p_enc->ops = &ops;
573
0
    p_enc->p_sys = p_sys;
574
575
0
    return VLC_SUCCESS;
576
0
}
577
578
/*****************************************************************************
579
 * CloseEncoder: lpcm encoder destruction
580
 *****************************************************************************/
581
static void CloseEncoder ( encoder_t *p_enc )
582
0
{
583
0
    encoder_sys_t *p_sys = p_enc->p_sys;
584
585
0
    free( p_sys->p_buffer );
586
0
    free( p_sys );
587
0
}
588
589
/*****************************************************************************
590
 * EncodeFrames: encode zero or more LCPM audio packets
591
 *****************************************************************************/
592
static block_t *EncodeFrames( encoder_t *p_enc, block_t *p_aout_buf )
593
0
{
594
0
    encoder_sys_t *p_sys = p_enc->p_sys;
595
0
    block_t *p_first_block = NULL, *p_last_block = NULL;
596
597
0
    if( !p_aout_buf || !p_aout_buf->i_buffer ) return NULL;
598
599
0
    const int i_num_frames = ( p_sys->i_buffer_used + p_aout_buf->i_nb_samples ) /
600
0
        p_sys->i_frame_samples;
601
0
    const int i_leftover_samples = ( p_sys->i_buffer_used + p_aout_buf->i_nb_samples ) %
602
0
        p_sys->i_frame_samples;
603
0
    const int i_frame_size = p_sys->i_frame_samples * p_sys->i_channels * 2 + LPCM_VOB_HEADER_LEN;
604
0
    const int i_start_offset = -p_sys->i_buffer_used;
605
606
0
    uint8_t i_freq_code = 0;
607
608
0
    switch( p_sys->i_rate ) {
609
0
    case 48000:
610
0
        i_freq_code = 0;
611
0
        break;
612
0
    case 96000:
613
0
        i_freq_code = 1;
614
0
        break;
615
0
    case 44100:
616
0
        i_freq_code = 2;
617
0
        break;
618
0
    case 32000:
619
0
        i_freq_code = 3;
620
0
        break;
621
0
    default:
622
0
        vlc_assert_unreachable();
623
0
    }
624
625
0
    int i_bytes_consumed = 0;
626
627
0
    for ( int i = 0; i < i_num_frames; ++i )
628
0
    {
629
0
        block_t *p_block = block_Alloc( i_frame_size );
630
0
        if( unlikely(p_block == NULL) )
631
0
        {
632
0
            if( p_first_block )
633
0
                block_ChainRelease( p_first_block );
634
635
0
            return NULL;
636
0
        }
637
638
0
        uint8_t *frame = (uint8_t *)p_block->p_buffer;
639
0
        frame[0] = 1;  /* one frame in packet */
640
0
        frame[1] = 0;
641
0
        frame[2] = 0;  /* no first access unit */
642
0
        frame[3] = (p_sys->i_frame_num + i) & 0x1f;  /* no emphasis, no mute */
643
0
        frame[4] = (i_freq_code << 4) | (p_sys->i_channels - 1);
644
0
        frame[5] = 0x80;  /* neutral dynamic range */
645
646
0
        const int i_consume_samples = p_sys->i_frame_samples - p_sys->i_buffer_used;
647
0
        const int i_kept_bytes = p_sys->i_buffer_used * p_sys->i_channels * 2;
648
0
        const int i_consume_bytes = i_consume_samples * p_sys->i_channels * 2;
649
650
#ifdef WORDS_BIGENDIAN
651
        memcpy( frame + 6, p_sys->p_buffer, i_kept_bytes );
652
        memcpy( frame + 6 + i_kept_bytes, p_aout_buf->p_buffer + i_bytes_consumed,
653
                i_consume_bytes );
654
#else
655
0
        swab( p_sys->p_buffer, frame + 6, i_kept_bytes );
656
0
        swab( p_aout_buf->p_buffer + i_bytes_consumed, frame + 6 + i_kept_bytes,
657
0
              i_consume_bytes );
658
0
#endif
659
660
0
        p_sys->i_frame_num++;
661
0
        p_sys->i_buffer_used = 0;
662
0
        i_bytes_consumed += i_consume_bytes;
663
664
        /* We need to find i_length by means of next_pts due to possible roundoff errors. */
665
0
        vlc_tick_t this_pts = p_aout_buf->i_pts +
666
0
            vlc_tick_from_samples(i * p_sys->i_frame_samples + i_start_offset, p_sys->i_rate);
667
0
        vlc_tick_t next_pts = p_aout_buf->i_pts +
668
0
            vlc_tick_from_samples((i + 1) * p_sys->i_frame_samples + i_start_offset, p_sys->i_rate);
669
670
0
        p_block->i_pts = p_block->i_dts = this_pts;
671
0
        p_block->i_length = next_pts - this_pts;
672
673
0
        if( !p_first_block )
674
0
            p_first_block = p_last_block = p_block;
675
0
        else
676
0
            p_last_block = p_last_block->p_next = p_block;
677
0
    }
678
679
0
    memcpy( p_sys->p_buffer,
680
0
            p_aout_buf->p_buffer + i_bytes_consumed,
681
0
            i_leftover_samples * p_sys->i_channels * 2 );
682
0
    p_sys->i_buffer_used = i_leftover_samples;
683
684
0
    return p_first_block;
685
0
}
686
#endif
687
688
/*****************************************************************************
689
 *
690
 *****************************************************************************/
691
static int VobHeader( unsigned *pi_rate,
692
                      unsigned *pi_channels, unsigned *pi_original_channels,
693
                      unsigned *pi_bits,
694
                      const uint8_t *p_header )
695
3.93k
{
696
3.93k
    const uint8_t i_header = p_header[4];
697
698
3.93k
    switch( (i_header >> 4) & 0x3 )
699
3.93k
    {
700
317
    case 0:
701
317
        *pi_rate = 48000;
702
317
        break;
703
80
    case 1:
704
80
        *pi_rate = 96000;
705
80
        break;
706
115
    case 2:
707
115
        *pi_rate = 44100;
708
115
        break;
709
3.42k
    case 3:
710
3.42k
        *pi_rate = 32000;
711
3.42k
        break;
712
3.93k
    }
713
714
3.93k
    *pi_channels = (i_header & 0x7) + 1;
715
3.93k
    switch( *pi_channels - 1 )
716
3.93k
    {
717
296
    case 0:
718
296
        *pi_original_channels = AOUT_CHAN_CENTER;
719
296
        break;
720
77
    case 1:
721
77
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
722
77
        break;
723
3
    case 2:
724
        /* This is unsure. */
725
3
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE;
726
3
        break;
727
117
    case 3:
728
117
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
729
117
                               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
730
117
        break;
731
9
    case 4:
732
        /* This is unsure. */
733
9
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
734
9
                               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
735
9
                               | AOUT_CHAN_LFE;
736
9
        break;
737
14
    case 5:
738
14
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
739
14
                               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
740
14
                               | AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
741
14
        break;
742
2
    case 6:
743
2
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
744
2
                               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
745
2
                               | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
746
2
                               | AOUT_CHAN_MIDDLERIGHT;
747
2
        break;
748
3.41k
    case 7:
749
3.41k
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
750
3.41k
                               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
751
3.41k
                               | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
752
3.41k
                               | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
753
3.41k
        break;
754
3.93k
    }
755
756
3.93k
    switch( (i_header >> 6) & 0x3 )
757
3.93k
    {
758
3
    case 2:
759
3
        *pi_bits = 24;
760
3
        break;
761
76
    case 1:
762
76
        *pi_bits = 20;
763
76
        break;
764
331
    case 0:
765
3.85k
    default:
766
3.85k
        *pi_bits = 16;
767
3.85k
        break;
768
3.93k
    }
769
770
    /* Check frame sync and drop it. */
771
3.93k
    if( p_header[5] != 0x80 )
772
608
        return -1;
773
3.32k
    return 0;
774
3.93k
}
775
776
static const unsigned p_aob_group1[21][6] = {
777
    { AOUT_CHAN_CENTER, 0 },
778
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
779
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
780
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
781
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
782
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
783
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
784
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
785
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
786
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
787
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
788
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
789
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
790
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
791
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
792
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
793
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
794
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
795
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0  },
796
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0  },
797
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0  },
798
};
799
static const unsigned p_aob_group2[21][6] = {
800
    { 0 },
801
    { 0 },
802
    { AOUT_CHAN_REARCENTER, 0 },
803
    { AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,    0 },
804
    { AOUT_CHAN_LFE,        0 },
805
    { AOUT_CHAN_LFE,        AOUT_CHAN_REARCENTER,   0 },
806
    { AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT,     AOUT_CHAN_REARRIGHT,    0 },
807
    { AOUT_CHAN_CENTER,     0 },
808
    { AOUT_CHAN_CENTER,     AOUT_CHAN_REARCENTER, 0 },
809
    { AOUT_CHAN_CENTER,     AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,    0 },
810
    { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,        0 },
811
    { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,        AOUT_CHAN_REARCENTER,   0 },
812
    { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT,     AOUT_CHAN_REARRIGHT,    0 },
813
    { AOUT_CHAN_REARCENTER, 0 },
814
    { AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,    0 },
815
    { AOUT_CHAN_LFE,        0 },
816
    { AOUT_CHAN_LFE,        AOUT_CHAN_REARCENTER,   0 },
817
    { AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT,     AOUT_CHAN_REARRIGHT,    0 },
818
    { AOUT_CHAN_LFE,        0 },
819
    { AOUT_CHAN_CENTER,     0 },
820
    { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,          0 },
821
};
822
823
static int AobHeader( unsigned *pi_rate,
824
                      unsigned *pi_channels, unsigned *pi_layout,
825
                      unsigned *pi_bits,
826
                      unsigned *pi_padding,
827
                      aob_group_t g[2],
828
                      const uint8_t *p_header )
829
41.9k
{
830
41.9k
    const unsigned i_header_size = GetWBE( &p_header[1] );
831
41.9k
    if( i_header_size + 3 < LPCM_AOB_HEADER_LEN )
832
14.4k
        return VLC_EGENERIC;
833
834
    /* Padding = Total header size - Normal AOB header
835
     *         + 3 bytes (1 for continuity counter + 2 for header_size ) */
836
27.4k
    *pi_padding = 3 + i_header_size - LPCM_AOB_HEADER_LEN;
837
838
27.4k
    const int i_index_size_g1 = (p_header[6] >> 4);
839
27.4k
    const int i_index_size_g2 = (p_header[6]     ) & 0x0f;
840
27.4k
    const int i_index_rate_g1 = (p_header[7] >> 4);
841
27.4k
    const int i_index_rate_g2 = (p_header[7]     ) & 0x0f;
842
27.4k
    const int i_assignment     = p_header[9];
843
844
    /* Validate */
845
27.4k
    if( i_index_size_g1 > 0x02 ||
846
18.3k
        ( i_index_size_g2 != 0x0f && i_index_size_g2 > 0x02 ) )
847
12.4k
        return VLC_EGENERIC;
848
15.0k
    if( (i_index_rate_g1 & 0x07) > 0x02 ||
849
14.1k
        ( i_index_rate_g2 != 0x0f && (i_index_rate_g1 & 0x07) > 0x02 ) )
850
932
        return VLC_EGENERIC;
851
14.1k
    if( i_assignment > 20 )
852
5.82k
        return VLC_EGENERIC;
853
854
    /* */
855
    /* max is 0x2, 0xf == unused */
856
8.30k
    g[0].i_bits = 16 + 4 * i_index_size_g1;
857
8.30k
    g[1].i_bits = ( i_index_size_g2 != 0x0f ) ? 16 + 4 * i_index_size_g2 : 0;
858
859
    /* No info about interlacing of different sampling rate */
860
8.30k
    if ( g[1].i_bits && ( i_index_rate_g1 != i_index_rate_g2 ) )
861
815
        return VLC_EGENERIC;
862
863
    /* only set 16bits if both are <= */
864
7.48k
    if( g[0].i_bits )
865
7.48k
    {
866
7.48k
        if( g[0].i_bits > 16 || g[1].i_bits > 16 )
867
3.25k
            *pi_bits = 32;
868
4.23k
        else
869
4.23k
            *pi_bits = 16;
870
7.48k
    }
871
0
    else
872
0
        return VLC_EGENERIC;
873
874
7.48k
    if( i_index_rate_g1 & 0x08 )
875
510
        *pi_rate = 44100 << (i_index_rate_g1 & 0x07);
876
6.97k
    else
877
6.97k
        *pi_rate = 48000 << (i_index_rate_g1 & 0x07);
878
879
880
    /* Group1 */
881
7.48k
    unsigned i_channels1 = 0;
882
7.48k
    unsigned i_layout1 = 0;
883
20.6k
    for( int i = 0; p_aob_group1[i_assignment][i] != 0; i++ )
884
13.1k
    {
885
13.1k
        i_channels1++;
886
13.1k
        i_layout1 |= p_aob_group1[i_assignment][i];
887
13.1k
    }
888
    /* Group2 */
889
7.48k
    unsigned i_channels2 = 0;
890
7.48k
    unsigned i_layout2 = 0;
891
7.48k
    if( i_index_size_g2 != 0x0f && i_index_rate_g2 != 0x0f )
892
6.66k
    {
893
13.2k
        for( int i = 0; p_aob_group2[i_assignment][i] != 0; i++ )
894
6.62k
        {
895
6.62k
            i_channels2++;
896
6.62k
            i_layout2 |= p_aob_group2[i_assignment][i];
897
6.62k
        }
898
6.66k
        assert( (i_layout1 & i_layout2) == 0 );
899
6.66k
    }
900
901
    /* */
902
7.48k
    *pi_channels = i_channels1 + ( g[1].i_bits ? i_channels2 : 0 );
903
7.48k
    *pi_layout   = i_layout1   | ( g[1].i_bits ? i_layout2   : 0 );
904
905
    /* */
906
22.4k
    for( unsigned i = 0; i < 2; i++ )
907
14.9k
    {
908
14.9k
        const unsigned *p_aob = i == 0 ? p_aob_group1[i_assignment] :
909
14.9k
                                         p_aob_group2[i_assignment];
910
14.9k
        g[i].i_channels = i == 0 ? i_channels1 :
911
14.9k
                                   i_channels2;
912
913
14.9k
        if( !g[i].i_bits )
914
827
            continue;
915
33.9k
        for( unsigned j = 0; j < g[i].i_channels; j++ )
916
19.7k
        {
917
19.7k
            g[i].pi_position[j] = 0;
918
95.3k
            for( int k = 0; pi_vlc_chan_order_wg4[k] != 0; k++ )
919
95.3k
            {
920
95.3k
                const unsigned i_channel = pi_vlc_chan_order_wg4[k];
921
95.3k
                if( i_channel == p_aob[j] )
922
19.7k
                    break;
923
75.5k
                if( (*pi_layout) & i_channel )
924
25.8k
                    g[i].pi_position[j]++;
925
75.5k
            }
926
19.7k
        }
927
14.1k
    }
928
7.48k
    return VLC_SUCCESS;
929
7.48k
}
930
931
static const uint32_t pi_8channels_in[] =
932
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
933
  AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
934
  AOUT_CHAN_MIDDLERIGHT, AOUT_CHAN_LFE, 0 };
935
936
static const uint32_t pi_7channels_in[] =
937
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
938
  AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
939
  AOUT_CHAN_MIDDLERIGHT, 0 };
940
941
static const uint32_t pi_6channels_in[] =
942
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
943
  AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_LFE, 0 };
944
945
static const uint32_t pi_5channels_in[] =
946
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
947
  AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, 0 };
948
949
static const uint32_t pi_4channels_in[] =
950
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
951
  AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 };
952
953
static const uint32_t pi_3channels_in[] =
954
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
955
  AOUT_CHAN_CENTER, 0 };
956
957
958
static int BdHeader( decoder_sys_t *p_sys,
959
                     unsigned *pi_rate,
960
                     unsigned *pi_channels,
961
                     unsigned *pi_channels_padding,
962
                     unsigned *pi_original_channels,
963
                     unsigned *pi_bits,
964
                     const uint8_t *p_header )
965
80.5k
{
966
80.5k
    const uint32_t h = GetDWBE( p_header );
967
80.5k
    const uint32_t *pi_channels_in = NULL;
968
80.5k
    switch( ( h & 0xf000) >> 12 )
969
80.5k
    {
970
4.26k
    case 1:
971
4.26k
        *pi_channels = 1;
972
4.26k
        *pi_original_channels = AOUT_CHAN_CENTER;
973
4.26k
        break;
974
2.83k
    case 3:
975
2.83k
        *pi_channels = 2;
976
2.83k
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
977
2.83k
        break;
978
5.77k
    case 4:
979
5.77k
        *pi_channels = 3;
980
5.77k
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER;
981
5.77k
        pi_channels_in = pi_3channels_in;
982
5.77k
        break;
983
2.90k
    case 5:
984
2.90k
        *pi_channels = 3;
985
2.90k
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER;
986
2.90k
        break;
987
8.18k
    case 6:
988
8.18k
        *pi_channels = 4;
989
8.18k
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
990
8.18k
                                AOUT_CHAN_REARCENTER;
991
8.18k
        break;
992
6.64k
    case 7:
993
6.64k
        *pi_channels = 4;
994
6.64k
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
995
6.64k
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
996
6.64k
        pi_channels_in = pi_4channels_in;
997
6.64k
        break;
998
2.95k
    case 8:
999
2.95k
        *pi_channels = 5;
1000
2.95k
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
1001
2.95k
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
1002
2.95k
        pi_channels_in = pi_5channels_in;
1003
2.95k
        break;
1004
1.92k
    case 9:
1005
1.92k
        *pi_channels = 6;
1006
1.92k
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
1007
1.92k
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
1008
1.92k
                                AOUT_CHAN_LFE;
1009
1.92k
        pi_channels_in = pi_6channels_in;
1010
1.92k
        break;
1011
2.53k
    case 10:
1012
2.53k
        *pi_channels = 7;
1013
2.53k
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
1014
2.53k
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
1015
2.53k
                                AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT;
1016
2.53k
        pi_channels_in = pi_7channels_in;
1017
2.53k
        break;
1018
1.78k
    case 11:
1019
1.78k
        *pi_channels = 8;
1020
1.78k
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
1021
1.78k
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
1022
1.78k
                                AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
1023
1.78k
                                AOUT_CHAN_LFE;
1024
1.78k
        pi_channels_in = pi_8channels_in;
1025
1.78k
        break;
1026
1027
40.7k
    default:
1028
40.7k
        return -1;
1029
80.5k
    }
1030
39.8k
    *pi_channels_padding = *pi_channels & 1;
1031
1032
39.8k
    switch( (h >> 6) & 0x03 )
1033
39.8k
    {
1034
18.1k
    case 1:
1035
18.1k
        *pi_bits = 16;
1036
18.1k
        break;
1037
6.07k
    case 2: /* 20 bits but samples are stored on 24 bits */
1038
12.2k
    case 3: /* 24 bits */
1039
12.2k
        *pi_bits = 24;
1040
12.2k
        break;
1041
9.43k
    default:
1042
9.43k
        return -1;
1043
39.8k
    }
1044
30.3k
    switch( (h >> 8) & 0x0f )
1045
30.3k
    {
1046
5.70k
    case 1:
1047
5.70k
        *pi_rate = 48000;
1048
5.70k
        break;
1049
5.10k
    case 4:
1050
5.10k
        *pi_rate = 96000;
1051
5.10k
        break;
1052
3.62k
    case 5:
1053
3.62k
        *pi_rate = 192000;
1054
3.62k
        break;
1055
15.9k
    default:
1056
15.9k
        return -1;
1057
30.3k
    }
1058
1059
14.4k
    if( pi_channels_in )
1060
8.43k
    {
1061
8.43k
        p_sys->i_chans_to_reorder =
1062
8.43k
            aout_CheckChannelReorder( pi_channels_in, NULL,
1063
8.43k
                                      *pi_original_channels,
1064
8.43k
                                      p_sys->pi_chan_table );
1065
8.43k
    }
1066
1067
14.4k
    return 0;
1068
30.3k
}
1069
1070
static int WidiHeader( unsigned *pi_rate,
1071
                       unsigned *pi_channels, unsigned *pi_original_channels,
1072
                       unsigned *pi_bits,
1073
                       const uint8_t *p_header )
1074
24.9k
{
1075
24.9k
    if ( p_header[0] != 0xa0 || p_header[1] != 0x06 )
1076
24.8k
        return -1;
1077
1078
75
    switch( ( p_header[3] & 0x38 ) >> 3 )
1079
75
    {
1080
36
    case 0x01: //0b001
1081
36
        *pi_rate = 44100;
1082
36
        break;
1083
36
    case 0x02: //0b010
1084
36
        *pi_rate = 48000;
1085
36
        break;
1086
3
    default:
1087
3
        return -1;
1088
75
    }
1089
1090
72
    if( p_header[3] >> 6 != 0 )
1091
36
        return -1;
1092
36
    else
1093
36
        *pi_bits = 16;
1094
1095
36
    *pi_channels = (p_header[3] & 0x7) + 1;
1096
1097
36
    *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
1098
1099
36
    return 0;
1100
72
}
1101
1102
static void VobExtract( block_t *p_aout_buffer, block_t *p_block,
1103
                        unsigned i_bits )
1104
0
{
1105
    /* 20/24 bits LPCM use special packing */
1106
0
    if( i_bits == 24 )
1107
0
    {
1108
0
        uint32_t *p_out = (uint32_t *)p_aout_buffer->p_buffer;
1109
1110
0
        while( p_block->i_buffer / 12 )
1111
0
        {
1112
            /* Sample 1 */
1113
0
            *(p_out++) = (p_block->p_buffer[ 0] << 24)
1114
0
                       | (p_block->p_buffer[ 1] << 16)
1115
0
                       | (p_block->p_buffer[ 8] <<  8);
1116
            /* Sample 2 */
1117
0
            *(p_out++) = (p_block->p_buffer[ 2] << 24)
1118
0
                       | (p_block->p_buffer[ 3] << 16)
1119
0
                       | (p_block->p_buffer[ 9] <<  8);
1120
            /* Sample 3 */
1121
0
            *(p_out++) = (p_block->p_buffer[ 4] << 24)
1122
0
                       | (p_block->p_buffer[ 5] << 16)
1123
0
                       | (p_block->p_buffer[10] <<  8);
1124
            /* Sample 4 */
1125
0
            *(p_out++) = (p_block->p_buffer[ 6] << 24)
1126
0
                       | (p_block->p_buffer[ 7] << 16)
1127
0
                       | (p_block->p_buffer[11] <<  8);
1128
1129
0
            p_block->i_buffer -= 12;
1130
0
            p_block->p_buffer += 12;
1131
0
        }
1132
0
    }
1133
0
    else if( i_bits == 20 )
1134
0
    {
1135
0
        uint32_t *p_out = (uint32_t *)p_aout_buffer->p_buffer;
1136
1137
0
        while( p_block->i_buffer / 10 )
1138
0
        {
1139
            /* Sample 1 */
1140
0
            *(p_out++) = ( p_block->p_buffer[0]         << 24)
1141
0
                       | ( p_block->p_buffer[1]         << 16)
1142
0
                       | ((p_block->p_buffer[8] & 0xF0) <<  8);
1143
            /* Sample 2 */
1144
0
            *(p_out++) = ( p_block->p_buffer[2]         << 24)
1145
0
                       | ( p_block->p_buffer[3]         << 16)
1146
0
                       | ((p_block->p_buffer[8] & 0x0F) << 12);
1147
            /* Sample 3 */
1148
0
            *(p_out++) = ( p_block->p_buffer[4]         << 24)
1149
0
                       | ( p_block->p_buffer[5]         << 16)
1150
0
                       | ((p_block->p_buffer[9] & 0xF0) <<  8);
1151
            /* Sample 4 */
1152
0
            *(p_out++) = ( p_block->p_buffer[6]         << 24)
1153
0
                       | ( p_block->p_buffer[7]         << 16)
1154
0
                       | ((p_block->p_buffer[9] & 0x0F) << 12);
1155
1156
0
            p_block->i_buffer -= 10;
1157
0
            p_block->p_buffer += 10;
1158
0
        }
1159
0
    }
1160
0
    else
1161
0
    {
1162
0
        assert( i_bits == 16 );
1163
#ifdef WORDS_BIGENDIAN
1164
        memcpy( p_aout_buffer->p_buffer, p_block->p_buffer, p_block->i_buffer );
1165
#else
1166
0
        swab( p_block->p_buffer, p_aout_buffer->p_buffer, p_block->i_buffer );
1167
0
#endif
1168
0
    }
1169
0
}
1170
1171
static void AobExtract( block_t *p_aout_buffer,
1172
                        block_t *p_block, unsigned i_aoutbits, aob_group_t p_group[2] )
1173
0
{
1174
0
    uint8_t *p_out = p_aout_buffer->p_buffer;
1175
0
    const unsigned i_total_channels = p_group[0].i_channels +
1176
0
                                      ( p_group[1].i_bits ? p_group[1].i_channels : 0 );
1177
1178
0
    while( p_block->i_buffer > 0 )
1179
0
    {
1180
0
        unsigned int i_aout_written = 0;
1181
1182
0
        for( int i = 0; i < 2; i++ )
1183
0
        {
1184
0
            const aob_group_t *g = &p_group[1-i];
1185
0
            const unsigned int i_group_size = 2 * g->i_channels * g->i_bits / 8;
1186
1187
0
            if( p_block->i_buffer < i_group_size )
1188
0
            {
1189
0
                p_block->i_buffer = 0;
1190
0
                break;
1191
0
            }
1192
1193
0
            if( !g->i_bits )
1194
0
                continue;
1195
1196
0
            for( unsigned n = 0; n < 2; n++ )
1197
0
            {
1198
0
                for( unsigned j = 0; j < g->i_channels; j++ )
1199
0
                {
1200
0
                    const int i_src = n * g->i_channels + j;
1201
0
                    const int i_dst = n * i_total_channels + g->pi_position[j];
1202
0
                    uint32_t *p_out32 = (uint32_t *) &p_out[4*i_dst];
1203
1204
0
                    if( g->i_bits == 24 )
1205
0
                    {
1206
0
                        assert( i_aoutbits == 32 );
1207
0
                        *p_out32 = (p_block->p_buffer[2*i_src+0] << 24)
1208
0
                                 | (p_block->p_buffer[2*i_src+1] << 16)
1209
0
                                 | (p_block->p_buffer[4*g->i_channels+i_src] <<  8);
1210
#ifdef WORDS_BIGENDIAN
1211
                        *p_out32 = vlc_bswap32(*p_out32);
1212
#endif
1213
0
                        i_aout_written += 4;
1214
0
                    }
1215
0
                    else if( g->i_bits == 20 )
1216
0
                    {
1217
0
                        assert( i_aoutbits == 32 );
1218
0
                        *p_out32 = (p_block->p_buffer[2*i_src+0] << 24)
1219
0
                                 | (p_block->p_buffer[2*i_src+1] << 16)
1220
0
                                 | (((p_block->p_buffer[4*g->i_channels+i_src] << ((!n)?0:4) ) & 0xf0) <<  8);
1221
#ifdef WORDS_BIGENDIAN
1222
                        *p_out32 = vlc_bswap32(*p_out32);
1223
#endif
1224
0
                        i_aout_written += 4;
1225
0
                    }
1226
0
                    else
1227
0
                    {
1228
0
                        assert( g->i_bits == 16 );
1229
0
                        assert( i_aoutbits == 16 || i_aoutbits == 32 );
1230
0
                        if( i_aoutbits == 16 )
1231
0
                        {
1232
#ifdef WORDS_BIGENDIAN
1233
                            memcpy( &p_out[2*i_dst], &p_block->p_buffer[2*i_src], 2 );
1234
#else
1235
0
                            p_out[2*i_dst+1] = p_block->p_buffer[2*i_src+0];
1236
0
                            p_out[2*i_dst+0] = p_block->p_buffer[2*i_src+1];
1237
0
#endif
1238
0
                            i_aout_written += 2;
1239
0
                        }
1240
0
                        else
1241
0
                        {
1242
0
                            *p_out32 = (p_block->p_buffer[2*i_src+0] << 24)
1243
0
                                     | (p_block->p_buffer[2*i_src+1] << 16);
1244
#ifdef WORDS_BIGENDIAN
1245
                            *p_out32 = vlc_bswap32(*p_out32);
1246
#endif
1247
0
                            i_aout_written += 4;
1248
0
                        }
1249
0
                    }
1250
0
                }
1251
0
            }
1252
1253
            /* */
1254
0
            p_block->i_buffer -= i_group_size;
1255
0
            p_block->p_buffer += i_group_size;
1256
0
        }
1257
0
        p_out += i_aout_written;
1258
0
    }
1259
0
}
1260
static void BdExtract( block_t *p_aout_buffer, block_t *p_block,
1261
                       unsigned i_frame_length,
1262
                       unsigned i_channels, unsigned i_channels_padding,
1263
                       unsigned i_bits )
1264
0
{
1265
0
    if( i_bits != 16 || i_channels_padding > 0 )
1266
0
    {
1267
0
        uint8_t *p_src = p_block->p_buffer;
1268
0
        uint8_t *p_dst = p_aout_buffer->p_buffer;
1269
0
        int dst_inc = ((i_bits == 16) ? 2 : 4) * i_channels;
1270
1271
0
        while( i_frame_length > 0 )
1272
0
        {
1273
#ifdef WORDS_BIGENDIAN
1274
            memcpy( p_dst, p_src, i_channels * i_bits / 8 );
1275
#else
1276
0
            if (i_bits == 16) {
1277
0
                swab( p_src, p_dst, (i_channels + i_channels_padding) * i_bits / 8 );
1278
0
            } else {
1279
0
                for (unsigned i = 0; i < i_channels; ++i) {
1280
0
                    p_dst[i * 4] = 0;
1281
0
                    p_dst[1 + (i * 4)] = p_src[2 + (i * 3)];
1282
0
                    p_dst[2 + (i * 4)] = p_src[1 + (i * 3)];
1283
0
                    p_dst[3 + (i * 4)] = p_src[i * 3];
1284
0
                }
1285
0
            }
1286
0
#endif
1287
0
            p_src += (i_channels + i_channels_padding) * i_bits / 8;
1288
0
            p_dst += dst_inc;
1289
0
            i_frame_length--;
1290
0
        }
1291
0
    }
1292
0
    else
1293
0
    {
1294
#ifdef WORDS_BIGENDIAN
1295
        memcpy( p_aout_buffer->p_buffer, p_block->p_buffer, p_block->i_buffer );
1296
#else
1297
0
        swab( p_block->p_buffer, p_aout_buffer->p_buffer, p_block->i_buffer );
1298
0
#endif
1299
0
    }
1300
0
}
1301