Skip to content

Commit ffb51fa

Browse files
committed
pulse: make tlength parameter configurable, reduce fragsize
PipeWire audio agent synchronizes to pacat-simple-vchan rate of taking data out of vchan and wants to ensure it never ends empty. Pulseaudio and PipeWire seems to handle them differently (looks like Pulseaudio is less accurate in this regard). With PipeWire in dom0, it is closer to what is configured, and theoretically could lead to underruns. Make it configurable (beyond just disabling low latency mode), so it's easier to mitigate issues. Note also that PA_STREAM_ADJUST_LATENCY is enabled, so the tlength avalue includes hardware buffer size, which may differ from system to system. And also, tlength affects default prebuf value. While at it, reduce fragsize for recording. Pulseaudio agent (used in older distributions, and in a stubdomain) uses vchan of 2048 bytes, so record stream chunked into 4096 doesn't fit. It works only because pacat-simple-vchan uses blocking vchan writes, but that may negatively impact parallel playback stream. And also, smaller fargsize may reduce latency (although it was good enough already). QubesOS/qubes-issues#8955
1 parent 68a5dba commit ffb51fa

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

pulse/pacat-simple-vchan.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ static pa_sample_spec sample_spec = {
8181
.rate = 44100,
8282
.channels = 2
8383
};
84-
static const pa_buffer_attr custom_bufattr ={
84+
static pa_buffer_attr custom_bufattr ={
8585
.maxlength = (uint32_t)-1,
8686
.minreq = (uint32_t)-1,
8787
.prebuf = (uint32_t)-1,
88-
.fragsize = 4096,
88+
.fragsize = 2048,
8989
.tlength = 4096
9090
};
9191
const pa_buffer_attr * bufattr = NULL;
@@ -1032,12 +1032,14 @@ static void vchan_rec_async_connect(pa_mainloop_api *UNUSED(a),
10321032

10331033
static _Noreturn void usage(char *arg0, int arg) {
10341034
FILE *stream = arg ? stderr : stdout;
1035-
fprintf(stream, "usage: %s [-l] [--] domid domname\n",
1035+
fprintf(stream, "usage: %s [options] [--] domid domname\n",
10361036
arg0 ? arg0 : "pacat-simple-vchan");
10371037
fprintf(stream, " -l - low-latency mode (higher CPU usage)\n");
10381038
fprintf(stream, " -n - never block on vchan I/O (overrides previous -b option)\n");
10391039
fprintf(stream, " -b - always block on vchan I/O (default, overrides previous -n option)\n");
10401040
fprintf(stream, " -v - verbose logging (a lot of output, may affect performance)\n");
1041+
fprintf(stream, " -t size - target playback buffer fill, implies -l, default %d\n",
1042+
custom_bufattr.tlength);
10411043
fprintf(stream, " -h - print this message\n");
10421044
if (fflush(NULL) || ferror(stdout) || ferror(stderr))
10431045
exit(1);
@@ -1055,11 +1057,12 @@ int main(int argc, char *argv[])
10551057
int pidfile_fd;
10561058
int play_watch_fd, rec_watch_fd;
10571059
int i;
1060+
char *endptr;
10581061

10591062
memset(&u, 0, sizeof(u));
10601063
if (argc <= 2)
10611064
usage(argv[0], 1);
1062-
while ((i = getopt(argc, argv, "+lnbvh")) != -1) {
1065+
while ((i = getopt(argc, argv, "+lnbvt:h")) != -1) {
10631066
switch (i) {
10641067
case 'l':
10651068
bufattr = &custom_bufattr;
@@ -1073,6 +1076,13 @@ int main(int argc, char *argv[])
10731076
case 'v':
10741077
verbose += 1;
10751078
break;
1079+
case 't':
1080+
bufattr = &custom_bufattr;
1081+
errno = 0;
1082+
custom_bufattr.tlength = strtoul(optarg, &endptr, 0);
1083+
if (*endptr || errno == ERANGE)
1084+
err(1, "Invalid -t argument: %s", optarg);
1085+
break;
10761086
case 'h':
10771087
usage(argv[0], 0);
10781088
default:
@@ -1082,7 +1092,6 @@ int main(int argc, char *argv[])
10821092
if (argc - optind != 2)
10831093
usage(argv[0], 1);
10841094
const char *domid_str = argv[optind], *domname = argv[optind + 1];
1085-
char *endptr;
10861095
errno = 0;
10871096
long l_domid = strtol(domid_str, &endptr, 10);
10881097
/* 0x7FF0 is DOMID_FIRST_RESERVED */

0 commit comments

Comments
 (0)