Browse Source

Keep queued video frames during in-place bitrate changes

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

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

@ -232,26 +232,27 @@ 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 || lastKey < 0 || pts - lastKey >= 1_000_000 val key = needKey || confirmingRequest != 0L || lastKey < 0 || pts - lastKey >= 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
confirmingPts = pts confirmingPts = pts
if (old.setBitrate(pendingRate)) { if (old.setBitrate(pendingRate)) {
confirmingRequest = requestId; needKey = true // References сохранены: уже закодированные P-кадры остаются пригодны до нового KEY.
confirmingRequest = requestId
} else { } else {
old.close(); encoder = null old.close(); encoder = null
try { try {
encoder = CallVideoCodec(f, pendingRate, name) encoder = CallVideoCodec(f, pendingRate, name)
encoder!!.prepare(); check(encoder!!.format == f) { "Bitrate change altered encoder format" } encoder!!.prepare(); check(encoder!!.format == f) { "Bitrate change altered encoder format" }
confirmingRequest = requestId; needKey = true confirmingRequest = requestId; needKey = true
report("Applying ${pendingRate / 1000} kbit/s on IDR") report("Applying ${pendingRate / 1000} kbit/s on IDR")
} catch (e: Exception) { } catch (e: Exception) {
LogManager.addLog("WARN", "call", "video bitrate replacement failed: ${e.message}; restoring $oldRate") LogManager.addLog("WARN", "call", "video bitrate replacement failed: ${e.message}; restoring $oldRate")
encoder?.close(); encoder = CallVideoCodec(f, oldRate, name) encoder?.close(); encoder = CallVideoCodec(f, oldRate, name)
encoder!!.prepare(); check(encoder!!.format == f) encoder!!.prepare(); check(encoder!!.format == f)
confirmingRequest = requestId; needKey = true confirmingRequest = requestId; needKey = true
} }
} }
} }
if (encoder?.submit(image, pts, key) == true) lastPts = pts if (encoder?.submit(image, pts, key) == true) lastPts = pts

Loading…
Cancel
Save