lpcm.c 41.4 KB
Newer Older
1
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
2
 * lpcm.c: lpcm decoder/packetizer module
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
4
 * Copyright (C) 1999-2008 VLC authors and VideoLAN
5
 * $Id$
6 7 8
 *
 * Authors: Samuel Hocevar <sam@zoy.org>
 *          Henri Fallon <henri@videolan.org>
9
 *          Christophe Massiot <massiot@via.ecp.fr>
10
 *          Gildas Bazin <gbazin@videolan.org>
11
 *          Lauren Aimar <fenrir _AT_ videolan _DOT_ org >
12
 *          Steinar H. Gunderson <steinar+vlc@gunderson.no>
13
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
14 15 16
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
17
 * (at your option) any later version.
18
 *
19 20
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
21 22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
23
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
24 25 26
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
27 28 29 30 31
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
32 33 34 35
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

36
#include <vlc_common.h>
37
#include <vlc_plugin.h>
Clément Stenac's avatar
Clément Stenac committed
38 39
#include <vlc_codec.h>
#include <vlc_aout.h>
40
#include <unistd.h>
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
41
#include <assert.h>
42

Laurent Aimar's avatar
Laurent Aimar committed
43 44 45 46 47 48 49
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int  OpenDecoder   ( vlc_object_t * );
static int  OpenPacketizer( vlc_object_t * );
static void CloseCommon   ( vlc_object_t * );

50 51 52
#ifdef ENABLE_SOUT
static int  OpenEncoder   ( vlc_object_t * );
static void CloseEncoder  ( vlc_object_t * );
53
static block_t *EncodeFrames( encoder_t *, block_t * );
54 55
#endif

Laurent Aimar's avatar
Laurent Aimar committed
56 57 58 59 60 61 62 63 64 65 66 67 68
vlc_module_begin ()

    set_category( CAT_INPUT )
    set_subcategory( SUBCAT_INPUT_ACODEC )
    set_description( N_("Linear PCM audio decoder") )
    set_capability( "decoder", 100 )
    set_callbacks( OpenDecoder, CloseCommon )

    add_submodule ()
    set_description( N_("Linear PCM audio packetizer") )
    set_capability( "packetizer", 100 )
    set_callbacks( OpenPacketizer, CloseCommon )

69 70 71 72 73 74 75 76
#ifdef ENABLE_SOUT
    add_submodule ()
    set_description( N_("Linear PCM audio encoder") )
    set_capability( "encoder", 100 )
    set_callbacks( OpenEncoder, CloseEncoder )
    add_shortcut( "lpcm" )
#endif

Laurent Aimar's avatar
Laurent Aimar committed
77 78 79
vlc_module_end ()


80
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
81
 * decoder_sys_t : lpcm decoder descriptor
82
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
83
struct decoder_sys_t
84
{
Gildas Bazin's avatar
 
Gildas Bazin committed
85
    /* Module mode */
86
    bool b_packetizer;
87 88 89 90

    /*
     * Output properties
     */
91
    date_t   end_date;
Gildas Bazin's avatar
 
Gildas Bazin committed
92

Laurent Aimar's avatar
Laurent Aimar committed
93
    /* */
94
    unsigned i_header_size;
95
    int      i_type;
96 97
    uint8_t  i_chans_to_reorder;
    uint8_t  pi_chan_table[AOUT_CHAN_MAX];
Gildas Bazin's avatar
 
Gildas Bazin committed
98
};
99

100 101 102 103 104 105 106 107 108 109 110 111 112
#ifdef ENABLE_SOUT
struct encoder_sys_t
{
    int     i_channels;
    int     i_rate;

    int     i_frame_samples;
    uint8_t *p_buffer;
    int     i_buffer_used;
    int     i_frame_num;
};
#endif

113
/*
Laurent Aimar's avatar
Laurent Aimar committed
114
 * LPCM DVD header :
115 116 117 118 119 120 121 122 123
 * - number of frames in this packet (8 bits)
 * - first access unit (16 bits) == 0x0003 ?
 * - emphasis (1 bit)
 * - mute (1 bit)
 * - reserved (1 bit)
 * - current frame (5 bits)
 * - quantisation (2 bits) 0 == 16bps, 1 == 20bps, 2 == 24bps, 3 == illegal
 * - frequency (2 bits) 0 == 48 kHz, 1 == 96 kHz, 2 == 44.1 kHz, 3 == 32 kHz
 * - reserved (1 bit)
124
 * - number of channels - 1 (3 bits) 1 == 2 channels
125
 * - dynamic range (8 bits) 0x80 == neutral
126
 *
127 128 129 130 131 132 133 134 135 136 137 138
 * LPCM DVD-A header (http://dvd-audio.sourceforge.net/spec/aob.shtml)
 * - continuity counter (8 bits, clipped to 0x00-0x1f)
 * - header size (16 bits)
 * - byte pointer to start of first audio frame.
 * - unknown (8bits, 0x10 for stereo, 0x00 for surround)
 * - sample size (4+4 bits)
 * - samplerate (4+4 bits)
 * - unknown (8 bits)
 * - group assignment (8 bits)
 * - unknown (8 bits)
 * - padding(variable)
 *
139
 * LPCM BD header :
Benjamin Drung's avatar
Benjamin Drung committed
140
 * - unknown (16 bits)
141 142 143 144
 * - number of channels (4 bits)
 * - frequency (4 bits)
 * - bits per sample (2 bits)
 * - unknown (6 bits)
145 146 147 148 149 150 151 152 153 154 155
 *
 * LPCM WIDI header
 * refers http://www.dvdforum.org/images/Guideline1394V10R0_20020911.pdf
  * - sub stream id (8 bits) = 0xa0
 * - frame header count (8 bits) = 0x06
 * [ 0b0000000 (7 bits)
 * - audio emphasis (1 bit) ] (8 bits)
 * [ qz word length (2 bits) 0x00 == 16bits
 * - sampling freq (3 bits) 0b001 == 44.1K, 0b010 == 48K Hz
 * - channels count(3 bits) ] (8 bits) 0b000 == dual mono, 0b001 == stereo
 * follows: LPCM data (15360 bits/1920 bytes)
156 157
 */

158 159
#define LPCM_VOB_HEADER_LEN (6)
#define LPCM_AOB_HEADER_LEN (11)
160
#define LPCM_BD_HEADER_LEN (4)
161
#define LPCM_WIDI_HEADER_LEN (4)
162

163 164 165 166 167
enum
{
    LPCM_VOB,
    LPCM_AOB,
    LPCM_BD,
168
    LPCM_WIDI,
169 170 171 172 173
};

typedef struct
{
    unsigned i_channels;
174
    unsigned i_bits;
175 176 177
    unsigned pi_position[6];
} aob_group_t;

178 179 180
/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
181
static block_t *DecodeFrame  ( decoder_t *, block_t ** );
182
static void Flush( decoder_t * );
183 184 185

/* */
static int VobHeader( unsigned *pi_rate,
186 187 188
                      unsigned *pi_channels, unsigned *pi_original_channels,
                      unsigned *pi_bits,
                      const uint8_t *p_header );
189
static void VobExtract( block_t *, block_t *, unsigned i_bits );
190 191 192 193 194 195 196
/* */
static int AobHeader( unsigned *pi_rate,
                      unsigned *pi_channels, unsigned *pi_layout,
                      unsigned *pi_bits,
                      unsigned *pi_padding,
                      aob_group_t g[2],
                      const uint8_t *p_header );
197
static void AobExtract( block_t *, block_t *, unsigned i_bits, aob_group_t p_group[2] );
198
/* */
199 200
static int BdHeader( decoder_sys_t *p_sys,
                     unsigned *pi_rate,
201 202 203
                     unsigned *pi_channels,
                     unsigned *pi_channels_padding,
                     unsigned *pi_original_channels,
204 205
                     unsigned *pi_bits,
                     const uint8_t *p_header );
206
static void BdExtract( block_t *, block_t *, unsigned, unsigned, unsigned, unsigned );
207 208 209 210 211
/* */
static int WidiHeader( unsigned *pi_rate,
                       unsigned *pi_channels, unsigned *pi_original_channels,
                       unsigned *pi_bits,
                       const uint8_t *p_header );
212 213

/*****************************************************************************
Laurent Aimar's avatar
Laurent Aimar committed
214
 * OpenCommon:
215
 *****************************************************************************/
Laurent Aimar's avatar
Laurent Aimar committed
216
static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
217
{
Gildas Bazin's avatar
 
Gildas Bazin committed
218
    decoder_t *p_dec = (decoder_t*)p_this;
Gildas Bazin's avatar
 
Gildas Bazin committed
219
    decoder_sys_t *p_sys;
220 221
    int i_type;
    int i_header_size;
222

Laurent Aimar's avatar
Laurent Aimar committed
223
    switch( p_dec->fmt_in.i_codec )
224
    {
225
    /* DVD LPCM */
226
    case VLC_CODEC_DVD_LPCM:
227 228 229 230 231 232 233
        i_type = LPCM_VOB;
        i_header_size = LPCM_VOB_HEADER_LEN;
        break;
    /* DVD-Audio LPCM */
    case VLC_CODEC_DVDA_LPCM:
        i_type = LPCM_AOB;
        i_header_size = LPCM_AOB_HEADER_LEN;
234 235
        break;
    /* BD LPCM */
236
    case VLC_CODEC_BD_LPCM:
237 238
        i_type = LPCM_BD;
        i_header_size = LPCM_BD_HEADER_LEN;
Laurent Aimar's avatar
Laurent Aimar committed
239
        break;
240 241 242 243 244
    /* WIDI LPCM */
    case VLC_CODEC_WIDI_LPCM:
        i_type = LPCM_WIDI;
        i_header_size = LPCM_WIDI_HEADER_LEN;
        break;
Laurent Aimar's avatar
Laurent Aimar committed
245
    default:
246 247 248
        return VLC_EGENERIC;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
249
    /* Allocate the memory needed to store the decoder's structure */
Laurent Aimar's avatar
Laurent Aimar committed
250
    if( ( p_dec->p_sys = p_sys = malloc(sizeof(decoder_sys_t)) ) == NULL )
251
        return VLC_ENOMEM;
252

Gildas Bazin's avatar
 
Gildas Bazin committed
253
    /* Misc init */
Laurent Aimar's avatar
Laurent Aimar committed
254
    p_sys->b_packetizer = b_packetizer;
255
    date_Set( &p_sys->end_date, 0 );
256 257
    p_sys->i_type = i_type;
    p_sys->i_header_size = i_header_size;
258
    p_sys->i_chans_to_reorder = 0;
259

Gildas Bazin's avatar
 
Gildas Bazin committed
260 261
    /* Set output properties */
    p_dec->fmt_out.i_cat = AUDIO_ES;
262

Laurent Aimar's avatar
Laurent Aimar committed
263
    if( b_packetizer )
264
    {
265 266 267 268 269 270 271 272
        switch( i_type )
        {
        case LPCM_VOB:
            p_dec->fmt_out.i_codec = VLC_CODEC_DVD_LPCM;
            break;
        case LPCM_AOB:
            p_dec->fmt_out.i_codec = VLC_CODEC_DVDA_LPCM;
            break;
273 274 275
        case LPCM_WIDI:
            p_dec->fmt_out.i_codec = VLC_CODEC_WIDI_LPCM;
            break;
276
        default:
277
            vlc_assert_unreachable();
278 279 280 281
        case LPCM_BD:
            p_dec->fmt_out.i_codec = VLC_CODEC_BD_LPCM;
            break;
        }
282 283 284
    }
    else
    {
Laurent Aimar's avatar
Laurent Aimar committed
285 286 287 288
        switch( p_dec->fmt_out.audio.i_bitspersample )
        {
        case 24:
        case 20:
289 290
            p_dec->fmt_out.i_codec = VLC_CODEC_S32N;
            p_dec->fmt_out.audio.i_bitspersample = 32;
Laurent Aimar's avatar
Laurent Aimar committed
291 292
            break;
        default:
293
            p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
Laurent Aimar's avatar
Laurent Aimar committed
294 295 296
            p_dec->fmt_out.audio.i_bitspersample = 16;
            break;
        }
297
    }
298

Gildas Bazin's avatar
 
Gildas Bazin committed
299
    /* Set callback */
300 301
    p_dec->pf_decode_audio = DecodeFrame;
    p_dec->pf_packetize    = DecodeFrame;
302
    p_dec->pf_flush        = Flush;
303

Gildas Bazin's avatar
 
Gildas Bazin committed
304 305
    return VLC_SUCCESS;
}
Laurent Aimar's avatar
Laurent Aimar committed
306 307 308 309
static int OpenDecoder( vlc_object_t *p_this )
{
    return OpenCommon( p_this, false );
}
Gildas Bazin's avatar
 
Gildas Bazin committed
310 311
static int OpenPacketizer( vlc_object_t *p_this )
{
Laurent Aimar's avatar
Laurent Aimar committed
312
    return OpenCommon( p_this, true );
313 314
}

315 316 317 318 319 320 321 322 323 324
/*****************************************************************************
 * Flush:
 *****************************************************************************/
static void Flush( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    date_Set( &p_sys->end_date, 0 );
}

325
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
326 327 328
 * DecodeFrame: decodes an lpcm frame.
 ****************************************************************************
 * Beware, this function must be fed with complete frames (PES packet).
329
 *****************************************************************************/
330
static block_t *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
331
{
Gildas Bazin's avatar
 
Gildas Bazin committed
332 333
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t       *p_block;
334 335
    unsigned int  i_rate = 0, i_original_channels = 0, i_channels = 0, i_bits = 0;
    int           i_frame_length;
336

Gildas Bazin's avatar
 
Gildas Bazin committed
337 338 339 340 341
    if( !pp_block || !*pp_block ) return NULL;

    p_block = *pp_block;
    *pp_block = NULL; /* So the packet doesn't get re-sent */

342
    if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
343
        Flush( p_dec );
344 345 346 347 348 349 350

    if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
    {
        block_Release( p_block );
        return NULL;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
351
    /* Date management */
352
    if( p_block->i_pts > VLC_TS_INVALID &&
353
        p_block->i_pts != date_Get( &p_sys->end_date ) )
354
    {
355
        date_Set( &p_sys->end_date, p_block->i_pts );
356
    }
357

358
    if( !date_Get( &p_sys->end_date ) )
359
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
360 361 362
        /* We've just started the stream, wait for the first PTS. */
        block_Release( p_block );
        return NULL;
363
    }
364

Laurent Aimar's avatar
Laurent Aimar committed
365
    if( p_block->i_buffer <= p_sys->i_header_size )
366
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
367 368 369
        msg_Err(p_dec, "frame is too short");
        block_Release( p_block );
        return NULL;
370 371
    }

372
    int i_ret;
373
    unsigned i_channels_padding = 0;
374
    unsigned i_padding = 0;
375 376 377 378 379
    aob_group_t p_aob_group[2];
    switch( p_sys->i_type )
    {
    case LPCM_VOB:
        i_ret = VobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits,
380
                           p_block->p_buffer );
381 382 383 384 385 386 387
        break;
    case LPCM_AOB:
        i_ret = AobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits, &i_padding,
                           p_aob_group,
                           p_block->p_buffer );
        break;
    case LPCM_BD:
388
        i_ret = BdHeader( p_sys, &i_rate, &i_channels, &i_channels_padding, &i_original_channels, &i_bits,
389
                          p_block->p_buffer );
390
        break;
391 392 393 394
    case LPCM_WIDI:
        i_ret = WidiHeader( &i_rate, &i_channels, &i_original_channels, &i_bits,
                            p_block->p_buffer );
        break;
395
    default:
396
        abort();
397
    }
398

399
    if( i_ret || p_block->i_buffer <= p_sys->i_header_size + i_padding )
400
    {
401
        msg_Warn( p_dec, "no frame sync or too small frame" );
402 403 404 405 406 407 408
        block_Release( p_block );
        return NULL;
    }

    /* Set output properties */
    if( p_dec->fmt_out.audio.i_rate != i_rate )
    {
409 410
        date_Init( &p_sys->end_date, i_rate, 1 );
        date_Set( &p_sys->end_date, p_block->i_pts );
411 412 413 414
    }
    p_dec->fmt_out.audio.i_rate = i_rate;
    p_dec->fmt_out.audio.i_channels = i_channels;
    p_dec->fmt_out.audio.i_original_channels = i_original_channels;
415
    p_dec->fmt_out.audio.i_physical_channels = i_original_channels;
416

417 418 419 420 421 422 423 424 425 426 427 428 429
    if ( p_sys->i_type == LPCM_AOB )
    {
        i_frame_length = (p_block->i_buffer - p_sys->i_header_size - i_padding) /
                         (
                            ( (p_aob_group[0].i_bits / 8) * p_aob_group[0].i_channels ) +
                            ( (p_aob_group[1].i_bits / 8) * p_aob_group[1].i_channels )
                         );
    }
    else
    {
        i_frame_length = (p_block->i_buffer - p_sys->i_header_size - i_padding) /
                         (i_channels + i_channels_padding) * 8 / i_bits;
    }
430 431 432

    if( p_sys->b_packetizer )
    {
433
        p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date );
434
        p_block->i_length =
435
            date_Increment( &p_sys->end_date, i_frame_length ) -
436 437 438 439 440 441 442 443 444 445
            p_block->i_pts;

        /* Just pass on the incoming frame */
        return p_block;
    }
    else
    {
        /* */
        if( i_bits == 16 )
        {
446
            p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
447 448 449 450
            p_dec->fmt_out.audio.i_bitspersample = 16;
        }
        else
        {
451 452
            p_dec->fmt_out.i_codec = VLC_CODEC_S32N;
            p_dec->fmt_out.audio.i_bitspersample = 32;
453 454 455
        }

        /* */
456
        block_t *p_aout_buffer;
457 458
        if( decoder_UpdateAudioFormat( p_dec ) )
            return NULL;
459 460 461 462
        p_aout_buffer = decoder_NewAudioBuffer( p_dec, i_frame_length );
        if( !p_aout_buffer )
            return NULL;

463
        p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
464 465 466
        p_aout_buffer->i_length =
            date_Increment( &p_sys->end_date, i_frame_length )
            - p_aout_buffer->i_pts;
467

468 469
        p_block->p_buffer += p_sys->i_header_size + i_padding;
        p_block->i_buffer -= p_sys->i_header_size + i_padding;
470

471 472
        switch( p_sys->i_type )
        {
473
        case LPCM_WIDI:
474 475 476 477 478 479 480
        case LPCM_VOB:
            VobExtract( p_aout_buffer, p_block, i_bits );
            break;
        case LPCM_AOB:
            AobExtract( p_aout_buffer, p_block, i_bits, p_aob_group );
            break;
        default:
481
            vlc_assert_unreachable();
482
        case LPCM_BD:
483
            BdExtract( p_aout_buffer, p_block, i_frame_length, i_channels, i_channels_padding, i_bits );
484 485
            break;
        }
486

487 488 489 490 491 492 493
        if( p_sys->i_chans_to_reorder )
        {
            aout_ChannelReorder( p_aout_buffer->p_buffer, p_aout_buffer->i_buffer,
                                 p_sys->i_chans_to_reorder, p_sys->pi_chan_table,
                                 p_dec->fmt_out.i_codec );
        }

494 495 496 497 498 499 500 501 502 503 504 505 506 507
        block_Release( p_block );
        return p_aout_buffer;
    }
}

/*****************************************************************************
 * CloseCommon : lpcm decoder destruction
 *****************************************************************************/
static void CloseCommon( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t*)p_this;
    free( p_dec->p_sys );
}

508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
#ifdef ENABLE_SOUT
/*****************************************************************************
 * OpenEncoder: lpcm encoder construction
 *****************************************************************************/
static int OpenEncoder( vlc_object_t *p_this )
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys;

    /* We only support DVD LPCM yet. */
    if( p_enc->fmt_out.i_codec != VLC_CODEC_DVD_LPCM )
        return VLC_EGENERIC;

    if( p_enc->fmt_in.audio.i_rate != 48000 &&
        p_enc->fmt_in.audio.i_rate != 96000 &&
        p_enc->fmt_in.audio.i_rate != 44100 &&
        p_enc->fmt_in.audio.i_rate != 32000 )
    {
        msg_Err( p_enc, "DVD LPCM supports only sample rates of 48, 96, 44.1 or 32 kHz" );
        return VLC_EGENERIC;
    }

    if( p_enc->fmt_in.audio.i_channels > 8 )
    {
        msg_Err( p_enc, "DVD LPCM supports a maximum of eight channels" );
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the encoder's structure */
    if( ( p_enc->p_sys = p_sys =
          (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
        return VLC_ENOMEM;

    /* In DVD LCPM, a frame is always 150 PTS ticks. */
    p_sys->i_frame_samples = p_enc->fmt_in.audio.i_rate * 150 / 90000;
543 544
    p_sys->p_buffer = xmalloc(p_sys->i_frame_samples
                            * p_enc->fmt_in.audio.i_channels * 16);
545 546 547 548 549 550 551 552 553 554
    p_sys->i_buffer_used = 0;
    p_sys->i_frame_num = 0;

    p_sys->i_channels = p_enc->fmt_in.audio.i_channels;
    p_sys->i_rate = p_enc->fmt_in.audio.i_rate;

    p_enc->pf_encode_audio = EncodeFrames;
    p_enc->fmt_in.i_codec = p_enc->fmt_out.i_codec;

    p_enc->fmt_in.audio.i_bitspersample = 16;
555
    p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581

    p_enc->fmt_out.i_bitrate =
        p_enc->fmt_in.audio.i_channels *
        p_enc->fmt_in.audio.i_rate *
        p_enc->fmt_in.audio.i_bitspersample *
        (p_sys->i_frame_samples + LPCM_VOB_HEADER_LEN) /
        p_sys->i_frame_samples;

    return VLC_SUCCESS;
}

/*****************************************************************************
 * CloseEncoder: lpcm encoder destruction
 *****************************************************************************/
static void CloseEncoder ( vlc_object_t *p_this )
{
    encoder_t     *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys = p_enc->p_sys;

    free( p_sys->p_buffer );
    free( p_sys );
}

/*****************************************************************************
 * EncodeFrames: encode zero or more LCPM audio packets
 *****************************************************************************/
582
static block_t *EncodeFrames( encoder_t *p_enc, block_t *p_aout_buf )
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    block_t *p_first_block = NULL, *p_last_block = NULL;

    if( !p_aout_buf || !p_aout_buf->i_buffer ) return NULL;

    const int i_num_frames = ( p_sys->i_buffer_used + p_aout_buf->i_nb_samples ) /
        p_sys->i_frame_samples;
    const int i_leftover_samples = ( p_sys->i_buffer_used + p_aout_buf->i_nb_samples ) %
        p_sys->i_frame_samples;
    const int i_frame_size = p_sys->i_frame_samples * p_sys->i_channels * 2 + LPCM_VOB_HEADER_LEN;
    const int i_start_offset = -p_sys->i_buffer_used;

    uint8_t i_freq_code = 0;

    switch( p_sys->i_rate ) {
    case 48000:
        i_freq_code = 0;
        break;
    case 96000:
        i_freq_code = 1;
        break;
    case 44100:
        i_freq_code = 2;
        break;
    case 32000:
        i_freq_code = 3;
        break;
    default:
612
        vlc_assert_unreachable();
613 614 615 616 617 618
    }

    int i_bytes_consumed = 0;

    for ( int i = 0; i < i_num_frames; ++i )
    {
619
        block_t *p_block = block_Alloc( i_frame_size );
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
        if( !p_block )
            return NULL;

        uint8_t *frame = (uint8_t *)p_block->p_buffer;
        frame[0] = 1;  /* one frame in packet */
        frame[1] = 0;
        frame[2] = 0;  /* no first access unit */
        frame[3] = (p_sys->i_frame_num + i) & 0x1f;  /* no emphasis, no mute */
        frame[4] = (i_freq_code << 4) | (p_sys->i_channels - 1);
        frame[5] = 0x80;  /* neutral dynamic range */

        const int i_consume_samples = p_sys->i_frame_samples - p_sys->i_buffer_used;
        const int i_kept_bytes = p_sys->i_buffer_used * p_sys->i_channels * 2;
        const int i_consume_bytes = i_consume_samples * p_sys->i_channels * 2;

635
#ifdef WORDS_BIGENDIAN
636
        memcpy( frame + 6, p_sys->p_buffer, i_kept_bytes );
637 638 639 640 641 642 643
        memcpy( frame + 6 + i_kept_bytes, p_aout_buf->p_buffer + i_bytes_consumed,
                i_consume_bytes );
#else
        swab( p_sys->p_buffer, frame + 6, i_kept_bytes );
        swab( p_aout_buf->p_buffer + i_bytes_consumed, frame + 6 + i_kept_bytes,
              i_consume_bytes );
#endif
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672

        p_sys->i_frame_num++;
        p_sys->i_buffer_used = 0;
        i_bytes_consumed += i_consume_bytes;

        /* We need to find i_length by means of next_pts due to possible roundoff errors. */
        mtime_t this_pts = p_aout_buf->i_pts +
            (i * p_sys->i_frame_samples + i_start_offset) * CLOCK_FREQ / p_sys->i_rate;
        mtime_t next_pts = p_aout_buf->i_pts +
            ((i + 1) * p_sys->i_frame_samples + i_start_offset) * CLOCK_FREQ / p_sys->i_rate;

        p_block->i_pts = p_block->i_dts = this_pts;
        p_block->i_length = next_pts - this_pts;

        if( !p_first_block )
            p_first_block = p_last_block = p_block;
        else
            p_last_block = p_last_block->p_next = p_block;
    }

    memcpy( p_sys->p_buffer,
            p_aout_buf->p_buffer + i_bytes_consumed,
            i_leftover_samples * p_sys->i_channels * 2 );
    p_sys->i_buffer_used = i_leftover_samples;

    return p_first_block;
}
#endif

673 674 675
/*****************************************************************************
 *
 *****************************************************************************/
676
static int VobHeader( unsigned *pi_rate,
677 678 679 680 681 682 683
                      unsigned *pi_channels, unsigned *pi_original_channels,
                      unsigned *pi_bits,
                      const uint8_t *p_header )
{
    const uint8_t i_header = p_header[4];

    switch( (i_header >> 4) & 0x3 )
684
    {
685
    case 0:
686
        *pi_rate = 48000;
687 688
        break;
    case 1:
689
        *pi_rate = 96000;
690 691
        break;
    case 2:
692
        *pi_rate = 44100;
693 694
        break;
    case 3:
695
        *pi_rate = 32000;
696
        break;
697
    }
698

699 700
    *pi_channels = (i_header & 0x7) + 1;
    switch( *pi_channels - 1 )
701 702
    {
    case 0:
703
        *pi_original_channels = AOUT_CHAN_CENTER;
704 705
        break;
    case 1:
706
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
707 708 709
        break;
    case 2:
        /* This is unsure. */
710
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE;
711 712
        break;
    case 3:
713
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
714
                               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
715 716 717
        break;
    case 4:
        /* This is unsure. */
718
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
719 720
                               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
                               | AOUT_CHAN_LFE;
721 722
        break;
    case 5:
723
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
724 725 726 727
                               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
                               | AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
        break;
    case 6:
728
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
729 730 731 732
                               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
                               | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
                               | AOUT_CHAN_MIDDLERIGHT;
        break;
733
    case 7:
734
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
735 736 737 738
                               | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
                               | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
                               | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
        break;
739 740
    }

741
    switch( (i_header >> 6) & 0x3 )
742 743
    {
    case 2:
744
        *pi_bits = 24;
745 746
        break;
    case 1:
747
        *pi_bits = 20;
748 749 750
        break;
    case 0:
    default:
751
        *pi_bits = 16;
752 753 754
        break;
    }

755
    /* Check frame sync and drop it. */
756 757 758 759
    if( p_header[5] != 0x80 )
        return -1;
    return 0;
}
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837

static const unsigned p_aob_group1[21][6] = {
    { AOUT_CHAN_CENTER, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0  },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0  },
    { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0  },
};
static const unsigned p_aob_group2[21][6] = {
    { 0 },
    { 0 },
    { AOUT_CHAN_REARCENTER, 0 },
    { AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,    0 },
    { AOUT_CHAN_LFE,        0 },
    { AOUT_CHAN_LFE,        AOUT_CHAN_REARCENTER,   0 },
    { AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT,     AOUT_CHAN_REARRIGHT,    0 },
    { AOUT_CHAN_CENTER,     0 },
    { AOUT_CHAN_CENTER,     AOUT_CHAN_REARCENTER, 0 },
    { AOUT_CHAN_CENTER,     AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,    0 },
    { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,        0 },
    { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,        AOUT_CHAN_REARCENTER,   0 },
    { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT,     AOUT_CHAN_REARRIGHT,    0 },
    { AOUT_CHAN_REARCENTER, 0 },
    { AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,    0 },
    { AOUT_CHAN_LFE,        0 },
    { AOUT_CHAN_LFE,        AOUT_CHAN_REARCENTER,   0 },
    { AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT,     AOUT_CHAN_REARRIGHT,    0 },
    { AOUT_CHAN_LFE,        0 },
    { AOUT_CHAN_CENTER,     0 },
    { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,          0 },
};

static int AobHeader( unsigned *pi_rate,
                      unsigned *pi_channels, unsigned *pi_layout,
                      unsigned *pi_bits,
                      unsigned *pi_padding,
                      aob_group_t g[2],
                      const uint8_t *p_header )
{
    const unsigned i_header_size = GetWBE( &p_header[1] );
    if( i_header_size + 3 < LPCM_AOB_HEADER_LEN )
        return VLC_EGENERIC;

    *pi_padding = 3+i_header_size - LPCM_AOB_HEADER_LEN;

    const int i_index_size_g1 = (p_header[6] >> 4) & 0x0f;
    const int i_index_size_g2 = (p_header[6]     ) & 0x0f;
    const int i_index_rate_g1 = (p_header[7] >> 4) & 0x0f;
    const int i_index_rate_g2 = (p_header[7]     ) & 0x0f;
    const int i_assignment     = p_header[9];

    /* Validate */
    if( i_index_size_g1 > 0x02 ||
        ( i_index_size_g2 != 0x0f && i_index_size_g2 > 0x02 ) )
        return VLC_EGENERIC;
    if( (i_index_rate_g1 & 0x07) > 0x02 ||
        ( i_index_rate_g2 != 0x0f && (i_index_rate_g1 & 0x07) > 0x02 ) )
        return VLC_EGENERIC;
    if( i_assignment > 20 )
        return VLC_EGENERIC;

    /* */
838
    /* max is 0x2, 0xf == unused */
839
    g[0].i_bits = 16 + 4 * i_index_size_g1;
840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856
    g[1].i_bits = ( i_index_size_g2 != 0x0f ) ? 16 + 4 * i_index_size_g2 : 0;

    /* No info about interlacing of different sampling rate */
    if ( g[1].i_bits && ( i_index_rate_g1 != i_index_rate_g2 ) )
        return VLC_EGENERIC;

    /* only set 16bits if both are <= */
    if( g[0].i_bits )
    {
        if( g[0].i_bits > 16 || g[1].i_bits > 16 )
            *pi_bits = 32;
        else
            *pi_bits = 16;
    }
    else
        return VLC_EGENERIC;

857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
    if( i_index_rate_g1 & 0x08 )
        *pi_rate = 44100 << (i_index_rate_g1 & 0x07);
    else
        *pi_rate = 48000 << (i_index_rate_g1 & 0x07);


    /* Group1 */
    unsigned i_channels1 = 0;
    unsigned i_layout1 = 0;
    for( int i = 0; p_aob_group1[i_assignment][i] != 0; i++ )
    {
        i_channels1++;
        i_layout1 |= p_aob_group1[i_assignment][i];
    }
    /* Group2 */
    unsigned i_channels2 = 0;
    unsigned i_layout2 = 0;
    if( i_index_size_g2 != 0x0f && i_index_rate_g2 != 0x0f )
    {
        for( int i = 0; p_aob_group2[i_assignment][i] != 0; i++ )
        {
            i_channels2++;
            i_layout2 |= p_aob_group2[i_assignment][i];
        }
        assert( (i_layout1 & i_layout2) == 0 );
    }

    /* */
885 886
    *pi_channels = i_channels1 + ( g[1].i_bits ? i_channels2 : 0 );
    *pi_layout   = i_layout1   | ( g[1].i_bits ? i_layout2   : 0 );
887 888

    /* */
889
    for( unsigned i = 0; i < 2; i++ )
890 891 892 893 894 895
    {
        const unsigned *p_aob = i == 0 ? p_aob_group1[i_assignment] :
                                         p_aob_group2[i_assignment];
        g[i].i_channels = i == 0 ? i_channels1 :
                                   i_channels2;

896
        if( !g[i].i_bits )
897
            continue;
898
        for( unsigned j = 0; j < g[i].i_channels; j++ )
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
        {
            g[i].pi_position[j] = 0;
            for( int k = 0; pi_vlc_chan_order_wg4[k] != 0; k++ )
            {
                const unsigned i_channel = pi_vlc_chan_order_wg4[k];
                if( i_channel == p_aob[j] )
                    break;
                if( (*pi_layout) & i_channel )
                    g[i].pi_position[j]++;
            }
        }
    }
    return VLC_SUCCESS;
}

914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
static const uint32_t pi_8channels_in[] =
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
  AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
  AOUT_CHAN_MIDDLERIGHT, AOUT_CHAN_LFE, 0 };

