[pulseaudio-discuss] [PATCH v6 17/25] loopback: Track and use average adjust time
Tanu Kaskinen
tanuk at iki.fi
Sat Aug 20 12:23:41 UTC 2016
On Sun, 2016-06-05 at 21:05 +0200, Georg Chini wrote:
> > @@ -79,11 +79,18 @@ struct userdata {
>
> pa_time_event *time_event;
>
> + /* Variables used to calculate the average time between
> + * subsequent calls of adjust_rates() */
> + pa_usec_t time_stamp;
"time_stamp" is quite generic name. I'd prefer
"last_adjustment(_time_stamp)" or something like that.
> + pa_usec_t real_adjust_time;
> + pa_usec_t real_adjust_time_sum;
> +
> /* Various counters */
> int64_t recv_counter;
> int64_t send_counter;
> uint32_t iteration_counter;
> uint32_t underrun_counter;
> + uint32_t adjust_counter;
iteration_counter and adjust_counter can be merged to just one
counter.
The counters have two differences. One difference is that
iteration_counter counts all adjust_rate() calls, while adjust_counter
skips the first call. The other difference is that iteration_counter is
reset when streams move or device latency changes, while adjust_counter
is not.
iteration_counter is used for calculating the time since the last reset
(stream move or device latency change), but that calculation ends up
being wrong, because the first adjust_rate() call is done much quicker
than the other calls. If iteration_counter would also skip the first
adjust_rate() call, the calculation would be more correct, although
still wrong, because the short first interval isn't included in the
calculation.
The other difference between the counters is that iteration_counter is
reset when streams move or device latency changes, while adjust_counter
is not reset. However, I don't see any harm in resetting adjust_counter
too.
So, in conclusion, both differences can be removed, and then only one
counter will be needed.
> @@ -232,11 +239,21 @@ static void adjust_rates(struct userdata *u) {
> }
>
> /* Allow one underrun per hour */
> - if (u->iteration_counter * u->adjust_time / PA_USEC_PER_SEC / 3600 > hours) {
> + if (u->iteration_counter * u->real_adjust_time / PA_USEC_PER_SEC / 3600 > hours) {
> pa_log_info("Underrun counter: %u", u->underrun_counter);
> u->underrun_counter = PA_CLIP_SUB(u->underrun_counter, 1u);
> }
>
> + /* Calculate real adjust time */
> + if (u->source_sink_changed)
> + u->time_stamp = pa_rtclock_now();
> + else {
> + u->adjust_counter++;
> + u->real_adjust_time_sum += pa_rtclock_now() - u->time_stamp;
> + u->time_stamp = pa_rtclock_now();
> + u->real_adjust_time = u->real_adjust_time_sum / u->adjust_counter;
> + }
u->time_stamp = pa_rtclock_now() is done in both branches, so it can be
moved out. Also, calling pa_rtclock_now() twice results in some timy
error in the calculations. I'd change this to:
now = pa_rtclock_now()
if (!u->source_sink_changed) {
u->adjust_counter++;
u->real_adjust_time_sum = now - u->time_stamp;
u->real_adjust_time = u->real_adjust_time_sum / u->adjust_counter;
}
u->time_stamp = now;
--
Tanu
More information about the pulseaudio-discuss
mailing list