VideoCacheThread: add directional preroll

- start cache rebuilds with a preroll offset (settings-based)
- tighten isReady to require frames ahead/behind playhead add unit tests for preroll clamping and readiness
This commit is contained in:
Jonathan Thomas
2026-02-05 12:39:06 -06:00
parent 47b308122f
commit 43f9ed89ae
4 changed files with 124 additions and 5 deletions

View File

@@ -33,9 +33,13 @@ public:
using VideoCacheThread::clearCacheIfPaused;
using VideoCacheThread::prefetchWindow;
using VideoCacheThread::handleUserSeek;
using VideoCacheThread::handleUserSeekWithPreroll;
using VideoCacheThread::computePrerollFrames;
int64_t getLastCachedIndex() const { return last_cached_index; }
void setLastCachedIndex(int64_t v) { last_cached_index = v; }
void setPlayhead(int64_t v) { requested_display_frame = v; }
void setMinFramesAhead(int64_t v) { min_frames_ahead = v; }
void setLastDir(int d) { last_dir = d; }
void forceUserSeekFlag() { userSeeked = true; }
};
@@ -95,6 +99,37 @@ TEST_CASE("computeWindowBounds: forward and backward bounds, clamped", "[VideoCa
CHECK(we == 3);
}
TEST_CASE("isReady: requires cached frames ahead of playhead", "[VideoCacheThread]") {
TestableVideoCacheThread thread;
Timeline timeline(/*width=*/1280, /*height=*/720, /*fps=*/Fraction(60,1),
/*sample_rate=*/48000, /*channels=*/2, ChannelLayout::LAYOUT_STEREO);
thread.Reader(&timeline);
thread.setMinFramesAhead(30);
thread.setPlayhead(200);
thread.setSpeed(1);
thread.setLastCachedIndex(200);
CHECK(!thread.isReady());
thread.setLastCachedIndex(229);
CHECK(!thread.isReady());
thread.setLastCachedIndex(230);
CHECK(thread.isReady());
thread.setSpeed(-1);
thread.setLastCachedIndex(200);
CHECK(!thread.isReady());
thread.setLastCachedIndex(171);
CHECK(!thread.isReady());
thread.setLastCachedIndex(170);
CHECK(thread.isReady());
}
TEST_CASE("clearCacheIfPaused: clears only when paused and not in cache", "[VideoCacheThread]") {
TestableVideoCacheThread thread;
CacheMemory cache(/*max_bytes=*/100000000);
@@ -139,6 +174,22 @@ TEST_CASE("handleUserSeek: sets last_cached_index to playhead - dir", "[VideoCac
CHECK(thread.getLastCachedIndex() == 51);
}
TEST_CASE("handleUserSeekWithPreroll: offsets start by preroll frames", "[VideoCacheThread]") {
TestableVideoCacheThread thread;
thread.handleUserSeekWithPreroll(/*playhead=*/60, /*dir=*/1, /*timeline_end=*/200, /*preroll_frames=*/30);
CHECK(thread.getLastCachedIndex() == 29);
thread.handleUserSeekWithPreroll(/*playhead=*/10, /*dir=*/1, /*timeline_end=*/200, /*preroll_frames=*/30);
CHECK(thread.getLastCachedIndex() == 0);
thread.handleUserSeekWithPreroll(/*playhead=*/1, /*dir=*/1, /*timeline_end=*/200, /*preroll_frames=*/30);
CHECK(thread.getLastCachedIndex() == 0);
thread.handleUserSeekWithPreroll(/*playhead=*/60, /*dir=*/-1, /*timeline_end=*/200, /*preroll_frames=*/30);
CHECK(thread.getLastCachedIndex() == 91);
}
TEST_CASE("prefetchWindow: forward caching with FFmpegReader & CacheMemory", "[VideoCacheThread]") {
TestableVideoCacheThread thread;
CacheMemory cache(/*max_bytes=*/100000000);