From ea5ef4abc2f3cacf87b5505f88c9384cb3205417 Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 14 Oct 2026 23:13:45 +0200 Subject: [PATCH] Probe hardware rate transitions and clear stale call port commands --- src/call/call_video_port.c | 8 ++++++-- .../debug/java/com/utun/chat/data/CallVideoProbe.kt | 11 +++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/call/call_video_port.c b/src/call/call_video_port.c index bd32e5c1..81852163 100644 --- a/src/call/call_video_port.c +++ b/src/call/call_video_port.c @@ -141,7 +141,10 @@ int call_video_port_open(uint64_t id, const struct call_video_caps *caps) { pthread_mutex_lock(&lock); int result = schedule(); if (!result) { - if (port.id != id) { clear_frames(); port.status = (struct call_video_port_status){0}; } + if (port.id != id) { + clear_frames(); port.status = (struct call_video_port_status){0}; + port.configure = port.completed = port.resume = port.key = port.range = 0; + } port.id = id; port.local = *caps; port.opening = 1; DEBUG_INFO(DEBUG_CATEGORY_CALL, "video port open requested call=%llu", (unsigned long long)id); } @@ -150,7 +153,8 @@ int call_video_port_open(uint64_t id, const struct call_video_caps *caps) { void call_video_port_close(uint64_t id) { pthread_mutex_lock(&lock); if (port.id == id) { - clear_frames(); port.id = 0; port.opening = 1; port.configure = port.completed = 0; + clear_frames(); port.id = 0; port.opening = 1; + port.configure = port.completed = port.resume = port.key = port.range = 0; if (port.inst) schedule(); DEBUG_INFO(DEBUG_CATEGORY_CALL, "video port close requested call=%llu", (unsigned long long)id); } diff --git a/tools/chatgui-android/app/src/debug/java/com/utun/chat/data/CallVideoProbe.kt b/tools/chatgui-android/app/src/debug/java/com/utun/chat/data/CallVideoProbe.kt index 8d4ea2b5..8ee5b4c9 100644 --- a/tools/chatgui-android/app/src/debug/java/com/utun/chat/data/CallVideoProbe.kt +++ b/tools/chatgui-android/app/src/debug/java/com/utun/chat/data/CallVideoProbe.kt @@ -8,9 +8,16 @@ class CallVideoProbe : Instrumentation() { override fun onCreate(arguments: Bundle?) { super.onCreate(arguments); start() } override fun onStart() { try { + val decoders = CallVideoCodec.probeDecoders() val codecs = CallVideoCodec.probe() - check(codecs.isNotEmpty()) { "No conforming encoder/decoder pair" } - finish(0, Bundle().apply { putString("codecs", codecs.toString()) }) + check(codecs.isNotEmpty() && decoders.isNotEmpty()) { "No verified encoders or decoders" } + for ((codec, entry) in codecs) { + val f = CallVideoFormat(1, 640, 480, codec = codec, level = entry.level, profile = entry.profile) + for (rate in listOf(4_000_000, 300_000, 4_000_000)) { + CallVideoCodec(f, rate, entry.name).use { it.prepare() } + } + } + finish(0, Bundle().apply { putString("codecs", codecs.toString()); putString("decoders", decoders.toString()) }) } catch (e: Exception) { android.util.Log.e("CallVideoProbe", "probe failed", e) finish(1, Bundle().apply { putString("error", e.toString()) })