audio.c 14 KB
Newer Older
1 2 3
/*****************************************************************************
 * audio.c: audio decoder using ffmpeg library
 *****************************************************************************
4
 * Copyright (C) 1999-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
 *
 * 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.
14
 *
15 16 17 18 19 20 21
 * 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
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
28 29 30 31
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

32
#include <vlc_common.h>
Clément Stenac's avatar
Clément Stenac committed
33 34
#include <vlc_aout.h>
#include <vlc_codec.h>
35

Gildas Bazin's avatar
 
Gildas Bazin committed
36
/* ffmpeg header */
37 38 39
#ifdef HAVE_LIBAVCODEC_AVCODEC_H
#   include <libavcodec/avcodec.h>
#elif defined(HAVE_FFMPEG_AVCODEC_H)
40
#   include <ffmpeg/avcodec.h>
Gildas Bazin's avatar
 
Gildas Bazin committed
41 42 43
#else
#   include <avcodec.h>
#endif
44

45
#include "avcodec.h"
46

47
static const unsigned int pi_channels_maps[9] =
48 49
{
    0,
50 51 52 53 54 55 56 57 58 59 60 61 62 63
    AOUT_CHAN_CENTER,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
        AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
        AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
        AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
        AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
        AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
        AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
64
};
65 66

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
67
 * decoder_sys_t : decoder descriptor
68
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
69 70
struct decoder_sys_t
{
71
    FFMPEG_COMMON_MEMBERS
Gildas Bazin's avatar
 
Gildas Bazin committed
72 73 74 75 76 77 78 79 80

    /* Temporary buffer for libavcodec */
    uint8_t *p_output;

    /*
     * Output properties
     */
    audio_sample_format_t aout_format;
    audio_date_t          end_date;
81 82 83 84 85 86

    /*
     *
     */
    uint8_t *p_samples;
    int     i_samples;
87 88 89

    /* */
    int     i_reject_count;
Gildas Bazin's avatar
 
Gildas Bazin committed
90
};
91

92 93
static void SetupOutputCodec( decoder_t *p_dec );

94
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
95
 * InitAudioDec: initialize audio decoder
96
 *****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
97
 * The ffmpeg codec will be opened, some memory allocated.
98
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
99
int InitAudioDec( decoder_t *p_dec, AVCodecContext *p_context,
100
                      AVCodec *p_codec, int i_codec_id, const char *psz_namecodec )
101
{
Gildas Bazin's avatar
 
Gildas Bazin committed
102
    decoder_sys_t *p_sys;
103

Gildas Bazin's avatar
 
Gildas Bazin committed
104
    /* Allocate the memory needed to store the decoder's structure */
105
    if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
106
    {
107
        return VLC_ENOMEM;
Gildas Bazin's avatar
 
Gildas Bazin committed
108 109
    }

110 111 112 113
    p_sys->p_context = p_context;
    p_sys->p_codec = p_codec;
    p_sys->i_codec_id = i_codec_id;
    p_sys->psz_namecodec = psz_namecodec;
114
    p_sys->b_delayed_open = false;
Gildas Bazin's avatar
 
Gildas Bazin committed
115

116
    /* ***** Fill p_context with init values ***** */
Gildas Bazin's avatar
 
Gildas Bazin committed
117 118
    p_sys->p_context->sample_rate = p_dec->fmt_in.audio.i_rate;
    p_sys->p_context->channels = p_dec->fmt_in.audio.i_channels;
119 120 121 122 123 124 125 126 127 128 129 130
    if( !p_dec->fmt_in.audio.i_physical_channels )
    {
        msg_Warn( p_dec, "Physical channel configuration not set : guessing" );
        p_dec->fmt_in.audio.i_original_channels =
            p_dec->fmt_in.audio.i_physical_channels =
                pi_channels_maps[p_sys->p_context->channels];
    }

    p_dec->fmt_out.audio.i_physical_channels =
        p_dec->fmt_out.audio.i_original_channels =
        p_dec->fmt_in.audio.i_physical_channels;

Gildas Bazin's avatar
 
Gildas Bazin committed
131 132
    p_sys->p_context->block_align = p_dec->fmt_in.audio.i_blockalign;
    p_sys->p_context->bit_rate = p_dec->fmt_in.i_bitrate;
Alexis Ballier's avatar
Alexis Ballier committed
133
#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
134
    p_sys->p_context->bits_per_sample = p_dec->fmt_in.audio.i_bitspersample;
Alexis Ballier's avatar
Alexis Ballier committed
135 136 137
#else
    p_sys->p_context->bits_per_coded_sample = p_dec->fmt_in.audio.i_bitspersample;
#endif
138

Laurent Aimar's avatar
Laurent Aimar committed
139
    if( p_dec->fmt_in.i_extra > 0 )
140
    {
Laurent Aimar's avatar
Laurent Aimar committed
141 142 143
        const uint8_t * const p_src = p_dec->fmt_in.p_extra;
        int i_offset;
        int i_size;
144 145

        if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'f', 'l', 'a', 'c' ) )
Laurent Aimar's avatar
Laurent Aimar committed
146
        {
147
            i_offset = 8;
Laurent Aimar's avatar
Laurent Aimar committed
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
            i_size = p_dec->fmt_in.i_extra - 8;
        }
        else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'l', 'a', 'c' ) )
        {
            static const uint8_t p_pattern[] = { 0, 0, 0, 36, 'a', 'l', 'a', 'c' };
            /* Find alac atom XXX it is a bit ugly */
            for( i_offset = 0; i_offset < p_dec->fmt_in.i_extra - sizeof(p_pattern); i_offset++ )
            {
                if( !memcmp( &p_src[i_offset], p_pattern, sizeof(p_pattern) ) )
                    break;
            }
            i_size = __MIN( p_dec->fmt_in.i_extra - i_offset, 36 );
            if( i_size < 36 )
                i_size = 0;
        }
        else
        {
            i_offset = 0;
            i_size = p_dec->fmt_in.i_extra;
        }
168

Laurent Aimar's avatar
Laurent Aimar committed
169
        if( i_size > 0 )
Rémi Duraffort's avatar
Rémi Duraffort committed
170
        {
Laurent Aimar's avatar
Laurent Aimar committed
171 172 173 174 175 176 177 178 179 180 181
            p_sys->p_context->extradata =
                malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
            if( p_sys->p_context->extradata )
            {
                uint8_t *p_dst = p_sys->p_context->extradata;

                p_sys->p_context->extradata_size = i_size;

                memcpy( &p_dst[0],            &p_src[i_offset], i_size );
                memset( &p_dst[i_size], 0, FF_INPUT_BUFFER_PADDING_SIZE );
            }
Rémi Duraffort's avatar
Rémi Duraffort committed
182
        }
183
    }
184
    else
Laurent Aimar's avatar
Laurent Aimar committed
185 186
    {
        p_sys->p_context->extradata_size = 0;
187
        p_sys->p_context->extradata = NULL;
Laurent Aimar's avatar
Laurent Aimar committed
188
    }
189

190
    /* ***** Open the codec ***** */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
191
    vlc_mutex_lock( &avcodec_lock );
192

193
    if( avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0 )
194
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
195
        vlc_mutex_unlock( &avcodec_lock );
Gildas Bazin's avatar
 
Gildas Bazin committed
196
        msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
197
        free( p_sys->p_context->extradata );
198
        free( p_sys );
Gildas Bazin's avatar
 
Gildas Bazin committed
199
        return VLC_EGENERIC;
200
    }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
201
    vlc_mutex_unlock( &avcodec_lock );
202 203

    msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );
204

205
    p_sys->p_output = malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE );
206 207
    p_sys->p_samples = NULL;
    p_sys->i_samples = 0;
208
    p_sys->i_reject_count = 0;
209

Laurent Aimar's avatar
Laurent Aimar committed
210
    aout_DateSet( &p_sys->end_date, 0 );
211 212
    if( p_dec->fmt_in.audio.i_rate )
        aout_DateInit( &p_sys->end_date, p_dec->fmt_in.audio.i_rate );
213

Gildas Bazin's avatar
 
Gildas Bazin committed
214 215
    /* Set output properties */
    p_dec->fmt_out.i_cat = AUDIO_ES;
216

217
    SetupOutputCodec( p_dec );
Gildas Bazin's avatar
 
Gildas Bazin committed
218

Gildas Bazin's avatar
 
Gildas Bazin committed
219
    return VLC_SUCCESS;
220 221
}

222 223 224 225
/*****************************************************************************
 * SplitBuffer: Needed because aout really doesn't like big audio chunk and
 * wma produces easily > 30000 samples...
 *****************************************************************************/
Clément Stenac's avatar
Clément Stenac committed
226
static aout_buffer_t *SplitBuffer( decoder_t *p_dec )
227 228 229 230 231
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    int i_samples = __MIN( p_sys->i_samples, 4096 );
    aout_buffer_t *p_buffer;

232 233
    if( i_samples == 0 ) return NULL;

234
    if( ( p_buffer = decoder_NewAudioBuffer( p_dec, i_samples ) ) == NULL )
235 236 237
        return NULL;

    p_buffer->start_date = aout_DateGet( &p_sys->end_date );
238
    p_buffer->end_date = aout_DateIncrement( &p_sys->end_date, i_samples );
239 240 241 242 243 244 245 246 247

    memcpy( p_buffer->p_buffer, p_sys->p_samples, p_buffer->i_nb_bytes );

    p_sys->p_samples += p_buffer->i_nb_bytes;
    p_sys->i_samples -= i_samples;

    return p_buffer;
}

248
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
249
 * DecodeAudio: Called to decode one frame
250
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
251
aout_buffer_t * DecodeAudio ( decoder_t *p_dec, block_t **pp_block )
252
{
Gildas Bazin's avatar
 
Gildas Bazin committed
253
    decoder_sys_t *p_sys = p_dec->p_sys;
254
    int i_used, i_output;
Gildas Bazin's avatar
 
Gildas Bazin committed
255 256 257 258
    aout_buffer_t *p_buffer;
    block_t *p_block;

    if( !pp_block || !*pp_block ) return NULL;
259

Gildas Bazin's avatar
 
Gildas Bazin committed
260
    p_block = *pp_block;
261

Laurent Aimar's avatar
Laurent Aimar committed
262 263 264 265
    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
    {
        block_Release( p_block );
        avcodec_flush_buffers( p_sys->p_context );
266 267
        p_sys->i_samples = 0;
        aout_DateSet( &p_sys->end_date, 0 );
268 269 270

        if( p_sys->i_codec_id == CODEC_ID_MP2 || p_sys->i_codec_id == CODEC_ID_MP3 )
            p_sys->i_reject_count = 3;
Laurent Aimar's avatar
Laurent Aimar committed
271 272 273 274
        return NULL;
    }

    if( p_sys->i_samples > 0 )
275 276 277
    {
        /* More data */
        p_buffer = SplitBuffer( p_dec );
278
        if( !p_buffer ) block_Release( p_block );
279 280 281
        return p_buffer;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
282 283 284 285
    if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
    {
        /* We've just started the stream, wait for the first PTS. */
        block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
286
        return NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
287
    }
288

Laurent Aimar's avatar
Laurent Aimar committed
289
    if( p_block->i_buffer <= 0 )
290
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
291 292 293
        block_Release( p_block );
        return NULL;
    }
294 295 296 297 298 299
    if( p_block->i_buffer > AVCODEC_MAX_AUDIO_FRAME_SIZE )
    {
        /* Grow output buffer if necessary (eg. for PCM data) */
        p_sys->p_output = realloc(p_sys->p_output, p_block->i_buffer);
    }

Laurent Aimar's avatar
Laurent Aimar committed
300 301 302 303 304 305
    *pp_block = p_block = block_Realloc( p_block, 0, p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE );
    if( !p_block )
        return NULL;
    p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE;
    memset( &p_block->p_buffer[p_block->i_buffer], 0, FF_INPUT_BUFFER_PADDING_SIZE );

306
#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(0<<8)+0)
Laurent Aimar's avatar
Laurent Aimar committed
307 308
    i_output = __MAX( AVCODEC_MAX_AUDIO_FRAME_SIZE, p_block->i_buffer );
    i_used = avcodec_decode_audio2( p_sys->p_context,
Gildas Bazin's avatar
 
Gildas Bazin committed
309 310
                                   (int16_t*)p_sys->p_output, &i_output,
                                   p_block->p_buffer, p_block->i_buffer );
311 312 313 314 315
#else
    i_used = avcodec_decode_audio( p_sys->p_context,
                                   (int16_t*)p_sys->p_output, &i_output,
                                   p_block->p_buffer, p_block->i_buffer );
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
316

317
    if( i_used < 0 || i_output < 0 )
Gildas Bazin's avatar
 
Gildas Bazin committed
318
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
319
        if( i_used < 0 )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
320
            msg_Warn( p_dec, "cannot decode one frame (%zu bytes)",
Gildas Bazin's avatar
 
Gildas Bazin committed
321 322 323 324
                      p_block->i_buffer );

        block_Release( p_block );
        return NULL;
325
    }
326
    else if( (size_t)i_used > p_block->i_buffer )
327 328 329
    {
        i_used = p_block->i_buffer;
    }
330

Gildas Bazin's avatar
 
Gildas Bazin committed
331 332 333
    p_block->i_buffer -= i_used;
    p_block->p_buffer += i_used;

334
    if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 8 ||
335
        p_sys->p_context->sample_rate <= 0 )
Gildas Bazin's avatar
 
Gildas Bazin committed
336
    {
337 338
        msg_Warn( p_dec, "invalid audio properties channels count %d, sample rate %d",
                  p_sys->p_context->channels, p_sys->p_context->sample_rate );
Gildas Bazin's avatar
 
Gildas Bazin committed
339 340 341 342
        block_Release( p_block );
        return NULL;
    }

343
    if( p_dec->fmt_out.audio.i_rate != (unsigned int)p_sys->p_context->sample_rate )
Gildas Bazin's avatar
 
Gildas Bazin committed
344 345 346 347 348 349
    {
        aout_DateInit( &p_sys->end_date, p_sys->p_context->sample_rate );
        aout_DateSet( &p_sys->end_date, p_block->i_pts );
    }

    /* **** Set audio output parameters **** */
350
    SetupOutputCodec( p_dec );
Gildas Bazin's avatar
 
Gildas Bazin committed
351 352 353 354 355 356 357 358 359 360 361
    p_dec->fmt_out.audio.i_rate     = p_sys->p_context->sample_rate;
    p_dec->fmt_out.audio.i_channels = p_sys->p_context->channels;
    p_dec->fmt_out.audio.i_original_channels =
        p_dec->fmt_out.audio.i_physical_channels =
            pi_channels_maps[p_sys->p_context->channels];

    if( p_block->i_pts != 0 &&
        p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
    {
        aout_DateSet( &p_sys->end_date, p_block->i_pts );
    }
362
    p_block->i_pts = 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
363 364

    /* **** Now we can output these samples **** */
365
    p_sys->i_samples = i_output / (p_dec->fmt_out.audio.i_bitspersample / 8) / p_sys->p_context->channels;
366
    p_sys->p_samples = p_sys->p_output;
Gildas Bazin's avatar
 
Gildas Bazin committed
367

368 369 370 371 372 373 374
    /* Silent unwanted samples */
    if( p_sys->i_reject_count > 0 )
    {
        memset( p_sys->p_output, 0, i_output );
        p_sys->i_reject_count--;
    }

375
    p_buffer = SplitBuffer( p_dec );
376
    if( !p_buffer ) block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
377
    return p_buffer;
378 379 380
}

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
381
 * EndAudioDec: audio decoder destruction
382
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
383
void EndAudioDec( decoder_t *p_dec )
384
{
Gildas Bazin's avatar
 
Gildas Bazin committed
385 386
    decoder_sys_t *p_sys = p_dec->p_sys;

387
    free( p_sys->p_output );
388
}
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427

/*****************************************************************************
 *
 *****************************************************************************/
static void SetupOutputCodec( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

#if defined(AV_VERSION_INT) && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 51, 65, 0 )
    switch( p_sys->p_context->sample_fmt )
    {
    case SAMPLE_FMT_U8:
        p_dec->fmt_out.i_codec = VLC_FOURCC('u','8',' ',' ');
        p_dec->fmt_out.audio.i_bitspersample = 8;
        break;
    case SAMPLE_FMT_S32:
        p_dec->fmt_out.i_codec = AOUT_FMT_S32_NE;
        p_dec->fmt_out.audio.i_bitspersample = 32;
        break;
    case SAMPLE_FMT_FLT:
        p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2');
        p_dec->fmt_out.audio.i_bitspersample = 32;
        break;
    case SAMPLE_FMT_DBL:
        p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','6','4');
        p_dec->fmt_out.audio.i_bitspersample = 64;
        break;

    case SAMPLE_FMT_S16:
    default:
        p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
        p_dec->fmt_out.audio.i_bitspersample = 16;
        break;
    }
#else
    p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
    p_dec->fmt_out.audio.i_bitspersample = 16;
#endif
}