Browse Source

Invalidate output measurements across concurrent Android route changes

master
evgeny 4 days ago
parent
commit
1a97219c43
  1. 16
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallAudioEngine.kt

16
tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallAudioEngine.kt

@ -625,10 +625,11 @@ class CallAudioEngine {
playFramesPlayed = played
operationNs = System.nanoTime()
val device = trace.device
val anchor = playbackClock.update(playFramesWritten, played, nowUs, routeGeneration,
device.generation, device.stampFrame, device.stampNs / 1000)
val generation = routeGeneration
val anchor = playbackClock.update(playFramesWritten, played, nowUs, generation,
device.generation, device.stampFrame, device.stampNs / 1000).takeIf { generation == routeGeneration }
outputUs = if (anchor?.measured == true) (anchor.atUs - nowUs).coerceAtLeast(0) else -1
outputSample = OutputSample(nowUs, routeGeneration, CallOutputLatency(
outputSample = OutputSample(nowUs, generation, CallOutputLatency(
((playFramesWritten - played) * 1000 / SAMPLE_RATE).toInt(),
if (outputUs >= 0) (outputUs / 1000).toInt() else -1))
if (anchor != null) NativeLib.callAudioProgress(callId, epoch, anchor.position, anchor.atUs, nowUs, anchor.measured)
@ -636,12 +637,13 @@ class CallAudioEngine {
val mode = if (anchor == null) "unavailable" else if (anchor.measured) "timestamp" else "head-estimate"
if (mode != clockMode) {
LogManager.addLog(if (mode == "unavailable") "WARN" else "INFO", "CallAudio",
"playback clock id=$callId mode=$mode routeGeneration=$routeGeneration outputUs=$outputUs")
"playback clock id=$callId mode=$mode routeGeneration=$generation outputUs=$outputUs")
clockMode = mode
}
} else if (!clockFailed) {
clockFailed = true
playFramesPlayed = -1
outputUs = -1; outputSample = null
// Отрицательная позиция немедленно инвалидирует снимок в native.
NativeLib.callAudioProgress(callId, epoch, -1, nowUs, nowUs, false)
LogManager.addLog("ERROR", "CallAudio",
@ -711,11 +713,13 @@ class CallAudioEngine {
} else {
playbackBuffer?.applied(now, change, actual, capacity)
}
val level = if (actual == requested && (change == null || change.underruns == 0)) "INFO" else "WARN"
val performance = track.performanceMode
val level = if (actual == requested && (change == null || change.underruns == 0) &&
performance == AudioTrack.PERFORMANCE_MODE_LOW_LATENCY) "INFO" else "WARN"
LogManager.addLog(level, "CallAudio",
"playback buffering id=$callId reason=$reason requestedFrames=$requested actualFrames=$actual " +
"previousFrames=$previous startFrames=$start capacityFrames=$capacity underruns=${change?.underruns ?: 0} " +
"performanceRequested=${AudioTrack.PERFORMANCE_MODE_LOW_LATENCY} performanceActual=${track.performanceMode} pacing=device")
"performanceRequested=${AudioTrack.PERFORMANCE_MODE_LOW_LATENCY} performanceActual=$performance pacing=device")
if (playReady && (previous != actual || reason == "route")) {
// Очередь сначала принимает новый размер; устаревшая задача не затронет следующий звонок.
mainHandler.post {

Loading…
Cancel
Save