Retry each pending encoder once per cleanup pass with the shared backoff

This commit is contained in:
evgeny committed 2026-10-29 13:34:24 +01:00
1 parent 682ed68d2f
commit 776cec590e
2 files changed
+9 -6

No files matched your search

@@ -685,7 +685,7 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
} catch (e: Exception) {
pendingEncoders.add(owned)
LogManager.addLog("ERROR", "call", "video encoder release failed id=$id; retained for retry: $e")
queueCleanup(250); false
queueCleanup(cleanupDelay); false
}
/** Вызывается на TX: закрыть независимые владельцы, не теряя refs до SDK ACK/callback. */
@@ -714,8 +714,9 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
if (ownedReaders.isEmpty() && sessions.isEmpty() && ownedSessions.isEmpty()) closing = false
}
if (camera != null && camera !in closingCameras && !opening) closing = false
for (owned in pendingEncoders.toList()) releaseEncoder(owned)
if (!wanted.enabled) encoder?.let { releaseEncoder(it) }
val release = pendingEncoders.toMutableSet()
if (!wanted.enabled) encoder?.let { release.add(it) }
for (owned in release) releaseEncoder(owned)
val pending = opening || closing || closingCameras.isNotEmpty() || closingSessions.isNotEmpty() || pendingEncoders.isNotEmpty() ||
(!wanted.enabled && (encoder != null || orientationEnabled))
if (stopped && !pending) {
@@ -83,12 +83,13 @@ internal object CallVideoNative {
val ports = ConcurrentHashMap.newKeySet<Long>()
val portOperations = CopyOnWriteArrayList<String>()
@Volatile var configured = 0L
@Volatile var statusError = 0L
@Volatile var onOpen: () -> Unit = {}
@Volatile var onClose: () -> Unit = {}
fun reset() {
frames.clear(); live.clear(); rejected.clear(); accepted.clear(); presented.clear(); destroys.clear()
failures = emptySet(); onCreate = {}; onPull = {}; keyRequests.set(0)
ports.clear(); portOperations.clear(); configured = 0; onOpen = {}; onClose = {}
ports.clear(); portOperations.clear(); configured = 0; statusError = 0; onOpen = {}; onClose = {}
}
private fun access(operation: String) { check(operation !in failures) { "native $operation failed" } }
fun playoutCreate(id: Long): Long {
@@ -118,10 +119,11 @@ internal object CallVideoNative {
fun close(id: Long) { onClose(); access("close"); ports.remove(id); portOperations.add("close:$id") }
fun range(id: Long, minimum: Int, maximum: Int): Boolean { access("range"); return "range reject" !in failures }
fun peer(id: Long): ByteArray? = if (id in ports) ByteArray(64) else null
fun status(id: Long): LongArray? = if (id in ports) longArrayOf(1, 0, 0, 1_000_000, configured, 0, 300_000, 4_000_000, 0, 0, 1, 1) else null
fun status(id: Long): LongArray? = if (id in ports && "status missing" !in failures)
longArrayOf(1, 0, 0, 1_000_000, configured, statusError, 300_000, 4_000_000, 0, 0, 1, 1) else null
fun choose(local: ByteArray, peer: ByteArray, desired: LongArray): LongArray? = desired.copyOf()
fun supported(local: ByteArray, peer: ByteArray, desired: LongArray): Boolean = true
fun format(id: Long, format: LongArray, bitrate: Int): Boolean { access("format"); configured = format[0]; return true }
fun format(id: Long, format: LongArray, bitrate: Int): Boolean { access("format"); configured = format[0]; statusError = 0; return true }
fun applied(id: Long, generation: Long, request: Long, bitrate: Int) { access("applied") }
fun send(id: Long, metadata: LongArray, bytes: ByteArray): Int { access("send"); return 1 }
}