audio.c 9.12 KB
Newer Older
1 2 3
/*****************************************************************************
 * audio.c: audio decoder using ffmpeg library
 *****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
4
 * Copyright (C) 1999-2003 VideoLAN
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 22 23 24 25 26 27 28 29 30
 * 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.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/decoder.h>

Gildas Bazin's avatar
 
Gildas Bazin committed
31 32 33 34 35 36
/* ffmpeg header */
#ifdef HAVE_FFMPEG_AVCODEC_H
#   include <ffmpeg/avcodec.h>
#else
#   include <avcodec.h>
#endif
37 38 39

#include "ffmpeg.h"

40
static unsigned int pi_channels_maps[6] =
41 42
{
    0,
43 44
    AOUT_CHAN_CENTER,   AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
    AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
Gildas Bazin's avatar
 
Gildas Bazin committed
45 46
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
     | AOUT_CHAN_REARRIGHT,
47 48
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
49
};
50 51

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
52
 * decoder_sys_t : decoder descriptor
53
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
struct decoder_sys_t
{
    /* Common part between video and audio decoder */
    int i_cat;
    int i_codec_id;
    char *psz_namecodec;
    AVCodecContext      *p_context;
    AVCodec             *p_codec;

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

    /*
     * Output properties
     */
    audio_sample_format_t aout_format;
    audio_date_t          end_date;
71 72 73 74 75 76

    /*
     *
     */
    uint8_t *p_samples;
    int     i_samples;
Gildas Bazin's avatar
 
Gildas Bazin committed
77
};
78 79

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
80
 * InitAudioDec: initialize audio decoder
81
 *****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
82
 * The ffmpeg codec will be opened, some memory allocated.
83
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
84 85
int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context,
                      AVCodec *p_codec, int i_codec_id, char *psz_namecodec )
86
{
Gildas Bazin's avatar
 
Gildas Bazin committed
87
    decoder_sys_t *p_sys;
88 89 90
    vlc_value_t lockval;

    var_Get( p_dec->p_libvlc, "avcodec", &lockval );
91

Gildas Bazin's avatar
 
Gildas Bazin committed
92 93 94
    /* 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 )
95
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
96 97 98 99
        msg_Err( p_dec, "out of memory" );
        return VLC_EGENERIC;
    }

100 101 102 103
    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;
Gildas Bazin's avatar
 
Gildas Bazin committed
104

105
    /* ***** Fill p_context with init values ***** */
Gildas Bazin's avatar
 
Gildas Bazin committed
106 107 108 109
    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;
    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;
110

Gildas Bazin's avatar
 
Gildas Bazin committed
111
    if( ( p_sys->p_context->extradata_size = p_dec->fmt_in.i_extra ) > 0 )
112
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
113
        p_sys->p_context->extradata =
Gildas Bazin's avatar
 
Gildas Bazin committed
114 115 116 117
            malloc( p_dec->fmt_in.i_extra + FF_INPUT_BUFFER_PADDING_SIZE );
        memcpy( p_sys->p_context->extradata,
                p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
        memset( p_sys->p_context->extradata + p_dec->fmt_in.i_extra, 0,
Gildas Bazin's avatar
 
Gildas Bazin committed
118
                FF_INPUT_BUFFER_PADDING_SIZE );
119
    }
120

121
    /* ***** Open the codec ***** */
122
    vlc_mutex_lock( lockval.p_address );
Gildas Bazin's avatar
 
Gildas Bazin committed
123
    if (avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0)
124
    {
125
        vlc_mutex_unlock( lockval.p_address );
Gildas Bazin's avatar
 
Gildas Bazin committed
126 127
        msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
        return VLC_EGENERIC;
128
    }
129 130 131
    vlc_mutex_unlock( lockval.p_address );

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

Gildas Bazin's avatar
 
Gildas Bazin committed
133
    p_sys->p_output = malloc( 3 * AVCODEC_MAX_AUDIO_FRAME_SIZE );
134 135
    p_sys->p_samples = NULL;
    p_sys->i_samples = 0;
136

137 138 139 140 141
    if( p_dec->fmt_in.audio.i_rate )
    {
        aout_DateInit( &p_sys->end_date, p_dec->fmt_in.audio.i_rate );
        aout_DateSet( &p_sys->end_date, 0 );
    }
142

Gildas Bazin's avatar
 
Gildas Bazin committed
143 144 145
    /* Set output properties */
    p_dec->fmt_out.i_cat = AUDIO_ES;
    p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
146
    p_dec->fmt_out.audio.i_bitspersample = 2;
Gildas Bazin's avatar
 
Gildas Bazin committed
147

Gildas Bazin's avatar
 
Gildas Bazin committed
148
    return VLC_SUCCESS;
149 150
}