static const uint32_t pi_7channels_in[] =
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
  AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
  AOUT_CHAN_MIDDLERIGHT, 0 };

static const uint32_t pi_6channels_in[] =
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
  AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_LFE, 0 };

static const uint32_t pi_5channels_in[] =
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
  AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, 0 };

static const uint32_t pi_4channels_in[] =
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
  AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 };

static const uint32_t pi_3channels_in[] =
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
  AOUT_CHAN_CENTER, 0 };


static int BdHeader( decoder_sys_t *p_sys,
                     unsigned *pi_rate,
943 944 945
                     unsigned *pi_channels,
                     unsigned *pi_channels_padding,
                     unsigned *pi_original_channels,
946 947 948 949
                     unsigned *pi_bits,
                     const uint8_t *p_header )
{
    const uint32_t h = GetDWBE( p_header );
950
    const uint32_t *pi_channels_in = NULL;
951
    switch( ( h & 0xf000) >> 12 )
952
    {
953 954 955 956 957 958 959 960 961 962 963
    case 1:
        *pi_channels = 1;
        *pi_original_channels = AOUT_CHAN_CENTER;
        break;
    case 3:
        *pi_channels = 2;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
        break;
    case 4:
        *pi_channels = 3;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER;
964
        pi_channels_in = pi_3channels_in;
965 966 967 968 969 970 971 972 973 974 975 976 977 978
        break;
    case 5:
        *pi_channels = 3;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER;
        break;
    case 6:
        *pi_channels = 4;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARCENTER;
        break;
    case 7:
        *pi_channels = 4;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
979
        pi_channels_in = pi_4channels_in;
980 981 982 983 984
        break;
    case 8:
        *pi_channels = 5;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
985
        pi_channels_in = pi_5channels_in;
986 987 988 989 990 991
        break;
    case 9:
        *pi_channels = 6;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
                                AOUT_CHAN_LFE;
992
        pi_channels_in = pi_6channels_in;
993 994 995 996 997 998
        break;
    case 10:
        *pi_channels = 7;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
                                AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT;
999
        pi_channels_in = pi_7channels_in;
1000 1001 1002 1003 1004 1005 1006
        break;
    case 11:
        *pi_channels = 8;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
                                AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
                                AOUT_CHAN_LFE;
1007
        pi_channels_in = pi_8channels_in;
1008
        break;
1009

1010 1011
    default:
        return -1;
1012
    }
1013 1014
    *pi_channels_padding = *pi_channels & 1;

1015
    switch( (h >> 6) & 0x03 )
1016
    {
1017 1018 1019 1020 1021 1022 1023 1024 1025
    case 1:
        *pi_bits = 16;
        break;
    case 2: /* 20 bits but samples are stored on 24 bits */
    case 3: /* 24 bits */
        *pi_bits = 24;
        break;
    default:
        return -1;
1026
    }
1027
    switch( (h >> 8) & 0x0f ) 
1028
    {
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
    case 1:
        *pi_rate = 48000;
        break;
    case 4:
        *pi_rate = 96000;
        break;
    case 5:
        *pi_rate = 192000;
        break;
    default:
        return -1;
    }
1041 1042 1043 1044 1045 1046 1047 1048 1049

    if( pi_channels_in )
    {
        p_sys->i_chans_to_reorder =
            aout_CheckChannelReorder( pi_channels_in, NULL,
                                      *pi_original_channels,
                                      p_sys->pi_chan_table );
    }

1050 1051
    return 0;
}
Gildas Bazin's avatar
 
