PulseAudio: cork input when it is not required

When self-muted or deafened, "cork" the audio input. Corking
instructs the audio source to stop producing audio samples which—
when the user is muted—are not needed and would never be
transmitted.

Without samples to process, the input DSP doesn't run. Corking can
halve mumble's CPU consumption when muted, but your mileage may
vary.

This patch adds the MainWindow::corkAudioInputStream() signal to
request changes in the corking state. Other audio backends could
be modified to connect to this signal.
This commit is contained in:
Colin Stagner 2020-03-01 21:47:30 +01:00 committed by Davide Beatrici
parent 5a4f5297a3
commit 7d0b933a7e
6 changed files with 46 additions and 1 deletions

View File

@ -36,6 +36,7 @@ AudioWizard::AudioWizard(QWidget *p) : QWizard(p) {
bInit = true;
bLastActive = false;
g.bInAudioWizard = true;
g.mw->onChangeMute();
ticker = new QTimer(this);
ticker->setObjectName(QLatin1String("Ticker"));
@ -398,6 +399,7 @@ void AudioWizard::reject() {
ao->wipe();
aosSource = NULL;
g.bInAudioWizard = false;
g.mw->onChangeMute();
QWizard::reject();
}
@ -433,6 +435,7 @@ void AudioWizard::accept() {
g.bPosTest = false;
restartAudio();
g.bInAudioWizard = false;
g.mw->onChangeMute();
QWizard::accept();
}

View File

@ -2306,6 +2306,7 @@ void MainWindow::on_qaAudioMute_triggered() {
g.sh->setSelfMuteDeafState(g.s.bMute, g.s.bDeaf);
}
onChangeMute();
updateTrayIcon();
}
@ -2342,6 +2343,7 @@ void MainWindow::on_qaAudioDeaf_triggered() {
g.sh->setSelfMuteDeafState(g.s.bMute, g.s.bDeaf);
}
onChangeMute();
updateTrayIcon();
}
@ -2790,6 +2792,15 @@ void MainWindow::whisperReleased(QVariant scdata) {
updateTarget();
}
void MainWindow::onChangeMute()
{
if (!g.ai) {
return;
}
emit corkAudioInputStream(g.s.bMute && !g.bInAudioWizard);
}
void MainWindow::onResetAudio()
{
qWarning("MainWindow: Start audio reset");
@ -2849,6 +2860,7 @@ void MainWindow::serverConnected() {
if (g.s.bMute || g.s.bDeaf) {
g.sh->setSelfMuteDeafState(g.s.bMute, g.s.bDeaf);
onChangeMute();
}
// Update QActions and menues

View File

@ -269,6 +269,9 @@ class MainWindow : public QMainWindow, public MessageHandler, public Ui::MainWin
void pttReleased();
void whisperReleased(QVariant scdata);
void onResetAudio();
/// Called whenever the self-mute state may have changed. Dispatches
/// corkAudioInputStream() if the desire for audio input has changed.
void onChangeMute();
void showRaiseWindow();
void on_qaFilterToggle_triggered();
/// Opens a save dialog for the image referenced by qtcSaveImageCursor.
@ -279,7 +282,16 @@ class MainWindow : public QMainWindow, public MessageHandler, public Ui::MainWin
/// Updates the user's image directory to the given path (any included
/// filename is discarded).
void updateImagePath(QString filepath) const;
signals:
/// Reports that audio input is now, or is no longer, required.
///
/// Signal allows an \ref AudioInput to suspend the input stream
/// when it is not required.
///
/// @param cork If true, the audio backend MAY now cork/suspend
/// the input stream. If false, the audio backend MUST immediately
/// un-cork/resume the stream.
void corkAudioInputStream(const bool cork);
public:
MainWindow(QWidget *parent);
~MainWindow() Q_DECL_OVERRIDE;

View File

@ -301,6 +301,11 @@ void PulseAudioSystem::eventCallback(pa_mainloop_api *api, pa_defer_event *) {
qsInputCache = idev;
pa_stream_connect_record(pasInput, qPrintable(idev), &buff, PA_STREAM_ADJUST_LATENCY);
// Ensure stream is initially un-muted
pa_stream_cork(pasInput, 0, NULL, NULL);
connect(g.mw, &MainWindow::corkAudioInputStream, this, &PulseAudioSystem::corkAudioInputStream);
}
}
@ -371,6 +376,15 @@ void PulseAudioSystem::eventCallback(pa_mainloop_api *api, pa_defer_event *) {
}
}
void PulseAudioSystem::corkAudioInputStream(const bool cork)
{
if (pasInput) {
pa_threaded_mainloop_lock(pam);
pa_stream_cork(pasInput, cork, nullptr, nullptr);
pa_threaded_mainloop_unlock(pam);
}
}
void PulseAudioSystem::context_state_callback(pa_context *c, void *userdata) {
PulseAudioSystem *pas = reinterpret_cast<PulseAudioSystem *>(userdata);
pas->contextCallback(c);

View File

@ -80,6 +80,9 @@ class PulseAudioSystem : public QObject {
void setVolumes();
PulseAttenuation* getAttenuation(QString stream_restore_id);
public slots:
void corkAudioInputStream(const bool cork);
public:
QHash<QString, QString> qhInput;
QHash<QString, QString> qhOutput;

View File

@ -479,6 +479,7 @@ int main(int argc, char **argv) {
g.p->rescanPlugins();
Audio::start();
g.mw->onChangeMute();
a.setQuitOnLastWindowClosed(false);