faad.c 12.6 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>
Gildas Bazin's avatar
 
Gildas Bazin committed
8
 *          Gildas Bazin <gbazin@netcourrier.com>
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 203
    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;
    }

    if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer )
204
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
205 206
        unsigned long i_rate;
        unsigned char i_channels;
207 208 209 210 211 212

        /* Init faad with the first frame */
        if( faacDecInit( p_sys->hfaad,
                         p_sys->p_buffer, p_sys->i_buffer,
                         &i_rate, &i_channels ) < 0 )
        {
213
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
214
            return NULL;
215
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231

        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;
232 233 234
    }

    /* Decode all data */
Gildas Bazin's avatar
 
Gildas Bazin committed
235
    if( p_sys->i_buffer )
236 237 238
    {
        void *samples;
        faacDecFrameInfo frame;
Gildas Bazin's avatar
 
Gildas Bazin committed
239
        aout_buffer_t *p_out;
Gildas Bazin's avatar
 
Gildas Bazin committed
240
        int i, j;
241 242

        samples = faacDecDecode( p_sys->hfaad, &frame,
Gildas Bazin's avatar
 
Gildas Bazin committed
243
                                 p_sys->p_buffer, p_sys->i_buffer );
244 245 246 247

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

            /* Flush the buffer */
250
            p_sys->i_buffer = 0;
251
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
252
            return NULL;
253
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
254

Gildas Bazin's avatar
 
Gildas Bazin committed
255
        if( frame.channels <= 0 || frame.channels > 8 || frame.channels == 7 )
256
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
257
            msg_Warn( p_dec, "invalid channels count: %i", frame.channels );
Gildas Bazin's avatar
 
Gildas Bazin committed
258 259

            /* Flush the buffer */
Gildas Bazin's avatar
 
Gildas Bazin committed
260 261 262 263 264 265
            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 );
            }
266
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
267
            return NULL;
268
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
269

270 271
        if( frame.samples <= 0 )
        {
Benjamin Pracht's avatar
Benjamin Pracht committed
272
            msg_Warn( p_dec, "decoded zero sample" );
Gildas Bazin's avatar
 
Gildas Bazin committed
273 274

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

Gildas Bazin's avatar
 
Gildas Bazin committed
285 286
        /* We decoded a valid frame */
        if( p_dec->fmt_out.audio.i_rate != frame.samplerate )
287
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
288 289
            aout_DateInit( &p_sys->date, frame.samplerate );
            aout_DateSet( &p_sys->date, p_block->i_pts );
290
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
291
        p_block->i_pts = 0;  /* PTS is valid only once */
292

Gildas Bazin's avatar
 
Gildas Bazin committed
293 294
        p_dec->fmt_out.audio.i_rate = frame.samplerate;
        p_dec->fmt_out.audio.i_channels = frame.channels;
295

Gildas Bazin's avatar
 
Gildas Bazin committed
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315

        /* 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;
                }
            }
        }
        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
316
        if( p_out == NULL )
317
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
318
            p_sys->i_buffer = 0;
319
            block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
320
            return NULL;
321 322
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
323 324 325 326
        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
327 328 329
        DoReordering( p_dec, (uint32_t *)p_out->p_buffer, samples,
                      frame.samples / frame.channels, frame.channels,
                      p_sys->pi_channel_positions );
330

Gildas Bazin's avatar
 
Gildas Bazin committed
331 332
        p_sys->i_buffer -= frame.bytesconsumed;
        if( p_sys->i_buffer > 0 )
333
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
334 335
            memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed],
                     p_sys->i_buffer );
336 337
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
338
        return p_out;
339 340
    }

341
    block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
342
    return NULL;
343 344 345
}

/*****************************************************************************
346
 * Close:
347
 *****************************************************************************/
348
static void Close( vlc_object_t *p_this )
349
{
Gildas Bazin's avatar
 
Gildas Bazin committed
350
    decoder_t *p_dec = (decoder_t *)p_this;
351 352 353 354 355
    decoder_sys_t *p_sys = p_dec->p_sys;

    faacDecClose( p_sys->hfaad );
    free( p_sys );
}
Gildas Bazin's avatar
 
Gildas Bazin committed
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381

/*****************************************************************************
 * 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 */
382 383 384 385 386 387 388 389 390 391
    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
392
}