From 98655284b23a06e494b8b8fa9b26c70d7afcae21 Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 13 Oct 2026 23:39:45 +0200 Subject: [PATCH] Discard stale playback snapshots before reseeking a media cursor --- tools/chatgui-android/libutun_lite/stream_bridge.c | 10 ++++++---- tools/chatgui/transport/stream_bridge.cpp | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/tools/chatgui-android/libutun_lite/stream_bridge.c b/tools/chatgui-android/libutun_lite/stream_bridge.c index 3c77b4a0..cca1adc8 100644 --- a/tools/chatgui-android/libutun_lite/stream_bridge.c +++ b/tools/chatgui-android/libutun_lite/stream_bridge.c @@ -244,14 +244,14 @@ static void media_process(void *arg) { } } if (viewer.stopping && viewer.id) media_close(&viewer, 5); - if (viewer.handle) { - int result = stream_media_get_status(viewer.handle, &viewer_status); - if (result < 0) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "Android media index failed result=%d", result); media_close(&viewer, 6); } - } if (viewer.handle && (viewer.resync || viewer.rx_overflow)) { viewer.resync = viewer.rx_overflow = 0; viewer.position = -1; viewer.waiting = 0; if (stream_media_resync(viewer.handle) != STREAM_OK) media_close(&viewer, 6); } + if (viewer.handle) { + int result = stream_media_get_status(viewer.handle, &viewer_status); + if (result < 0) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "Android media index failed result=%d", result); media_close(&viewer, 6); } + } unsigned queued_viewer = 0; for (struct media_record *r = output_queue.head; r; r = r->next) if (r->id == viewer.id) queued_viewer++; if (viewer.handle && viewer.want_read && queued_viewer < 2 @@ -271,6 +271,7 @@ static void media_process(void *arg) { else if (result == STREAM_GAP || result == STREAM_EXPIRED) { DEBUG_INFO(DEBUG_CATEGORY_STREAM, "Android playback resync id=%llu result=%d", (unsigned long long)viewer.id, result); stream_media_resync(viewer.handle); viewer.position = -1; media_output(viewer.id, 3, NULL, 0, 0, NULL, 0); + memset(&viewer_status, 0, sizeof(viewer_status)); } else { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "Android playback read failed result=%d", result); media_close(&viewer, 6); } } if (publisher.handle && !stream_handle_active(publisher.handle)) media_close(&publisher, 6); @@ -495,6 +496,7 @@ int android_stream_resync(uint64_t id) { int result = -1; if (viewer.id == id && viewer.handle) { media_drop_output(); viewer.resync = viewer.want_read = 1; viewer.waiting = 0; viewer.position = -1; + memset(&viewer_status, 0, sizeof(viewer_status)); result = media_schedule(); } pthread_mutex_unlock(&media_lock); return result; diff --git a/tools/chatgui/transport/stream_bridge.cpp b/tools/chatgui/transport/stream_bridge.cpp index 0c050489..998e3f83 100644 --- a/tools/chatgui/transport/stream_bridge.cpp +++ b/tools/chatgui/transport/stream_bridge.cpp @@ -135,15 +135,15 @@ void process(void*) { bridge.wantRead = true; } if (!bridge.handle) return; + if (bridge.resync) { + bridge.resync = false; bridge.position = -1; + if (stream_media_resync(bridge.handle) != STREAM_OK) { closeViewer(StreamRecordKind::Closed, STREAM_CLOSE_FAILED); return; } + } int statusResult = stream_media_get_status(bridge.handle, &bridge.status); if (statusResult < 0) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop media index failed result=%d", statusResult); closeViewer(StreamRecordKind::Closed, STREAM_CLOSE_FAILED); return; } - if (bridge.resync) { - bridge.resync = false; bridge.position = -1; - if (stream_media_resync(bridge.handle) != STREAM_OK) { closeViewer(StreamRecordKind::Closed, STREAM_CLOSE_FAILED); return; } - } if (!bridge.wantRead || bridge.output.size() >= 2 || bridge.bytes + STREAM_MEDIA_MAX_FRAME > 4u * 1024u * 1024u) return; bridge.wantRead = false; stream_media_packet packet{}; @@ -158,6 +158,7 @@ void process(void*) { else if (result == STREAM_GAP || result == STREAM_EXPIRED) { DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop playback resync id=%llu result=%d", (unsigned long long)bridge.viewer.id, result); stream_media_resync(bridge.handle); bridge.position = -1; + bridge.status = {}; output({bridge.viewer.id, 0, StreamRecordKind::Gap}); } else { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop playback read failed result=%d", result); @@ -245,6 +246,7 @@ bool gui_stream_resync(uint64_t id) { std::lock_guard guard(bridge.lock); if (bridge.viewer.id != id || !bridge.handle) return false; bridge.resync = bridge.wantRead = true; bridge.waiting = false; bridge.position = -1; + bridge.status = {}; bridge.output.clear(); bridge.bytes = 0; return schedule(); }