* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
-#include <vlc/decoder.h>
+#include <vlc_aout.h>
+#include <vlc_codec.h>
+#include <vlc_input.h>
/* ffmpeg header */
#ifdef HAVE_FFMPEG_AVCODEC_H
*****************************************************************************/
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;
+ FFMPEG_COMMON_MEMBERS
/* Temporary buffer for libavcodec */
uint8_t *p_output;
*/
uint8_t *p_samples;
int i_samples;
+
+ /* */
+ int i_reject_count;
+
+ int i_input_rate;
};
/*****************************************************************************
* The ffmpeg codec will be opened, some memory allocated.
*****************************************************************************/
int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context,
- AVCodec *p_codec, int i_codec_id, char *psz_namecodec )
+ AVCodec *p_codec, int i_codec_id, const char *psz_namecodec )
{
decoder_sys_t *p_sys;
vlc_value_t lockval;
- var_Get( p_dec->p_libvlc, "avcodec", &lockval );
+ var_Get( p_dec->p_libvlc_global, "avcodec", &lockval );
/* Allocate the memory needed to store the decoder's structure */
if( ( p_dec->p_sys = p_sys =
p_sys->p_output = malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE );
p_sys->p_samples = NULL;
p_sys->i_samples = 0;
+ p_sys->i_reject_count = 0;
+ p_sys->i_input_rate = INPUT_RATE_DEFAULT;
+ 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;
* 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 )
+static 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 );
}
p_buffer->start_date = aout_DateGet( &p_sys->end_date );
- p_buffer->end_date = aout_DateIncrement( &p_sys->end_date, i_samples );
+ p_buffer->end_date = aout_DateIncrement( &p_sys->end_date,
+ i_samples * p_sys->i_input_rate / INPUT_RATE_DEFAULT );
memcpy( p_buffer->p_buffer, p_sys->p_samples, p_buffer->i_nb_bytes );
p_block = *pp_block;
- if( p_block->i_buffer <= 0 && p_sys->i_samples > 0 )
+ if( p_block->i_rate > 0 )
+ p_sys->i_input_rate = p_block->i_rate;
+
+ if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
+ {
+ block_Release( p_block );
+ avcodec_flush_buffers( p_sys->p_context );
+
+ if( p_sys->i_codec_id == CODEC_ID_MP2 || p_sys->i_codec_id == CODEC_ID_MP3 )
+ p_sys->i_reject_count = 3;
+ return NULL;
+ }
+
+ if( p_sys->i_samples > 0 )
{
/* More data */
p_buffer = SplitBuffer( p_dec );
return NULL;
}
- if( p_block->i_buffer <= 0 ||
- (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) )
+ if( p_block->i_buffer <= 0 )
{
block_Release( p_block );
return NULL;
}
-
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);
}
- i_used = avcodec_decode_audio( p_sys->p_context,
+ *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 );
+
+ i_output = __MAX( AVCODEC_MAX_AUDIO_FRAME_SIZE, p_block->i_buffer );
+ i_used = avcodec_decode_audio2( p_sys->p_context,
(int16_t*)p_sys->p_output, &i_output,
p_block->p_buffer, p_block->i_buffer );
p_block->i_pts = 0;
/* **** Now we can output these samples **** */
- p_sys->i_samples = i_output / 2 / p_sys->p_context->channels;
+ p_sys->i_samples = i_output / sizeof(int16_t) / p_sys->p_context->channels;
p_sys->p_samples = p_sys->p_output;
+ /* Silent unwanted samples */
+ if( p_sys->i_reject_count > 0 )
+ {
+ memset( p_sys->p_output, 0, i_output );
+ p_sys->i_reject_count--;
+ }
+
p_buffer = SplitBuffer( p_dec );
if( !p_buffer ) block_Release( p_block );
return p_buffer;