44 const std::vector<uint32_t>& chunk_ms) {
45 std::vector<uint64_t> out(chunk_ms.size(), arrival_ns);
58 const uint64_t max_gap_ms =
static_cast<uint64_t
>(
cfg_.max_plausible_gap_s) * 1000ULL;
59 const uint32_t newest_raw = chunk_ms.back();
62 bool reinitialized =
false;
64 resync(s, newest_raw, arrival_ns,
false);
67 const uint32_t step = forward_step_ms(s.
last_raw_ms, newest_raw);
68 if (step <= max_gap_ms) {
75 resync(s, newest_raw, arrival_ns,
true);
82 const int64_t residual =
static_cast<int64_t
>(arrival_ns) - board_ns(s.
last_unwrapped_ms);
85 const int64_t resync_thr_ns =
static_cast<int64_t
>(
cfg_.resync_threshold_ms) * NS_PER_MS;
86 if (residual - s.
offset_ns > resync_thr_ns || s.
offset_ns - residual > resync_thr_ns) {
87 resync(s, newest_raw, arrival_ns,
true);
89 s.
window.emplace_back(arrival_ns, residual);
90 const uint64_t window_ns =
91 static_cast<uint64_t
>(
cfg_.window_seconds) * 1000ULL * NS_PER_MS;
92 while (!s.
window.empty() && s.
window.front().first + window_ns < arrival_ns) {
95 int64_t mn = s.
window.front().second;
96 for (
const auto& e : s.
window)
97 mn = std::min(mn, e.second);
103 const double excess_ms =
104 static_cast<double>(residual - s.
offset_ns) /
static_cast<double>(NS_PER_MS);
112 const size_t n = chunk_ms.size();
113 std::vector<uint64_t> unwrapped(
n, 0);
114 std::vector<char> valid(
n, 1);
116 for (
size_t i =
n - 1; i-- > 0;) {
117 const uint32_t step = forward_step_ms(chunk_ms[i], chunk_ms[i + 1]);
118 if (step <= max_gap_ms && unwrapped[i + 1] >= step) {
119 unwrapped[i] = unwrapped[i + 1] - step;
120 valid[i] = valid[i + 1];
127 const int64_t arrival =
static_cast<int64_t
>(arrival_ns);
128 const int64_t age_ns =
static_cast<int64_t
>(
cfg_.max_batch_age_s) * 1000LL * NS_PER_MS;
129 const int64_t lower = arrival - age_ns;
131 for (
size_t i = 0; i <
n; i++) {
133 const int64_t t = board_ns(unwrapped[i]) + s.
offset_ns;
134 if (!valid[i] || t < lower || t > arrival) {
139 t_ns =
static_cast<uint64_t
>(t);