From af2209ec9675596fe15cc5866ea1196ce7955da7 Mon Sep 17 00:00:00 2001 From: evgeny Date: Thu, 29 Oct 2026 00:22:50 +0100 Subject: [PATCH] Prepare host video tests and initialize receive ownership before starting its worker --- .../java/com/utun/chat/data/CallVideoPlayer.kt | 7 +++++-- .../chatgui-android/video-tests/build.gradle.kts | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tools/chatgui-android/video-tests/build.gradle.kts diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoPlayer.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoPlayer.kt index 0eaa8e8e..fd005b0e 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoPlayer.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoPlayer.kt @@ -43,7 +43,8 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin private val displayed = MutableStateFlow(null) val display: StateFlow = displayed @Volatile private var verified = emptyMap() - private val worker = Thread(::loop, "call-video-rx").apply { start() } + private val worker = Thread(::loop, "call-video-rx") + init { worker.start() } @Synchronized fun surface(surface: Surface?, release: () -> Unit = {}) { val owner = Output(surface, release) ownedOutputs.add(owner) @@ -63,6 +64,7 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin "Video RX cannot join itself" } synchronized(this) { running = false } + worker.interrupt() try { worker.join(250) } catch (e: InterruptedException) { Thread.currentThread().interrupt() LogManager.addLog("ERROR", "call", "video RX join interrupted call=$id: $e") @@ -307,7 +309,8 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin if (!worked && waitUs > 0) Thread.sleep(waitUs / 1000, (waitUs % 1000 * 1000).toInt()) } } catch (e: Exception) { - reportFailure("Video RX stopped: $e") + if (!running && e is InterruptedException) LogManager.addLog("DEBUG", "call", "video RX wait cancelled call=$id") + else reportFailure("Video RX stopped: $e") } finally { synchronized(this) { running = false; displayed.value = null; awaiting = null; presentations.clear(); outputs.clear() diff --git a/tools/chatgui-android/video-tests/build.gradle.kts b/tools/chatgui-android/video-tests/build.gradle.kts new file mode 100644 index 00000000..11147e33 --- /dev/null +++ b/tools/chatgui-android/video-tests/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { id("org.jetbrains.kotlin.jvm") } + +kotlin { + jvmToolchain(17) + sourceSets.named("main") { + // Настоящий RX/протокольный формат; Android codecs, probe и JNI управляются на аппаратных границах. + kotlin.srcDir("../app/src/main/java") + kotlin.include("android/**", "com/utun/chat/data/VideoHost.kt", "com/utun/chat/data/CallVideoPlayer.kt", + "com/utun/chat/data/CallVideoFormat.kt", "com/utun/chat/data/StreamVideoCodec.kt", "com/utun/chat/data/H264AnnexB.kt") + } +} +dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + testImplementation("junit:junit:4.13.2") +} +tasks.test { testLogging { showStandardStreams = true } }