Commit f74dd10e authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

aout: move actual filtering to filters.c

This leaves only synchronization code in input.c. This patch introduces
a small regression where resampling adjustment have a latency of two
packets instead of currently one. That will be fixed later.
parent dfdc2d1b
...@@ -79,9 +79,10 @@ typedef struct ...@@ -79,9 +79,10 @@ typedef struct
filter_t *rate_filter; /**< The filter adjusting samples count filter_t *rate_filter; /**< The filter adjusting samples count
(either the scaletempo filter or a resampler) */ (either the scaletempo filter or a resampler) */
filter_t *resampler; /**< The resampler */ filter_t *resampler; /**< The resampler */
int resampling; /**< Current resampling (Hz) */
unsigned nb_filters;
filter_t *filters[AOUT_MAX_FILTERS]; /**< Configured user filters filter_t *filters[AOUT_MAX_FILTERS]; /**< Configured user filters
(e.g. equalization) and their conversions */ (e.g. equalization) and their conversions */
unsigned nb_filters;
unsigned nb_converters; unsigned nb_converters;
filter_t *converters[5]; /**< Converters to the output */ filter_t *converters[5]; /**< Converters to the output */
...@@ -123,6 +124,8 @@ block_t *aout_FiltersPipelinePlay(filter_t *const *, unsigned, block_t *); ...@@ -123,6 +124,8 @@ block_t *aout_FiltersPipelinePlay(filter_t *const *, unsigned, block_t *);
int aout_FiltersNew(audio_output_t *, const audio_sample_format_t *, int aout_FiltersNew(audio_output_t *, const audio_sample_format_t *,
const audio_sample_format_t *, const aout_request_vout_t *); const audio_sample_format_t *, const aout_request_vout_t *);
void aout_FiltersDelete(audio_output_t *); void aout_FiltersDelete(audio_output_t *);
bool aout_FiltersAdjustResampling(audio_output_t *, int);
block_t *aout_FiltersPlay(audio_output_t *, block_t *, int rate);
/* From mixer.c : */ /* From mixer.c : */
aout_volume_t *aout_volume_New(vlc_object_t *, const audio_replay_gain_t *); aout_volume_t *aout_volume_New(vlc_object_t *, const audio_replay_gain_t *);
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <vlc_aout.h> #include <vlc_aout.h>
#include <vlc_filter.h> #include <vlc_filter.h>
#include <vlc_vout.h> /* for vout_Request */ #include <vlc_vout.h> /* for vout_Request */
#include <vlc_input.h>
#include <libvlc.h> #include <libvlc.h>
#include "aout_internal.h" #include "aout_internal.h"
...@@ -502,6 +503,7 @@ int aout_FiltersNew (audio_output_t *aout, ...@@ -502,6 +503,7 @@ int aout_FiltersNew (audio_output_t *aout,
owner->resampler->fmt_in.audio.i_rate = rate_bak; owner->resampler->fmt_in.audio.i_rate = rate_bak;
if (owner->rate_filter == NULL) if (owner->rate_filter == NULL)
owner->rate_filter = owner->resampler; owner->rate_filter = owner->resampler;
owner->resampling = 0;
return 0; return 0;
...@@ -534,3 +536,57 @@ void aout_FiltersDelete (audio_output_t *aout) ...@@ -534,3 +536,57 @@ void aout_FiltersDelete (audio_output_t *aout)
owner->recycle_vout = (visual != NULL) && *visual; owner->recycle_vout = (visual != NULL) && *visual;
free (visual); free (visual);
} }
bool aout_FiltersAdjustResampling (audio_output_t *aout, int adjust)
{
aout_owner_t *owner = aout_owner (aout);
if (owner->resampler == NULL)
return false;
if (adjust)
owner->resampling += adjust;
else
owner->resampling = 0;
return !owner->resampling;
}
block_t *aout_FiltersPlay (audio_output_t *aout, block_t *block, int rate)
{
aout_owner_t *owner = aout_owner (aout);
int nominal_rate = 0;
if (rate != INPUT_RATE_DEFAULT)
{
filter_t *rate_filter = owner->rate_filter;
if (rate_filter == NULL)
goto drop; /* Without linear, non-nominal rate is impossible. */
/* Override input rate */
nominal_rate = rate_filter->fmt_in.audio.i_rate;
rate_filter->fmt_in.audio.i_rate =
(nominal_rate * INPUT_RATE_DEFAULT) / rate;
}
block = aout_FiltersPipelinePlay (owner->filters, owner->nb_filters,
block);
if (owner->resampler != NULL)
{ /* NOTE: the resampler needs to run even if resampling is 0.
* The decoder and output rates can still be different. */
owner->resampler->fmt_in.audio.i_rate += owner->resampling;
block = aout_FiltersPipelinePlay (&owner->resampler, 1, block);
owner->resampler->fmt_in.audio.i_rate -= owner->resampling;
}
if (nominal_rate != 0)
{ /* Restore input rate */
assert (owner->rate_filter != NULL);
owner->rate_filter->fmt_in.audio.i_rate = nominal_rate;
}
return block;
drop:
block_Release (block);
return NULL;
}
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include "aout_internal.h" #include "aout_internal.h"
static void inputDrop( aout_input_t *, block_t * ); static void inputDrop( aout_input_t *, block_t * );
static void inputResamplingStop( audio_output_t *, aout_input_t *, int ); static void inputResamplingStop( audio_output_t *, aout_input_t * );
/***************************************************************************** /*****************************************************************************
* aout_InputNew : allocate a new input and rework the filter pipeline * aout_InputNew : allocate a new input and rework the filter pipeline
...@@ -74,27 +74,9 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, ...@@ -74,27 +74,9 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input,
block_t *p_buffer, int i_input_rate, date_t *date ) block_t *p_buffer, int i_input_rate, date_t *date )
{ {
mtime_t start_date; mtime_t start_date;
aout_owner_t *owner = aout_owner(p_aout);
aout_assert_locked( p_aout ); aout_assert_locked( p_aout );
if( i_input_rate != INPUT_RATE_DEFAULT && owner->rate_filter == NULL )
{
inputDrop( p_input, p_buffer );
return NULL;
}
/* Handle input rate change, but keep drift correction */
if( i_input_rate != p_input->i_last_input_rate )
{
unsigned int * const pi_rate = &owner->rate_filter->fmt_in.audio.i_rate;
#define F(r,ir) ( INPUT_RATE_DEFAULT * (r) / (ir) )
const int i_delta = *pi_rate - F(p_input->samplerate,p_input->i_last_input_rate);
*pi_rate = F(p_input->samplerate + i_delta, i_input_rate);
#undef F
p_input->i_last_input_rate = i_input_rate;
}
mtime_t now = mdate(); mtime_t now = mdate();
/* 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
...@@ -112,7 +94,7 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, ...@@ -112,7 +94,7 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input,
aout_OutputFlush( p_aout, false ); aout_OutputFlush( p_aout, false );
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" );
inputResamplingStop( p_aout, p_input, i_input_rate ); inputResamplingStop( p_aout, p_input );
p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY; p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY;
start_date = VLC_TS_INVALID; start_date = VLC_TS_INVALID;
} }
...@@ -124,7 +106,7 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, ...@@ -124,7 +106,7 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input,
msg_Warn( p_aout, "PTS is out of range (%"PRId64"), dropping buffer", msg_Warn( p_aout, "PTS is out of range (%"PRId64"), dropping buffer",
now - p_buffer->i_pts ); now - p_buffer->i_pts );
inputDrop( p_input, p_buffer ); inputDrop( p_input, p_buffer );
inputResamplingStop( p_aout, p_input, i_input_rate ); inputResamplingStop( p_aout, p_input );
return NULL; return NULL;
} }
...@@ -145,7 +127,7 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, ...@@ -145,7 +127,7 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input,
aout_OutputFlush( p_aout, false ); aout_OutputFlush( p_aout, false );
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" );
inputResamplingStop( p_aout, p_input, i_input_rate ); inputResamplingStop( p_aout, p_input );
p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY; p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY;
start_date = p_buffer->i_pts; start_date = p_buffer->i_pts;
date_Set (date, start_date); date_Set (date, start_date);
...@@ -160,17 +142,14 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, ...@@ -160,17 +142,14 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input,
return NULL; return NULL;
} }
/* Run pre-filters. */ p_buffer = aout_FiltersPlay( p_aout, p_buffer, i_input_rate );
p_buffer = aout_FiltersPipelinePlay( owner->filters, owner->nb_filters,
p_buffer );
if( !p_buffer ) if( !p_buffer )
return NULL; return NULL;
/* 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. */
if ( ( p_input->i_resampling_type == AOUT_RESAMPLING_NONE ) && if ( ( p_input->i_resampling_type == AOUT_RESAMPLING_NONE ) &&
( drift < -AOUT_MAX_PTS_ADVANCE || drift > +AOUT_MAX_PTS_DELAY ) && ( drift < -AOUT_MAX_PTS_ADVANCE || drift > +AOUT_MAX_PTS_DELAY ) )
owner->resampler != NULL )
{ {
/* Can happen in several circumstances : /* Can happen in several circumstances :
* 1. A problem at the input (clock drift) * 1. A problem at the input (clock drift)
...@@ -192,19 +171,12 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, ...@@ -192,19 +171,12 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input,
/* Resampling has been triggered previously (because of dates /* Resampling has been triggered previously (because of dates
* mismatch). We want the resampling to happen progressively so * mismatch). We want the resampling to happen progressively so
* it isn't too audible to the listener. */ * it isn't too audible to the listener. */
const int adjust = ( p_input->i_resampling_type == AOUT_RESAMPLING_UP )
if( p_input->i_resampling_type == AOUT_RESAMPLING_UP ) ? +2 : -2;
owner->resampler->fmt_in.audio.i_rate += 2; /* Hz */
else
owner->resampler->fmt_in.audio.i_rate -= 2; /* Hz */
/* 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 */
unsigned int i_nominal_rate = if( !aout_FiltersAdjustResampling( p_aout, adjust ) )
(owner->resampler == owner->rate_filter)
? INPUT_RATE_DEFAULT * p_input->samplerate / i_input_rate
: p_input->samplerate;
if( owner->resampler->fmt_in.audio.i_rate == i_nominal_rate )
{ {
p_input->i_resampling_type = AOUT_RESAMPLING_NONE; p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
msg_Warn( p_aout, "resampling stopped (drift: %"PRIi64")", msg_Warn( p_aout, "resampling stopped (drift: %"PRIi64")",
...@@ -228,23 +200,11 @@ block_t *aout_InputPlay(audio_output_t *p_aout, aout_input_t *p_input, ...@@ -228,23 +200,11 @@ block_t *aout_InputPlay(audio_output_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" );
inputResamplingStop( p_aout, p_input, i_input_rate ); inputResamplingStop( p_aout, p_input );
p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY; p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY;
} }
} }
/* Actually run the resampler now. */
if ( owner->resampler != NULL )
p_buffer = aout_FiltersPipelinePlay( &owner->resampler, 1, p_buffer );
if( !p_buffer )
return NULL;
if( p_buffer->i_nb_samples <= 0 )
{
block_Release( p_buffer );
return NULL;
}
p_buffer->i_pts = start_date; p_buffer->i_pts = start_date;
return p_buffer; return p_buffer;
} }
...@@ -260,17 +220,8 @@ static void inputDrop( aout_input_t *p_input, block_t *p_buffer ) ...@@ -260,17 +220,8 @@ static void inputDrop( aout_input_t *p_input, block_t *p_buffer )
p_input->i_buffer_lost++; p_input->i_buffer_lost++;
} }
static void inputResamplingStop( audio_output_t *p_aout, aout_input_t *p_input, static void inputResamplingStop( audio_output_t *p_aout, aout_input_t *p_input )
int input_rate )
{ {
aout_owner_t *owner = aout_owner(p_aout);
p_input->i_resampling_type = AOUT_RESAMPLING_NONE; p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
if( owner->resampler != NULL ) aout_FiltersAdjustResampling( p_aout, 0 );
{
owner->resampler->fmt_in.audio.i_rate =
( owner->resampler == owner->rate_filter )
? INPUT_RATE_DEFAULT * p_input->samplerate / input_rate
: p_input->samplerate;
}
} }
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