faad.c 13.3 KB
Newer Older
1 2 3 4
/*****************************************************************************
 * decoder.c: AAC decoder using libfaad2
 *****************************************************************************
 * Copyright (C) 2001, 2003 VideoLAN
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 22 23 24
 *
 * 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
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

25
#include <vlc/vlc.h>
26 27 28 29 30 31 32 33 34
#include <vlc/aout.h>
#include <vlc/decoder.h>

#include <faad.h>

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

vlc_module_begin();
    set_description( _("AAC audio decoder (using libfaad2)") );
39
    set_capability( "decoder", 100 );
40
    set_callbacks( Open, Close );
41 42 43 44 45
vlc_module_end();

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

#define MAX_CHANNEL_POSITIONS 9
51 52 53 54 55 56 57

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

    /* samples */
Gildas Bazin's avatar
 
Gildas Bazin committed
58
    audio_date_t date;
59 60

    /* temporary buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
61 62 63
    uint8_t *p_buffer;
    int     i_buffer;
    int     i_buffer_size;
64

Gildas Bazin's avatar
 
Gildas Bazin committed
65 66
    /* Channel positions of the current stream (for re-ordering) */
    uint32_t pi_channel_positions[MAX_CHANNEL_POSITIONS];
67 68
};

Gildas Bazin's avatar
 
Gildas Bazin committed
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
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
    };

86
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
87
 * OpenDecoder: probe the decoder and return score
88
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
89
static int Open( vlc_object_t *p_this )
90
{
Gildas Bazin's avatar
 
Gildas Bazin committed
91
    decoder_t *p_dec = (decoder_t*)p_this;
92 93 94
    decoder_sys_t *p_sys = p_dec->p_sys;
    faacDecConfiguration *cfg;

Gildas Bazin's avatar
 
Gildas Bazin committed
95
    if( p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','4','a') )
96
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
97 98 99 100 101 102 103 104 105
        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;
106 107 108 109 110
    }

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

Gildas Bazin's avatar
 
Gildas Bazin committed
115 116 117
    /* Misc init */
    aout_DateSet( &p_sys->date, 0 );
    p_dec->fmt_out.i_cat = AUDIO_ES;
118

119
    if (p_this->p_libvlc->i_cpu & CPU_CAPABILITY_FPU)
120 121
        p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2');
    else
122
        p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
Gildas Bazin's avatar
 
Gildas Bazin committed
123 124
    p_dec->pf_decode_audio = DecodeBlock;

Gildas Bazin's avatar
 
Gildas Bazin committed
125 126 127
    p_dec->fmt_out.audio.i_physical_channels =
        p_dec->fmt_out.audio.i_original_channels = 0;

Gildas Bazin's avatar
 
Gildas Bazin committed
128
    if( p_dec->fmt_in.i_extra > 0 )
129 130
    {
        /* We have a decoder config so init the handle */
Gildas Bazin's avatar
 
Gildas Bazin committed
131 132
        unsigned long i_rate;
        unsigned char i_channels;
133

Gildas Bazin's avatar
 
Gildas Bazin committed
134 135
        if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra,
                          p_dec->fmt_in.i_extra,
136 137 138 139 140
                          &i_rate, &i_channels ) < 0 )
        {
            return VLC_EGENERIC;
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
141 142 143
        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 );
144 145 146 147
    }
    else
    {
        /* Will be initalised from first frame */
Gildas Bazin's avatar
 
Gildas Bazin committed
148 149
        p_dec->fmt_out.audio.i_rate = 0;
        p_dec->fmt_out.audio.i_channels = 0;
150 151
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
152
    /* Set the faad config */
153
    cfg = faacDecGetCurrentConfiguration( p_sys->hfaad );
154
    if (p_this->p_libvlc->i_cpu & CPU_CAPABILITY_FPU)
155 156
        cfg->outputFormat = FAAD_FMT_FLOAT;
    else
157
        cfg->outputFormat = FAAD_FMT_16BIT;
158 159 160
    faacDecSetConfiguration( p_sys->hfaad, cfg );

    /* buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
161 162
    p_sys->i_buffer = p_sys->i_buffer_size = 0;
    p_sys->p_buffer = 0;
163

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

167 168 169 170
    return VLC_SUCCESS;
}

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
171
 * DecodeBlock:
172
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
173
static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
174 175
{
    decoder_sys_t *p_sys = p_dec->p_sys;
Gildas Bazin's avatar
 
Gildas Bazin committed
176
    block_t *p_block;
177

Gildas Bazin's avatar
 
Gildas Bazin committed
178 179 180
    if( !pp_block || !*pp_block ) return NULL;

    p_block = *pp_block;
181

182
    if( p_block->i_flags&BLOCK_FLAG_DISCONTINUITY )
183 184 185 186 187
    {
        block_Release( p_block );
        return NULL;
    }

188 189 190
    /* 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
191
        p_sys->i_buffer_size = p_sys->i_buffer + p_block->i_buffer;
192 193 194
        p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size );
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
195 196 197 198 199 200 201 202
    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;
    }

203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
    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
219
    if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer )
220
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
221 222
        unsigned long i_rate;
        unsigned char i_channels;
223 224 225 226 227 228

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

        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;
248 249 250
    }

    /* Decode all data */
Gildas Bazin's avatar
 
Gildas Bazin committed
251
    if( p_sys->i_buffer )
252 253 254
    {
        void *samples;
        faacDecFrameInfo frame;
Gildas Bazin's avatar
 
Gildas Bazin committed
255
        aout_buffer_t *p_out;
Gildas Bazin's avatar
 
Gildas Bazin committed
256
        int i, j;
257 258

        samples = faacDecDecode( p_sys->hfaad, &frame,
Gildas Bazin's avatar
 
Gildas Bazin committed
259
                                 p_sys->p_buffer, p_sys->i_buffer );
260 261 262 263

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

            /* Flush the buffer */
266
            p_sys->i_buffer = 0;
267
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
268
            return NULL;
269
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
270

Gildas Bazin's avatar
 
Gildas Bazin committed
271
        if( frame.channels <= 0 || frame.channels > 8 || frame.channels == 7 )
272
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
273
            msg_Warn( p_dec, "invalid channels count: %i", frame.channels );
Gildas Bazin's avatar
 
Gildas Bazin committed
274 275

            /* Flush the buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
276 277 278 279 280 281
            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 );
            }
282
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
283
            return NULL;
284
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
285

286 287
        if( frame.samples <= 0 )
        {
Benjamin Pracht's avatar
Benjamin Pracht committed
288
            msg_Warn( p_dec, "decoded zero sample" );
Gildas Bazin's avatar
 
Gildas Bazin committed
289 290

            /* Flush the buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
291 292 293 294 295 296
            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 );
            }
297
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
298
            return NULL;
299 300
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
301 302
        /* We decoded a valid frame */
        if( p_dec->fmt_out.audio.i_rate != frame.samplerate )
303
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
304 305
            aout_DateInit( &p_sys->date, frame.samplerate );
            aout_DateSet( &p_sys->date, p_block->i_pts );
306
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
307
        p_block->i_pts = 0;  /* PTS is valid only once */
308

Gildas Bazin's avatar
 
Gildas Bazin committed
309 310
        p_dec->fmt_out.audio.i_rate = frame.samplerate;
        p_dec->fmt_out.audio.i_channels = frame.channels;
311

Gildas Bazin's avatar
 
Gildas Bazin committed
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326

        /* 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;
                }
            }
327 328 329

            if( j == MAX_CHANNEL_POSITIONS )
            {
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
330
                msg_Warn( p_dec, "unknown channel ordering" );
331 332 333
                block_Release( p_block );
                return NULL;
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
334 335 336 337 338
        }
        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
339
        if( p_out == NULL )
340
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
341
            p_sys->i_buffer = 0;
342
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
343
            return NULL;
344 345
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
346 347 348 349
        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
350 351 352
        DoReordering( p_dec, (uint32_t *)p_out->p_buffer, samples,
                      frame.samples / frame.channels, frame.channels,
                      p_sys->pi_channel_positions );
353

Gildas Bazin's avatar
 
Gildas Bazin committed
354 355
        p_sys->i_buffer -= frame.bytesconsumed;
        if( p_sys->i_buffer > 0 )
356
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
357 358
            memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed],
                     p_sys->i_buffer );
359 360
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
361
        return p_out;
362 363
    }

364
    block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
365
    return NULL;
366 367 368
}

/*****************************************************************************
369
 * Close:
370
 *****************************************************************************/
371
static void Close( vlc_object_t *p_this )
372
{
Gildas Bazin's avatar
 
Gildas Bazin committed
373
    decoder_t *p_dec = (decoder_t *)p_this;
374 375 376 377 378
    decoder_sys_t *p_sys = p_dec->p_sys;

    faacDecClose( p_sys->hfaad );
    free( p_sys );
}
Gildas Bazin's avatar
 
Gildas Bazin committed
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404

/*****************************************************************************
 * 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 */
405 406 407 408 409 410 411 412 413 414
    if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_FPU )
        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
415
}