From c8daa276fca0220b1f31f6019762cc7c12c7babf Mon Sep 17 00:00:00 2001 From: ua1zbe Date: Wed, 19 Aug 2026 09:37:44 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D1=81=D1=87=D1=91=D1=82=D0=B0=20=D0=BF=D0=BE=D1=82=D0=B5=D1=80?= =?UTF-8?q?=D1=8C:=20=D0=BF=D0=BE=D0=B2=D1=82=D0=BE=D1=80=D1=8B/=D0=B8?= =?UTF-8?q?=D0=BD=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B8=20seq=20=D0=B3=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D1=80=D1=8F=D1=89=D0=B5=D0=B3=D0=BE=20=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=B0=D1=83=D0=B7=D1=8B=20=D0=BD=D0=B5=20=D1=81=D1=87?= =?UTF-8?q?=D0=B8=D1=82=D0=B0=D1=8E=D1=82=D1=81=D1=8F=20=D0=BF=D0=BE=D1=82?= =?UTF-8?q?=D0=B5=D1=80=D1=8F=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/ru/ua1zbe/svxremote/audio/OpusEngine.kt | 12 +++++++++--- .../ru/ua1zbe/svxremote/proto/ReflectorClient.kt | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/ru/ua1zbe/svxremote/audio/OpusEngine.kt b/app/src/main/java/ru/ua1zbe/svxremote/audio/OpusEngine.kt index 8f9c5ae..9f3a944 100644 --- a/app/src/main/java/ru/ua1zbe/svxremote/audio/OpusEngine.kt +++ b/app/src/main/java/ru/ua1zbe/svxremote/audio/OpusEngine.kt @@ -331,10 +331,15 @@ class OpusEngine( private fun updateRxStats(seq: Int) { val now = System.currentTimeMillis() if (lastSeq >= 0) { - val gap = ((seq - lastSeq - 1) and 0xFFFF).toLong() - if (gap > 0) lossCount += gap - pktCount++ val dt = now - lastPktTime + // seq — счётчик ГОВОРЯЩЕГО: при повторах кадров он может + // повторяться или идти назад — это не потери. Пауза > 200 мс + // между пакетами — смена реплики/говорящего, тоже не потери. + if (dt <= 200) { + val gap = (seq - lastSeq - 1).toLong() + if (gap in 1..50000) lossCount += gap + } + pktCount++ val j = abs(dt - 20).toDouble() if (j < 100) { jitterAccum += j @@ -350,6 +355,7 @@ class OpusEngine( if (now - lastEvalTime < 5000 || pktCount < 30) return val lossPct = lossCount * 100.0 / pktCount val jitterMs = if (jitterN > 0) jitterAccum / jitterN else 0.0 + Log.d(TAG, "stats window: pkt=$pktCount loss=$lossCount pct=$lossPct j=$jitterMs lastSeq=$lastSeq") if (lossPct > 3.0 || jitterMs > 60.0) { if (autoKbps > AUTO_BITRATE_MIN) { autoKbps -= AUTO_BITRATE_STEP diff --git a/app/src/main/java/ru/ua1zbe/svxremote/proto/ReflectorClient.kt b/app/src/main/java/ru/ua1zbe/svxremote/proto/ReflectorClient.kt index ca2abca..b08ca3e 100644 --- a/app/src/main/java/ru/ua1zbe/svxremote/proto/ReflectorClient.kt +++ b/app/src/main/java/ru/ua1zbe/svxremote/proto/ReflectorClient.kt @@ -541,7 +541,7 @@ class ReflectorClient( if (data.size < 6) return val r = BinReader(data) val type = r.u16() - r.u16() // client id + val cid = r.u16() // client id val seq = r.u16() val payload = data.copyOfRange(6, data.size) when (type) { @@ -549,7 +549,7 @@ class ReflectorClient( ReflectorProtocol.MSG_UDP_AUDIO -> { val audio = MsgParser.udpAudio(payload) if (audio != null && audio.isNotEmpty()) { - Log.d(TAG, "UDP RX audio seq=$seq len=${audio.size}") + Log.d(TAG, "UDP RX audio seq=$seq cid=$cid len=${audio.size}") callbacks.onAudioPacket(audio, seq) } else { Log.w(TAG, "UDP RX audio empty/null len=${payload.size}")