diff options
Diffstat (limited to 'third_party/libwebrtc/test/pc/e2e/analyzer/video/dvqa/frames_storage.cc')
-rw-r--r-- | third_party/libwebrtc/test/pc/e2e/analyzer/video/dvqa/frames_storage.cc | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/third_party/libwebrtc/test/pc/e2e/analyzer/video/dvqa/frames_storage.cc b/third_party/libwebrtc/test/pc/e2e/analyzer/video/dvqa/frames_storage.cc new file mode 100644 index 0000000000..2a70468e69 --- /dev/null +++ b/third_party/libwebrtc/test/pc/e2e/analyzer/video/dvqa/frames_storage.cc @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2023 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "test/pc/e2e/analyzer/video/dvqa/frames_storage.h" + +#include <cstdint> +#include <utility> + +#include "absl/types/optional.h" +#include "api/units/timestamp.h" +#include "api/video/video_frame.h" + +namespace webrtc { + +void FramesStorage::Add(const VideoFrame& frame, Timestamp captured_time) { + heap_.push_back(HeapNode{.frame = frame, .captured_time = captured_time}); + frame_id_index_[frame.id()] = heap_.size() - 1; + Heapify(heap_.size() - 1); + RemoveTooOldFrames(); +} + +absl::optional<VideoFrame> FramesStorage::Get(uint16_t frame_id) { + auto it = frame_id_index_.find(frame_id); + if (it == frame_id_index_.end()) { + return absl::nullopt; + } + + return heap_[it->second].frame; +} + +void FramesStorage::Remove(uint16_t frame_id) { + RemoveInternal(frame_id); + RemoveTooOldFrames(); +} + +void FramesStorage::RemoveInternal(uint16_t frame_id) { + auto it = frame_id_index_.find(frame_id); + if (it == frame_id_index_.end()) { + return; + } + + size_t index = it->second; + frame_id_index_.erase(it); + + // If it's not the last element in the heap, swap the last element in the heap + // with element to remove. + if (index != heap_.size() - 1) { + heap_[index] = std::move(heap_[heap_.size() - 1]); + frame_id_index_[heap_[index].frame.id()] = index; + } + + // Remove the last element. + heap_.pop_back(); + + if (index < heap_.size()) { + Heapify(index); + } +} + +void FramesStorage::Heapify(size_t index) { + HeapifyUp(index); + HeapifyDown(index); +} + +void FramesStorage::HeapifyUp(size_t index) { + if (index == 0) { + return; + } + RTC_CHECK_LT(index, heap_.size()); + size_t parent = index / 2; + if (heap_[parent].captured_time <= heap_[index].captured_time) { + return; + } + HeapNode tmp = std::move(heap_[index]); + heap_[index] = std::move(heap_[parent]); + heap_[parent] = std::move(tmp); + + frame_id_index_[heap_[index].frame.id()] = index; + frame_id_index_[heap_[parent].frame.id()] = parent; + + HeapifyUp(parent); +} + +void FramesStorage::HeapifyDown(size_t index) { + RTC_CHECK_GE(index, 0); + RTC_CHECK_LT(index, heap_.size()); + + size_t left_child = 2 * index; + size_t right_child = 2 * index + 1; + + if (left_child >= heap_.size()) { + return; + } + size_t smallest_child = left_child; + if (right_child < heap_.size() && + heap_[right_child].captured_time < heap_[left_child].captured_time) { + smallest_child = right_child; + } + + if (heap_[index].captured_time <= heap_[smallest_child].captured_time) { + return; + } + + HeapNode tmp = std::move(heap_[index]); + heap_[index] = std::move(heap_[smallest_child]); + heap_[smallest_child] = std::move(tmp); + + frame_id_index_[heap_[index].frame.id()] = index; + frame_id_index_[heap_[smallest_child].frame.id()] = smallest_child; + + HeapifyDown(smallest_child); +} + +void FramesStorage::RemoveTooOldFrames() { + Timestamp now = clock_->CurrentTime(); + while (!heap_.empty() && + (heap_[0].captured_time + max_storage_duration_) < now) { + RemoveInternal(heap_[0].frame.id()); + } +} + +} // namespace webrtc |