151 152 153 154
/*****************************************************************************
 * SplitBuffer: Needed because aout really doesn't like big audio chunk and
 * wma produces easily > 30000 samples...
 *****************************************************************************/
155 156 157 158 159 160
aout_buffer_t *SplitBuffer( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    int i_samples = __MIN( p_sys->i_samples, 4096 );
    aout_buffer_t *p_buffer;

161 162
    if( i_samples == 0 ) return NULL;

163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
    if( ( p_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples ) ) == NULL )
    {
        msg_Err( p_dec, "cannot get aout buffer" );
        return NULL;
    }

    p_buffer->start_date = aout_DateGet( &p_sys->end_date );
    p_buffer->end_date = aout_DateIncrement( &p_sys->end_date, i_samples );

    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;
}

180
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
181
 * DecodeAudio: Called to decode one frame
182
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
183
aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block )
184
{
Gildas Bazin's avatar
 
Gildas Bazin committed
185
    decoder_sys_t *p_sys = p_dec->p_sys;
186
    int i_used, i_output;
Gildas Bazin's avatar
 
Gildas Bazin committed
187 188 189 190
    aout_buffer_t *p_buffer;
    block_t *p_block;

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

Gildas Bazin's avatar
 
Gildas Bazin committed
192
    p_block = *pp_block;
193

194 195 196 197
    if( p_block->i_buffer <= 0 && p_sys->i_samples > 0 )
    {
        /* More data */
        p_buffer = SplitBuffer( p_dec );
198
        if( !p_buffer ) block_Release( p_block );
199 200 201
        return p_buffer;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
202 203 204 205
    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
206
        return NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
207
    }
208

209
    if( p_block->i_buffer <= 0 || p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
210
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
211 212 213
        block_Release( p_block );
        return NULL;
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
214

Gildas Bazin's avatar
 
Gildas Bazin committed
215 216 217 218
    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 );

219
    if( i_used < 0 || i_output < 0 )
Gildas Bazin's avatar
 
Gildas Bazin committed
220
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
221
        if( i_used < 0 )
Gildas Bazin's avatar
 
Gildas Bazin committed
222 223 224 225 226
            msg_Warn( p_dec, "cannot decode one frame (%d bytes)",
                      p_block->i_buffer );

        block_Release( p_block );
        return NULL;
227
    }
228 229 230 231
    else if( i_used > p_block->i_buffer )
    {
        i_used = p_block->i_buffer;
    }
232

Gildas Bazin's avatar
 
Gildas Bazin committed
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
    p_block->i_buffer -= i_used;
    p_block->p_buffer += i_used;

    if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 6 )
    {
        msg_Warn( p_dec, "invalid channels count %d",
                  p_sys->p_context->channels );
        block_Release( p_block );
        return NULL;
    }

    if( p_dec->fmt_out.audio.i_rate != p_sys->p_context->sample_rate )
    {
        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 **** */
    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 );
    }
262
    p_block->i_pts = 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
263 264

    /* **** Now we can output these samples **** */
265 266
    p_sys->i_samples = i_output / 2 / p_sys->p_context->channels;
    p_sys->p_samples = p_sys->p_output;
Gildas Bazin's avatar
 
Gildas Bazin committed
267

268
    p_buffer = SplitBuffer( p_dec );
269
    if( !p_buffer ) block_Release( p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
270
    return p_buffer;
271 272 273
}

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
274
 * EndAudioDec: audio decoder destruction
275
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
276
void E_(EndAudioDec)( decoder_t *p_dec )
277
{
Gildas Bazin's avatar
 
Gildas Bazin committed
278 279 280
    decoder_sys_t *p_sys = p_dec->p_sys;

    if( p_sys->p_output ) free( p_sys->p_output );
281
}