Browse Source

Bound Android bitrate wait by requested keyframe cadence

master
evgeny 5 days ago
parent
commit
5666da8859
  1. 16
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoEngine.kt

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

@ -56,7 +56,7 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
private var generation = 0L private var generation = 0L
private var frame = 0L private var frame = 0L
private var lastPts = -1L private var lastPts = -1L
private var lastKey = -1L private var lastKeyRequest = -1L
private var keySerial = -1L private var keySerial = -1L
private var needKey = true private var needKey = true
private var request = 0L private var request = 0L
@ -151,6 +151,7 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
} }
if (s[1] == format?.generation && s[2] > request) { if (s[1] == format?.generation && s[2] > request) {
request = s[2]; pendingRequest = request; pendingRate = s[3].toInt() request = s[2]; pendingRequest = request; pendingRate = s[3].toInt()
LogManager.addLog("DEBUG", "call", "video bitrate queued id=$id request=$request target=$pendingRate lastKeyRequest=$lastKeyRequest")
} }
if (!wanted.enabled) { if (!wanted.enabled) {
if (active != null) { if (active != null) {
@ -159,7 +160,7 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
confirmingRequest = 0; pendingRequest = 0 confirmingRequest = 0; pendingRequest = 0
closeCamera(); encoder?.close(); encoder = null; active = null; report("Video off") closeCamera(); encoder?.close(); encoder = null; active = null; report("Video off")
} }
} else if (wanted != active && !opening && !closing && (lastKey < 0 || System.nanoTime() / 1000 - lastKey >= 1_000_000)) { } else if (wanted != active && !opening && !closing && (lastKeyRequest < 0 || System.nanoTime() / 1000 - lastKeyRequest >= 1_000_000)) {
val peer = CallVideoNative.peer(id) val peer = CallVideoNative.peer(id)
if (peer != null) change(peer) if (peer != null) change(peer)
} }
@ -190,7 +191,7 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
check(CallVideoNative.supported(caps, peer, next.array())) { "Actual encoder format exceeds peer capabilities: $next" } check(CallVideoNative.supported(caps, peer, next.array())) { "Actual encoder format exceeds peer capabilities: $next" }
check(CallVideoNative.format(id, next.array(), candidate.bitrate)) { "Video format rejected" } check(CallVideoNative.format(id, next.array(), candidate.bitrate)) { "Video format rejected" }
closeCamera(); encoder = candidate; format = next; active = wanted closeCamera(); encoder = candidate; format = next; active = wanted
pendingRequest = 0; confirmingRequest = 0; request = 0; lastKey = -1; needKey = true pendingRequest = 0; confirmingRequest = 0; request = 0; lastKeyRequest = -1; needKey = true
mutable.value = mutable.value.copy(bitrate = candidate.bitrate) mutable.value = mutable.value.copy(bitrate = candidate.bitrate)
if (!closing) openCamera() if (!closing) openCamera()
return return
@ -229,7 +230,8 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
val pts = (image.timestamp + offset) / 1000 val pts = (image.timestamp + offset) / 1000
// Camera2 уже ограничена 30 fps. Порог 33333 мкс отбрасывал каждый второй кадр при дрожании часов. // Camera2 уже ограничена 30 fps. Порог 33333 мкс отбрасывал каждый второй кадр при дрожании часов.
if (pts <= lastPts) return@setOnImageAvailableListener if (pts <= lastPts) return@setOnImageAvailableListener
val key = needKey || confirmingRequest != 0L || lastKey < 0 || pts - lastKey >= 1_000_000 // Автоматический IDR кодека не переносит нашу границу: иначе смена bitrate может ждать бесконечно.
val key = needKey || confirmingRequest != 0L || lastKeyRequest < 0 || pts - lastKeyRequest >= 1_000_000
if (key && pendingRequest != 0L) { if (key && pendingRequest != 0L) {
val requestId = pendingRequest; pendingRequest = 0 val requestId = pendingRequest; pendingRequest = 0
val old = checkNotNull(encoder); val oldRate = old.bitrate; val name = old.name val old = checkNotNull(encoder); val oldRate = old.bitrate; val name = old.name
@ -252,7 +254,10 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
} }
} }
} }
if (encoder?.submit(image, pts, key) == true) lastPts = pts if (encoder?.submit(image, pts, key) == true) {
lastPts = pts
if (key) lastKeyRequest = pts
}
drain() drain()
} catch (e: Exception) { fail("Camera encode: ${e.message}") } } catch (e: Exception) { fail("Camera encode: ${e.message}") }
finally { image.close() } finally { image.close() }
@ -335,7 +340,6 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
val codec = encoder ?: return; val f = format ?: return val codec = encoder ?: return; val f = format ?: return
for (p in codec.drain()) { for (p in codec.drain()) {
encodedBytes += p.bytes.size; encodedFrames++ encodedBytes += p.bytes.size; encodedFrames++
if (p.key) lastKey = p.pts
if (confirmingRequest != 0L && p.key && p.pts >= confirmingPts) { if (confirmingRequest != 0L && p.key && p.pts >= confirmingPts) {
CallVideoNative.applied(id, f.generation, confirmingRequest, codec.bitrate); confirmingRequest = 0 CallVideoNative.applied(id, f.generation, confirmingRequest, codec.bitrate); confirmingRequest = 0
mutable.value = mutable.value.copy(bitrate = codec.bitrate) mutable.value = mutable.value.copy(bitrate = codec.bitrate)

Loading…
Cancel
Save