2 Commits

3 changed files with 13 additions and 7 deletions

View File

@@ -11,8 +11,8 @@ android {
applicationId = "ru.ua1zbe.svxremote" applicationId = "ru.ua1zbe.svxremote"
minSdk = 26 minSdk = 26
targetSdk = 34 targetSdk = 34
versionCode = 12 versionCode = 13
versionName = "1.0.10" versionName = "1.0.11"
} }
buildTypes { buildTypes {

View File

@@ -331,10 +331,15 @@ class OpusEngine(
private fun updateRxStats(seq: Int) { private fun updateRxStats(seq: Int) {
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
if (lastSeq >= 0) { if (lastSeq >= 0) {
val gap = ((seq - lastSeq - 1) and 0xFFFF).toLong()
if (gap > 0) lossCount += gap
pktCount++
val dt = now - lastPktTime 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() val j = abs(dt - 20).toDouble()
if (j < 100) { if (j < 100) {
jitterAccum += j jitterAccum += j
@@ -350,6 +355,7 @@ class OpusEngine(
if (now - lastEvalTime < 5000 || pktCount < 30) return if (now - lastEvalTime < 5000 || pktCount < 30) return
val lossPct = lossCount * 100.0 / pktCount val lossPct = lossCount * 100.0 / pktCount
val jitterMs = if (jitterN > 0) jitterAccum / jitterN else 0.0 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 (lossPct > 3.0 || jitterMs > 60.0) {
if (autoKbps > AUTO_BITRATE_MIN) { if (autoKbps > AUTO_BITRATE_MIN) {
autoKbps -= AUTO_BITRATE_STEP autoKbps -= AUTO_BITRATE_STEP

View File

@@ -541,7 +541,7 @@ class ReflectorClient(
if (data.size < 6) return if (data.size < 6) return
val r = BinReader(data) val r = BinReader(data)
val type = r.u16() val type = r.u16()
r.u16() // client id val cid = r.u16() // client id
val seq = r.u16() val seq = r.u16()
val payload = data.copyOfRange(6, data.size) val payload = data.copyOfRange(6, data.size)
when (type) { when (type) {
@@ -549,7 +549,7 @@ class ReflectorClient(
ReflectorProtocol.MSG_UDP_AUDIO -> { ReflectorProtocol.MSG_UDP_AUDIO -> {
val audio = MsgParser.udpAudio(payload) val audio = MsgParser.udpAudio(payload)
if (audio != null && audio.isNotEmpty()) { 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) callbacks.onAudioPacket(audio, seq)
} else { } else {
Log.w(TAG, "UDP RX audio empty/null len=${payload.size}") Log.w(TAG, "UDP RX audio empty/null len=${payload.size}")