faad.c 19.3 KB
Newer Older
1
/*****************************************************************************
Pere Orga's avatar
Pere Orga committed
2
 * faad.c: AAC decoder using libfaad2
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
4
 * Copyright (C) 2001, 2003 VLC authors and VideoLAN
5
 * $Id$
6 7
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8
 *          Gildas Bazin <gbazin@videolan.org>
9
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
10 11 12
 * 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
13 14 15 16
 * (at your option) any later version.
 *
 * 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
17 18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
19
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
20 21 22
 * 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.
23 24
 *****************************************************************************/

Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
25 26 27 28 29 30 31 32
/*****************************************************************************
 * NOTA BENE: this module requires the linking against a library which is
 * known to require licensing under the GNU General Public License version 2
 * (or later). Therefore, the result of compiling this module will normally
 * be subject to the terms of that later license.
 *****************************************************************************/


33 34 35 36
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

37
#include <vlc_common.h>
38
#include <vlc_plugin.h>
39
#include <vlc_input.h>
zorglub's avatar
zorglub committed
40
#include <vlc_codec.h>
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
41
#include <vlc_cpu.h>
42 43 44 45 46 47 48

#include <faad.h>

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int  Open( vlc_object_t * );
49
static void Close( vlc_object_t * );
50

51 52 53 54 55 56 57
vlc_module_begin ()
    set_description( N_("AAC audio decoder (using libfaad2)") )
    set_capability( "decoder", 100 )
    set_category( CAT_INPUT )
    set_subcategory( SUBCAT_INPUT_ACODEC )
    set_callbacks( Open, Close )
vlc_module_end ()
58 59 60 61

/****************************************************************************
 * Local prototypes
 ****************************************************************************/
62
static block_t *DecodeBlock( decoder_t *, block_t ** );
63
static void DoReordering( uint32_t *, uint32_t *, int, int, uint32_t * );
gbazin's avatar
 
gbazin committed
64 65

#define MAX_CHANNEL_POSITIONS 9
66 67 68 69 70 71 72

struct decoder_sys_t
{
    /* faad handler */
    faacDecHandle *hfaad;

    /* samples */
73
    date_t date;
74 75

    /* temporary buffer */
gbazin's avatar
 
gbazin committed
76 77
    uint8_t *p_buffer;
    int     i_buffer;
78
    size_t  i_buffer_size;
79

gbazin's avatar
 
gbazin committed
80 81
    /* Channel positions of the current stream (for re-ordering) */
    uint32_t pi_channel_positions[MAX_CHANNEL_POSITIONS];
82

83
    bool b_sbr, b_ps;
84 85
};

gbazin's avatar
 
gbazin committed
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
static const uint32_t pi_channels_in[MAX_CHANNEL_POSITIONS] =
    { FRONT_CHANNEL_CENTER, FRONT_CHANNEL_LEFT, FRONT_CHANNEL_RIGHT,
      SIDE_CHANNEL_LEFT, SIDE_CHANNEL_RIGHT,
      BACK_CHANNEL_LEFT, BACK_CHANNEL_RIGHT,
      BACK_CHANNEL_CENTER, LFE_CHANNEL };
static const uint32_t pi_channels_out[MAX_CHANNEL_POSITIONS] =
    { AOUT_CHAN_CENTER, AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
      AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT,
      AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
      AOUT_CHAN_REARCENTER, AOUT_CHAN_LFE };
static const uint32_t pi_channels_ordered[MAX_CHANNEL_POSITIONS] =
    { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
      AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT,
      AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
      AOUT_CHAN_CENTER, AOUT_CHAN_REARCENTER, AOUT_CHAN_LFE
    };
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
static const uint32_t pi_channels_guessed[MAX_CHANNEL_POSITIONS] =
    { 0, AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
      AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE,
      AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
          | AOUT_CHAN_REARRIGHT,
      AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
          | AOUT_CHAN_REARRIGHT | AOUT_CHAN_CENTER,
      AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
          | AOUT_CHAN_REARRIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_LFE,
      AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_MIDDLELEFT
          | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
          | AOUT_CHAN_CENTER,
      AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_MIDDLELEFT
          | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
          | AOUT_CHAN_CENTER | AOUT_CHAN_LFE
    };
gbazin's avatar
 
gbazin committed
118

119
/*****************************************************************************
gbazin's avatar
 
gbazin committed
120
 * OpenDecoder: probe the decoder and return score
121
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
122
static int Open( vlc_object_t *p_this )
123
{
gbazin's avatar
 
gbazin committed
124
    decoder_t *p_dec = (decoder_t*)p_this;
125 126 127
    decoder_sys_t *p_sys = p_dec->p_sys;
    faacDecConfiguration *cfg;

128
    if( p_dec->fmt_in.i_codec != VLC_CODEC_MP4A )
129
    {
gbazin's avatar
 
gbazin committed
130 131 132 133
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
134
    if( ( p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) ) ) == NULL )
135
        return VLC_ENOMEM;
136 137 138 139

    /* Open a faad context */
    if( ( p_sys->hfaad = faacDecOpen() ) == NULL )
    {
bigben's avatar
bigben committed
140
        msg_Err( p_dec, "cannot initialize faad" );
ivoire's avatar
ivoire committed
141
        free( p_sys );
142 143 144
        return VLC_EGENERIC;
    }

gbazin's avatar
 
gbazin committed
145
    /* Misc init */
146
    date_Set( &p_sys->date, 0 );
gbazin's avatar
 
gbazin committed
147
    p_dec->fmt_out.i_cat = AUDIO_ES;
148

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
149
    p_dec->fmt_out.i_codec = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
gbazin's avatar
 
gbazin committed
150 151
    p_dec->pf_decode_audio = DecodeBlock;

gbazin's avatar
 
gbazin committed
152 153 154
    p_dec->fmt_out.audio.i_physical_channels =
        p_dec->fmt_out.audio.i_original_channels = 0;

gbazin's avatar
 
gbazin committed
155
    if( p_dec->fmt_in.i_extra > 0 )
156 157
    {
        /* We have a decoder config so init the handle */
gbazin's avatar
 
gbazin committed
158 159
        unsigned long i_rate;
        unsigned char i_channels;
160

gbazin's avatar
 
gbazin committed
161 162
        if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra,
                          p_dec->fmt_in.i_extra,
163 164
                          &i_rate, &i_channels ) < 0 )
        {
165
            msg_Err( p_dec, "Failed to initialize faad using extra data" );
ivoire's avatar
ivoire committed
166 167
            faacDecClose( p_sys->hfaad );
            free( p_sys );
168 169 170
            return VLC_EGENERIC;
        }

gbazin's avatar
 
gbazin committed
171 172
        p_dec->fmt_out.audio.i_rate = i_rate;
        p_dec->fmt_out.audio.i_channels = i_channels;
173 174 175
        p_dec->fmt_out.audio.i_physical_channels
            = p_dec->fmt_out.audio.i_original_channels
            = pi_channels_guessed[i_channels];
176
        date_Init( &p_sys->date, i_rate, 1 );
177 178 179 180
    }
    else
    {
        /* Will be initalised from first frame */
gbazin's avatar
 
gbazin committed
181
        p_dec->fmt_out.audio.i_rate = 0;
182 183 184
        /*FIXME: Try to guess channel count, so transcode module doesn't burb and do funny stuff
            Revert back to 0 when transcode module/audio encoders can reinit stuff after Open()*/
        p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
185 186
    }

gbazin's avatar
 
gbazin committed
187
    /* Set the faad config */
188
    cfg = faacDecGetCurrentConfiguration( p_sys->hfaad );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
189
    cfg->outputFormat = HAVE_FPU ? FAAD_FMT_FLOAT : FAAD_FMT_16BIT;
190 191 192
    faacDecSetConfiguration( p_sys->hfaad, cfg );

    /* buffer */
gbazin's avatar
 
gbazin committed
193
    p_sys->i_buffer = p_sys->i_buffer_size = 0;
194
    p_sys->p_buffer = NULL;
195

196
    /* Faad2 can't deal with truncated data (eg. from MPEG TS) */
197
    p_dec->b_need_packetized = true;
198

199
    p_sys->b_sbr = p_sys->b_ps = false;
200 201 202 203
    return VLC_SUCCESS;
}

/*****************************************************************************
gbazin's avatar
 
gbazin committed
204
 * DecodeBlock:
205
 *****************************************************************************/
206
static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
207 208
{
    decoder_sys_t *p_sys = p_dec->p_sys;
209
    block_t *p_block;
210

211 212 213
    if( !pp_block || !*pp_block ) return NULL;

    p_block = *pp_block;
214

Laurent Aimar's avatar
Laurent Aimar committed
215
    if( p_block->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
216 217 218 219 220
    {
        block_Release( p_block );
        return NULL;
    }

221 222 223 224 225 226 227 228 229 230 231
    /* Remove ADTS header if we have decoder specific config */
    if( p_dec->fmt_in.i_extra && p_block->i_buffer > 7 )
    {
        if( p_block->p_buffer[0] == 0xff &&
            ( p_block->p_buffer[1] & 0xf0 ) == 0xf0 ) /* syncword */
        {   /* ADTS header present */
            size_t i_header_size; /* 7 bytes (+ 2 bytes for crc) */
            i_header_size = 7 + ( ( p_block->p_buffer[1] & 0x01 ) ? 0 : 2 );
            /* FIXME: multiple blocks per frame */
            if( p_block->i_buffer > i_header_size )
            {
232
                p_block->p_buffer += i_header_size;
233 234 235 236 237
                p_block->i_buffer -= i_header_size;
            }
        }
    }

238 239 240
    /* Append the block to the temporary buffer */
    if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
    {
241 242 243 244 245 246 247 248 249 250 251
        size_t  i_buffer_size = p_sys->i_buffer + p_block->i_buffer;
        uint8_t *p_buffer     = realloc( p_sys->p_buffer, i_buffer_size );
        if( p_buffer )
        {
            p_sys->i_buffer_size = i_buffer_size;
            p_sys->p_buffer      = p_buffer;
        }
        else
        {
            p_block->i_buffer = 0;
        }
252 253
    }

254
    if( p_block->i_buffer > 0 )
gbazin's avatar
 
gbazin committed
255
    {
Rafaël Carré's avatar
Rafaël Carré committed
256
        memcpy( &p_sys->p_buffer[p_sys->i_buffer],
257
                     p_block->p_buffer, p_block->i_buffer );
gbazin's avatar
 
gbazin committed
258 259 260 261
        p_sys->i_buffer += p_block->i_buffer;
        p_block->i_buffer = 0;
    }

262 263 264 265 266 267 268 269 270 271 272 273
    if( p_dec->fmt_out.audio.i_rate == 0 && p_dec->fmt_in.i_extra > 0 )
    {
        /* We have a decoder config so init the handle */
        unsigned long i_rate;
        unsigned char i_channels;

        if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra,
                          p_dec->fmt_in.i_extra,
                          &i_rate, &i_channels ) >= 0 )
        {
            p_dec->fmt_out.audio.i_rate = i_rate;
            p_dec->fmt_out.audio.i_channels = i_channels;
274 275 276 277
            p_dec->fmt_out.audio.i_physical_channels
                = p_dec->fmt_out.audio.i_original_channels
                = pi_channels_guessed[i_channels];

278
            date_Init( &p_sys->date, i_rate, 1 );
279 280 281
        }
    }

gbazin's avatar
 
gbazin committed
282
    if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer )
283
    {
gbazin's avatar
 
gbazin committed
284 285
        unsigned long i_rate;
        unsigned char i_channels;
286 287 288 289 290 291

        /* Init faad with the first frame */
        if( faacDecInit( p_sys->hfaad,
                         p_sys->p_buffer, p_sys->i_buffer,
                         &i_rate, &i_channels ) < 0 )
        {
292
            block_Release( p_block );
gbazin's avatar
 
gbazin committed
293
            return NULL;
294
        }
gbazin's avatar
 
gbazin committed
295 296 297

        p_dec->fmt_out.audio.i_rate = i_rate;
        p_dec->fmt_out.audio.i_channels = i_channels;
298 299 300
        p_dec->fmt_out.audio.i_physical_channels
            = p_dec->fmt_out.audio.i_original_channels
            = pi_channels_guessed[i_channels];
301
        date_Init( &p_sys->date, i_rate, 1 );
gbazin's avatar
 
gbazin committed
302 303
    }

