From c2c202e716a6514c6ab6319108a09223439e915f Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 12 Oct 2026 07:22:43 +0200 Subject: [PATCH] Mute local preview and clear Android media queues at detach --- .../java/com/utun/chat/data/StreamPlayerEngine.kt | 3 ++- tools/chatgui-android/libutun_lite/stream_bridge.c | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamPlayerEngine.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamPlayerEngine.kt index d17b5d74..98269070 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamPlayerEngine.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamPlayerEngine.kt @@ -20,7 +20,7 @@ import kotlin.math.roundToInt /** Один worker владеет декодерами и AudioTrack. Hardware audio clock управляет временем показа видео. * Просроченные P-кадры декодируются без показа, чтобы сохранить references; при переполнении ждём KEY. * viewerLock сериализует stop/open разных экранов до подтверждения освобождения native owner. */ -class StreamPlayerEngine(private val group: Long, private val source: Long) { +class StreamPlayerEngine(private val group: Long, private val source: Long, private val muteAudio: Boolean = false) { companion object { private val viewerLock = ReentrantLock() } private data class Frame(val pts: Long, val key: Boolean, val width: Int, val height: Int, val rotation: Int, val data: ByteArray) private val mutableAspect = MutableStateFlow(16f / 9f) @@ -116,6 +116,7 @@ class StreamPlayerEngine(private val group: Long, private val source: Long) { videos.addLast(frame); videoBytes += size } } else { + if (muteAudio) return@repeat if (audios.size >= 16) { LogManager.addLog("WARN", "stream", "audio queue overflow id=$id; reset timeline") resetAudio(); resetVideo() diff --git a/tools/chatgui-android/libutun_lite/stream_bridge.c b/tools/chatgui-android/libutun_lite/stream_bridge.c index f3304aa8..b102d7c6 100644 --- a/tools/chatgui-android/libutun_lite/stream_bridge.c +++ b/tools/chatgui-android/libutun_lite/stream_bridge.c @@ -151,7 +151,7 @@ static void media_event(struct UTUN_INSTANCE *inst, const struct stream_event *e /* Publisher держит конечное окно выдачи после FIN; abrupt detach ничего не обещает получателям. */ static void media_close(struct android_media_session *s, int kind) { - media_output(s->id, kind, NULL, 0, 0, NULL, 0); + if (kind) media_output(s->id, kind, NULL, 0, 0, NULL, 0); if (s->handle) stream_close(s->handle); stream_media_receiver_destroy(s->receiver); if (s == &publisher) { queue_clear(&video_queue); queue_clear(&audio_queue); } @@ -217,8 +217,8 @@ static void media_list_sources(void) { struct stream_member_state state; if (stream_member_load(media_inst, group_id, node, &state, NULL) != STREAM_OK || !state.published) continue; if (count >= 256) { DEBUG_WARN(DEBUG_CATEGORY_STREAM, "Android stream source list truncated group=%llx", (unsigned long long)group_id); break; } - if (strbuf_addf(&json, "%s{\"id\":\"%llu\",\"epoch\":\"%016llx\",\"name\":", count ? "," : "", - (unsigned long long)node, (unsigned long long)state.source.source_epoch) < 0 + if (strbuf_addf(&json, "%s{\"id\":\"%llu\",\"epoch\":\"%016llx\",\"self\":%d,\"name\":", count ? "," : "", + (unsigned long long)node, (unsigned long long)state.source.source_epoch, node == media_inst->node_id) < 0 || strbuf_add_json_string(&json, (const char *)sqlite3_column_text(statement, 1)) < 0 || strbuf_addf(&json, "}") < 0) { failed = 1; break; } count++; @@ -316,8 +316,9 @@ void android_stream_detach(struct UTUN_INSTANCE *inst) { if (media_timer) uasync_cancel_timeout(inst->ua, media_timer); media_post = NULL; media_timer = NULL; stream_set_event_callback(inst, NULL, NULL); - if (publisher.id) media_close(&publisher, 6); - if (viewer.id) media_close(&viewer, 6); + queue_clear(&output_queue); + if (publisher.id) media_close(&publisher, 0); + if (viewer.id) media_close(&viewer, 0); media_inst = NULL; u_free(source_list); source_list = NULL; list_group = cached_group = list_updated = 0; DEBUG_INFO(DEBUG_CATEGORY_STREAM, "Android stream bridge detached; producers rejected");