| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- #ifndef RINGBUFFER_H
- #define RINGBUFFER_H
- #pragma once
- #include <cmath>
- #include <functional>
- #include <mutex>
- #include <vector>
- template<typename T>
- class RingBuffer
- {
- public:
- RingBuffer(size_t capacity)
- : m_capacity(capacity)
- , m_data(capacity)
- , m_pts(capacity)
- {}
- void push(const T& value, double pts)
- {
- std::unique_lock<std::mutex> lock(m_mutex);
- if (m_data[m_writeIndex]) {
- // 释放旧帧
- if (m_deleter)
- m_deleter(m_data[m_writeIndex]);
- }
- m_data[m_writeIndex] = value;
- m_pts[m_writeIndex] = pts;
- m_writeIndex = (m_writeIndex + 1) % m_capacity;
- if (m_size < m_capacity)
- ++m_size;
- else
- m_readIndex = (m_readIndex + 1) % m_capacity; // 覆盖最旧
- }
- // 按索引获取
- T get(size_t index)
- {
- std::unique_lock<std::mutex> lock(m_mutex);
- if (index >= m_size)
- return nullptr;
- size_t realIndex = (m_readIndex + index) % m_capacity;
- return m_data[realIndex];
- }
- // 按PTS查找最近帧
- size_t getIndexByPts(double pts)
- {
- std::unique_lock<std::mutex> lock(m_mutex);
- if (m_size == 0)
- return 0;
- size_t best = m_readIndex;
- double minDiff = std::abs(m_pts[best] - pts);
- for (size_t i = 1; i < m_size; ++i) {
- size_t idx = (m_readIndex + i) % m_capacity;
- double diff = std::abs(m_pts[idx] - pts);
- if (diff < minDiff) {
- minDiff = diff;
- best = idx;
- }
- }
- if (best >= m_readIndex)
- return best - m_readIndex;
- else
- return m_capacity - m_readIndex + best;
- }
- size_t size() const { return m_size; }
- size_t capacity() const { return m_capacity; }
- double firstPts() const { return m_pts[m_readIndex]; }
- double lastPts() const { return m_pts[(m_writeIndex + m_capacity - 1) % m_capacity]; }
- void setDeleter(std::function<void(T&)> deleter) { m_deleter = deleter; }
- void clear()
- {
- std::unique_lock<std::mutex> lock(m_mutex);
- if (m_deleter) {
- for (size_t i = 0; i < m_capacity; ++i) {
- if (m_data[i])
- m_deleter(m_data[i]);
- }
- }
- m_data.assign(m_capacity, nullptr);
- m_pts.assign(m_capacity, 0.0);
- m_size = 0;
- m_readIndex = 0;
- m_writeIndex = 0;
- }
- // 按PTS弹出最近帧
- T popNearest(double pts) {
- std::unique_lock<std::mutex> lock(m_mutex);
- if (m_size == 0) return nullptr;
- size_t best = m_readIndex;
- double minDiff = std::abs(m_pts[best] - pts);
- for (size_t i = 1; i < m_size; ++i) {
- size_t idx = (m_readIndex + i) % m_capacity;
- double diff = std::abs(m_pts[idx] - pts);
- if (diff < minDiff) {
- minDiff = diff;
- best = idx;
- }
- }
- T result = m_data[best];
- m_data[best] = nullptr;
- // 移动readIndex和size
- if (best == m_readIndex) {
- m_readIndex = (m_readIndex + 1) % m_capacity;
- --m_size;
- } else {
- // 只清空,不移动readIndex,保证弹出的是最近帧
- }
- return result;
- }
- private:
- std::vector<T> m_data;
- std::vector<double> m_pts;
- size_t m_capacity;
- size_t m_size = 0;
- size_t m_readIndex = 0;
- size_t m_writeIndex = 0;
- std::function<void(T&)> m_deleter;
- mutable std::mutex m_mutex;
- };
- #endif // RINGBUFFER_H
|