audio.c 16.4 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 );
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
    /* */
    es_format_Init( &p_dec->fmt_out, AUDIO_ES, 0 );
Gildas Bazin's avatar
 
Gildas Bazin committed
215

Gildas Bazin's avatar
 
Gildas Bazin committed
216
    return VLC_SUCCESS;
217 218
}

219 220 221 222
/*****************************************************************************
 * 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
223
static aout_buffer_t *SplitBuffer( decoder_t *p_dec )
224 225 226 227 228
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    int i_samples = __MIN( p_sys->i_samples, 4096 );
    aout_buffer_t *p_buffer;

229 230
    if( i_samples == 0 ) return NULL;

231
    if( ( p_buffer = decoder_NewAudioBuffer( p_dec, i_samples ) ) == NULL )
232 233 234
        return NULL;

    p_buffer->start_date = aout_DateGet( &p_sys->end_date );
235
    p_buffer->end_date = aout_DateIncrement( &p_sys->end_date, i_samples );
236

237 238 239 240 241 242
    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 );
243 244 245 246 247 248 249

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

    return p_buffer;
}

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

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

Gildas Bazin's avatar
 
Gildas Bazin committed
262
    p_block = *pp_block;
263

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

        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
273 274 275 276
        return NULL;
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
284 285 286 287
    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
288
        return NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
289
    }
290

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

297 298
    i_output = __MAX( p_block->i_buffer, p_sys->i_output_max );
    if( i_output < p_sys->i_output_max )
299 300 301 302 303
    {
        /* Grow output buffer if necessary (eg. for PCM data) */
        p_sys->p_output = realloc(p_sys->p_output, p_block->i_buffer);
    }

Laurent Aimar's avatar
Laurent Aimar committed
304 305 306 307 308 309
    *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 );

310
#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(0<<8)+0)
Laurent Aimar's avatar
Laurent Aimar committed
311
    i_used = avcodec_decode_audio2( p_sys->p_context,
Gildas Bazin's avatar
 
Gildas Bazin committed
312 313
                                   (int16_t*)p_sys->p_output, &i_output,
                                   p_block->p_buffer, p_block->i_buffer );
314 315 316 317 318
#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
319

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

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

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

337
    if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 8 ||
338
        p_sys->p_context->sample_rate <= 0 )
Gildas Bazin's avatar
 
Gildas Bazin committed
339
    {
340 341
        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
342 343 344 345
        block_Release( p_block );
        return NULL;
    }

346
    if( p_dec->fmt_out.audio.i_rate != (unsigned int)p_sys->p_context->sample_rate )
Gildas Bazin's avatar
 
Gildas Bazin committed
347 348 349 350 351 352
    {
        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 **** */
353
    SetupOutputFormat( p_dec );
Gildas Bazin's avatar
 
Gildas Bazin committed
354 355 356 357 358 359

    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 );
    }
360
    p_block->i_pts = 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
361 362

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

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

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

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

385
    free( p_sys->p_output );
386
}
387 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
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 },
};

static void SetupOutputFormat( decoder_t *p_dec )
416 417 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
{
    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
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
    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;
    p_sys->i_previous_channels = p_sys->p_context->channels;
    p_sys->i_previous_layout = p_sys->p_context->channel_layout;

    /* 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  */
        msg_Warn( p_dec, "Physical channel configuration not set : guessing" );
        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];
        }
    }
    if( i_channels_src != p_sys->p_context->channels )
        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 );
    if( i_channels_dst != i_channels_src )
        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;
498
}
499