Commit fee75dc7 authored by Max Kellermann's avatar Max Kellermann

{output,mixer}/alsa: use snd_pcm_poll_descriptors_revents()

This call was missing, causing very high CPU usage when the ALSA output plugin was used with dmix. Closes #391
parent ba5c856f
......@@ -3,6 +3,7 @@ ver 0.21.2 (not yet released)
- ffmpeg: require FFmpeg 3.1 or later
- ffmpeg: fix broken sound with certain codecs
* output
- alsa: fix high CPU usage with dmix
- httpd: fix two crash bugs
* mixer
- alsa: fix more rounding errors
......
......@@ -185,6 +185,8 @@ AlsaInputStream::PrepareSockets() noexcept
void
AlsaInputStream::DispatchSockets() noexcept
{
non_block.DispatchSockets(*this, capture_handle);
const std::lock_guard<Mutex> protect(mutex);
auto w = PrepareWriteBuffer();
......
......@@ -49,6 +49,30 @@ AlsaNonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
return std::chrono::steady_clock::duration(-1);
}
void
AlsaNonBlockPcm::DispatchSockets(MultiSocketMonitor &m,
snd_pcm_t *pcm) noexcept
{
int count = snd_pcm_poll_descriptors_count(pcm);
if (count <= 0)
return;
const auto pfds = pfd_buffer.Get(count), end = pfds + count;
auto *i = pfds;
m.ForEachReturnedEvent([&i, end](SocketDescriptor s, unsigned events){
if (i >= end)
return;
i->fd = s.Get();
i->events = i->revents = events;
++i;
});
unsigned short dummy;
snd_pcm_poll_descriptors_revents(pcm, pfds, i - pfds, &dummy);
}
std::chrono::steady_clock::duration
AlsaNonBlockMixer::PrepareSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexcept
{
......@@ -67,3 +91,27 @@ AlsaNonBlockMixer::PrepareSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noe
m.ReplaceSocketList(pfds, count);
return std::chrono::steady_clock::duration(-1);
}
void
AlsaNonBlockMixer::DispatchSockets(MultiSocketMonitor &m,
snd_mixer_t *mixer) noexcept
{
int count = snd_mixer_poll_descriptors_count(mixer);
if (count <= 0)
return;
const auto pfds = pfd_buffer.Get(count), end = pfds + count;
auto *i = pfds;
m.ForEachReturnedEvent([&i, end](SocketDescriptor s, unsigned events){
if (i >= end)
return;
i->fd = s.Get();
i->events = i->revents = events;
++i;
});
unsigned short dummy;
snd_mixer_poll_descriptors_revents(mixer, pfds, i - pfds, &dummy);
}
......@@ -42,6 +42,12 @@ public:
*/
std::chrono::steady_clock::duration PrepareSockets(MultiSocketMonitor &m,
snd_pcm_t *pcm);
/**
* Wrapper for snd_pcm_poll_descriptors_revents(), to be
* called from MultiSocketMonitor::DispatchSockets().
*/
void DispatchSockets(MultiSocketMonitor &m, snd_pcm_t *pcm) noexcept;
};
/**
......@@ -54,6 +60,12 @@ class AlsaNonBlockMixer {
public:
std::chrono::steady_clock::duration PrepareSockets(MultiSocketMonitor &m,
snd_mixer_t *mixer) noexcept;
/**
* Wrapper for snd_mixer_poll_descriptors_revents(), to be
* called from MultiSocketMonitor::DispatchSockets().
*/
void DispatchSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexcept;
};
#endif
......@@ -117,6 +117,8 @@ AlsaMixerMonitor::DispatchSockets() noexcept
{
assert(mixer != nullptr);
non_block.DispatchSockets(*this, mixer);
int err = snd_mixer_handle_events(mixer);
if (err < 0) {
FormatError(alsa_mixer_domain,
......
......@@ -889,6 +889,8 @@ AlsaOutput::PrepareSockets() noexcept
void
AlsaOutput::DispatchSockets() noexcept
try {
non_block.DispatchSockets(*this, pcm);
{
const std::lock_guard<Mutex> lock(mutex);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment