aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2020-03-26 22:50:54 -0700
committerChris Robinson <[email protected]>2020-03-26 22:50:54 -0700
commite73c0979a16ebde1cfa9bda308c9b62b24541a91 (patch)
treed633c0a05d517c9cdee3de7212bb25880647985d
parentd344c5a228711855165d6058da3ae8b54c473f7c (diff)
Use "zero-copy" writes with pulseaudio playback
-rw-r--r--alc/backends/pulseaudio.cpp26
1 files changed, 20 insertions, 6 deletions
diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp
index 1ab04a9c..bd1dd54a 100644
--- a/alc/backends/pulseaudio.cpp
+++ b/alc/backends/pulseaudio.cpp
@@ -158,7 +158,7 @@ PULSE_FUNCS(MAKE_FUNC)
#define pa_stream_get_device_name ppa_stream_get_device_name
#define pa_stream_get_latency ppa_stream_get_latency
#define pa_stream_set_buffer_attr_callback ppa_stream_set_buffer_attr_callback
-#define pa_stream_begin_write ppa_stream_begin_write*/
+#define pa_stream_begin_write ppa_stream_begin_write
#define pa_channel_map_init_auto ppa_channel_map_init_auto
#define pa_channel_map_parse ppa_channel_map_parse
#define pa_channel_map_snprint ppa_channel_map_snprint
@@ -763,12 +763,26 @@ void PulsePlayback::streamStateCallback(pa_stream *stream) noexcept
void PulsePlayback::streamWriteCallback(pa_stream *stream, size_t nbytes) noexcept
{
- void *buf{pa_xmalloc(nbytes)};
- aluMixData(mDevice, buf, static_cast<ALuint>(nbytes/mFrameSize), mSpec.channels);
+ do {
+ pa_free_cb_t free_func{nullptr};
+ auto buflen = static_cast<size_t>(-1);
+ void *buf;
+ if UNLIKELY(pa_stream_begin_write(stream, &buf, &buflen) || !buf)
+ {
+ buflen = nbytes;
+ buf = pa_xmalloc(buflen);
+ free_func = pa_xfree;
+ }
+ else
+ buflen = minz(buflen, nbytes);
+ nbytes -= buflen;
+
+ aluMixData(mDevice, buf, static_cast<ALuint>(buflen/mFrameSize), mSpec.channels);
- int ret{pa_stream_write(stream, buf, nbytes, pa_xfree, 0, PA_SEEK_RELATIVE)};
- if UNLIKELY(ret != PA_OK)
- ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret));
+ int ret{pa_stream_write(stream, buf, buflen, free_func, 0, PA_SEEK_RELATIVE)};
+ if UNLIKELY(ret != PA_OK)
+ ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret));
+ } while(nbytes > 0);
}
void PulsePlayback::sinkInfoCallback(pa_context*, const pa_sink_info *info, int eol) noexcept