|
|
|
@ -31,6 +31,8 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin |
|
|
|
var held = -1; var heldPts = -1L; var inflight = 0; var draining = false |
|
|
|
var held = -1; var heldPts = -1L; var inflight = 0; var draining = false |
|
|
|
var sourceEpoch = 0L; var lastOutput = -1L; var lastProgress = System.nanoTime() |
|
|
|
var sourceEpoch = 0L; var lastOutput = -1L; var lastProgress = System.nanoTime() |
|
|
|
var reportedGeneration = 0L; var rejectedGeneration = 0L |
|
|
|
var reportedGeneration = 0L; var rejectedGeneration = 0L |
|
|
|
|
|
|
|
var reportAt = System.nanoTime(); var pulled = 0; var queued = 0; var decoded = 0; var rendered = 0; var late = 0 |
|
|
|
|
|
|
|
var maxAheadUs = 0L; var maxLateUs = 0L; var invalidClock = 0 |
|
|
|
val clock = LongArray(8); val info = MediaCodec.BufferInfo() |
|
|
|
val clock = LongArray(8); val info = MediaCodec.BufferInfo() |
|
|
|
fun close() { |
|
|
|
fun close() { |
|
|
|
try { decoder?.stop() } catch (e: Exception) { LogManager.addLog("WARN", "call", "video decoder stop: ${e.message}") } |
|
|
|
try { decoder?.stop() } catch (e: Exception) { LogManager.addLog("WARN", "call", "video decoder stop: ${e.message}") } |
|
|
|
@ -48,6 +50,10 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin |
|
|
|
LogManager.addLog("INFO", "call", "video output attached=${surface != null} call=$id") |
|
|
|
LogManager.addLog("INFO", "call", "video output attached=${surface != null} call=$id") |
|
|
|
} |
|
|
|
} |
|
|
|
val valid = NativeLib.callAudioClock(id, now / 1000, clock) && clock[5] != 0L |
|
|
|
val valid = NativeLib.callAudioClock(id, now / 1000, clock) && clock[5] != 0L |
|
|
|
|
|
|
|
if (!valid) invalidClock++ |
|
|
|
|
|
|
|
if (held >= 0 && valid) { |
|
|
|
|
|
|
|
maxAheadUs = maxOf(maxAheadUs, heldPts - clock[4]); maxLateUs = maxOf(maxLateUs, clock[4] - heldPts) |
|
|
|
|
|
|
|
} |
|
|
|
if (valid && sourceEpoch != clock[1]) { |
|
|
|
if (valid && sourceEpoch != clock[1]) { |
|
|
|
if (sourceEpoch != 0L) LogManager.addLog("DEBUG", "call", |
|
|
|
if (sourceEpoch != 0L) LogManager.addLog("DEBUG", "call", |
|
|
|
"video audio clock epoch $sourceEpoch -> ${clock[1]}; decoder retained generation=${format?.generation}") |
|
|
|
"video audio clock epoch $sourceEpoch -> ${clock[1]}; decoder retained generation=${format?.generation}") |
|
|
|
@ -57,9 +63,10 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin |
|
|
|
val render = heldPts >= clock[4] - 500_000 |
|
|
|
val render = heldPts >= clock[4] - 500_000 |
|
|
|
decoder!!.releaseOutputBuffer(held, render); held = -1 |
|
|
|
decoder!!.releaseOutputBuffer(held, render); held = -1 |
|
|
|
if (render) { |
|
|
|
if (render) { |
|
|
|
|
|
|
|
rendered++ |
|
|
|
if (displayed.value != format) LogManager.addLog("INFO", "call", "video visible call=$id format=$format") |
|
|
|
if (displayed.value != format) LogManager.addLog("INFO", "call", "video visible call=$id format=$format") |
|
|
|
displayed.value = format; lastRendered = now |
|
|
|
displayed.value = format; lastRendered = now |
|
|
|
} |
|
|
|
} else late++ |
|
|
|
lastProgress = now |
|
|
|
lastProgress = now |
|
|
|
} |
|
|
|
} |
|
|
|
if (decoder != null && held < 0) { |
|
|
|
if (decoder != null && held < 0) { |
|
|
|
@ -75,10 +82,13 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin |
|
|
|
} } |
|
|
|
} } |
|
|
|
lastOutput = info.presentationTimeUs; inflight = (inflight - 1).coerceAtLeast(0) |
|
|
|
lastOutput = info.presentationTimeUs; inflight = (inflight - 1).coerceAtLeast(0) |
|
|
|
held = out; heldPts = info.presentationTimeUs; lastProgress = now |
|
|
|
held = out; heldPts = info.presentationTimeUs; lastProgress = now |
|
|
|
|
|
|
|
decoded++ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (pending == null && held < 0 && inflight < 8) pending = CallVideoNative.pull(id, meta) |
|
|
|
if (pending == null && held < 0 && inflight < 8) { |
|
|
|
|
|
|
|
pending = CallVideoNative.pull(id, meta); if (pending != null) pulled++ |
|
|
|
|
|
|
|
} |
|
|
|
val data = pending |
|
|
|
val data = pending |
|
|
|
if (data != null && surface?.isValid == true && held < 0) { |
|
|
|
if (data != null && surface?.isValid == true && held < 0) { |
|
|
|
val next = CallVideoFormat.from(meta) |
|
|
|
val next = CallVideoFormat.from(meta) |
|
|
|
@ -109,7 +119,7 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin |
|
|
|
} else data |
|
|
|
} else data |
|
|
|
val buffer = checkNotNull(decoder!!.getInputBuffer(index)); check(bytes.size <= buffer.capacity()) |
|
|
|
val buffer = checkNotNull(decoder!!.getInputBuffer(index)); check(bytes.size <= buffer.capacity()) |
|
|
|
buffer.put(bytes); decoder!!.queueInputBuffer(index, 0, bytes.size, meta[10], 0) |
|
|
|
buffer.put(bytes); decoder!!.queueInputBuffer(index, 0, bytes.size, meta[10], 0) |
|
|
|
pending = null; inflight++ |
|
|
|
pending = null; inflight++; queued++ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (data != null && surface == null) { pending = null; CallVideoNative.requestKey(id) } |
|
|
|
} else if (data != null && surface == null) { pending = null; CallVideoNative.requestKey(id) } |
|
|
|
@ -118,6 +128,14 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin |
|
|
|
displayed.value = null; lastRendered = 0 |
|
|
|
displayed.value = null; lastRendered = 0 |
|
|
|
LogManager.addLog("INFO", "call", "video hidden: no rendered frames for 5s call=$id") |
|
|
|
LogManager.addLog("INFO", "call", "video hidden: no rendered frames for 5s call=$id") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (now - reportAt >= 1_000_000_000) { |
|
|
|
|
|
|
|
LogManager.addLog("DEBUG", "call", "video playback call=$id intervalMs=${(now - reportAt) / 1_000_000} " + |
|
|
|
|
|
|
|
"pulled=$pulled queued=$queued decoded=$decoded rendered=$rendered late=$late inflight=$inflight " + |
|
|
|
|
|
|
|
"pending=${pending != null} held=$held aheadUs=$maxAheadUs lateUs=$maxLateUs " + |
|
|
|
|
|
|
|
"invalidClock=$invalidClock audioPts=${clock[4]} videoPts=$heldPts") |
|
|
|
|
|
|
|
reportAt = now; pulled = 0; queued = 0; decoded = 0; rendered = 0; late = 0 |
|
|
|
|
|
|
|
maxAheadUs = 0; maxLateUs = 0; invalidClock = 0 |
|
|
|
|
|
|
|
} |
|
|
|
} catch (e: Exception) { |
|
|
|
} catch (e: Exception) { |
|
|
|
LogManager.addLog("ERROR", "call", "video receive call=$id: ${e.message}") |
|
|
|
LogManager.addLog("ERROR", "call", "video receive call=$id: ${e.message}") |
|
|
|
val generation = if (pending != null) meta[0] else format?.generation ?: 0 |
|
|
|
val generation = if (pending != null) meta[0] else format?.generation ?: 0 |
|
|
|
|