OpenShot Library | libopenshot 1.1.1
Loading...
Searching...
No Matches
AdaptivePreroll.h
Go to the documentation of this file.
1
9// Copyright (c) 2026 OpenShot Studios, LLC
10//
11// SPDX-License-Identifier: LGPL-3.0-or-later
12#ifndef OPENSHOT_ADAPTIVE_PREROLL_H
13#define OPENSHOT_ADAPTIVE_PREROLL_H
14
15#include <algorithm>
16#include <cmath>
17#include <cstdint>
18
19namespace openshot {
20// No clocks, readers, or worker ownership: callers supply monotonic microseconds.
21// All access is serialized by VideoCacheThread's existing seek-state mutex.
23public:
24 static constexpr int64_t StartupLimitUs = 500000;
25 static constexpr int64_t MaxProbeFrames = 120;
26 void Reset(int64_t now) {
27 started = now;
28 samples = 0;
29 mean = deviation = 0;
30 target = 0;
31 released = false;
32 timed_out = false;
33 }
34 void Observe(int64_t duration_us) {
35 if (duration_us < 0) return;
36 const double value = static_cast<double>(duration_us);
37 if (!samples) mean = value;
38 else {
39 deviation += 0.25 * (std::abs(value - mean) - deviation);
40 mean += 0.25 * (value - mean);
41 }
42 ++samples;
43 }
44 // Capacity is the worker's reachable directional window, excluding playhead.
45 int64_t Target(double fps, int speed, int64_t capacity,
46 int64_t conservative, int64_t maximum) {
47 const int64_t stride = std::max<int64_t>(1, std::abs(static_cast<int64_t>(speed)));
48 const int64_t limit = std::max<int64_t>(0, std::min({capacity, maximum, MaxProbeFrames}));
49 if (conservative < 0 || limit == 0) return target = 0;
50 int64_t wanted = std::min(conservative, limit);
51 if (samples >= 3 && fps > 0) {
52 const double budget = 1000000.0 / fps / stride;
53 const double cost = (mean + 3 * deviation) / budget;
54 const double demand = cost < 0.5 ? 2.0 * stride
55 : std::ceil(2 + 4 * cost) * stride;
56 // Clamp in floating point before conversion, including corrupt or
57 // extreme timing/speed metadata, so demand cannot overflow int64.
58 wanted = static_cast<int64_t>(std::min<double>(limit, demand));
59 }
60 wanted = std::clamp<int64_t>(wanted, 0, limit);
61 // Demand rises promptly; decay only after a two-frame difference.
62 if (!target || wanted > target || wanted + 2 <= target) target = wanted;
63 return target = std::min(target, limit);
64 }
65 bool Ready(int64_t now, int64_t contiguous_ahead, bool current_available,
66 int64_t required, int64_t minimum_step = 1) {
67 timed_out = now - started >= StartupLimitUs;
68 const int64_t threshold = released || timed_out ? minimum_step : required;
69 const bool ready = current_available && contiguous_ahead >= threshold;
70 if (ready) released = true;
71 return ready;
72 }
73 bool TimedOut() const { return timed_out; }
74 bool Released() const { return released; }
75private:
76 int64_t started = 0, target = 0;
77 unsigned samples = 0;
78 double mean = 0, deviation = 0;
79 bool released = false, timed_out = false;
80};
81}
82#endif
void Observe(int64_t duration_us)
int64_t Target(double fps, int speed, int64_t capacity, int64_t conservative, int64_t maximum)
bool Ready(int64_t now, int64_t contiguous_ahead, bool current_available, int64_t required, int64_t minimum_step=1)
static constexpr int64_t MaxProbeFrames
static constexpr int64_t StartupLimitUs
This namespace is the default namespace for all code in the openshot library.