audio.c 16.6 KB
Newer Older
1 2 3
/*****************************************************************************
 * audio.c: audio decoder using ffmpeg library
 *****************************************************************************
4
 * Copyright (C) 1999-2003 the VideoLAN team
5
 * $Id$
6 7
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8
 *          Gildas Bazin <gbazin@videolan.org>
9 10 11 12 13
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
14
 *
15 16 17 18 19 20 21
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
Antoine Cellerier's avatar
Antoine Cellerier committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 24 25 26 27
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
28 29 30 31
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

32
#include <vlc_common.h>
Clément Stenac's avatar
Clément Stenac committed
33 34
#include <vlc_aout.h>
#include <vlc_codec.h>
35
#include <vlc_avcodec.h>
36

Gildas Bazin's avatar
 
Gildas Bazin committed
37
/* ffmpeg header */
38 39 40
#ifdef HAVE_LIBAVCODEC_AVCODEC_H
#   include <libavcodec/avcodec.h>
#elif defined(HAVE_FFMPEG_AVCODEC_H)
41
#   include <ffmpeg/avcodec.h>
Gildas Bazin's avatar
 
Gildas Bazin committed
42 43 44
#else
#   include <avcodec.h>
#endif
45

46
#include "avcodec.h"
47 48

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
49
 * decoder_sys_t : decoder descriptor
50
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
51 52
struct decoder_sys_t
{
53
    FFMPEG_COMMON_MEMBERS
Gildas Bazin's avatar
 
Gildas Bazin committed
54 55

    /* Temporary buffer for libavcodec */
56
    int     i_output_max;
Gildas Bazin's avatar
 
Gildas Bazin committed
57 58 59 60 61 62 63
    uint8_t *p_output;

    /*
     * Output properties
     */
    audio_sample_format_t aout_format;
    audio_date_t          end_date;
64 65 66 67 68 69

    /*
     *
     */
    uint8_t *p_samples;
    int     i_samples;
70 71 72

    /* */
    int     i_reject_count;
73 74 75 76 77 78

    /* */
    bool    b_extract;
    int     pi_extraction[AOUT_CHAN_MAX];
    int     i_previous_channels;
    int64_t i_previous_layout;
Gildas Bazin's avatar
 
Gildas Bazin committed
79
};
80

81
static void SetupOutputFormat( decoder_t *p_dec, bool b_trust );
82

83
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
84
 * InitAudioDec: initialize audio decoder
85
 *****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
86
 * The ffmpeg codec will be opened, some memory allocated.
87
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
88
int InitAudioDec( decoder_t *p_dec, AVCodecContext *p_context,
89
                      AVCodec *p_codec, int i_codec_id, const char *psz_namecodec )
90
{
Gildas Bazin's avatar
 
Gildas Bazin committed
91
    decoder_sys_t *p_sys;
92

Gildas Bazin's avatar
 
Gildas Bazin committed
93
    /* Allocate the memory needed to store the decoder's structure */
94
    if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
95
    {
96
        return VLC_ENOMEM;
Gildas Bazin's avatar
 
Gildas Bazin committed
97 98
    }

99 100 101 102
    p_sys->p_context = p_context;
    p_sys->p_codec = p_codec;
    p_sys->i_codec_id = i_codec_id;
    p_sys->psz_namecodec = psz_namecodec;
103
    p_sys->b_delayed_open = false;
Gildas Bazin's avatar
 
Gildas Bazin committed
104

105
    /* ***** Fill p_context with init values ***** */
Gildas Bazin's avatar
 
Gildas Bazin committed
106 107
    p_sys->p_context->sample_rate = p_dec->fmt_in.audio.i_rate;
    p_sys->p_context->channels = p_dec->fmt_in.audio.i_channels;
108

Gildas Bazin's avatar
 
Gildas Bazin committed
109 110
    p_sys->p_context->block_align = p_dec->fmt_in.audio.i_blockalign;
    p_sys->p_context->bit_rate = p_dec->fmt_in.i_bitrate;
Alexis Ballier's avatar
Alexis Ballier committed
111
#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
112
    p_sys->p_context->bits_per_sample = p_dec->fmt_in.audio.i_bitspersample;
Alexis Ballier's avatar
Alexis Ballier committed
113 114 115
#else
    p_sys->p_context->bits_per_coded_sample = p_dec->fmt_in.audio.i_bitspersample;
#endif
116

Laurent Aimar's avatar
Laurent Aimar committed
117
    if( p_dec->fmt_in.i_extra > 0 )
118
    {
Laurent Aimar's avatar
Laurent Aimar committed
119 120 121
        const uint8_t * const p_src = p_dec->fmt_in.p_extra;
        int i_offset;
        int i_size;
122 123

        if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'f', 'l', 'a', 'c' ) )