Gildas Bazin committed
1052

1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
static int WidiHeader( unsigned *pi_rate,
                       unsigned *pi_channels, unsigned *pi_original_channels,
                       unsigned *pi_bits,
                       const uint8_t *p_header )
{
    if ( p_header[0] != 0xa0 || p_header[1] != 0x06 )
        return -1;

    switch( ( p_header[3] & 0x38 ) >> 3 )
    {
1063
    case 0x01: //0b001
1064 1065
        *pi_rate = 44100;
        break;
1066
    case 0x02: //0b010
1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
        *pi_rate = 48000;
        break;
    default:
        return -1;
    }

    if( p_header[3] >> 6 != 0 )
        return -1;
    else
        *pi_bits = 16;

    *pi_channels = (p_header[3] & 0x7) + 1;

    *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;

    return 0;
}

1085
static void VobExtract( block_t *p_aout_buffer, block_t *p_block,
1086 1087 1088 1089 1090
                        unsigned i_bits )
{
    /* 20/24 bits LPCM use special packing */
    if( i_bits == 24 )
    {
1091 1092
        uint32_t *p_out = (uint32_t *)p_aout_buffer->p_buffer;

1093
        while( p_block->i_buffer / 12 )
1094
        {
1095
            /* Sample 1 */
1096 1097 1098
            *(p_out++) = (p_block->p_buffer[ 0] << 24)
                       | (p_block->p_buffer[ 1] << 16)
                       | (p_block->p_buffer[ 8] <<  8);
1099
            /* Sample 2 */
1100 1101 1102
            *(p_out++) = (p_block->p_buffer[ 2] << 24)
                       | (p_block->p_buffer[ 3] << 16)
                       | (p_block->p_buffer[ 9] <<  8);
1103
            /* Sample 3 */
1104 1105 1106
            *(p_out++) = (p_block->p_buffer[ 4] << 24)
                       | (p_block->p_buffer[ 5] << 16)
                       | (p_block->p_buffer[10] <<  8);
1107
            /* Sample 4 */
1108 1109 1110
            *(p_out++) = (p_block->p_buffer[ 6] << 24)
                       | (p_block->p_buffer[ 7] << 16)
                       | (p_block->p_buffer[11] <<  8);
1111 1112 1113

            p_block->i_buffer -= 12;
            p_block->p_buffer += 12;
1114
        }
1115 1116 1117
    }
    else if( i_bits == 20 )
    {
1118 1119
        uint32_t *p_out = (uint32_t *)p_aout_buffer->p_buffer;

1120
        while( p_block->i_buffer / 10 )
1121
        {
1122
            /* Sample 1 */
1123 1124 1125
            *(p_out++) = ( p_block->p_buffer[0]         << 24)
                       | ( p_block->p_buffer[1]         << 16)
                       | ((p_block->p_buffer[8] & 0xF0) <<  8);
1126
            /* Sample 2 */
1127 1128 1129
            *(p_out++) = ( p_block->p_buffer[2]         << 24)
                       | ( p_block->p_buffer[3]         << 16)
                       | ((p_block->p_buffer[8] & 0x0F) << 12);
1130
            /* Sample 3 */
1131 1132 1133
            *(p_out++) = ( p_block->p_buffer[4]         << 24)
                       | ( p_block->p_buffer[5]         << 16)
                       | ((p_block->p_buffer[9] & 0xF0) <<  8);
1134
            /* Sample 4 */
1135 1136 1137
            *(p_out++) = ( p_block->p_buffer[6]         << 24)
                       | ( p_block->p_buffer[7]         << 16)
                       | ((p_block->p_buffer[9] & 0x0F) << 12);
1138 1139 1140

            p_block->i_buffer -= 10;
            p_block->p_buffer += 10;
1141
        }
1142 1143 1144 1145
    }
    else
    {
        assert( i_bits == 16 );
1146 1147 1148 1149 1150
#ifdef WORDS_BIGENDIAN
        memcpy( p_aout_buffer->p_buffer, p_block->p_buffer, p_block->i_buffer );
#else
        swab( p_block->p_buffer, p_aout_buffer->p_buffer, p_block->i_buffer );
#endif
1151
    }
1152
}
1153

1154
static void AobExtract( block_t *p_aout_buffer,
1155
                        block_t *p_block, unsigned i_aoutbits, aob_group_t p_group[2] )
1156 1157
{
    uint8_t *p_out = p_aout_buffer->p_buffer;
1158 1159
    const unsigned i_total_channels = p_group[0].i_channels +
                                      ( p_group[1].i_bits ? p_group[1].i_channels : 0 );
1160 1161 1162

    while( p_block->i_buffer > 0 )
    {
1163 1164
        unsigned int i_aout_written = 0;

1165 1166 1167
        for( int i = 0; i < 2; i++ )
        {
            const aob_group_t *g = &p_group[1-i];
1168
            const unsigned int i_group_size = 2 * g->i_channels * g->i_bits / 8;
1169 1170 1171 1172 1173 1174

            if( p_block->i_buffer < i_group_size )
            {
                p_block->i_buffer = 0;
                break;
            }
1175 1176 1177 1178

            if( !g->i_bits )
                continue;

1179
            for( unsigned n = 0; n < 2; n++ )
1180
            {
1181
                for( unsigned j = 0; j < g->i_channels; j++ )
1182 1183
                {
                    const int i_src = n * g->i_channels + j;
1184 1185
                    const int i_dst = n * i_total_channels + g->pi_position[j];
                    uint32_t *p_out32 = (uint32_t *) &p_out[4*i_dst];
1186

1187
                    if( g->i_bits == 24 )
1188
                    {
1189 1190 1191 1192 1193 1194 1195 1196
                        assert( i_aoutbits == 32 );
                        *p_out32 = (p_block->p_buffer[2*i_src+0] << 24)
                                 | (p_block->p_buffer[2*i_src+1] << 16)
                                 | (p_block->p_buffer[4*g->i_channels+i_src] <<  8);
#ifdef WORDS_BIGENDIAN
                        *p_out32 = bswap32(*p_out32);
#endif
                        i_aout_written += 4;
1197
                    }
1198
                    else if( g->i_bits == 20 )
1199
                    {
1200 1201 1202 1203 1204 1205 1206 1207
                        assert( i_aoutbits == 32 );
                        *p_out32 = (p_block->p_buffer[2*i_src+0] << 24)
                                 | (p_block->p_buffer[2*i_src+1] << 16)
                                 | (((p_block->p_buffer[4*g->i_channels+i_src] << ((!n)?0:4) ) & 0xf0) <<  8);
#ifdef WORDS_BIGENDIAN
                        *p_out32 = bswap32(*p_out32);
#endif
                        i_aout_written += 4;
1208 1209 1210
                    }
                    else
                    {
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
                        assert( g->i_bits == 16 );
                        assert( i_aoutbits == 16 || i_aoutbits == 32 );
                        if( i_aoutbits == 16 )
                        {
#ifdef WORDS_BIGENDIAN
                            memcpy( &p_out[2*i_dst], &p_block->p_buffer[2*i_src], 2 );
#else
                            p_out[2*i_dst+1] = p_block->p_buffer[2*i_src+0];
                            p_out[2*i_dst+0] = p_block->p_buffer[2*i_src+1];
#endif
                            i_aout_written += 2;
                        }
                        else
                        {
                            *p_out32 = (p_block->p_buffer[2*i_src+0] << 24)
                                     | (p_block->p_buffer[2*i_src+1] << 16);
#ifdef WORDS_BIGENDIAN
                            *p_out32 = bswap32(*p_out32);
#endif
                            i_aout_written += 4;
                        }
1232 1233 1234 1235
                    }
                }
            }

1236
            /* */
1237 1238 1239
            p_block->i_buffer -= i_group_size;
            p_block->p_buffer += i_group_size;
        }
1240
        p_out += i_aout_written;
1241 1242
    }
}
1243
static void BdExtract( block_t *p_aout_buffer, block_t *p_block,
1244 1245 1246
                       unsigned i_frame_length,
                       unsigned i_channels, unsigned i_channels_padding,
                       unsigned i_bits )
1247
{
1248
    if( i_bits != 16 || i_channels_padding > 0 )
1249 1250 1251
    {
        uint8_t *p_src = p_block->p_buffer;
        uint8_t *p_dst = p_aout_buffer->p_buffer;
1252 1253
        int dst_inc = ((i_bits == 16) ? 2 : 4) * i_channels;

1254 1255
        while( i_frame_length > 0 )
        {
1256
#ifdef WORDS_BIGENDIAN
1257
            memcpy( p_dst, p_src, i_channels * i_bits / 8 );
1258
#else
1259
            if (i_bits == 16) {
1260
                swab( p_src, p_dst, (i_channels + i_channels_padding) * i_bits / 8 );
1261
            } else {
1262 1263 1264 1265 1266 1267
                for (unsigned i = 0; i < i_channels; ++i) {
                    p_dst[i * 4] = 0;
                    p_dst[1 + (i * 4)] = p_src[2 + (i * 3)];
                    p_dst[2 + (i * 4)] = p_src[1 + (i * 3)];
                    p_dst[3 + (i * 4)] = p_src[i * 3];
                }
Rafaël Carré's avatar