304
    if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != date_Get( &p_sys->date ) )
gbazin's avatar
 
gbazin committed
305
    {
306
        date_Set( &p_sys->date, p_block->i_pts );
gbazin's avatar
 
gbazin committed
307
    }
308
    else if( !date_Get( &p_sys->date ) )
gbazin's avatar
 
gbazin committed
309 310 311 312 313
    {
        /* We've just started the stream, wait for the first PTS. */
        block_Release( p_block );
        p_sys->i_buffer = 0;
        return NULL;
314 315 316
    }

    /* Decode all data */
gbazin's avatar
 
gbazin committed
317
    if( p_sys->i_buffer )
318 319 320
    {
        void *samples;
        faacDecFrameInfo frame;
321
        block_t *p_out;
322 323

        samples = faacDecDecode( p_sys->hfaad, &frame,
gbazin's avatar
 
gbazin committed
324
                                 p_sys->p_buffer, p_sys->i_buffer );
325 326 327 328

        if( frame.error > 0 )
        {
            msg_Warn( p_dec, "%s", faacDecGetErrorMessage( frame.error ) );
gbazin's avatar
 
gbazin committed
329

330
            if( frame.error == 21 || frame.error == 12 )
331 332
            {
                /*
333 334
                 * Once an "Unexpected channel configuration change"
                 * or a "Invalid number of channels" error
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
                 * occurs, it will occurs afterwards, and we got no sound.
                 * Reinitialization of the decoder is required.
                 */
                unsigned long i_rate;
                unsigned char i_channels;
                faacDecHandle *hfaad;
                faacDecConfiguration *cfg,*oldcfg;

                oldcfg = faacDecGetCurrentConfiguration( p_sys->hfaad );
                hfaad = faacDecOpen();
                cfg = faacDecGetCurrentConfiguration( hfaad );
                if( oldcfg->defSampleRate )
                    cfg->defSampleRate = oldcfg->defSampleRate;
                cfg->defObjectType = oldcfg->defObjectType;
                cfg->outputFormat = oldcfg->outputFormat;
                faacDecSetConfiguration( hfaad, cfg );

                if( faacDecInit( hfaad, p_sys->p_buffer, p_sys->i_buffer,
                                &i_rate,&i_channels ) < 0 )
                {
                    /* reinitialization failed */
                    faacDecClose( hfaad );
                    faacDecSetConfiguration( p_sys->hfaad, oldcfg );
                }
                else
                {
                    faacDecClose( p_sys->hfaad );
                    p_sys->hfaad = hfaad;
                    p_dec->fmt_out.audio.i_rate = i_rate;
                    p_dec->fmt_out.audio.i_channels = i_channels;
                    p_dec->fmt_out.audio.i_physical_channels
                        = p_dec->fmt_out.audio.i_original_channels
                        = pi_channels_guessed[i_channels];
                    date_Init( &p_sys->date, i_rate, 1 );
                }
            }

gbazin's avatar
 
gbazin committed
372
            /* Flush the buffer */
373
            p_sys->i_buffer = 0;
374
            block_Release( p_block );
gbazin's avatar
 
gbazin committed
375
            return NULL;
376
        }
gbazin's avatar
 
gbazin committed
377

gbazin's avatar
 
gbazin committed
378
        if( frame.channels <= 0 || frame.channels > 8 || frame.channels == 7 )
379
        {
gbazin's avatar
 
gbazin committed
380
            msg_Warn( p_dec, "invalid channels count: %i", frame.channels );
gbazin's avatar
 
gbazin committed
381 382

            /* Flush the buffer */
gbazin's avatar
 
gbazin committed
383 384 385 386 387 388
            p_sys->i_buffer -= frame.bytesconsumed;
            if( p_sys->i_buffer > 0 )
            {
                memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed],
                         p_sys->i_buffer );
            }
