From 5e293ce8b8985e2170e07ff180be6091dcaf45f9 Mon Sep 17 00:00:00 2001 From: Alex Andres Date: Sat, 24 Oct 2026 03:59:27 +0200 Subject: [PATCH] fix: keep what a seek decoded at the new position MediaPlayer::Seek flushed the pacer after releasing its lock. When the decode thread performed the seek in between and decoded at the new position, that flush threw it away: an audio source, decoded seconds ahead, skipped ahead or ended at once. The flush now happens under the lock the decode thread takes the request with. This made MediaPlayerTest.positionFollowsABackwardSeekOfAudio fail now and then, which now also checks that playback goes on. --- .../src/main/cpp/src/media/MediaPlayer.cpp | 25 +++++++++++-------- .../webrtc/media/player/MediaPlayerTest.java | 5 ++++ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/webrtc-java-media/src/main/cpp/src/media/MediaPlayer.cpp b/webrtc-java-media/src/main/cpp/src/media/MediaPlayer.cpp index 948a41041..75fb7a9b1 100644 --- a/webrtc-java-media/src/main/cpp/src/media/MediaPlayer.cpp +++ b/webrtc-java-media/src/main/cpp/src/media/MediaPlayer.cpp @@ -156,25 +156,28 @@ namespace ffmpeg void MediaPlayer::Seek(int64_t position_us) { - { - std::lock_guard lock(mutex_); - - if (closing_) { - return; - } - - seek_pending_ = true; - seek_position_us_ = position_us; - ended_ = false; + std::lock_guard lock(mutex_); - command_.notify_all(); + if (closing_) { + return; } + seek_pending_ = true; + seek_position_us_ = position_us; + ended_ = false; + // The decode thread may be held up by a full queue, and it cannot act // on the request until it gets out of that. Dropping what is queued // both frees it and throws away what belongs to the old position; the // thread flushes again once the seek has actually happened. + // + // Under the lock, as the thread takes the request only under it: a + // flush after that would throw away what it has decoded at the new + // position, and an audio source, decoded seconds ahead, would skip + // ahead or end at once. pacer_->Flush(position_us + loop_offset_us_.load()); + + command_.notify_all(); } void MediaPlayer::SetLooping(bool looping) diff --git a/webrtc-java-media/src/test/java/dev/onvoid/webrtc/media/player/MediaPlayerTest.java b/webrtc-java-media/src/test/java/dev/onvoid/webrtc/media/player/MediaPlayerTest.java index aa0fa1117..642a26160 100644 --- a/webrtc-java-media/src/test/java/dev/onvoid/webrtc/media/player/MediaPlayerTest.java +++ b/webrtc-java-media/src/test/java/dev/onvoid/webrtc/media/player/MediaPlayerTest.java @@ -335,6 +335,11 @@ void positionFollowsABackwardSeekOfAudio() throws Exception { // About 0.4 s into the source again, not held at where it was. assertTrue(after < before / 2, "position after seeking back: " + after + " us, " + before + " us before it"); + // And still playing: the source is decoded to its end long before + // it plays out, and a flush that came after the seek had happened + // threw away all of it, so that the player ended at once. + assertEquals(MediaPlayerState.PLAYING, playback.player.getState()); + assertTrue(after > 0, "position after seeking back: " + after + " us"); } }