/* Number of samples in an A/52 frame. */
#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
* rounding errors
*/
/* Did we just change the output format? (expect buffer inconsistencies) */
vlc_bool_t b_changed;
+ /* last rate from input */
+ int i_last_input_rate;
/* internal caching delay from input */
int i_pts_delay;
/* desynchronisation delay request by the user */
/* Calculate worst case for the length of the filter wing */
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)
* __MAX(1.0, 1.0/d_factor) + 10;
p_filter->p_sys->i_buf_size = aout_FormatNbChannels( &p_filter->input ) *
#include <vlc/vlc.h>
#include <vlc_codec.h>
#include <vlc_aout.h>
+#include <vlc_input.h>
#include <vlc_block_helper.h>
#define A52_HEADER_SIZE 7
int i_frame_size, i_bit_rate;
unsigned int i_rate, i_channels, i_channels_conf;
+ int i_input_rate;
};
enum {
aout_DateSet( &p_sys->end_date, 0 );
p_sys->bytestream = block_BytestreamInit( p_dec );
+ p_sys->i_input_rate = INPUT_RATE_DEFAULT;
/* Set output properties */
p_dec->fmt_out.i_cat = AUDIO_ES;
return NULL;
}
+ if( (*pp_block)->i_rate > 0 )
+ p_sys->i_input_rate = (*pp_block)->i_rate;
+
block_BytestreamPush( &p_sys->bytestream, *pp_block );
while( 1 )
if( p_buf == NULL ) return NULL;
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;
}
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_pts;
+ 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;
return p_block;
}
uint32_t pi_channel_positions[MAX_CHANNEL_POSITIONS];
vlc_bool_t b_sbr, b_ps;
+
+ int i_input_rate;
};
static const uint32_t pi_channels_in[MAX_CHANNEL_POSITIONS] =
p_sys->i_buffer = p_sys->i_buffer_size = 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) */
p_dec->b_need_packetized = VLC_TRUE;
return NULL;
}
+ if( p_block->i_rate > 0 )
+ p_sys->i_input_rate = p_block->i_rate;
+
/* Append the block to the temporary buffer */
if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
{
p_out->start_date = aout_DateGet( &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,
frame.samples / frame.channels, frame.channels,
#include <vlc/vlc.h>
#include <vlc_aout.h>
#include <vlc_codec.h>
+#include <vlc_input.h>
/* ffmpeg header */
#ifdef HAVE_FFMPEG_AVCODEC_H
/* */
int i_reject_count;
+
+ int i_input_rate;
};
/*****************************************************************************
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 )
}
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_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 );
#include <vlc/vlc.h>
#include <vlc_codec.h>
#include <vlc_aout.h>
+#include <vlc_input.h>
#include <vlc_block_helper.h>
unsigned int i_layer, i_bit_rate;
vlc_bool_t b_discontinuity;
+
+ int i_input_rate;
};
enum {
aout_DateSet( &p_sys->end_date, 0 );
p_sys->bytestream = block_BytestreamInit( p_dec );
p_sys->b_discontinuity = VLC_FALSE;
+ p_sys->i_input_rate = INPUT_RATE_DEFAULT;
/* Set output properties */
p_dec->fmt_out.i_cat = AUDIO_ES;
return NULL;
}
+ if( (*pp_block)->i_rate > 0 )
+ p_sys->i_input_rate = (*pp_block)->i_rate;
+
block_BytestreamPush( &p_sys->bytestream, *pp_block );
while( 1 )
p_buf->start_date = aout_DateGet( &p_sys->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_sys->b_discontinuity = VLC_FALSE;
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_sys->i_frame_length ) -
- p_block->i_pts;
+ aout_DateIncrement( &p_sys->end_date,
+ p_sys->i_frame_length * p_sys->i_input_rate / INPUT_RATE_DEFAULT ) -
+ p_block->i_pts;
return p_block;
}
audio_date_t end_date;
int i_last_block_size;
+ int i_input_rate;
+
/*
** Channel reordering
*/
p_sys->i_last_block_size = 0;
p_sys->b_packetizer = VLC_FALSE;
p_sys->i_headers = 0;
+ p_sys->i_input_rate = INPUT_RATE_DEFAULT;
/* Take care of vorbis init */
vorbis_info_init( &p_sys->vi );
/* Block to Ogg packet */
oggpacket.packet = (*pp_block)->p_buffer;
oggpacket.bytes = (*pp_block)->i_buffer;
+
+ if( (*pp_block)->i_rate > 0 )
+ p_sys->i_input_rate = (*pp_block)->i_rate;
}
else
{
/* Date management */
p_aout_buffer->start_date = aout_DateGet( &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;
}
else
p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date );
if( p_sys->i_headers >= 3 )
- p_block->i_length = aout_DateIncrement( &p_sys->end_date, i_samples ) -
- p_block->i_pts;
+ p_block->i_length = aout_DateIncrement( &p_sys->end_date,
+ i_samples * p_sys->i_input_rate / INPUT_RATE_DEFAULT ) -
+ p_block->i_pts;
else
p_block->i_length = 0;
#include <vlc_block.h>
#include <vlc_sout.h>
#include <vlc_codecs.h>
+#include <vlc_input.h>
#include "vlc_block_helper.h"
unsigned int i_raw_blocks;
unsigned int i_channels;
unsigned int i_rate, i_frame_length, i_header_size;
+
+ int i_input_rate;
};
enum {
p_sys->i_state = STATE_NOSYNC;
aout_DateSet( &p_sys->end_date, 0 );
p_sys->bytestream = block_BytestreamInit( p_dec );
+ p_sys->i_input_rate = INPUT_RATE_DEFAULT;
/* Set output properties */
p_dec->fmt_out.i_cat = AUDIO_ES;
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_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 NULL;
}
+ if( (*pp_block)->i_rate > 0 )
+ p_sys->i_input_rate = (*pp_block)->i_rate;
+
block_BytestreamPush( &p_sys->bytestream, *pp_block );
while( 1 )
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_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;
return p_block->p_buffer;
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_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 : */
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_DecDelete ( aout_instance_t *, aout_input_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 * );
-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 );
* aout_DecPlay : filter & mix the decoded buffer
*****************************************************************************/
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 )
{
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 */
p_buffer->start_date += p_input->i_desync;
p_buffer->end_date += p_input->i_desync;
/* If the buffer is too early, wait a while. */
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 );
return -1;
aout_filter_t * p_filter = pp_filters[i];
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;
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_first_alloc->i_bytes_per_sec = __MAX( p_first_alloc->i_bytes_per_sec,
aout_BufferFree( *pp_input_buffer );
*pp_input_buffer = p_output_buffer;
}
+
+ if( p_output_buffer->i_nb_samples <= 0 )
+ break;
}
}
#include "input/input_internal.h"
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 *,
vlc_value_t, vlc_value_t, void * );
static int EqualizerCallback( vlc_object_t *, char const *,
(int)(p_input->input.i_bytes_per_frame
* p_input->input.i_rate
/ p_input->input.i_frame_length) );
-
/* Success */
p_input->b_error = VLC_FALSE;
p_input->b_restart = VLC_FALSE;
+ p_input->i_last_input_rate = INPUT_RATE_DEFAULT;
return 0;
}
*****************************************************************************
* 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,
- aout_buffer_t * p_buffer )
+ aout_buffer_t * p_buffer, int i_input_rate )
{
mtime_t start_date;
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
* this. We'll deal with that when pushing the buffer, and compensate
* with the next incoming buffer. */
vlc_mutex_unlock( &p_aout->input_fifos_lock );
if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE )
msg_Warn( p_aout, "timing screwed, stopping resampling" );
- 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;
- }
+ inputResamplingStop( p_input );
start_date = 0;
- inputDrop( p_aout, p_input );
}
if ( p_buffer->start_date < mdate() + AOUT_MIN_PREPARE_TIME )
msg_Warn( p_aout, "PTS is out of range ("I64Fd"), dropping buffer",
mdate() - p_buffer->start_date );
- inputDrop( p_aout, p_input );
- aout_BufferFree( p_buffer );
- 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;
- }
+ inputDrop( p_aout, p_input, p_buffer );
+ inputResamplingStop( p_input );
return 0;
}
vlc_mutex_unlock( &p_aout->input_fifos_lock );
if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE )
msg_Warn( p_aout, "timing screwed, stopping resampling" );
- 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;
- }
+ inputResamplingStop( p_input );
start_date = 0;
}
else if ( start_date != 0 &&
{
msg_Warn( p_aout, "audio drift is too big ("I64Fd"), dropping buffer",
start_date - p_buffer->start_date );
- aout_BufferFree( p_buffer );
- inputDrop( p_aout, p_input );
+ inputDrop( p_aout, p_input, p_buffer );
return 0;
}
if ( start_date == 0 ) start_date = p_buffer->start_date;
+#ifndef AOUT_PROCESS_BEFORE_CHEKS
/* Run pre-filters. */
-
aout_FiltersPlay( p_aout, p_input->pp_filters, p_input->i_nb_filters,
&p_buffer );
+#endif
/* Run the resampler if needed.
* We first need to calculate the output rate of this resampler. */
/* Check if everything is back to normal, in which case we can stop the
* resampling */
- if( p_input->pp_resamplers[0]->input.i_rate ==
- p_input->input.i_rate )
+ if( p_input->pp_resamplers[0]->input.i_rate == 1000 * p_input->input.i_rate / i_input_rate )
{
p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
msg_Warn( p_aout, "resampling stopped after "I64Fi" usec "
/* If the drift is increasing and not decreasing, than something
* is bad. We'd better stop the resampling right now. */
msg_Warn( p_aout, "timing screwed, stopping resampling" );
- p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
- p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate;
+ inputResamplingStop( p_input );
}
}
- /* 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;
-
+#ifndef AOUT_PROCESS_BEFORE_CHEKS
/* Actually run the resampler now. */
if ( p_input->i_nb_resamplers > 0 )
{
&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 );
aout_FifoPush( p_aout, &p_input->fifo, p_buffer );
vlc_mutex_unlock( &p_aout->input_fifos_lock );
-
return 0;
}
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 )
return;
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,
const char *psz_name, vlc_bool_t b_add )
{
static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
{
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;
while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
}
aout_DecPlay( p_dec->p_owner->p_aout,
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 )
{
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,
* Just make sure they won't be displayed */
#include <vlc_input.h>
#include <vlc_es_out.h>
#include <vlc_block.h>
+#include <vlc_aout.h>
#include "input_internal.h"
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) )
{
p_block->i_dts += i_delay;
p_block->i_rate = p_input->p->i_rate;
/* TODO handle mute */
- if( es->p_dec && ( es->fmt.i_cat != AUDIO_ES ||
- p_input->p->i_rate == INPUT_RATE_DEFAULT ) )
+ if( es->p_dec &&
+ ( 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 );
}
i_pcr = (int64_t)va_arg( args, int64_t );
/* 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 );
return VLC_SUCCESS;
}
val.i_int = i_rate;
var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
- /* We will not send audio data if new rate != default */
- if( i_rate != INPUT_RATE_DEFAULT && p_input->p->i_rate == INPUT_RATE_DEFAULT )
- input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_FALSE, VLC_TRUE );
+ input_EsOutDiscontinuity( p_input->p->p_es_out,
+ VLC_FALSE, VLC_FALSE );
p_input->p->i_rate = i_rate;