faad.c 18.4 KB
Newer Older
1
/*****************************************************************************
Pere Orga's avatar
Pere Orga committed
2
 * faad.c: AAC decoder using libfaad2
3
 *****************************************************************************
4
 * Copyright (C) 2001, 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 14 15 16 17 18 19 20 21
 *
 * 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.
 *
 * 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 28
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

29
#include <vlc_common.h>
30
#include <vlc_plugin.h>
31
#include <vlc_input.h>
Clément Stenac's avatar
Clément Stenac committed
32
#include <vlc_codec.h>
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
33
#include <vlc_cpu.h>
34 35 36 37 38 39 40

#include <faad.h>

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int  Open( vlc_object_t * );
41
static void Close( vlc_object_t * );
42

43 44 45 46 47 48 49
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 ()
50 51 52 53

/****************************************************************************
 * Local prototypes
 ****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
54
static aout_buffer_t *DecodeBlock( decoder_t *, block_t ** );
55
static void DoReordering( uint32_t *, uint32_t *, int, int, uint32_t * );
Gildas Bazin's avatar
 
Gildas Bazin committed
56 57

#define MAX_CHANNEL_POSITIONS 9
58 59 60 61 62 63 64

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

    /* samples */
65
    date_t date;
66 67

    /* temporary buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
68 69
    uint8_t *p_buffer;
    int     i_buffer;
70
    size_t  i_buffer_size;
71

Gildas Bazin's avatar
 
Gildas Bazin committed
72 73
    /* Channel positions of the current stream (for re-ordering) */
    uint32_t pi_channel_positions[MAX_CHANNEL_POSITIONS];
74

75
    bool b_sbr, b_ps;
76 77
};

Gildas Bazin's avatar
 
Gildas Bazin committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
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
    };
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
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
    };
Gildas Bazin's avatar
 
Gildas Bazin committed
110

111
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
112
 * OpenDecoder: probe the decoder and return score
113
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
114
static int Open( vlc_object_t *p_this )
115
{
Gildas Bazin's avatar
 
Gildas Bazin committed
116
    decoder_t *p_dec = (decoder_t*)p_this;
117 118 119
    decoder_sys_t *p_sys = p_dec->p_sys;
    faacDecConfiguration *cfg;

120
    if( p_dec->fmt_in.i_codec != VLC_CODEC_MP4A )
121
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
122 123 124 125
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
126
    if( ( p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) ) ) == NULL )
127
        return VLC_ENOMEM;
128 129 130 131

    /* Open a faad context */
    if( ( p_sys->hfaad = faacDecOpen() ) == NULL )
    {
Benjamin Pracht's avatar
Benjamin Pracht committed
132
        msg_Err( p_dec, "cannot initialize faad" );
Rémi Duraffort's avatar
Rémi Duraffort committed
133
        free( p_sys );
134 135 136
        return VLC_EGENERIC;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
137
    /* Misc init */
138
    date_Set( &p_sys->date, 0 );
Gildas Bazin's avatar
 
Gildas Bazin committed
139
    p_dec->fmt_out.i_cat = AUDIO_ES;
140

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
141
    if (HAVE_FPU)
142
        p_dec->fmt_out.i_codec = VLC_CODEC_FL32;
143
    else
144
        p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
Gildas Bazin's avatar
 
Gildas Bazin committed
145 146
    p_dec->pf_decode_audio = DecodeBlock;

Gildas Bazin's avatar
 
Gildas Bazin committed
147 148 149
    p_dec->fmt_out.audio.i_physical_channels =
        p_dec->fmt_out.audio.i_original_channels = 0;

Gildas Bazin's avatar
 
Gildas Bazin committed
150
    if( p_dec->fmt_in.i_extra > 0 )
151 152
    {
        /* We have a decoder config so init the handle */
Gildas Bazin's avatar
 
Gildas Bazin committed
153 154
        unsigned long i_rate;
        unsigned char i_channels;
155

Gildas Bazin's avatar
 
Gildas Bazin committed
156 157
        if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra,
                          p_dec->fmt_in.i_extra,
158 159
                          &i_rate, &i_channels ) < 0 )
        {
160
            msg_Err( p_dec, "Failed to initialize faad using extra data" );
Rémi Duraffort's avatar
Rémi Duraffort committed
161 162
            faacDecClose( p_sys->hfaad );
            free( p_sys );
163 164 165
            return VLC_EGENERIC;
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
166 167
        p_dec->fmt_out.audio.i_rate = i_rate;
        p_dec->fmt_out.audio.i_channels = i_channels;
168 169 170
        p_dec->fmt_out.audio.i_physical_channels
            = p_dec->fmt_out.audio.i_original_channels
            = pi_channels_guessed[i_channels];
171
        date_Init( &p_sys->date, i_rate, 1 );
172 173 174 175
    }
    else
    {
        /* Will be initalised from first frame */
Gildas Bazin's avatar
 
Gildas Bazin committed
176 177
        p_dec->fmt_out.audio.i_rate = 0;
        p_dec->fmt_out.audio.i_channels = 0;
178 179
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
180
    /* Set the faad config */
181
    cfg = faacDecGetCurrentConfiguration( p_sys->hfaad );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
182
    if (HAVE_FPU)
183 184
        cfg->outputFormat = FAAD_FMT_FLOAT;
    else
185
        cfg->outputFormat = FAAD_FMT_16BIT;
186 187 188
    faacDecSetConfiguration( p_sys->hfaad, cfg );

    /* buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
189
    p_sys->i_buffer = p_sys->i_buffer_size = 0;
190
    p_sys->p_buffer = NULL;
191

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

195
    p_sys->b_sbr = p_sys->b_ps = false;
196 197 198 199
    return VLC_SUCCESS;
}

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
200
 * DecodeBlock:
201
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
202
static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
203 204
{
    decoder_sys_t *p_sys = p_dec->p_sys;
205
    block_t *p_block;
206

207 208 209
    if( !pp_block || !*pp_block ) return NULL;

    p_block = *pp_block;
210

Laurent Aimar's avatar
Laurent Aimar committed
211
    if( p_block->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
212 213 214 215 216
    {
        block_Release( p_block );
        return NULL;
    }

217 218 219 220 221 222 223 224 225 226 227
    /* 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 )
            {
228
                p_block->p_buffer += i_header_size;
229 230 231 232 233
                p_block->i_buffer -= i_header_size;
            }
        }
    }

234 235 236
    /* Append the block to the temporary buffer */
    if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
    {
237 238 239 240 241 242 243 244 245 246 247
        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;
        }
248 249
    }

250
    if( p_block->i_buffer > 0 )
Gildas Bazin's avatar
 
Gildas Bazin committed
251
    {
252
        vlc_memcpy( &p_sys->p_buffer[p_sys->i_buffer],
253
                     p_block->p_buffer, p_block->i_buffer );
Gildas Bazin's avatar
 
Gildas Bazin committed
254 255 256 257
        p_sys->i_buffer += p_block->i_buffer;
        p_block->i_buffer = 0;
    }

258 259 260 261 262 263 264 265 266 267 268 269
    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;
270 271 272 273
            p_dec->fmt_out.audio.i_physical_channels
                = p_dec->fmt_out.audio.i_original_channels
                = pi_channels_guessed[i_channels];

274
            date_Init( &p_sys->date, i_rate, 1 );
275 276 277
        }
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
278
    if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer )
279
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
280 281
        unsigned long i_rate;
        unsigned char i_channels;
282 283 284 285 286 287

        /* Init faad with the first frame */
        if( faacDecInit( p_sys->hfaad,
                         p_sys->p_buffer, p_sys->i_buffer,
                         &i_rate, &i_channels ) < 0 )
        {
288
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
289
            return NULL;
290
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
291 292 293

        p_dec->fmt_out.audio.i_rate = i_rate;
        p_dec->fmt_out.audio.i_channels = i_channels;
294 295 296
        p_dec->fmt_out.audio.i_physical_channels
            = p_dec->fmt_out.audio.i_original_channels
            = pi_channels_guessed[i_channels];
297
        date_Init( &p_sys->date, i_rate, 1 );
Gildas Bazin's avatar
 
Gildas Bazin committed
298 299
    }

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

    /* Decode all data */
Gildas Bazin's avatar
 
Gildas Bazin committed
313
    if( p_sys->i_buffer )