389
            block_Release( p_block );
gbazin's avatar
 
gbazin committed
390
            return NULL;
391
        }
gbazin's avatar
 
gbazin committed
392

393 394
        if( frame.samples <= 0 )
        {
bigben's avatar
bigben committed
395
            msg_Warn( p_dec, "decoded zero sample" );
gbazin's avatar
 
gbazin committed
396 397

            /* Flush the buffer */
gbazin's avatar
 
gbazin committed
398 399 400 401 402 403
            p_sys->i_buffer -= frame.bytesconsumed;
            if( p_sys->i_buffer > 0 )
            {
                memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed],
                         p_sys->i_buffer );
            }
404
            block_Release( p_block );
gbazin's avatar
 
gbazin committed
405
            return NULL;
406 407
        }

gbazin's avatar
 
gbazin committed
408 409
        /* We decoded a valid frame */
        if( p_dec->fmt_out.audio.i_rate != frame.samplerate )
410
        {
411 412
            date_Init( &p_sys->date, frame.samplerate, 1 );
            date_Set( &p_sys->date, p_block->i_pts );
413
        }
414
        p_block->i_pts = VLC_TS_INVALID;  /* PTS is valid only once */
415

gbazin's avatar
 
gbazin committed
416 417
        p_dec->fmt_out.audio.i_rate = frame.samplerate;
        p_dec->fmt_out.audio.i_channels = frame.channels;
418

419
        /* Adjust stream info when dealing with SBR/PS */
420 421
        bool b_sbr = (frame.sbr == 1) || (frame.sbr == 2);
        if( p_sys->b_sbr != b_sbr || p_sys->b_ps != frame.ps )
422
        {
423 424
            const char *psz_ext = (b_sbr && frame.ps) ? "SBR+PS" :
                                    b_sbr ? "SBR" : "PS";
425

426 427 428
            msg_Dbg( p_dec, "AAC %s (channels: %u, samplerate: %lu)",
                    psz_ext, frame.channels, frame.samplerate );

429 430 431 432 433
            if( !p_dec->p_description )
                p_dec->p_description = vlc_meta_New();
            if( p_dec->p_description )
                vlc_meta_AddExtra( p_dec->p_description, _("AAC extension"), psz_ext );

434 435
            p_sys->b_sbr = b_sbr;
            p_sys->b_ps = frame.ps;
436
        }
gbazin's avatar
 
gbazin committed
437 438

        /* Convert frame.channel_position to our own channel values */
439
        p_dec->fmt_out.audio.i_physical_channels = 0;
440
        const uint32_t nbChannels = frame.channels;
441 442
        unsigned j;
        for( unsigned i = 0; i < nbChannels; i++ )
gbazin's avatar
 
gbazin committed
443 444 445 446 447 448 449
        {
            /* Find the channel code */
            for( j = 0; j < MAX_CHANNEL_POSITIONS; j++ )
            {
                if( frame.channel_position[i] == pi_channels_in[j] )
                    break;
            }
450
            if( j >= MAX_CHANNEL_POSITIONS )
451
            {
hartman's avatar
hartman committed
452
                msg_Warn( p_dec, "unknown channel ordering" );
453 454
                /* Invent something */
                j = i;
455
            }
456 457 458 459 460 461
            /* */
            p_sys->pi_channel_positions[i] = pi_channels_out[j];
            if( p_dec->fmt_out.audio.i_physical_channels & pi_channels_out[j] )
                frame.channels--; /* We loose a duplicated channel */
            else
                p_dec->fmt_out.audio.i_physical_channels |= pi_channels_out[j];
gbazin's avatar
 
gbazin committed
462
        }
463 464 465 466 467 468 469 470 471 472 473 474 475
        if ( nbChannels != frame.channels )
        {
            p_dec->fmt_out.audio.i_physical_channels
                = p_dec->fmt_out.audio.i_original_channels
                = pi_channels_guessed[nbChannels];
        }
        else
        {
            p_dec->fmt_out.audio.i_original_channels =
                p_dec->fmt_out.audio.i_physical_channels;
        }
        p_dec->fmt_out.audio.i_channels = nbChannels;
        p_out = decoder_NewAudioBuffer( p_dec, frame.samples / nbChannels );
gbazin's avatar
 
gbazin committed
476
        if( p_out == NULL )
477
        {
gbazin's avatar
 
gbazin committed
478
            p_sys->i_buffer = 0;
479
            block_Release( p_block );
gbazin's avatar
 
gbazin committed
480
            return NULL;
481 482
        }

483
        p_out->i_pts = date_Get( &p_sys->date );
484
        p_out->i_length = date_Increment( &p_sys->date,
485
                                          frame.samples / nbChannels )
486
                          - p_out->i_pts;
gbazin's avatar
 
gbazin committed
487

488
        DoReordering( (uint32_t *)p_out->p_buffer, samples,
489
                      frame.samples / nbChannels, nbChannels,
gbazin's avatar
 
gbazin committed
490
                      p_sys->pi_channel_positions );
491

gbazin's avatar
 
gbazin committed
492 493
        p_sys->i_buffer -= frame.bytesconsumed;
        if( p_sys->i_buffer > 0 )
494
        {
gbazin's avatar
 
gbazin committed
495 496
            memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed],
                     p_sys->i_buffer );
497 498
        }

gbazin's avatar
 
gbazin committed
499
        return p_out;
500 501
    }

502
    block_Release( p_block );
gbazin's avatar
 
gbazin committed
503
    return NULL;
504 505 506
}

/*****************************************************************************
507
 * Close:
508
 *****************************************************************************/
509
static void Close( vlc_object_t *p_this )
510
{
gbazin's avatar
 
gbazin committed
511
    decoder_t *p_dec = (decoder_t *)p_this;
512 513 514
    decoder_sys_t *p_sys = p_dec->p_sys;

    faacDecClose( p_sys->hfaad );
ivoire's avatar
ivoire committed
515
    free( p_sys->p_buffer );
516 517
    free( p_sys );
}
gbazin's avatar
 
gbazin committed
518 519 520 521 522

/*****************************************************************************
 * DoReordering: do some channel re-ordering (the ac3 channel order is
 *   different from the aac one).
 *****************************************************************************/
523
static void DoReordering( uint32_t *p_out, uint32_t *p_in, int i_samples,
gbazin's avatar
 
gbazin committed
524 525
                          int i_nb_channels, uint32_t *pi_chan_positions )
{
526
    int pi_chan_table[MAX_CHANNEL_POSITIONS] = {0};
gbazin's avatar
 
gbazin committed
527 528 529
    int i, j, k;

    /* Find the channels mapping */
530
    for( i = 0, j = 0; i < MAX_CHANNEL_POSITIONS; i++ )
gbazin's avatar
 
gbazin committed
531
    {
532
        for( k = 0; k < i_nb_channels; k++ )
gbazin's avatar
 
gbazin committed
533 534 535 536 537 538 539 540 541 542
        {
            if( pi_channels_ordered[i] == pi_chan_positions[k] )
            {
                pi_chan_table[k] = j++;
                break;
            }
        }
    }

    /* Do the actual reordering */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
543
    if( HAVE_FPU )
544 545 546 547 548 549 550 551 552
        for( i = 0; i < i_samples; i++ )
            for( j = 0; j < i_nb_channels; j++ )
                p_out[i * i_nb_channels + pi_chan_table[j]] =
                    p_in[i * i_nb_channels + j];
    else
        for( i = 0; i < i_samples; i++ )
            for( j = 0; j < i_nb_channels; j++ )
                ((uint16_t *)p_out)[i * i_nb_channels + pi_chan_table[j]] =
                    ((uint16_t *)p_in)[i * i_nb_channels + j];
gbazin's avatar
 
gbazin committed
553
}
554