| 143 | } |
| 144 | |
| 145 | void VideoCacheThread::Seek(int64_t new_position, bool start_preroll) |
| 146 | { |
| 147 | const int64_t timeline_end = resolveTimelineEnd(); |
| 148 | const int64_t clamped_new_position = clampToTimelineRange(new_position, timeline_end); |
| 149 | const int64_t current_requested = requested_display_frame.load(); |
| 150 | |
| 151 | bool should_mark_seek = false; |
| 152 | bool should_preroll = false; |
| 153 | int64_t new_cached_count = cached_frame_count.load(); |
| 154 | bool entering_scrub = false; |
| 155 | bool leaving_scrub = false; |
| 156 | bool cache_contains = false; |
| 157 | bool should_clear_cache = false; |
| 158 | CacheBase* cache = reader ? reader->GetCache() : nullptr; |
| 159 | const bool same_frame_refresh = (new_position == current_requested); |
| 160 | if (cache) { |
| 161 | cache_contains = cache->Contains(clamped_new_position); |
| 162 | } |
| 163 | |
| 164 | if (start_preroll) { |
| 165 | if (same_frame_refresh) { |
| 166 | const bool is_paused = (speed.load() == 0); |
| 167 | if (is_paused) { |
| 168 | const bool was_scrubbing = scrub_active.load(); |
| 169 | if (was_scrubbing && cache && cache_contains) { |
| 170 | // Preserve in-range cache for paused scrub preview -> same-frame commit. |
| 171 | should_mark_seek = false; |
| 172 | should_preroll = false; |
| 173 | should_clear_cache = false; |
| 174 | new_cached_count = cache->Count(); |
| 175 | } else { |
| 176 | // Paused same-frame edit refresh: force full cache refresh. |
| 177 | if (Timeline* timeline = dynamic_cast<Timeline*>(reader)) { |
| 178 | timeline->ClearAllCache(); |
| 179 | } |
| 180 | new_cached_count = 0; |
| 181 | should_mark_seek = true; |
| 182 | should_preroll = true; |
| 183 | should_clear_cache = false; |
| 184 | } |
| 185 | } else { |
| 186 | // Same-frame refresh during playback should stay lightweight. |
| 187 | should_mark_seek = false; |
| 188 | should_preroll = false; |
| 189 | should_clear_cache = false; |
| 190 | if (cache && cache_contains) { |
| 191 | cache->Remove(clamped_new_position); |
| 192 | } |
| 193 | if (cache) { |
| 194 | new_cached_count = cache->Count(); |
| 195 | } |
| 196 | } |
| 197 | } else { |
| 198 | if (cache && !cache_contains) { |
| 199 | should_mark_seek = true; |
| 200 | // Uncached commit seek: defer cache clear to cache thread loop. |
| 201 | new_cached_count = 0; |
| 202 | should_preroll = true; |
nothing calls this directly
no test coverage detected