summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton <anton@picapica.im>2026-08-13 00:55:22 +0400
committerAnton <anton@picapica.im>2026-08-13 00:55:22 +0400
commit07697978227d9d938a2ce2b72010d3b9cebea041 (patch)
tree41d1fcbc9296836196bd5da3889b83c7e04023fe
parentf65bda4889e67dac8df0d972f3adade837a2fa79 (diff)
downloadpica-pica-07697978227d9d938a2ce2b72010d3b9cebea041.tar.gz
pica-pica-07697978227d9d938a2ce2b72010d3b9cebea041.zip
pica-client: audio jitter improvements
-rw-r--r--pica-client/audiodevice.cpp15
-rw-r--r--pica-client/audiodevice.h8
2 files changed, 22 insertions, 1 deletions
diff --git a/pica-client/audiodevice.cpp b/pica-client/audiodevice.cpp
index 487df7e..aa4c42a 100644
--- a/pica-client/audiodevice.cpp
+++ b/pica-client/audiodevice.cpp
@@ -235,6 +235,12 @@ void AudioDevice::Capture()
enc_ctx->time_base = AVRational{1, m_sampleRate};
applyMonoLayout(enc_ctx);
+ // "voip" favors speech intelligibility over faithfulness and has lower
+ // algorithmic delay than the default "audio" mode - a better fit for a
+ // live call than for e.g. music. Only libopus exposes this private
+ // option; harmless no-op on the native "opus" encoder fallback.
+ av_opt_set(enc_ctx->priv_data, "application", "voip", 0);
+
if ((ret = avcodec_open2(enc_ctx, enc, nullptr)) < 0)
{
QString msg = QString("Could not open Opus encoder: %1").arg(ff_errstr(ret));
@@ -473,6 +479,15 @@ void AudioDevice::Play()
bool loggedResamplerError = false;
bool loggedEncodeError = false;
+ // Preroll: wait for a small cushion of buffered packets before writing
+ // the first one, so ordinary arrival jitter doesn't immediately drain
+ // the queue and starve the ALSA buffer (heard as crackling/xruns).
+ {
+ QMutexLocker locker(&m_queueMutex);
+ while (m_playQueue.size() < kPrerollDepth && !m_abort.loadRelaxed())
+ m_queueCond.wait(&m_queueMutex, 100);
+ }
+
while (true)
{
QByteArray pktData;
diff --git a/pica-client/audiodevice.h b/pica-client/audiodevice.h
index ef78f8e..60f64a5 100644
--- a/pica-client/audiodevice.h
+++ b/pica-client/audiodevice.h
@@ -97,7 +97,13 @@ private:
QMutex m_queueMutex;
QWaitCondition m_queueCond;
QQueue<QByteArray> m_playQueue;
- static const int kMaxQueueDepth = 4;
+ static const int kMaxQueueDepth = 8;
+
+ // Number of packets Play() waits to have buffered before writing the
+ // first one, to build up a cushion against arrival jitter (packets
+ // this call apart arrive roughly every 20ms - see
+ // AudioVideoCallController::startAudioPipeline()).
+ static const int kPrerollDepth = 3;
};
#endif // AUDIODEVICE_H