faad.c 14.8 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
#include <vlc/vlc.h>
26 27
#include <vlc/aout.h>
#include <vlc/decoder.h>
28
#include <vlc/input.h>
29 30 31 32 33 34 35

#include <faad.h>

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int  Open( vlc_object_t * );
36
static void Close( vlc_object_t * );
37 38 39

vlc_module_begin();
    set_description( _("AAC audio decoder (using libfaad2)") );
40
    set_capability( "decoder", 100 );
Clément Stenac's avatar
Clément Stenac committed
41 42
    set_category( CAT_INPUT );
    set_subcategory( SUBCAT_INPUT_ACODEC );
43
    set_callbacks( Open, Close );
44 45 46 47 48
vlc_module_end();

/****************************************************************************
 * Local prototypes
 ****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
49
static aout_buffer_t *DecodeBlock( decoder_t *, block_t ** );
Gildas Bazin's avatar
 
Gildas Bazin committed
50 51 52 53
static void DoReordering( decoder_t *, uint32_t *, uint32_t *, int, int,
                          uint32_t * );

#define MAX_CHANNEL_POSITIONS 9
54 55 56 57 58 59 60

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

    /* samples */
Gildas Bazin's avatar
 
Gildas Bazin committed
61
    audio_date_t date;
62 63

    /* temporary buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
64 65 66
    uint8_t *p_buffer;
    int     i_buffer;
    int     i_buffer_size;
67

Gildas Bazin's avatar
 
Gildas Bazin committed
68 69
    /* Channel positions of the current stream (for re-ordering) */
    uint32_t pi_channel_positions[MAX_CHANNEL_POSITIONS];
70 71

    vlc_bool_t b_sbr, b_ps;
72 73
};

Gildas Bazin's avatar
 
Gildas Bazin committed
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
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
    };

91
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
92
 * OpenDecoder: probe the decoder and return score
93
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
94
static int Open( vlc_object_t *p_this )
95
{
Gildas Bazin's avatar
 
Gildas Bazin committed
96
    decoder_t *p_dec = (decoder_t*)p_this;
97 98 99
    decoder_sys_t *p_sys = p_dec->p_sys;
    faacDecConfiguration *cfg;

Gildas Bazin's avatar
 
Gildas Bazin committed
100
    if( p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','4','a') )
101
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
102 103 104 105 106 107 108 109 110
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_dec->p_sys = p_sys =
          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
    {
        msg_Err( p_dec, "out of memory" );
        return VLC_EGENERIC;
111 112 113 114 115
    }

    /* Open a faad context */
    if( ( p_sys->hfaad = faacDecOpen() ) == NULL )
    {
Benjamin Pracht's avatar
Benjamin Pracht committed
116
        msg_Err( p_dec, "cannot initialize faad" );
117 118 119
        return VLC_EGENERIC;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
120 121 122
    /* Misc init */
    aout_DateSet( &p_sys->date, 0 );
    p_dec->fmt_out.i_cat = AUDIO_ES;
123

124
    if (p_this->p_libvlc_global->i_cpu & CPU_CAPABILITY_FPU)
125 126
        p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2');
    else
127
        p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
Gildas Bazin's avatar
 
Gildas Bazin committed
128 129
    p_dec->pf_decode_audio = DecodeBlock;

Gildas Bazin's avatar
 
Gildas Bazin committed
130 131 132
    p_dec->fmt_out.audio.i_physical_channels =
        p_dec->fmt_out.audio.i_original_channels = 0;

Gildas Bazin's avatar
 
Gildas Bazin committed
133
    if( p_dec->fmt_in.i_extra > 0 )
134 135
    {
        /* We have a decoder config so init the handle */
Gildas Bazin's avatar
 
Gildas Bazin committed
136 137
        unsigned long i_rate;
        unsigned char i_channels;
138

Gildas Bazin's avatar
 
Gildas Bazin committed
139 140
        if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra,
                          p_dec->fmt_in.i_extra,
141 142 143 144 145
                          &i_rate, &i_channels ) < 0 )
        {
            return VLC_EGENERIC;
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
146 147 148
        p_dec->fmt_out.audio.i_rate = i_rate;
        p_dec->fmt_out.audio.i_channels = i_channels;
        aout_DateInit( &p_sys->date, i_rate );
149 150 151 152
    }
    else
    {
        /* Will be initalised from first frame */
Gildas Bazin's avatar
 
Gildas Bazin committed
153 154
        p_dec->fmt_out.audio.i_rate = 0;
        p_dec->fmt_out.audio.i_channels = 0;
155 156
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
157
    /* Set the faad config */
158
    cfg = faacDecGetCurrentConfiguration( p_sys->hfaad );
159
    if (p_this->p_libvlc_global->i_cpu & CPU_CAPABILITY_FPU)
160 161
        cfg->outputFormat = FAAD_FMT_FLOAT;
    else
162
        cfg->outputFormat = FAAD_FMT_16BIT;
163 164 165
    faacDecSetConfiguration( p_sys->hfaad, cfg );

    /* buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
166 167
    p_sys->i_buffer = p_sys->i_buffer_size = 0;
    p_sys->p_buffer = 0;
168

169 170 171
    /* Faad2 can't deal with truncated data (eg. from MPEG TS) */
    p_dec->b_need_packetized = VLC_TRUE;

172
    p_sys->b_sbr = p_sys->b_ps = VLC_FALSE;
173 174 175 176
    return VLC_SUCCESS;
}

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
177
 * DecodeBlock:
178
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
179
static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
180 181
{
    decoder_sys_t *p_sys = p_dec->p_sys;
Gildas Bazin's avatar
 
Gildas Bazin committed
182
    block_t *p_block;
183

Gildas Bazin's avatar
 
Gildas Bazin committed
184 185 186
    if( !pp_block || !*pp_block ) return NULL;

    p_block = *pp_block;
187

Laurent Aimar's avatar
Laurent Aimar committed
188
    if( p_block->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
189 190 191 192 193
    {
        block_Release( p_block );
        return NULL;
    }

194 195 196
    /* Append the block to the temporary buffer */
    if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
197
        p_sys->i_buffer_size = p_sys->i_buffer + p_block->i_buffer;
198 199 200
        p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size );
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
201 202 203 204 205 206 207 208
    if( p_block->i_buffer )
    {
        memcpy( &p_sys->p_buffer[p_sys->i_buffer],
                p_block->p_buffer, p_block->i_buffer );
        p_sys->i_buffer += p_block->i_buffer;
        p_block->i_buffer = 0;
    }

209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
    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;
            aout_DateInit( &p_sys->date, i_rate );
        }
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
225
    if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer )
226
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
227 228
        unsigned long i_rate;
        unsigned char i_channels;
229 230 231 232 233 234

        /* Init faad with the first frame */
        if( faacDecInit( p_sys->hfaad,
                         p_sys->p_buffer, p_sys->i_buffer,
                         &i_rate, &i_channels ) < 0 )
        {
235
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
236
            return NULL;
237
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253

        p_dec->fmt_out.audio.i_rate = i_rate;
        p_dec->fmt_out.audio.i_channels = i_channels;
        aout_DateInit( &p_sys->date, i_rate );
    }

    if( p_block->i_pts != 0 && p_block->i_pts != aout_DateGet( &p_sys->date ) )
    {
        aout_DateSet( &p_sys->date, p_block->i_pts );
    }
    else if( !aout_DateGet( &p_sys->date ) )
    {
        /* We've just started the stream, wait for the first PTS. */
        block_Release( p_block );
        p_sys->i_buffer = 0;
        return NULL;
254 255 256
    }

    /* Decode all data */
Gildas Bazin's avatar
 
Gildas Bazin committed
257
    if( p_sys->i_buffer )
258 259 260
    {
        void *samples;
        faacDecFrameInfo frame;
Gildas Bazin's avatar
 
Gildas Bazin committed
261
        aout_buffer_t *p_out;
Gildas Bazin's avatar
 
Gildas Bazin committed
262
        int i, j;
263 264

        samples = faacDecDecode( p_sys->hfaad, &frame,
Gildas Bazin's avatar
 
Gildas Bazin committed
265
                                 p_sys->p_buffer, p_sys->i_buffer );
266 267 268 269

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

            /* Flush the buffer */
272
            p_sys->i_buffer = 0;
273
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
274
            return NULL;
275
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
276

Gildas Bazin's avatar
 
Gildas Bazin committed
277
        if( frame.channels <= 0 || frame.channels > 8 || frame.channels == 7 )
278
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
279
            msg_Warn( p_dec, "invalid channels count: %i", frame.channels );
Gildas Bazin's avatar
 
Gildas Bazin committed
280 281

            /* Flush the buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
282 283 284 285 286 287
            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 );
            }
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
        if( frame.samples <= 0 )
        {
Benjamin Pracht's avatar
Benjamin Pracht committed
294
            msg_Warn( p_dec, "decoded zero sample" );
Gildas Bazin's avatar
 
Gildas Bazin committed
295 296

            /* Flush the buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
297 298 299 300 301 302
            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 );
            }
303
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
304
            return NULL;
305 306
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
307 308
        /* We decoded a valid frame */
        if( p_dec->fmt_out.audio.i_rate != frame.samplerate )
309
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
310 311
            aout_DateInit( &p_sys->date, frame.samplerate );
            aout_DateSet( &p_sys->date, p_block->i_pts );
312
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
313
        p_block->i_pts = 0;  /* PTS is valid only once */
314

Gildas Bazin's avatar
 
Gildas Bazin committed
315 316
        p_dec->fmt_out.audio.i_rate = frame.samplerate;
        p_dec->fmt_out.audio.i_channels = frame.channels;
317

318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
        /* Adjust stream info when dealing with SBR/PS */
        if( (p_sys->b_sbr != frame.sbr || p_sys->b_ps != frame.ps) &&
            p_dec->p_parent->i_object_type == VLC_OBJECT_INPUT )
        {
          input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
          char *psz_cat, *psz_ext = (frame.sbr && frame.ps) ? "SBR+PS" :
            frame.sbr ? "SBR" : "PS";

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

          asprintf( &psz_cat, _("Stream %d"), p_dec->fmt_in.i_id );
          input_Control( p_input, INPUT_ADD_INFO, psz_cat,
                          _("AAC extension"), "%s", psz_ext );
          input_Control( p_input, INPUT_ADD_INFO, psz_cat,
                         _("Channels"), "%d", frame.channels );
          input_Control( p_input, INPUT_ADD_INFO, psz_cat,
                         _("Sample rate"), _("%d Hz"), frame.samplerate );
          free( psz_cat );
          p_sys->b_sbr = frame.sbr; p_sys->b_ps = frame.ps;
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353

        /* Convert frame.channel_position to our own channel values */
        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] )
                {
                    p_sys->pi_channel_positions[i] = pi_channels_out[j];
                    p_dec->fmt_out.audio.i_physical_channels |=
                        pi_channels_out[j];
                    break;
                }
            }
354 355 356

            if( j == MAX_CHANNEL_POSITIONS )
            {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
357
                msg_Warn( p_dec, "unknown channel ordering" );
358 359 360 361 362

                /* Try to invent something */
                p_sys->pi_channel_positions[i] = pi_channels_out[i];
                p_dec->fmt_out.audio.i_physical_channels |=
                    pi_channels_out[i];
363
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
364 365 366 367 368
        }
        p_dec->fmt_out.audio.i_original_channels =
            p_dec->fmt_out.audio.i_physical_channels;

        p_out = p_dec->pf_aout_buffer_new(p_dec, frame.samples/frame.channels);
Gildas Bazin's avatar
 
Gildas Bazin committed
369
        if( p_out == NULL )
370
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
371
            p_sys->i_buffer = 0;
372
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
373
            return NULL;
374 375
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
376 377 378 379
        p_out->start_date = aout_DateGet( &p_sys->date );
        p_out->end_date = aout_DateIncrement( &p_sys->date,
                                              frame.samples / frame.channels );

Gildas Bazin's avatar
 
Gildas Bazin committed
380 381 382
        DoReordering( p_dec, (uint32_t *)p_out->p_buffer, samples,
                      frame.samples / frame.channels, frame.channels,
                      p_sys->pi_channel_positions );
383

Gildas Bazin's avatar
 
Gildas Bazin committed
384 385
        p_sys->i_buffer -= frame.bytesconsumed;
        if( p_sys->i_buffer > 0 )
386
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
387 388
            memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed],
                     p_sys->i_buffer );
389 390
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
391
        return p_out;
392 393
    }

394
    block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
395
    return NULL;
396 397 398
}

/*****************************************************************************
399
 * Close:
400
 *****************************************************************************/
401
static void Close( vlc_object_t *p_this )
402
{
Gildas Bazin's avatar
 
Gildas Bazin committed
403
    decoder_t *p_dec = (decoder_t *)p_this;
404 405 406
    decoder_sys_t *p_sys = p_dec->p_sys;

    faacDecClose( p_sys->hfaad );
407
    if( p_sys->p_buffer ) free( p_sys->p_buffer );
408 409
    free( p_sys );
}
Gildas Bazin's avatar
 
Gildas Bazin committed
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435

/*****************************************************************************
 * DoReordering: do some channel re-ordering (the ac3 channel order is
 *   different from the aac one).
 *****************************************************************************/
static void DoReordering( decoder_t *p_dec,
                          uint32_t *p_out, uint32_t *p_in, int i_samples,
                          int i_nb_channels, uint32_t *pi_chan_positions )
{
    int pi_chan_table[MAX_CHANNEL_POSITIONS];
    int i, j, k;

    /* Find the channels mapping */
    for( i = 0, j = 0; i < MAX_CHANNEL_POSITIONS; i++ )
    {
        for( k = 0; k < i_nb_channels; k++ )
        {
            if( pi_channels_ordered[i] == pi_chan_positions[k] )
            {
                pi_chan_table[k] = j++;
                break;
            }
        }
    }

    /* Do the actual reordering */
436
    if( p_dec->p_libvlc_global->i_cpu & CPU_CAPABILITY_FPU )
437 438 439 440 441 442 443 444 445
        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
446
}