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 948a4104..75fb7a9b 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 aa0fa111..642a2616 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"); } }