314 315 316
    {
        void *samples;
        faacDecFrameInfo frame;
Gildas Bazin's avatar
 
Gildas Bazin committed
317
        aout_buffer_t *p_out;
Gildas Bazin's avatar
 
Gildas Bazin committed
318
        int i, j;
319 320

        samples = faacDecDecode( p_sys->hfaad, &frame,
Gildas Bazin's avatar
 
Gildas Bazin committed
321
                                 p_sys->p_buffer, p_sys->i_buffer );
322 323 324 325

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

327 328 329 330 331 332 333 334 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
            if( frame.error == 21 )
            {
                /*
                 * Once an "Unexpected channel configuration change" error
                 * 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 );
                }
            }

Gildas Bazin's avatar
 
Gildas Bazin committed
368
            /* Flush the buffer */
369
            p_sys->i_buffer = 0;
370
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
371
            return NULL;
372
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
373

Gildas Bazin's avatar
 
Gildas Bazin committed
374
        if( frame.channels <= 0 || frame.channels > 8 || frame.channels == 7 )
375
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
376
            msg_Warn( p_dec, "invalid channels count: %i", frame.channels );
Gildas Bazin's avatar
 
Gildas Bazin committed
377 378

            /* Flush the buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
379 380 381 382 383 384
            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 );
            }
385
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
386
            return NULL;
387
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
388

389 390
        if( frame.samples <= 0 )
        {
Benjamin Pracht's avatar
Benjamin Pracht committed
391
            msg_Warn( p_dec, "decoded zero sample" );
Gildas Bazin's avatar
 
Gildas Bazin committed
392 393

            /* Flush the buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
394 395 396 397 398 399
            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 );
            }
400
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
401
            return NULL;
402 403
        }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
412 413
        p_dec->fmt_out.audio.i_rate = frame.samplerate;
        p_dec->fmt_out.audio.i_channels = frame.channels;
414

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

422 423 424
            msg_Dbg( p_dec, "AAC %s (channels: %u, samplerate: %lu)",
                    psz_ext, frame.channels, frame.samplerate );

425 426 427 428 429
            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 );

430 431
            p_sys->b_sbr = b_sbr;
            p_sys->b_ps = frame.ps;
432
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
433 434

        /* Convert frame.channel_position to our own channel values */
435
        p_dec->fmt_out.audio.i_physical_channels = 0;
436 437
        const uint32_t nbChannels = frame.channels;
        for( i = 0; i < nbChannels; i++ )
Gildas Bazin's avatar
 
Gildas Bazin committed
438 439 440 441 442 443 444
        {
            /* Find the channel code */
            for( j = 0; j < MAX_CHANNEL_POSITIONS; j++ )
            {
                if( frame.channel_position[i] == pi_channels_in[j] )
                    break;
            }
445
            if( j >= MAX_CHANNEL_POSITIONS )
446
            {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
447
                msg_Warn( p_dec, "unknown channel ordering" );
448 449
                /* Invent something */
                j = i;
450
            }
451 452 453 454 455 456
            /* */
            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];
Gildas Bazin's avatar
 
Gildas Bazin committed
457 458 459 460
        }
        p_dec->fmt_out.audio.i_original_channels =
            p_dec->fmt_out.audio.i_physical_channels;

461
        p_out = decoder_NewAudioBuffer(p_dec, frame.samples/frame.channels);
Gildas Bazin's avatar
 
Gildas Bazin committed
462
        if( p_out == NULL )
463
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
464
            p_sys->i_buffer = 0;
465
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
466
            return NULL;
467 468
        }

469
        p_out->i_pts = date_Get( &p_sys->date );
470
        p_out->i_length = date_Increment( &p_sys->date,
471
                                          frame.samples / frame.channels )
472
                          - p_out->i_pts;
Gildas Bazin's avatar
 
Gildas Bazin committed
473

474
        DoReordering( (uint32_t *)p_out->p_buffer, samples,
Gildas Bazin's avatar
 
Gildas Bazin committed
475 476
                      frame.samples / frame.channels, frame.channels,
                      p_sys->pi_channel_positions );
477

Gildas Bazin's avatar
 
Gildas Bazin committed
478 479
        p_sys->i_buffer -= frame.bytesconsumed;
        if( p_sys->i_buffer > 0 )
480
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
481 482
            memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed],
                     p_sys->i_buffer );
483 484
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
485
        return p_out;
486 487
    }

488
    block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
489
    return NULL;
490 491 492
}

/*****************************************************************************
493
 * Close:
494
 *****************************************************************************/
495
static void Close( vlc_object_t *p_this )
496
{
Gildas Bazin's avatar
 
Gildas Bazin committed
497
    decoder_t *p_dec = (decoder_t *)p_this;
498 499 500
    decoder_sys_t *p_sys = p_dec->p_sys;

    faacDecClose( p_sys->hfaad );
Rémi Duraffort's avatar
Rémi Duraffort committed
501
    free( p_sys->p_buffer );
502 503
    free( p_sys );
}
Gildas Bazin's avatar
 
Gildas Bazin committed
504 505 506 507 508

/*****************************************************************************
 * DoReordering: do some channel re-ordering (the ac3 channel order is
 *   different from the aac one).
 *****************************************************************************/
509
static void DoReordering( uint32_t *p_out, uint32_t *p_in, int i_samples,
Gildas Bazin's avatar
 
Gildas Bazin committed
510 511 512 513 514 515
                          int i_nb_channels, uint32_t *pi_chan_positions )
{
    int pi_chan_table[MAX_CHANNEL_POSITIONS];
    int i, j, k;

    /* Find the channels mapping */
516
    for( i = 0, j = 0; i < MAX_CHANNEL_POSITIONS; i++ )
Gildas Bazin's avatar
 
Gildas Bazin committed
517
    {
518
        for( k = 0; k < i_nb_channels; k++ )
Gildas Bazin's avatar
 
Gildas Bazin committed
519 520 521 522 523 524 525 526 527 528
        {
            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
529
    if( HAVE_FPU )
530 531 532 533 534 535 536 537 538
        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];
Gildas Bazin's avatar
 
Gildas Bazin committed
539
}
540