Laurent Aimar's avatar
Laurent Aimar committed
124
        {
125
            i_offset = 8;
Laurent Aimar's avatar
Laurent Aimar committed
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
            i_size = p_dec->fmt_in.i_extra - 8;
        }
        else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'l', 'a', 'c' ) )
        {
            static const uint8_t p_pattern[] = { 0, 0, 0, 36, 'a', 'l', 'a', 'c' };
            /* Find alac atom XXX it is a bit ugly */
            for( i_offset = 0; i_offset < p_dec->fmt_in.i_extra - sizeof(p_pattern); i_offset++ )
            {
                if( !memcmp( &p_src[i_offset], p_pattern, sizeof(p_pattern) ) )
                    break;
            }
            i_size = __MIN( p_dec->fmt_in.i_extra - i_offset, 36 );
            if( i_size < 36 )
                i_size = 0;
        }
        else
        {
            i_offset = 0;
            i_size = p_dec->fmt_in.i_extra;
        }
146

Laurent Aimar's avatar
Laurent Aimar committed
147
        if( i_size > 0 )
Rémi Duraffort's avatar
Rémi Duraffort committed
148
        {
Laurent Aimar's avatar
Laurent Aimar committed
149 150 151 152 153 154 155 156 157 158 159
            p_sys->p_context->extradata =
                malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
            if( p_sys->p_context->extradata )
            {
                uint8_t *p_dst = p_sys->p_context->extradata;

                p_sys->p_context->extradata_size = i_size;

                memcpy( &p_dst[0],            &p_src[i_offset], i_size );
                memset( &p_dst[i_size], 0, FF_INPUT_BUFFER_PADDING_SIZE );
            }
Rémi Duraffort's avatar
Rémi Duraffort committed
160
        }
161
    }
162
    else
Laurent Aimar's avatar
Laurent Aimar committed
163 164
    {
        p_sys->p_context->extradata_size = 0;
165
        p_sys->p_context->extradata = NULL;
Laurent Aimar's avatar
Laurent Aimar committed
166
    }
167

168
    /* ***** Open the codec ***** */
169 170 171 172 173
    int ret;
    vlc_avcodec_lock();
    ret = avcodec_open( p_sys->p_context, p_sys->p_codec );
    vlc_avcodec_unlock();
    if( ret < 0 )
174
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
175
        msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
176
        free( p_sys->p_context->extradata );
177
        free( p_sys );
Gildas Bazin's avatar
 
Gildas Bazin committed
178
        return VLC_EGENERIC;
179
    }
180 181

    msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );
182

183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
    switch( i_codec_id )
    {
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 51, 16, 0 )
    case CODEC_ID_WAVPACK:
        p_sys->i_output_max = 8 * sizeof(int32_t) * 131072;
        break;
#endif
    case CODEC_ID_FLAC:
        p_sys->i_output_max = 8 * sizeof(int32_t) * 65535;
        break;
    default:
        p_sys->i_output_max = 0;
        break;
    }
    if( p_sys->i_output_max < AVCODEC_MAX_AUDIO_FRAME_SIZE )
        p_sys->i_output_max = AVCODEC_MAX_AUDIO_FRAME_SIZE;
    msg_Dbg( p_dec, "Using %d bytes output buffer", p_sys->i_output_max );
    p_sys->p_output = malloc( p_sys->i_output_max );
201

202 203
    p_sys->p_samples = NULL;
    p_sys->i_samples = 0;
204
    p_sys->i_reject_count = 0;
205 206 207
    p_sys->b_extract = false;
    p_sys->i_previous_channels = 0;
    p_sys->i_previous_layout = 0;
208

Laurent Aimar's avatar
Laurent Aimar committed
209
    aout_DateSet( &p_sys->end_date, 0 );
210 211
    if( p_dec->fmt_in.audio.i_rate )
        aout_DateInit( &p_sys->end_date, p_dec->fmt_in.audio.i_rate );
212

213
    /* */
214 215 216
    p_dec->fmt_out.i_cat = AUDIO_ES;
    /* Try to set as much informations as possible but do not trust it */
    SetupOutputFormat( p_dec, false );
