Commit 70a8bb96 authored by Laurent Aimar's avatar Laurent Aimar

All: preliminary support for audio while playing faster/slower (1/4 -> 4).

It use our standard resampler to do it and so we do not keep
pitch yet (I am working on a soundtouch resampler).
Please test any regression.
parent 8f1901a6
...@@ -169,6 +169,9 @@ struct aout_buffer_t ...@@ -169,6 +169,9 @@ struct aout_buffer_t
/* Number of samples in an A/52 frame. */ /* Number of samples in an A/52 frame. */
#define A52_FRAME_NB 1536 #define A52_FRAME_NB 1536
/* Max input rate factor (1/4 -> 4) */
#define AOUT_MAX_INPUT_RATE (4)
/** date incrementation helper structure without long-term /** date incrementation helper structure without long-term
* rounding errors * rounding errors
*/ */
...@@ -277,6 +280,8 @@ struct aout_input_t ...@@ -277,6 +280,8 @@ struct aout_input_t
/* Did we just change the output format? (expect buffer inconsistencies) */ /* Did we just change the output format? (expect buffer inconsistencies) */
vlc_bool_t b_changed; vlc_bool_t b_changed;
/* last rate from input */
int i_last_input_rate;
/* internal caching delay from input */ /* internal caching delay from input */
int i_pts_delay; int i_pts_delay;
/* desynchronisation delay request by the user */ /* desynchronisation delay request by the user */
......
...@@ -123,7 +123,7 @@ static int Create( vlc_object_t *p_this ) ...@@ -123,7 +123,7 @@ static int Create( vlc_object_t *p_this )
/* Calculate worst case for the length of the filter wing */ /* Calculate worst case for the length of the filter wing */
d_factor = (double)p_filter->output.i_rate d_factor = (double)p_filter->output.i_rate
/ p_filter->input.i_rate; / p_filter->input.i_rate / AOUT_MAX_INPUT_RATE;
i_filter_wing = ((SMALL_FILTER_NMULT + 1)/2.0) i_filter_wing = ((SMALL_FILTER_NMULT + 1)/2.0)
* __MAX(1.0, 1.0/d_factor) + 10; * __MAX(1.0, 1.0/d_factor) + 10;
p_filter->p_sys->i_buf_size = aout_FormatNbChannels( &p_filter->input ) * p_filter->p_sys->i_buf_size = aout_FormatNbChannels( &p_filter->input ) *
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc_codec.h> #include <vlc_codec.h>
#include <vlc_aout.h> #include <vlc_aout.h>
#include <vlc_input.h>
#include <vlc_block_helper.h> #include <vlc_block_helper.h>
#define A52_HEADER_SIZE 7 #define A52_HEADER_SIZE 7
...@@ -57,6 +58,7 @@ struct decoder_sys_t ...@@ -57,6 +58,7 @@ struct decoder_sys_t
int i_frame_size, i_bit_rate; int i_frame_size, i_bit_rate;
unsigned int i_rate, i_channels, i_channels_conf; unsigned int i_rate, i_channels, i_channels_conf;
int i_input_rate;
}; };
enum { enum {
...@@ -128,6 +130,7 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -128,6 +130,7 @@ static int OpenDecoder( vlc_object_t *p_this )
aout_DateSet( &p_sys->end_date, 0 ); aout_DateSet( &p_sys->end_date, 0 );
p_sys->bytestream = block_BytestreamInit( p_dec ); p_sys->bytestream = block_BytestreamInit( p_dec );
p_sys->i_input_rate = INPUT_RATE_DEFAULT;
/* Set output properties */ /* Set output properties */
p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_cat = AUDIO_ES;
...@@ -187,6 +190,9 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -187,6 +190,9 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
return NULL; return NULL;
} }
if( (*pp_block)->i_rate > 0 )
p_sys->i_input_rate = (*pp_block)->i_rate;
block_BytestreamPush( &p_sys->bytestream, *pp_block ); block_BytestreamPush( &p_sys->bytestream, *pp_block );
while( 1 ) while( 1 )
...@@ -385,7 +391,8 @@ static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec ) ...@@ -385,7 +391,8 @@ static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
if( p_buf == NULL ) return NULL; if( p_buf == NULL ) return NULL;
p_buf->start_date = aout_DateGet( &p_sys->end_date ); p_buf->start_date = aout_DateGet( &p_sys->end_date );
p_buf->end_date = aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB ); p_buf->end_date = aout_DateIncrement( &p_sys->end_date,
A52_FRAME_NB * p_sys->i_input_rate / INPUT_RATE_DEFAULT );
return p_buf; return p_buf;
} }
...@@ -403,7 +410,9 @@ static block_t *GetSoutBuffer( decoder_t *p_dec ) ...@@ -403,7 +410,9 @@ static block_t *GetSoutBuffer( decoder_t *p_dec )
p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date ); p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
p_block->i_length = aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB ) - p_block->i_length =
aout_DateIncrement( &p_sys->end_date,
A52_FRAME_NB * p_sys->i_input_rate / INPUT_RATE_DEFAULT ) -
p_block->i_pts; p_block->i_pts;
return p_block; return p_block;
......
...@@ -69,6 +69,8 @@ struct decoder_sys_t ...@@ -69,6 +69,8 @@ struct decoder_sys_t
uint32_t pi_channel_positions[MAX_CHANNEL_POSITIONS]; uint32_t pi_channel_positions[MAX_CHANNEL_POSITIONS];
vlc_bool_t b_sbr, b_ps; vlc_bool_t b_sbr, b_ps;
int i_input_rate;
}; };
static const uint32_t pi_channels_in[MAX_CHANNEL_POSITIONS] = static const uint32_t pi_channels_in[MAX_CHANNEL_POSITIONS] =
...@@ -166,6 +168,8 @@ static int Open( vlc_object_t *p_this ) ...@@ -166,6 +168,8 @@ static int Open( vlc_object_t *p_this )
p_sys->i_buffer = p_sys->i_buffer_size = 0; p_sys->i_buffer = p_sys->i_buffer_size = 0;
p_sys->p_buffer = 0; p_sys->p_buffer = 0;
p_sys->i_input_rate = INPUT_RATE_DEFAULT;
/* Faad2 can't deal with truncated data (eg. from MPEG TS) */ /* Faad2 can't deal with truncated data (eg. from MPEG TS) */
p_dec->b_need_packetized = VLC_TRUE; p_dec->b_need_packetized = VLC_TRUE;
...@@ -191,6 +195,9 @@ static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -191,6 +195,9 @@ static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
return NULL; return NULL;
} }
if( p_block->i_rate > 0 )
p_sys->i_input_rate = p_block->i_rate;
/* Append the block to the temporary buffer */ /* Append the block to the temporary buffer */
if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer ) if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
{ {
...@@ -374,7 +381,7 @@ static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -374,7 +381,7 @@ static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
p_out->start_date = aout_DateGet( &p_sys->date ); p_out->start_date = aout_DateGet( &p_sys->date );
p_out->end_date = aout_DateIncrement( &p_sys->date, p_out->end_date = aout_DateIncrement( &p_sys->date,
frame.samples / frame.channels ); (frame.samples / frame.channels) * p_sys->i_input_rate / INPUT_RATE_DEFAULT );
DoReordering( p_dec, (uint32_t *)p_out->p_buffer, samples, DoReordering( p_dec, (uint32_t *)p_out->p_buffer, samples,
frame.samples / frame.channels, frame.channels, frame.samples / frame.channels, frame.channels,
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc_aout.h> #include <vlc_aout.h>
#include <vlc_codec.h> #include <vlc_codec.h>
#include <vlc_input.h>
/* ffmpeg header */ /* ffmpeg header */
#ifdef HAVE_FFMPEG_AVCODEC_H #ifdef HAVE_FFMPEG_AVCODEC_H
...@@ -75,6 +76,8 @@ struct decoder_sys_t ...@@ -75,6 +76,8 @@ struct decoder_sys_t
/* */ /* */
int i_reject_count; int i_reject_count;
int i_input_rate;
}; };
/***************************************************************************** /*****************************************************************************
...@@ -146,6 +149,7 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context, ...@@ -146,6 +149,7 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context,
p_sys->p_samples = NULL; p_sys->p_samples = NULL;
p_sys->i_samples = 0; p_sys->i_samples = 0;
p_sys->i_reject_count = 0; p_sys->i_reject_count = 0;
p_sys->i_input_rate = INPUT_RATE_DEFAULT;
aout_DateSet( &p_sys->end_date, 0 ); aout_DateSet( &p_sys->end_date, 0 );
if( p_dec->fmt_in.audio.i_rate ) if( p_dec->fmt_in.audio.i_rate )
...@@ -178,7 +182,8 @@ static aout_buffer_t *SplitBuffer( decoder_t *p_dec ) ...@@ -178,7 +182,8 @@ static aout_buffer_t *SplitBuffer( decoder_t *p_dec )
} }
p_buffer->start_date = aout_DateGet( &p_sys->end_date ); 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 ); memcpy( p_buffer->p_buffer, p_sys->p_samples, p_buffer->i_nb_bytes );
...@@ -202,6 +207,9 @@ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block ) ...@@ -202,6 +207,9 @@ aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block )
p_block = *pp_block; p_block = *pp_block;
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) ) if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
{ {
block_Release( p_block ); block_Release( p_block );
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc_codec.h> #include <vlc_codec.h>
#include <vlc_aout.h> #include <vlc_aout.h>
#include <vlc_input.h>
#include <vlc_block_helper.h> #include <vlc_block_helper.h>
...@@ -62,6 +63,8 @@ struct decoder_sys_t ...@@ -62,6 +63,8 @@ struct decoder_sys_t
unsigned int i_layer, i_bit_rate; unsigned int i_layer, i_bit_rate;
vlc_bool_t b_discontinuity; vlc_bool_t b_discontinuity;
int i_input_rate;
}; };
enum { enum {
...@@ -155,6 +158,7 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -155,6 +158,7 @@ static int OpenDecoder( vlc_object_t *p_this )
aout_DateSet( &p_sys->end_date, 0 ); aout_DateSet( &p_sys->end_date, 0 );
p_sys->bytestream = block_BytestreamInit( p_dec ); p_sys->bytestream = block_BytestreamInit( p_dec );
p_sys->b_discontinuity = VLC_FALSE; p_sys->b_discontinuity = VLC_FALSE;
p_sys->i_input_rate = INPUT_RATE_DEFAULT;
/* Set output properties */ /* Set output properties */
p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_cat = AUDIO_ES;
...@@ -220,6 +224,9 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -220,6 +224,9 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
return NULL; return NULL;
} }
if( (*pp_block)->i_rate > 0 )
p_sys->i_input_rate = (*pp_block)->i_rate;
block_BytestreamPush( &p_sys->bytestream, *pp_block ); block_BytestreamPush( &p_sys->bytestream, *pp_block );
while( 1 ) while( 1 )
...@@ -535,7 +542,8 @@ static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec ) ...@@ -535,7 +542,8 @@ static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
p_buf->start_date = aout_DateGet( &p_sys->end_date ); p_buf->start_date = aout_DateGet( &p_sys->end_date );
p_buf->end_date = p_buf->end_date =
aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length ); aout_DateIncrement( &p_sys->end_date,
p_sys->i_frame_length * p_sys->i_input_rate / INPUT_RATE_DEFAULT );
p_buf->b_discontinuity = p_sys->b_discontinuity; p_buf->b_discontinuity = p_sys->b_discontinuity;
p_sys->b_discontinuity = VLC_FALSE; p_sys->b_discontinuity = VLC_FALSE;
...@@ -559,7 +567,8 @@ static block_t *GetSoutBuffer( decoder_t *p_dec ) ...@@ -559,7 +567,8 @@ static block_t *GetSoutBuffer( decoder_t *p_dec )
p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date ); p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
p_block->i_length = p_block->i_length =
aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length ) - aout_DateIncrement( &p_sys->end_date,
p_sys->i_frame_length * p_sys->i_input_rate / INPUT_RATE_DEFAULT ) -
p_block->i_pts; p_block->i_pts;
return p_block; return p_block;
......
...@@ -78,6 +78,8 @@ struct decoder_sys_t ...@@ -78,6 +78,8 @@ struct decoder_sys_t
audio_date_t end_date; audio_date_t end_date;
int i_last_block_size; int i_last_block_size;
int i_input_rate;
/* /*
** Channel reordering ** Channel reordering
*/ */
...@@ -237,6 +239,7 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -237,6 +239,7 @@ static int OpenDecoder( vlc_object_t *p_this )
p_sys->i_last_block_size = 0; p_sys->i_last_block_size = 0;
p_sys->b_packetizer = VLC_FALSE; p_sys->b_packetizer = VLC_FALSE;
p_sys->i_headers = 0; p_sys->i_headers = 0;
p_sys->i_input_rate = INPUT_RATE_DEFAULT;
/* Take care of vorbis init */ /* Take care of vorbis init */
vorbis_info_init( &p_sys->vi ); vorbis_info_init( &p_sys->vi );
...@@ -291,6 +294,9 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -291,6 +294,9 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
/* Block to Ogg packet */ /* Block to Ogg packet */
oggpacket.packet = (*pp_block)->p_buffer; oggpacket.packet = (*pp_block)->p_buffer;
oggpacket.bytes = (*pp_block)->i_buffer; oggpacket.bytes = (*pp_block)->i_buffer;
if( (*pp_block)->i_rate > 0 )
p_sys->i_input_rate = (*pp_block)->i_rate;
} }
else else
{ {
...@@ -563,7 +569,7 @@ static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) ...@@ -563,7 +569,7 @@ static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
/* Date management */ /* Date management */
p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date ); p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date, p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date,
i_samples ); i_samples * p_sys->i_input_rate / INPUT_RATE_DEFAULT );
return p_aout_buffer; return p_aout_buffer;
} }
else else
...@@ -590,7 +596,8 @@ static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, ...@@ -590,7 +596,8 @@ static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date ); p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date );
if( p_sys->i_headers >= 3 ) if( p_sys->i_headers >= 3 )
p_block->i_length = aout_DateIncrement( &p_sys->end_date, i_samples ) - p_block->i_length = aout_DateIncrement( &p_sys->end_date,
i_samples * p_sys->i_input_rate / INPUT_RATE_DEFAULT ) -
p_block->i_pts; p_block->i_pts;
else else
p_block->i_length = 0; p_block->i_length = 0;
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <vlc_block.h> #include <vlc_block.h>
#include <vlc_sout.h> #include <vlc_sout.h>
#include <vlc_codecs.h> #include <vlc_codecs.h>
#include <vlc_input.h>
#include "vlc_block_helper.h" #include "vlc_block_helper.h"
...@@ -72,6 +73,8 @@ struct decoder_sys_t ...@@ -72,6 +73,8 @@ struct decoder_sys_t
unsigned int i_raw_blocks; unsigned int i_raw_blocks;
unsigned int i_channels; unsigned int i_channels;
unsigned int i_rate, i_frame_length, i_header_size; unsigned int i_rate, i_frame_length, i_header_size;
int i_input_rate;
}; };
enum { enum {
...@@ -146,6 +149,7 @@ static int OpenPacketizer( vlc_object_t *p_this ) ...@@ -146,6 +149,7 @@ static int OpenPacketizer( vlc_object_t *p_this )
p_sys->i_state = STATE_NOSYNC; p_sys->i_state = STATE_NOSYNC;
aout_DateSet( &p_sys->end_date, 0 ); aout_DateSet( &p_sys->end_date, 0 );
p_sys->bytestream = block_BytestreamInit( p_dec ); p_sys->bytestream = block_BytestreamInit( p_dec );
p_sys->i_input_rate = INPUT_RATE_DEFAULT;
/* Set output properties */ /* Set output properties */
p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_cat = AUDIO_ES;
...@@ -241,7 +245,7 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -241,7 +245,7 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date ); p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
p_block->i_length = aout_DateIncrement( &p_sys->end_date, p_block->i_length = aout_DateIncrement( &p_sys->end_date,
p_dec->fmt_out.audio.i_frame_length ) - p_block->i_pts; p_dec->fmt_out.audio.i_frame_length * p_sys->i_input_rate / INPUT_RATE_DEFAULT ) - p_block->i_pts;
return p_block; return p_block;
} }
...@@ -277,6 +281,9 @@ static block_t *ADTSPacketizeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -277,6 +281,9 @@ static block_t *ADTSPacketizeBlock( decoder_t *p_dec, block_t **pp_block )
return NULL; return NULL;
} }
if( (*pp_block)->i_rate > 0 )
p_sys->i_input_rate = (*pp_block)->i_rate;
block_BytestreamPush( &p_sys->bytestream, *pp_block ); block_BytestreamPush( &p_sys->bytestream, *pp_block );
while( 1 ) while( 1 )
...@@ -443,7 +450,8 @@ static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer ) ...@@ -443,7 +450,8 @@ static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date ); p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
p_block->i_length = aout_DateIncrement( &p_sys->end_date, p_block->i_length = aout_DateIncrement( &p_sys->end_date,
p_sys->i_frame_length ) - p_block->i_pts; p_sys->i_frame_length * p_sys->i_input_rate / INPUT_RATE_DEFAULT ) -
p_block->i_pts;
*pp_out_buffer = p_block; *pp_out_buffer = p_block;
return p_block->p_buffer; return p_block->p_buffer;
......
...@@ -79,7 +79,7 @@ ...@@ -79,7 +79,7 @@
int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input ); int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input );
int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input ); int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input );
int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
aout_buffer_t * p_buffer ); aout_buffer_t * p_buffer, int i_input_rate );
/* From filters.c : */ /* From filters.c : */
int aout_FiltersCreatePipeline ( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int * pi_nb_filters, const audio_sample_format_t * p_input_format, const audio_sample_format_t * p_output_format ); int aout_FiltersCreatePipeline ( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int * pi_nb_filters, const audio_sample_format_t * p_input_format, const audio_sample_format_t * p_output_format );
...@@ -129,5 +129,5 @@ aout_input_t * __aout_DecNew( vlc_object_t *, aout_instance_t **, audio_sample_f ...@@ -129,5 +129,5 @@ aout_input_t * __aout_DecNew( vlc_object_t *, aout_instance_t **, audio_sample_f
int aout_DecDelete ( aout_instance_t *, aout_input_t * ); int aout_DecDelete ( aout_instance_t *, aout_input_t * );
aout_buffer_t * aout_DecNewBuffer( aout_instance_t *, aout_input_t *, size_t ); aout_buffer_t * aout_DecNewBuffer( aout_instance_t *, aout_input_t *, size_t );
void aout_DecDeleteBuffer( aout_instance_t *, aout_input_t *, aout_buffer_t * ); void aout_DecDeleteBuffer( aout_instance_t *, aout_input_t *, aout_buffer_t * );
int aout_DecPlay( aout_instance_t *, aout_input_t *, aout_buffer_t * ); int aout_DecPlay( aout_instance_t *, aout_input_t *, aout_buffer_t *, int i_input_rate );
...@@ -310,7 +310,7 @@ void aout_DecDeleteBuffer( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -310,7 +310,7 @@ void aout_DecDeleteBuffer( aout_instance_t * p_aout, aout_input_t * p_input,
* aout_DecPlay : filter & mix the decoded buffer * aout_DecPlay : filter & mix the decoded buffer
*****************************************************************************/ *****************************************************************************/
int aout_DecPlay( aout_instance_t * p_aout, aout_input_t * p_input, int aout_DecPlay( aout_instance_t * p_aout, aout_input_t * p_input,
aout_buffer_t * p_buffer ) aout_buffer_t * p_buffer, int i_input_rate )
{ {
if ( p_buffer->start_date == 0 ) if ( p_buffer->start_date == 0 )
{ {
...@@ -319,6 +319,13 @@ int aout_DecPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -319,6 +319,13 @@ int aout_DecPlay( aout_instance_t * p_aout, aout_input_t * p_input,
return -1; return -1;
} }
if( i_input_rate > INPUT_RATE_DEFAULT * AOUT_MAX_INPUT_RATE ||
i_input_rate < INPUT_RATE_DEFAULT / AOUT_MAX_INPUT_RATE )
{
aout_BufferFree( p_buffer );
return 0;
}
/* Apply the desynchronisation requested by the user */ /* Apply the desynchronisation requested by the user */
p_buffer->start_date += p_input->i_desync; p_buffer->start_date += p_input->i_desync;
p_buffer->end_date += p_input->i_desync; p_buffer->end_date += p_input->i_desync;
...@@ -375,7 +382,7 @@ int aout_DecPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -375,7 +382,7 @@ int aout_DecPlay( aout_instance_t * p_aout, aout_input_t * p_input,
/* If the buffer is too early, wait a while. */ /* If the buffer is too early, wait a while. */
mwait( p_buffer->start_date - AOUT_MAX_PREPARE_TIME ); mwait( p_buffer->start_date - AOUT_MAX_PREPARE_TIME );
if ( aout_InputPlay( p_aout, p_input, p_buffer ) == -1 ) if ( aout_InputPlay( p_aout, p_input, p_buffer, i_input_rate ) == -1 )
{ {
vlc_mutex_unlock( &p_input->lock ); vlc_mutex_unlock( &p_input->lock );
return -1; return -1;
......
...@@ -293,10 +293,10 @@ void aout_FiltersHintBuffers( aout_instance_t * p_aout, ...@@ -293,10 +293,10 @@ void aout_FiltersHintBuffers( aout_instance_t * p_aout,
aout_filter_t * p_filter = pp_filters[i]; aout_filter_t * p_filter = pp_filters[i];
int i_output_size = p_filter->output.i_bytes_per_frame int i_output_size = p_filter->output.i_bytes_per_frame
* p_filter->output.i_rate * p_filter->output.i_rate * AOUT_MAX_INPUT_RATE
/ p_filter->output.i_frame_length; / p_filter->output.i_frame_length;
int i_input_size = p_filter->input.i_bytes_per_frame int i_input_size = p_filter->input.i_bytes_per_frame
* p_filter->input.i_rate * p_filter->input.i_rate * AOUT_MAX_INPUT_RATE
/ p_filter->input.i_frame_length; / p_filter->input.i_frame_length;
p_first_alloc->i_bytes_per_sec = __MAX( p_first_alloc->i_bytes_per_sec, p_first_alloc->i_bytes_per_sec = __MAX( p_first_alloc->i_bytes_per_sec,
...@@ -357,6 +357,9 @@ void aout_FiltersPlay( aout_instance_t * p_aout, ...@@ -357,6 +357,9 @@ void aout_FiltersPlay( aout_instance_t * p_aout,
aout_BufferFree( *pp_input_buffer ); aout_BufferFree( *pp_input_buffer );
*pp_input_buffer = p_output_buffer; *pp_input_buffer = p_output_buffer;
} }
if( p_output_buffer->i_nb_samples <= 0 )
break;
} }
} }
...@@ -44,7 +44,9 @@ ...@@ -44,7 +44,9 @@
#include "input/input_internal.h" #include "input/input_internal.h"
static void inputFailure( aout_instance_t *, aout_input_t *, const char * ); static void inputFailure( aout_instance_t *, aout_input_t *, const char * );
static void inputDrop( aout_instance_t *, aout_input_t * ); static void inputDrop( aout_instance_t *, aout_input_t *, aout_buffer_t * );
static void inputResamplingStop( aout_input_t *p_input );
static int VisualizationCallback( vlc_object_t *, char const *, static int VisualizationCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * ); vlc_value_t, vlc_value_t, void * );
static int EqualizerCallback( vlc_object_t *, char const *, static int EqualizerCallback( vlc_object_t *, char const *,
...@@ -364,10 +366,10 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input ) ...@@ -364,10 +366,10 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input )
(int)(p_input->input.i_bytes_per_frame (int)(p_input->input.i_bytes_per_frame
* p_input->input.i_rate * p_input->input.i_rate
/ p_input->input.i_frame_length) ); / p_input->input.i_frame_length) );
/* Success */ /* Success */
p_input->b_error = VLC_FALSE; p_input->b_error = VLC_FALSE;
p_input->b_restart = VLC_FALSE; p_input->b_restart = VLC_FALSE;
p_input->i_last_input_rate = INPUT_RATE_DEFAULT;
return 0; return 0;
} }
...@@ -397,8 +399,10 @@ int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input ) ...@@ -397,8 +399,10 @@ int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input )
***************************************************************************** *****************************************************************************
* This function must be entered with the input lock. * This function must be entered with the input lock.
*****************************************************************************/ *****************************************************************************/
/* XXX Do not activate it !! */
//#define AOUT_PROCESS_BEFORE_CHEKS
int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
aout_buffer_t * p_buffer ) aout_buffer_t * p_buffer, int i_input_rate )
{ {
mtime_t start_date; mtime_t start_date;
...@@ -422,6 +426,38 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -422,6 +426,38 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
vlc_mutex_unlock( &p_aout->mixer_lock ); vlc_mutex_unlock( &p_aout->mixer_lock );
} }
#ifdef AOUT_PROCESS_BEFORE_CHEKS
/* Run pre-filters. */
aout_FiltersPlay( p_aout, p_input->pp_filters, p_input->i_nb_filters,
&p_buffer );
/* Actually run the resampler now. */
if ( p_input->i_nb_resamplers > 0 )
{
const mtime_t i_date = p_buffer->start_date;
aout_FiltersPlay( p_aout, p_input->pp_resamplers,
p_input->i_nb_resamplers,
&p_buffer );
}
if( p_buffer->i_nb_samples <= 0 )
{
aout_BufferFree( p_buffer );
return 0;
}
#endif
/* Handle input rate change by modifying resampler input rate */
if( i_input_rate != p_input->i_last_input_rate )
{
unsigned int * const pi_rate = &p_input->pp_resamplers[0]->input.i_rate;
#define F(r,ir) ( INPUT_RATE_DEFAULT * (r) / (ir) )
const int i_delta = *pi_rate - F(p_input->input.i_rate,p_input->i_last_input_rate);
*pi_rate = F(p_input->input.i_rate + i_delta, i_input_rate);
#undef F
p_input->i_last_input_rate = i_input_rate;
}
/* We don't care if someone changes the start date behind our back after /* We don't care if someone changes the start date behind our back after
* this. We'll deal with that when pushing the buffer, and compensate * this. We'll deal with that when pushing the buffer, and compensate
* with the next incoming buffer. */ * with the next incoming buffer. */
...@@ -442,14 +478,8 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -442,14 +478,8 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
vlc_mutex_unlock( &p_aout->input_fifos_lock ); vlc_mutex_unlock( &p_aout->input_fifos_lock );
if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE ) if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE )
msg_Warn( p_aout, "timing screwed, stopping resampling" ); msg_Warn( p_aout, "timing screwed, stopping resampling" );
p_input->i_resampling_type = AOUT_RESAMPLING_NONE; inputResamplingStop( p_input );
if ( p_input->i_nb_resamplers != 0 )
{
p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate;
p_input->pp_resamplers[0]->b_continuity = VLC_FALSE;
}
start_date = 0; start_date = 0;
inputDrop( p_aout, p_input );
} }
if ( p_buffer->start_date < mdate() + AOUT_MIN_PREPARE_TIME ) if ( p_buffer->start_date < mdate() + AOUT_MIN_PREPARE_TIME )
...@@ -459,14 +489,8 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -459,14 +489,8 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
msg_Warn( p_aout, "PTS is out of range ("I64Fd"), dropping buffer", msg_Warn( p_aout, "PTS is out of range ("I64Fd"), dropping buffer",
mdate() - p_buffer->start_date ); mdate() - p_buffer->start_date );
inputDrop( p_aout, p_input ); inputDrop( p_aout, p_input, p_buffer );
aout_BufferFree( p_buffer ); inputResamplingStop( p_input );
p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
if ( p_input->i_nb_resamplers != 0 )
{
p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate;
p_input->pp_resamplers[0]->b_continuity = VLC_FALSE;
}
return 0; return 0;
} }
...@@ -483,12 +507,7 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -483,12 +507,7 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
vlc_mutex_unlock( &p_aout->input_fifos_lock ); vlc_mutex_unlock( &p_aout->input_fifos_lock );
if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE ) if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE )
msg_Warn( p_aout, "timing screwed, stopping resampling" ); msg_Warn( p_aout, "timing screwed, stopping resampling" );
p_input->i_resampling_type = AOUT_RESAMPLING_NONE; inputResamplingStop( p_input );
if ( p_input->i_nb_resamplers != 0 )
{
p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate;
p_input->pp_resamplers[0]->b_continuity = VLC_FALSE;
}
start_date = 0; start_date = 0;
} }
else if ( start_date != 0 && else if ( start_date != 0 &&
...@@ -496,17 +515,17 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -496,17 +515,17 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
{ {
msg_Warn( p_aout, "audio drift is too big ("I64Fd"), dropping buffer", msg_Warn( p_aout, "audio drift is too big ("I64Fd"), dropping buffer",
start_date - p_buffer->start_date ); start_date - p_buffer->start_date );
aout_BufferFree( p_buffer ); inputDrop( p_aout, p_input, p_buffer );
inputDrop( p_aout, p_input );
return 0; return 0;
} }
if ( start_date == 0 ) start_date = p_buffer->start_date; if ( start_date == 0 ) start_date = p_buffer->start_date;
#ifndef AOUT_PROCESS_BEFORE_CHEKS
/* Run pre-filters. */ /* Run pre-filters. */
aout_FiltersPlay( p_aout, p_input->pp_filters, p_input->i_nb_filters, aout_FiltersPlay( p_aout, p_input->pp_filters, p_input->i_nb_filters,
&p_buffer ); &p_buffer );
#endif
/* Run the resampler if needed. /* Run the resampler if needed.
* We first need to calculate the output rate of this resampler. */ * We first need to calculate the output rate of this resampler. */
...@@ -555,8 +574,7 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -555,8 +574,7 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
/* Check if everything is back to normal, in which case we can stop the /* Check if everything is back to normal, in which case we can stop the
* resampling */ * resampling */
if( p_input->pp_resamplers[0]->input.i_rate == if( p_input->pp_resamplers[0]->input.i_rate == 1000 * p_input->input.i_rate / i_input_rate )
p_input->input.i_rate )
{ {
p_input->i_resampling_type = AOUT_RESAMPLING_NONE; p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
msg_Warn( p_aout, "resampling stopped after "I64Fi" usec " msg_Warn( p_aout, "resampling stopped after "I64Fi" usec "
...@@ -582,16 +600,11 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -582,16 +600,11 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
/* If the drift is increasing and not decreasing, than something /* If the drift is increasing and not decreasing, than something
* is bad. We'd better stop the resampling right now. */ * is bad. We'd better stop the resampling right now. */
msg_Warn( p_aout, "timing screwed, stopping resampling" ); msg_Warn( p_aout, "timing screwed, stopping resampling" );
p_input->i_resampling_type = AOUT_RESAMPLING_NONE; inputResamplingStop( p_input );
p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate;
} }
} }
/* Adding the start date will be managed by aout_FifoPush(). */ #ifndef AOUT_PROCESS_BEFORE_CHEKS
p_buffer->end_date = start_date +
(p_buffer->end_date - p_buffer->start_date);
p_buffer->start_date = start_date;
/* Actually run the resampler now. */ /* Actually run the resampler now. */
if ( p_input->i_nb_resamplers > 0 ) if ( p_input->i_nb_resamplers > 0 )
{ {
...@@ -600,10 +613,21 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -600,10 +613,21 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
&p_buffer ); &p_buffer );
} }
if( p_buffer->i_nb_samples <= 0 )
{
aout_BufferFree( p_buffer );
return 0;
}
#endif
/* Adding the start date will be managed by aout_FifoPush(). */
p_buffer->end_date = start_date +
(p_buffer->end_date - p_buffer->start_date);
p_buffer->start_date = start_date;
vlc_mutex_lock( &p_aout->input_fifos_lock ); vlc_mutex_lock( &p_aout->input_fifos_lock );
aout_FifoPush( p_aout, &p_input->fifo, p_buffer ); aout_FifoPush( p_aout, &p_input->fifo, p_buffer );
vlc_mutex_unlock( &p_aout->input_fifos_lock ); vlc_mutex_unlock( &p_aout->input_fifos_lock );
return 0; return 0;
} }
...@@ -632,8 +656,10 @@ static void inputFailure( aout_instance_t * p_aout, aout_input_t * p_input, ...@@ -632,8 +656,10 @@ static void inputFailure( aout_instance_t * p_aout, aout_input_t * p_input,
p_input->b_error = 1; p_input->b_error = 1;
} }
static void inputDrop( aout_instance_t *p_aout, aout_input_t *p_input ) static void inputDrop( aout_instance_t *p_aout, aout_input_t *p_input, aout_buffer_t *p_buffer )
{ {
aout_BufferFree( p_buffer );
if( !p_input->p_input_thread ) if( !p_input->p_input_thread )
return; return;
...@@ -642,6 +668,17 @@ static void inputDrop( aout_instance_t *p_aout, aout_input_t *p_input ) ...@@ -642,6 +668,17 @@ static void inputDrop( aout_instance_t *p_aout, aout_input_t *p_input )
vlc_mutex_unlock( &p_input->p_input_thread->p->counters.counters_lock); vlc_mutex_unlock( &p_input->p_input_thread->p->counters.counters_lock);
} }
static void inputResamplingStop( aout_input_t *p_input )
{
p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
if( p_input->i_nb_resamplers != 0 )
{
p_input->pp_resamplers[0]->input.i_rate = INPUT_RATE_DEFAULT *
p_input->input.i_rate / p_input->i_last_input_rate;
p_input->pp_resamplers[0]->b_continuity = VLC_FALSE;
}
}
static int ChangeFiltersString( aout_instance_t * p_aout, const char* psz_variable, static int ChangeFiltersString( aout_instance_t * p_aout, const char* psz_variable,
const char *psz_name, vlc_bool_t b_add ) const char *psz_name, vlc_bool_t b_add )
{ {
......
...@@ -468,6 +468,7 @@ static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p ) ...@@ -468,6 +468,7 @@ static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p )
static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block ) static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
{ {
input_thread_t *p_input = p_dec->p_owner->p_input; input_thread_t *p_input = p_dec->p_owner->p_input;
const int i_rate = p_block->i_rate;
aout_buffer_t *p_aout_buf; aout_buffer_t *p_aout_buf;
while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) ) while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
...@@ -491,7 +492,7 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block ) ...@@ -491,7 +492,7 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
} }
aout_DecPlay( p_dec->p_owner->p_aout, aout_DecPlay( p_dec->p_owner->p_aout,
p_dec->p_owner->p_aout_input, p_dec->p_owner->p_aout_input,
p_aout_buf ); p_aout_buf, i_rate );
} }
} }
static void VoutDisplayedPicture( vout_thread_t *p_vout, picture_t *p_pic ) static void VoutDisplayedPicture( vout_thread_t *p_vout, picture_t *p_pic )
...@@ -523,7 +524,8 @@ static void VoutFlushPicture( vout_thread_t *p_vout ) ...@@ -523,7 +524,8 @@ static void VoutFlushPicture( vout_thread_t *p_vout )
{ {
picture_t *p_pic = p_vout->render.pp_picture[i]; picture_t *p_pic = p_vout->render.pp_picture[i];
if( p_pic->i_status != READY_PICTURE ) if( p_pic->i_status == READY_PICTURE ||
p_pic->i_status == DISPLAYED_PICTURE )
{ {
/* We cannot change picture status if it is in READY_PICTURE state, /* We cannot change picture status if it is in READY_PICTURE state,
* Just make sure they won't be displayed */ * Just make sure they won't be displayed */
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <vlc_input.h> #include <vlc_input.h>
#include <vlc_es_out.h> #include <vlc_es_out.h>
#include <vlc_block.h> #include <vlc_block.h>
#include <vlc_aout.h>
#include "input_internal.h" #include "input_internal.h"
...@@ -1216,7 +1217,6 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block ) ...@@ -1216,7 +1217,6 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
es->i_preroll_end = -1; es->i_preroll_end = -1;
} }
/* +11 -> avoid null value with non null dts/pts */
if( p_block->i_dts > 0 && (p_block->i_flags&BLOCK_FLAG_PREROLL) ) if( p_block->i_dts > 0 && (p_block->i_flags&BLOCK_FLAG_PREROLL) )
{ {
p_block->i_dts += i_delay; p_block->i_dts += i_delay;
...@@ -1252,8 +1252,10 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block ) ...@@ -1252,8 +1252,10 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
p_block->i_rate = p_input->p->i_rate; p_block->i_rate = p_input->p->i_rate;
/* TODO handle mute */ /* TODO handle mute */
if( es->p_dec && ( es->fmt.i_cat != AUDIO_ES || if( es->p_dec &&
p_input->p->i_rate == INPUT_RATE_DEFAULT ) ) ( es->fmt.i_cat != AUDIO_ES ||
( p_input->p->i_rate >= INPUT_RATE_DEFAULT/AOUT_MAX_INPUT_RATE &&
p_input->p->i_rate <= INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE ) ) )
{ {
input_DecoderDecode( es->p_dec, p_block ); input_DecoderDecode( es->p_dec, p_block );
} }
...@@ -1511,7 +1513,6 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args ) ...@@ -1511,7 +1513,6 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
i_pcr = (int64_t)va_arg( args, int64_t ); i_pcr = (int64_t)va_arg( args, int64_t );
/* search program */ /* search program */
/* 11 is a vodoo trick to avoid non_pcr*9/100 to be null */
input_ClockSetPCR( p_sys->p_input, &p_pgrm->clock, i_pcr ); input_ClockSetPCR( p_sys->p_input, &p_pgrm->clock, i_pcr );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
...@@ -1670,9 +1670,8 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type, ...@@ -1670,9 +1670,8 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type,
val.i_int = i_rate; val.i_int = i_rate;
var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL ); var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
/* We will not send audio data if new rate != default */ input_EsOutDiscontinuity( p_input->p->p_es_out,
if( i_rate != INPUT_RATE_DEFAULT && p_input->p->i_rate == INPUT_RATE_DEFAULT ) VLC_FALSE, VLC_FALSE );
input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_FALSE, VLC_TRUE );
p_input->p->i_rate = i_rate; p_input->p->i_rate = i_rate;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment