80 int64_t bytes =
static_cast<int64_t
>(width) * height *
sizeof(
char) * 4;
82 bytes += ((sample_rate * channels) / fps) *
sizeof(
float);
91 startThread(Priority::high);
92 return isThreadRunning();
98 stopThread(timeoutMs);
99 return !isThreadRunning();
109 if (cache && !cache->
Contains(new_position))
126 Seek(new_position,
false);
145 if (paused && !cache->
Contains(playhead)) {
158 int64_t timeline_end,
159 int64_t& window_begin,
160 int64_t& window_end)
const
164 window_begin = playhead;
165 window_end = playhead + ahead_count;
169 window_begin = playhead - ahead_count;
170 window_end = playhead;
173 window_begin = std::max<int64_t>(window_begin, 1);
174 window_end = std::min<int64_t>(window_end, timeline_end);
178 int64_t window_begin,
183 bool window_full =
true;
187 while ((dir > 0 && next_frame <= window_end) ||
188 (dir < 0 && next_frame >= window_begin))
190 if (threadShouldExit()) {
201 auto framePtr =
reader->GetFrame(next_frame);
202 cache->
Add(framePtr);
211 cache->
Touch(next_frame);
223 using micro_sec = std::chrono::microseconds;
224 using double_micro_sec = std::chrono::duration<double, micro_sec::period>;
226 while (!threadShouldExit()) {
234 std::this_thread::sleep_for(double_micro_sec(50000));
244 bool paused = (
speed == 0);
260 reader->info.fps.ToFloat()
263 int64_t capacity = 0;
264 if (max_bytes > 0 && bytes_per_frame > 0) {
265 capacity = max_bytes / bytes_per_frame;
276 else if (!paused && capacity >= 1) {
280 int64_t window_begin, window_end;
290 bool outside_window =
293 if (outside_window) {
300 std::this_thread::sleep_for(double_micro_sec(50000));
303 int64_t ahead_count =
static_cast<int64_t
>(capacity *
305 int64_t window_size = ahead_count + 1;
306 if (window_size < 1) {
309 int64_t ready_target = window_size - 1;
310 if (ready_target < 0) {
323 int64_t window_begin, window_end;
335 if (paused && window_full) {
336 cache->
Touch(playhead);
340 int64_t sleep_us =
static_cast<int64_t
>(
341 1000000.0 /
reader->info.fps.ToFloat() / 4.0
343 std::this_thread::sleep_for(double_micro_sec(sleep_us));
Header file for CacheBase class.
Header file for all Exception classes.
Header file for Frame class.
Header file for global Settings class.
Header file for Timeline class.
Header file for VideoCacheThread class.
All cache managers in libopenshot are based on this CacheBase class.
virtual bool Contains(int64_t frame_number)=0
Check if frame is already contained in cache.
virtual int64_t Count()=0
Count the frames in the queue.
virtual void Add(std::shared_ptr< openshot::Frame > frame)=0
Add a Frame to the cache.
virtual void Touch(int64_t frame_number)=0
Move frame to front of queue (so it lasts longer).
int64_t GetMaxBytes()
Gets the maximum bytes value.
Exception for frames that are out of bounds.
This abstract class is the base class, used by all readers in libopenshot.
This class is contains settings used by libopenshot (and can be safely toggled at any point).
static Settings * Instance()
Create or get an instance of this logger singleton (invoke the class with this method).
int VIDEO_CACHE_MIN_PREROLL_FRAMES
Minimum number of frames to cache before playback begins.
int VIDEO_CACHE_MAX_FRAMES
Max number of frames (when paused) to cache for playback.
float VIDEO_CACHE_PERCENT_AHEAD
Percentage of cache in front of the playhead (0.0 to 1.0).
bool ENABLE_PLAYBACK_CACHING
Enable/Disable the cache thread to pre-fetch and cache video frames before we need them.
int preview_height
Optional preview width of timeline image. If your preview window is smaller than the timeline,...
int preview_width
Optional preview width of timeline image. If your preview window is smaller than the timeline,...
This class represents a timeline.
int64_t GetMaxFrame()
Look up the end frame number of the latest element on the timeline.
void ClearAllCache(bool deep=false)
bool StopThread(int timeoutMs=0)
Stop the cache thread (wait up to timeoutMs ms). Returns true if it stopped.
void setSpeed(int new_speed)
Set playback speed/direction. Positive = forward, negative = rewind, zero = pause.
bool force_directional_cache
(Reserved for future use).
bool prefetchWindow(CacheBase *cache, int64_t window_begin, int64_t window_end, int dir, ReaderBase *reader)
Prefetch all missing frames in [window_begin ... window_end] or [window_end ... window_begin].
~VideoCacheThread() override
int64_t requested_display_frame
Frame index the user requested.
int64_t timeline_max_frame
Highest valid frame index in the timeline.
bool clearCacheIfPaused(int64_t playhead, bool paused, CacheBase *cache)
When paused and playhead is outside current cache, clear all frames.
int64_t last_cached_index
Index of the most recently cached frame.
int64_t cached_frame_count
Estimated count of frames currently stored in cache.
void run() override
Thread entry point: loops until threadShouldExit() is true.
int last_speed
Last non-zero speed (for tracking).
int64_t current_display_frame
Currently displayed frame (unused here, reserved).
VideoCacheThread()
Constructor: initializes member variables and assumes forward direction on first launch.
void handleUserSeek(int64_t playhead, int dir)
If userSeeked is true, reset last_cached_index just behind the playhead.
int64_t getBytes(int width, int height, int sample_rate, int channels, float fps)
Estimate memory usage for a single frame (video + audio).
ReaderBase * reader
The source reader (e.g., Timeline, FFmpegReader).
void Seek(int64_t new_position)
Seek to a specific frame (no preroll).
bool userSeeked
True if Seek(..., true) was called (forces a cache reset).
void computeWindowBounds(int64_t playhead, int dir, int64_t ahead_count, int64_t timeline_end, int64_t &window_begin, int64_t &window_end) const
Compute the “window” of frames to cache around playhead.
int64_t min_frames_ahead
Minimum number of frames considered “ready” (pre-roll).
int last_dir
Last direction sign (+1 forward, –1 backward).
bool StartThread()
Start the cache thread at high priority. Returns true if it’s actually running.
int computeDirection() const
int speed
Current playback speed (0=paused, >0 forward, <0 backward).
This namespace is the default namespace for all code in the openshot library.