Gildas Bazin's avatar
 
Gildas Bazin committed
217

Gildas Bazin's avatar
 
Gildas Bazin committed
218
    return VLC_SUCCESS;
219 220
}

221 222 223 224
/*****************************************************************************
 * SplitBuffer: Needed because aout really doesn't like big audio chunk and
 * wma produces easily > 30000 samples...
 *****************************************************************************/
Clément Stenac's avatar
Clément Stenac committed
225
static aout_buffer_t *SplitBuffer( decoder_t *p_dec )
226 227 228 229 230
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    int i_samples = __MIN( p_sys->i_samples, 4096 );
    aout_buffer_t *p_buffer;

231 232
    if( i_samples == 0 ) return NULL;

233
    if( ( p_buffer = decoder_NewAudioBuffer( p_dec, i_samples ) ) == NULL )
234 235 236
        return NULL;

    p_buffer->start_date = aout_DateGet( &p_sys->end_date );
237
    p_buffer->end_date = aout_DateIncrement( &p_sys->end_date, i_samples );
238

239 240 241 242 243 244
    if( p_sys->b_extract )
        aout_ChannelExtract( p_buffer->p_buffer, p_dec->fmt_out.audio.i_channels,
                             p_sys->p_samples, p_sys->p_context->channels, i_samples,
                             p_sys->pi_extraction, p_dec->fmt_out.audio.i_bitspersample );
    else
        memcpy( p_buffer->p_buffer, p_sys->p_samples, p_buffer->i_nb_bytes );
245 246 247 248 249 250 251

    p_sys->p_samples += p_buffer->i_nb_bytes;
    p_sys->i_samples -= i_samples;

    return p_buffer;
}

252
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
253
 * DecodeAudio: Called to decode one frame
254
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
255
aout_buffer_t * DecodeAudio ( decoder_t *p_dec, block_t **pp_block )
256
{
Gildas Bazin's avatar
 
Gildas Bazin committed
257
    decoder_sys_t *p_sys = p_dec->p_sys;
258
    int i_used, i_output;
Gildas Bazin's avatar
 
Gildas Bazin committed
259 260 261 262
    aout_buffer_t *p_buffer;
    block_t *p_block;

    if( !pp_block || !*pp_block ) return NULL;
263

Gildas Bazin's avatar
 
Gildas Bazin committed
264
    p_block = *pp_block;
265

Laurent Aimar's avatar
Laurent Aimar committed
266 267 268 269
    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
    {
        block_Release( p_block );
        avcodec_flush_buffers( p_sys->p_context );
270 271
        p_sys->i_samples = 0;
        aout_DateSet( &p_sys->end_date, 0 );
272 273 274

        if( p_sys->i_codec_id == CODEC_ID_MP2 || p_sys->i_codec_id == CODEC_ID_MP3 )
            p_sys->i_reject_count = 3;
Laurent Aimar's avatar
Laurent Aimar committed
275 276 277 278
        return NULL;
    }

    if( p_sys->i_samples > 0 )
279 280 281
    {
        /* More data */
        p_buffer = SplitBuffer( p_dec );
282
        if( !p_buffer ) block_Release( p_block );
283 284 285
        return p_buffer;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
286 287 288 289
    if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
    {
        /* We've just started the stream, wait for the first PTS. */
        block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
290
        return NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
291
    }
292

Laurent Aimar's avatar
Laurent Aimar committed
293
    if( p_block->i_buffer <= 0 )
294
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
295 296 297
        block_Release( p_block );
        return NULL;
    }
298

299
    i_output = __MAX( p_block->i_buffer, p_sys->i_output_max );
Laurent Aimar's avatar
Laurent Aimar committed
300
    if( i_output > p_sys->i_output_max )
301 302
    {
        /* Grow output buffer if necessary (eg. for PCM data) */
Laurent Aimar's avatar
Laurent Aimar committed
303
        p_sys->p_output = realloc( p_sys->p_output, i_output );
304 305
    }

Laurent Aimar's avatar
Laurent Aimar committed
306 307 308 309 310 311
    *pp_block = p_block = block_Realloc( p_block, 0, p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE );
    if( !p_block )
        return NULL;
    p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE;
    memset( &p_block->p_buffer[p_block->i_buffer], 0, FF_INPUT_BUFFER_PADDING_SIZE );

312
#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(0<<8)+0)
Laurent Aimar's avatar
Laurent Aimar committed
313
    i_used = avcodec_decode_audio2( p_sys->p_context,
Gildas Bazin's avatar
 
Gildas Bazin committed
314 315
                                   (int16_t*)p_sys->p_output, &i_output,
                                   p_block->p_buffer, p_block->i_buffer );
316 317 318 319 320
#else
    i_used = avcodec_decode_audio( p_sys->p_context,
                                   (int16_t*)p_sys->p_output, &i_output,
                                   p_block->p_buffer, p_block->i_buffer );
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
321

322
    if( i_used < 0 || i_output < 0 )
Gildas Bazin's avatar
 
Gildas Bazin committed
323
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
324
        if( i_used < 0 )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
325
            msg_Warn( p_dec, "cannot decode one frame (%zu bytes)",
Gildas Bazin's avatar
 
Gildas Bazin committed
326 327 328 329
                      p_block->i_buffer );

        block_Release( p_block );
        return NULL;
330
    }
331
    else if( (size_t)i_used > p_block->i_buffer )
332 333 334
    {
        i_used = p_block->i_buffer;
    }
335

Gildas Bazin's avatar
 
Gildas Bazin committed
336 337 338
    p_block->i_buffer -= i_used;
    p_block->p_buffer += i_used;

339
    if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 8 ||
340
        p_sys->p_context->sample_rate <= 0 )
Gildas Bazin's avatar
 
Gildas Bazin committed
341
    {
342 343
        msg_Warn( p_dec, "invalid audio properties channels count %d, sample rate %d",
                  p_sys->p_context->channels, p_sys->p_context->sample_rate );
Gildas Bazin's avatar
 
Gildas Bazin committed
344 345 346 347
        block_Release( p_block );
        return NULL;
    }

348
    if( p_dec->fmt_out.audio.i_rate != (unsigned int)p_sys->p_context->sample_rate )
Gildas Bazin's avatar
 
Gildas Bazin committed
349 350 351 352 353 354
    {
        aout_DateInit( &p_sys->end_date, p_sys->p_context->sample_rate );
        aout_DateSet( &p_sys->end_date, p_block->i_pts );
    }

    /* **** Set audio output parameters **** */
355
    SetupOutputFormat( p_dec, true );
Gildas Bazin's avatar
 
Gildas Bazin committed
356 357 358 359 360 361

    if( p_block->i_pts != 0 &&
        p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
    {
        aout_DateSet( &p_sys->end_date, p_block->i_pts );
    }
362
    p_block->i_pts = 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
363 364

    /* **** Now we can output these samples **** */
365
    p_sys->i_samples = i_output / (p_dec->fmt_out.audio.i_bitspersample / 8) / p_sys->p_context->channels;
366
    p_sys->p_samples = p_sys->p_output;
Gildas Bazin's avatar
 
Gildas Bazin committed
367

368 369 370 371 372 373 374
    /* Silent unwanted samples */
    if( p_sys->i_reject_count > 0 )
    {
        memset( p_sys->p_output, 0, i_output );
        p_sys->i_reject_count--;
    }

375
    p_buffer = SplitBuffer( p_dec );
376
    if( !p_buffer ) block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
377
    return p_buffer;
378 379 380
}

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
381
 * EndAudioDec: audio decoder destruction
382
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
383
void EndAudioDec( decoder_t *p_dec )
384
{
Gildas Bazin's avatar
 
Gildas Bazin committed
385 386
    decoder_sys_t *p_sys = p_dec->p_sys;

387
    free( p_sys->p_output );
388
}
389 390 391 392

/*****************************************************************************
 *
 *****************************************************************************/
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
static const uint64_t pi_channels_map[][2] =
{
    { CH_FRONT_LEFT,        AOUT_CHAN_LEFT },
    { CH_FRONT_RIGHT,       AOUT_CHAN_RIGHT },
    { CH_FRONT_CENTER,      AOUT_CHAN_CENTER },
    { CH_LOW_FREQUENCY,     AOUT_CHAN_LFE },
    { CH_BACK_LEFT,         AOUT_CHAN_REARLEFT },
    { CH_BACK_RIGHT,        AOUT_CHAN_REARRIGHT },
    { CH_FRONT_LEFT_OF_CENTER, 0 },
    { CH_FRONT_RIGHT_OF_CENTER, 0 },
    { CH_BACK_CENTER,       AOUT_CHAN_REARCENTER },
    { CH_SIDE_LEFT,         AOUT_CHAN_MIDDLELEFT },
    { CH_SIDE_RIGHT,        AOUT_CHAN_MIDDLERIGHT },
    { CH_TOP_CENTER,        0 },
    { CH_TOP_FRONT_LEFT,    0 },
    { CH_TOP_FRONT_CENTER,  0 },
    { CH_TOP_FRONT_RIGHT,   0 },
    { CH_TOP_BACK_LEFT,     0 },
    { CH_TOP_BACK_CENTER,   0 },
    { CH_TOP_BACK_RIGHT,    0 },
    { CH_STEREO_LEFT,       0 },
    { CH_STEREO_RIGHT,      0 },
};

417
static void SetupOutputFormat( decoder_t *p_dec, bool b_trust )
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
{
    decoder_sys_t *p_sys = p_dec->p_sys;

#if defined(AV_VERSION_INT) && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 51, 65, 0 )
    switch( p_sys->p_context->sample_fmt )
    {
    case SAMPLE_FMT_U8:
        p_dec->fmt_out.i_codec = VLC_FOURCC('u','8',' ',' ');
        p_dec->fmt_out.audio.i_bitspersample = 8;
        break;
    case SAMPLE_FMT_S32:
        p_dec->fmt_out.i_codec = AOUT_FMT_S32_NE;
        p_dec->fmt_out.audio.i_bitspersample = 32;
        break;
    case SAMPLE_FMT_FLT:
        p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2');
        p_dec->fmt_out.audio.i_bitspersample = 32;
        break;
    case SAMPLE_FMT_DBL:
        p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','6','4');
        p_dec->fmt_out.audio.i_bitspersample = 64;
        break;

    case SAMPLE_FMT_S16:
    default:
        p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
        p_dec->fmt_out.audio.i_bitspersample = 16;
        break;
    }
#else
    p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
    p_dec->fmt_out.audio.i_bitspersample = 16;
#endif
451 452 453 454 455 456 457
    p_dec->fmt_out.audio.i_rate     = p_sys->p_context->sample_rate;
    p_dec->fmt_out.audio.i_channels = p_sys->p_context->channels;

    /* */
    if( p_sys->i_previous_channels == p_sys->p_context->channels &&
        p_sys->i_previous_layout == p_sys->p_context->channel_layout )
        return;
458 459 460 461 462
    if( b_trust )
    {
        p_sys->i_previous_channels = p_sys->p_context->channels;
        p_sys->i_previous_layout = p_sys->p_context->channel_layout;
    }
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481

    /* Specified order
     * FIXME should we use fmt_in.audio.i_physical_channels or not ?
     */
    const unsigned i_order_max = 8 * sizeof(p_sys->p_context->channel_layout);
    uint32_t pi_order_src[i_order_max];
    int i_channels_src = 0;

    if( p_sys->p_context->channel_layout )
    {
        for( unsigned i = 0; i < sizeof(pi_channels_map)/sizeof(*pi_channels_map); i++ )
        {
            if( p_sys->p_context->channel_layout & pi_channels_map[i][0] )
                pi_order_src[i_channels_src++] = pi_channels_map[i][1];
        }
    }
    else
    {
        /* Create default order  */
482 483
        if( b_trust )
            msg_Warn( p_dec, "Physical channel configuration not set : guessing" );
484 485 486 487 488 489
        for( unsigned int i = 0; i < __MIN( i_order_max, (unsigned)p_sys->p_context->channels ); i++ )
        {
            if( i < sizeof(pi_channels_map)/sizeof(*pi_channels_map) )
                pi_order_src[i_channels_src++] = pi_channels_map[i][1];
        }
    }
490
    if( i_channels_src != p_sys->p_context->channels && b_trust )
491 492 493 494 495 496 497
        msg_Err( p_dec, "Channel layout not understood" );

    uint32_t i_layout_dst;
    int      i_channels_dst;
    p_sys->b_extract = aout_CheckChannelExtraction( p_sys->pi_extraction,
                                                    &i_layout_dst, &i_channels_dst,
                                                    NULL, pi_order_src, i_channels_src );
498
    if( i_channels_dst != i_channels_src && b_trust )
499 500 501 502 503
        msg_Warn( p_dec, "%d channels are dropped", i_channels_src - i_channels_dst );

    p_dec->fmt_out.audio.i_physical_channels =
    p_dec->fmt_out.audio.i_original_channels = i_layout_dst;
    p_dec->fmt_out.audio.i_channels = i_channels_dst;
504
}
505