faad.c 18.5 KB
Newer Older
1 2 3
/*****************************************************************************
 * decoder.c: AAC decoder using libfaad2
 *****************************************************************************
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 33
#include <vlc_aout.h>
#include <vlc_codec.h>
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
34
#include <vlc_cpu.h>
35 36 37 38 39 40 41

#include <faad.h>

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

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

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

#define MAX_CHANNEL_POSITIONS 9
59 60 61 62 63 64 65

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

    /* samples */
66
    date_t date;
67 68

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

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

76
    bool b_sbr, b_ps;
77 78
};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    p_block = *pp_block;
211

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

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

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

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

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

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

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

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

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

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

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

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

        if( frame.error > 0 )
        {
            msg_Warn( p_dec, "%s", faacDecGetErrorMessage( frame.error ) );
Gildas Bazin's avatar
 
Gildas Bazin committed
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 368
            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
369
            /* Flush the buffer */
370
            p_sys->i_buffer = 0;
371
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
372
            return NULL;
373
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
374

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

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

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

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

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

Gildas Bazin's avatar
 
Gildas Bazin committed
413 414
        p_dec->fmt_out.audio.i_rate = frame.samplerate;
        p_dec->fmt_out.audio.i_channels = frame.channels;
415 416 417
        p_dec->fmt_out.audio.i_physical_channels
            = p_dec->fmt_out.audio.i_original_channels
            = pi_channels_guessed[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
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
437 438

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

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

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

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

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

Gildas Bazin's avatar
 
Gildas Bazin committed
488
        return p_out;
489 490
    }

491
    block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
492
    return NULL;
493 494 495
}

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

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

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

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