mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-31 22:25:33 -04:00
loopback: Track and use average adjust time
The configured adjust time does not match exactly the real adjust time. Also the adjust time varies. To improve latency estimation use an average of the measured adjust times instead of the configured value in all calculations.
This commit is contained in:
parent
2f54296046
commit
4f1041c271
1 changed files with 32 additions and 4 deletions
|
|
@ -83,6 +83,12 @@ struct userdata {
|
||||||
|
|
||||||
pa_time_event *time_event;
|
pa_time_event *time_event;
|
||||||
|
|
||||||
|
/* Variables used to calculate the average time between
|
||||||
|
* subsequent calls of adjust_rates() */
|
||||||
|
pa_usec_t adjust_time_stamp;
|
||||||
|
pa_usec_t real_adjust_time;
|
||||||
|
pa_usec_t real_adjust_time_sum;
|
||||||
|
|
||||||
/* Values from command line configuration */
|
/* Values from command line configuration */
|
||||||
pa_usec_t latency;
|
pa_usec_t latency;
|
||||||
pa_usec_t adjust_time;
|
pa_usec_t adjust_time;
|
||||||
|
|
@ -104,8 +110,10 @@ struct userdata {
|
||||||
/* Various counters */
|
/* Various counters */
|
||||||
uint32_t iteration_counter;
|
uint32_t iteration_counter;
|
||||||
uint32_t underrun_counter;
|
uint32_t underrun_counter;
|
||||||
|
uint32_t adjust_counter;
|
||||||
|
|
||||||
bool fixed_alsa_source;
|
bool fixed_alsa_source;
|
||||||
|
bool source_sink_changed;
|
||||||
|
|
||||||
/* Used for sink input and source output snapshots */
|
/* Used for sink input and source output snapshots */
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -307,14 +315,14 @@ static void adjust_rates(struct userdata *u) {
|
||||||
int32_t latency_difference;
|
int32_t latency_difference;
|
||||||
pa_usec_t current_buffer_latency, snapshot_delay;
|
pa_usec_t current_buffer_latency, snapshot_delay;
|
||||||
int64_t current_source_sink_latency, current_latency, latency_at_optimum_rate;
|
int64_t current_source_sink_latency, current_latency, latency_at_optimum_rate;
|
||||||
pa_usec_t final_latency;
|
pa_usec_t final_latency, now;
|
||||||
|
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
pa_assert_ctl_context();
|
pa_assert_ctl_context();
|
||||||
|
|
||||||
/* Runtime and counters since last change of source or sink
|
/* Runtime and counters since last change of source or sink
|
||||||
* or source/sink latency */
|
* or source/sink latency */
|
||||||
run_hours = u->iteration_counter * u->adjust_time / PA_USEC_PER_SEC / 3600;
|
run_hours = u->iteration_counter * u->real_adjust_time / PA_USEC_PER_SEC / 3600;
|
||||||
u->iteration_counter +=1;
|
u->iteration_counter +=1;
|
||||||
|
|
||||||
/* If we are seeing underruns then the latency is too small */
|
/* If we are seeing underruns then the latency is too small */
|
||||||
|
|
@ -327,11 +335,20 @@ static void adjust_rates(struct userdata *u) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allow one underrun per hour */
|
/* Allow one underrun per hour */
|
||||||
if (u->iteration_counter * u->adjust_time / PA_USEC_PER_SEC / 3600 > run_hours) {
|
if (u->iteration_counter * u->real_adjust_time / PA_USEC_PER_SEC / 3600 > run_hours) {
|
||||||
u->underrun_counter = PA_CLIP_SUB(u->underrun_counter, 1u);
|
u->underrun_counter = PA_CLIP_SUB(u->underrun_counter, 1u);
|
||||||
pa_log_info("Underrun counter: %u", u->underrun_counter);
|
pa_log_info("Underrun counter: %u", u->underrun_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate real adjust time */
|
||||||
|
now = pa_rtclock_now();
|
||||||
|
if (!u->source_sink_changed) {
|
||||||
|
u->adjust_counter++;
|
||||||
|
u->real_adjust_time_sum += now - u->adjust_time_stamp;
|
||||||
|
u->real_adjust_time = u->real_adjust_time_sum / u->adjust_counter;
|
||||||
|
}
|
||||||
|
u->adjust_time_stamp = now;
|
||||||
|
|
||||||
/* Rates and latencies*/
|
/* Rates and latencies*/
|
||||||
old_rate = u->sink_input->sample_spec.rate;
|
old_rate = u->sink_input->sample_spec.rate;
|
||||||
base_rate = u->source_output->sample_spec.rate;
|
base_rate = u->source_output->sample_spec.rate;
|
||||||
|
|
@ -364,7 +381,9 @@ static void adjust_rates(struct userdata *u) {
|
||||||
pa_log_debug("Loopback latency at base rate is %0.2f ms", (double)latency_at_optimum_rate / PA_USEC_PER_MSEC);
|
pa_log_debug("Loopback latency at base rate is %0.2f ms", (double)latency_at_optimum_rate / PA_USEC_PER_MSEC);
|
||||||
|
|
||||||
/* Calculate new rate */
|
/* Calculate new rate */
|
||||||
new_rate = rate_controller(base_rate, u->adjust_time, latency_difference);
|
new_rate = rate_controller(base_rate, u->real_adjust_time, latency_difference);
|
||||||
|
|
||||||
|
u->source_sink_changed = false;
|
||||||
|
|
||||||
/* Set rate */
|
/* Set rate */
|
||||||
pa_sink_input_set_rate(u->sink_input, new_rate);
|
pa_sink_input_set_rate(u->sink_input, new_rate);
|
||||||
|
|
@ -695,6 +714,8 @@ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
|
||||||
u->iteration_counter = 0;
|
u->iteration_counter = 0;
|
||||||
u->underrun_counter = 0;
|
u->underrun_counter = 0;
|
||||||
|
|
||||||
|
u->source_sink_changed = true;
|
||||||
|
|
||||||
/* Send a mesage to the output thread that the source has changed.
|
/* Send a mesage to the output thread that the source has changed.
|
||||||
* If the sink is invalid here during a profile switching situation
|
* If the sink is invalid here during a profile switching situation
|
||||||
* we can safely set push_called to false directly. */
|
* we can safely set push_called to false directly. */
|
||||||
|
|
@ -1077,6 +1098,8 @@ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
|
||||||
u->iteration_counter = 0;
|
u->iteration_counter = 0;
|
||||||
u->underrun_counter = 0;
|
u->underrun_counter = 0;
|
||||||
|
|
||||||
|
u->source_sink_changed = true;
|
||||||
|
|
||||||
u->output_thread_info.pop_called = false;
|
u->output_thread_info.pop_called = false;
|
||||||
u->output_thread_info.first_pop_done = false;
|
u->output_thread_info.first_pop_done = false;
|
||||||
|
|
||||||
|
|
@ -1325,6 +1348,9 @@ int pa__init(pa_module *m) {
|
||||||
u->iteration_counter = 0;
|
u->iteration_counter = 0;
|
||||||
u->underrun_counter = 0;
|
u->underrun_counter = 0;
|
||||||
u->underrun_latency_limit = 0;
|
u->underrun_latency_limit = 0;
|
||||||
|
u->source_sink_changed = true;
|
||||||
|
u->real_adjust_time_sum = 0;
|
||||||
|
u->adjust_counter = 0;
|
||||||
|
|
||||||
adjust_time_sec = DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC;
|
adjust_time_sec = DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC;
|
||||||
if (pa_modargs_get_value_u32(ma, "adjust_time", &adjust_time_sec) < 0) {
|
if (pa_modargs_get_value_u32(ma, "adjust_time", &adjust_time_sec) < 0) {
|
||||||
|
|
@ -1337,6 +1363,8 @@ int pa__init(pa_module *m) {
|
||||||
else
|
else
|
||||||
u->adjust_time = DEFAULT_ADJUST_TIME_USEC;
|
u->adjust_time = DEFAULT_ADJUST_TIME_USEC;
|
||||||
|
|
||||||
|
u->real_adjust_time = u->adjust_time;
|
||||||
|
|
||||||
pa_sink_input_new_data_init(&sink_input_data);
|
pa_sink_input_new_data_init(&sink_input_data);
|
||||||
sink_input_data.driver = __FILE__;
|
sink_input_data.driver = __FILE__;
|
||||||
sink_input_data.module = m;
|
sink_input_data.module = m;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue