{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
This commit is contained in:
parent
ba5c856f15
commit
fee75dc766
1
NEWS
1
NEWS
|
@ -3,6 +3,7 @@ ver 0.21.2 (not yet released)
|
||||||
- ffmpeg: require FFmpeg 3.1 or later
|
- ffmpeg: require FFmpeg 3.1 or later
|
||||||
- ffmpeg: fix broken sound with certain codecs
|
- ffmpeg: fix broken sound with certain codecs
|
||||||
* output
|
* output
|
||||||
|
- alsa: fix high CPU usage with dmix
|
||||||
- httpd: fix two crash bugs
|
- httpd: fix two crash bugs
|
||||||
* mixer
|
* mixer
|
||||||
- alsa: fix more rounding errors
|
- alsa: fix more rounding errors
|
||||||
|
|
|
@ -185,6 +185,8 @@ AlsaInputStream::PrepareSockets() noexcept
|
||||||
void
|
void
|
||||||
AlsaInputStream::DispatchSockets() noexcept
|
AlsaInputStream::DispatchSockets() noexcept
|
||||||
{
|
{
|
||||||
|
non_block.DispatchSockets(*this, capture_handle);
|
||||||
|
|
||||||
const std::lock_guard<Mutex> protect(mutex);
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
|
|
||||||
auto w = PrepareWriteBuffer();
|
auto w = PrepareWriteBuffer();
|
||||||
|
|
|
@ -49,6 +49,30 @@ AlsaNonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
|
||||||
return std::chrono::steady_clock::duration(-1);
|
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
|
std::chrono::steady_clock::duration
|
||||||
AlsaNonBlockMixer::PrepareSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexcept
|
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);
|
m.ReplaceSocketList(pfds, count);
|
||||||
return std::chrono::steady_clock::duration(-1);
|
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,
|
std::chrono::steady_clock::duration PrepareSockets(MultiSocketMonitor &m,
|
||||||
snd_pcm_t *pcm);
|
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:
|
public:
|
||||||
std::chrono::steady_clock::duration PrepareSockets(MultiSocketMonitor &m,
|
std::chrono::steady_clock::duration PrepareSockets(MultiSocketMonitor &m,
|
||||||
snd_mixer_t *mixer) noexcept;
|
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
|
#endif
|
||||||
|
|
|
@ -117,6 +117,8 @@ AlsaMixerMonitor::DispatchSockets() noexcept
|
||||||
{
|
{
|
||||||
assert(mixer != nullptr);
|
assert(mixer != nullptr);
|
||||||
|
|
||||||
|
non_block.DispatchSockets(*this, mixer);
|
||||||
|
|
||||||
int err = snd_mixer_handle_events(mixer);
|
int err = snd_mixer_handle_events(mixer);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
FormatError(alsa_mixer_domain,
|
FormatError(alsa_mixer_domain,
|
||||||
|
|
|
@ -889,6 +889,8 @@ AlsaOutput::PrepareSockets() noexcept
|
||||||
void
|
void
|
||||||
AlsaOutput::DispatchSockets() noexcept
|
AlsaOutput::DispatchSockets() noexcept
|
||||||
try {
|
try {
|
||||||
|
non_block.DispatchSockets(*this, pcm);
|
||||||
|
|
||||||
{
|
{
|
||||||
const std::lock_guard<Mutex> lock(mutex);
|
const std::lock_guard<Mutex> lock(mutex);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue