X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fcodec%2Fffmpeg%2Faudio.c;h=1135baa28c4a87092909c0bc0bffe01b94b4a063;hb=b368eddeef63a8bdacba2062f2733e063e10795f;hp=10ad364d0dfeb3a2aa91f002d38b0db3e7b3a793;hpb=f8c7410eb9ec329a2dae56cb99270e3b7e5a1a5d;p=vlc diff --git a/modules/codec/ffmpeg/audio.c b/modules/codec/ffmpeg/audio.c index 10ad364d0d..1135baa28c 100644 --- a/modules/codec/ffmpeg/audio.c +++ b/modules/codec/ffmpeg/audio.c @@ -2,10 +2,10 @@ * audio.c: audio decoder using ffmpeg library ***************************************************************************** * Copyright (C) 1999-2003 VideoLAN - * $Id: audio.c,v 1.29 2004/02/26 17:07:37 hartman Exp $ + * $Id$ * * Authors: Laurent Aimar - * Gildas Bazin + * Gildas Bazin * * 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 @@ -37,7 +37,7 @@ #include "ffmpeg.h" -static unsigned int pi_channels_maps[6] = +static unsigned int pi_channels_maps[7] = { 0, AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT, @@ -45,7 +45,9 @@ static unsigned int pi_channels_maps[6] = 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_REARLEFT | AOUT_CHAN_REARRIGHT, + AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER + | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE }; /***************************************************************************** @@ -68,6 +70,12 @@ struct decoder_sys_t */ audio_sample_format_t aout_format; audio_date_t end_date; + + /* + * + */ + uint8_t *p_samples; + int i_samples; }; /***************************************************************************** @@ -91,24 +99,34 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context, return VLC_EGENERIC; } - p_dec->p_sys->p_context = p_context; - p_dec->p_sys->p_codec = p_codec; - p_dec->p_sys->i_codec_id = i_codec_id; - p_dec->p_sys->psz_namecodec = psz_namecodec; + 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; /* ***** Fill p_context with init values ***** */ 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; + p_sys->p_context->bits_per_sample = p_dec->fmt_in.audio.i_bitspersample; if( ( p_sys->p_context->extradata_size = p_dec->fmt_in.i_extra ) > 0 ) { + int i_offset = 0; + + if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'f', 'l', 'a', 'c' ) ) + i_offset = 8; + + p_sys->p_context->extradata_size -= i_offset; p_sys->p_context->extradata = - malloc( p_dec->fmt_in.i_extra + FF_INPUT_BUFFER_PADDING_SIZE ); + malloc( p_sys->p_context->extradata_size + + 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, + (char*)p_dec->fmt_in.p_extra + i_offset, + p_sys->p_context->extradata_size ); + memset( (char*)p_sys->p_context->extradata + + p_sys->p_context->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE ); } @@ -118,6 +136,7 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context, { vlc_mutex_unlock( lockval.p_address ); msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec ); + free( p_sys ); return VLC_EGENERIC; } vlc_mutex_unlock( lockval.p_address ); @@ -125,24 +144,59 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context, msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec ); p_sys->p_output = malloc( 3 * AVCODEC_MAX_AUDIO_FRAME_SIZE ); + p_sys->p_samples = NULL; + p_sys->i_samples = 0; - aout_DateSet( &p_sys->end_date, 0 ); + 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 ); + } /* Set output properties */ p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE; + p_dec->fmt_out.audio.i_bitspersample = 16; return VLC_SUCCESS; } +/***************************************************************************** + * SplitBuffer: Needed because aout really doesn't like big audio chunk and + * wma produces easily > 30000 samples... + *****************************************************************************/ +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; + + if( i_samples == 0 ) return NULL; + + 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; +} + /***************************************************************************** * DecodeAudio: Called to decode one frame *****************************************************************************/ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; - int i_used, i_output, i_samples; - uint8_t *p_samples; + int i_used, i_output; aout_buffer_t *p_buffer; block_t *p_block; @@ -150,6 +204,14 @@ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block ) p_block = *pp_block; + if( p_block->i_buffer <= 0 && p_sys->i_samples > 0 ) + { + /* More data */ + p_buffer = SplitBuffer( p_dec ); + if( !p_buffer ) block_Release( p_block ); + return p_buffer; + } + if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts ) { /* We've just started the stream, wait for the first PTS. */ @@ -157,8 +219,7 @@ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block ) return NULL; } - if( p_block->i_buffer <= 0 || - ( p_block->i_flags&BLOCK_FLAG_DISCONTINUITY ) ) + if( p_block->i_buffer <= 0 || ( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) ) { block_Release( p_block ); return NULL; @@ -214,22 +275,11 @@ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block ) p_block->i_pts = 0; /* **** Now we can output these samples **** */ - i_samples = i_output / 2 / p_sys->p_context->channels; - p_samples = p_sys->p_output; - - p_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples ); - if( !p_buffer ) - { - msg_Err( p_dec, "cannot get aout buffer" ); - block_Release( p_block ); - 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_samples, p_buffer->i_nb_bytes ); + p_sys->i_samples = i_output / 2 / p_sys->p_context->channels; + p_sys->p_samples = p_sys->p_output; + p_buffer = SplitBuffer( p_dec ); + if( !p_buffer ) block_Release( p_block ); return p_buffer; }