mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
tunnel: Fix latency calculations
Currently module-tunnel uses only a rough estimate of the current stream latency and reports wrong latencies in certain situations. This leads to very inexact and unstable latency reports for the virtual sink. This patch fixes the issue by introducing latency snapshots like they are used in module-loopback. Because the latency reports are now correct, the update interval for latency re-calculations can be reduced to 1s. Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/53>
This commit is contained in:
parent
45a5e6f0f1
commit
4c180214c8
1 changed files with 36 additions and 12 deletions
|
|
@ -121,7 +121,7 @@ static const char* const valid_modargs[] = {
|
|||
|
||||
#define DEFAULT_TIMEOUT 5
|
||||
|
||||
#define LATENCY_INTERVAL (10*PA_USEC_PER_SEC)
|
||||
#define LATENCY_INTERVAL (1*PA_USEC_PER_SEC)
|
||||
|
||||
#define MIN_NETWORK_LATENCY_USEC (8*PA_USEC_PER_MSEC)
|
||||
|
||||
|
|
@ -131,6 +131,7 @@ enum {
|
|||
SINK_MESSAGE_REQUEST = PA_SINK_MESSAGE_MAX,
|
||||
SINK_MESSAGE_REMOTE_SUSPEND,
|
||||
SINK_MESSAGE_UPDATE_LATENCY,
|
||||
SINK_MESSAGE_GET_LATENCY_SNAPSHOT,
|
||||
SINK_MESSAGE_POST
|
||||
};
|
||||
|
||||
|
|
@ -142,7 +143,8 @@ enum {
|
|||
enum {
|
||||
SOURCE_MESSAGE_POST = PA_SOURCE_MESSAGE_MAX,
|
||||
SOURCE_MESSAGE_REMOTE_SUSPEND,
|
||||
SOURCE_MESSAGE_UPDATE_LATENCY
|
||||
SOURCE_MESSAGE_UPDATE_LATENCY,
|
||||
SOURCE_MESSAGE_GET_LATENCY_SNAPSHOT
|
||||
};
|
||||
|
||||
#define DEFAULT_FRAGSIZE_MSEC 25
|
||||
|
|
@ -212,7 +214,9 @@ struct userdata {
|
|||
uint32_t device_index;
|
||||
uint32_t channel;
|
||||
|
||||
int64_t counter, counter_delta;
|
||||
int64_t counter;
|
||||
uint64_t receive_counter;
|
||||
uint64_t receive_snapshot;
|
||||
|
||||
bool remote_corked:1;
|
||||
bool remote_suspended:1;
|
||||
|
|
@ -517,6 +521,13 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
|
|||
return 0;
|
||||
}
|
||||
|
||||
case SINK_MESSAGE_GET_LATENCY_SNAPSHOT: {
|
||||
int64_t *send_counter = data;
|
||||
|
||||
*send_counter = u->counter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SINK_MESSAGE_REQUEST:
|
||||
|
||||
pa_assert(offset > 0);
|
||||
|
|
@ -559,7 +570,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
|
|||
|
||||
pa_pstream_send_memblock(u->pstream, u->channel, 0, PA_SEEK_RELATIVE, chunk);
|
||||
|
||||
u->counter_delta += (int64_t) chunk->length;
|
||||
u->receive_counter += chunk->length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -628,6 +639,13 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
|
|||
return 0;
|
||||
}
|
||||
|
||||
case SOURCE_MESSAGE_GET_LATENCY_SNAPSHOT: {
|
||||
int64_t *send_counter = data;
|
||||
|
||||
*send_counter = u->counter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SOURCE_MESSAGE_POST: {
|
||||
pa_memchunk c;
|
||||
|
||||
|
|
@ -779,6 +797,9 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint
|
|||
struct timeval local, remote, now;
|
||||
pa_sample_spec *ss;
|
||||
int64_t delay;
|
||||
#ifdef TUNNEL_SINK
|
||||
uint64_t send_counter;
|
||||
#endif
|
||||
|
||||
pa_assert(pd);
|
||||
pa_assert(u);
|
||||
|
|
@ -826,7 +847,7 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint
|
|||
pa_gettimeofday(&now);
|
||||
|
||||
/* Calculate transport usec */
|
||||
if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) {
|
||||
if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now) < 0) {
|
||||
/* local and remote seem to have synchronized clocks */
|
||||
#ifdef TUNNEL_SINK
|
||||
u->transport_usec = pa_timeval_diff(&remote, &local);
|
||||
|
|
@ -859,11 +880,12 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint
|
|||
delay += (int64_t) u->transport_usec;
|
||||
#endif
|
||||
|
||||
/* Now correct by what we have have read/written since we requested the update */
|
||||
/* Now correct by what we have have written since we requested the update. This
|
||||
* is not necessary for the source, because if data is received between request
|
||||
* and reply, it was already posted before we requested the source latency. */
|
||||
#ifdef TUNNEL_SINK
|
||||
delay += (int64_t) pa_bytes_to_usec((uint64_t) u->counter_delta, ss);
|
||||
#else
|
||||
delay -= (int64_t) pa_bytes_to_usec((uint64_t) u->counter_delta, ss);
|
||||
pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_GET_LATENCY_SNAPSHOT, &send_counter, 0, NULL);
|
||||
delay += (int64_t) pa_bytes_to_usec(send_counter - u->receive_snapshot, ss);
|
||||
#endif
|
||||
|
||||
#ifdef TUNNEL_SINK
|
||||
|
|
@ -901,7 +923,7 @@ static void request_latency(struct userdata *u) {
|
|||
pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u, NULL);
|
||||
|
||||
u->ignore_latency_before = tag;
|
||||
u->counter_delta = 0;
|
||||
u->receive_snapshot = u->receive_counter;
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
|
|
@ -1823,7 +1845,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
|
|||
|
||||
pa_asyncmsgq_send(u->source->asyncmsgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_POST, PA_UINT_TO_PTR(seek), offset, chunk);
|
||||
|
||||
u->counter_delta += (int64_t) chunk->length;
|
||||
u->receive_counter += chunk->length;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1979,7 +2001,9 @@ int pa__init(pa_module*m) {
|
|||
u->ignore_latency_before = 0;
|
||||
u->transport_usec = u->thread_transport_usec = 0;
|
||||
u->remote_suspended = u->remote_corked = false;
|
||||
u->counter = u->counter_delta = 0;
|
||||
u->counter = 0;
|
||||
u->receive_snapshot = 0;
|
||||
u->receive_counter = 0;
|
||||
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue