| /* | |
| * Copyright (c) 2019 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 "modules/video_coding/utility/decoded_frames_history.h" | |
| #include <algorithm> | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <optional> | |
| #include "rtc_base/checks.h" | |
| #include "rtc_base/logging.h" | |
| namespace webrtc { | |
| namespace video_coding { | |
| DecodedFramesHistory::DecodedFramesHistory(size_t window_size) | |
| : buffer_(window_size) {} | |
| DecodedFramesHistory::~DecodedFramesHistory() = default; | |
| void DecodedFramesHistory::InsertDecoded(int64_t frame_id, uint32_t timestamp) { | |
| last_decoded_frame_ = frame_id; | |
| last_decoded_frame_timestamp_ = timestamp; | |
| int new_index = FrameIdToIndex(frame_id); | |
| RTC_DCHECK(last_frame_id_ < frame_id); | |
| // Clears expired values from the cyclic buffer_. | |
| if (last_frame_id_) { | |
| int64_t id_jump = frame_id - *last_frame_id_; | |
| int last_index = FrameIdToIndex(*last_frame_id_); | |
| if (id_jump >= static_cast<int64_t>(buffer_.size())) { | |
| std::fill(buffer_.begin(), buffer_.end(), false); | |
| } else if (new_index > last_index) { | |
| std::fill(buffer_.begin() + last_index + 1, buffer_.begin() + new_index, | |
| false); | |
| } else { | |
| std::fill(buffer_.begin() + last_index + 1, buffer_.end(), false); | |
| std::fill(buffer_.begin(), buffer_.begin() + new_index, false); | |
| } | |
| } | |
| buffer_[new_index] = true; | |
| last_frame_id_ = frame_id; | |
| } | |
| bool DecodedFramesHistory::WasDecoded(int64_t frame_id) const { | |
| if (!last_frame_id_) | |
| return false; | |
| // Reference to the picture_id out of the stored should happen. | |
| if (frame_id <= *last_frame_id_ - static_cast<int64_t>(buffer_.size())) { | |
| RTC_LOG(LS_WARNING) << "Referencing a frame out of the window. " | |
| "Assuming it was undecoded to avoid artifacts."; | |
| return false; | |
| } | |
| if (frame_id > last_frame_id_) | |
| return false; | |
| return buffer_[FrameIdToIndex(frame_id)]; | |
| } | |
| void DecodedFramesHistory::Clear() { | |
| last_decoded_frame_timestamp_.reset(); | |
| last_decoded_frame_.reset(); | |
| std::fill(buffer_.begin(), buffer_.end(), false); | |
| last_frame_id_.reset(); | |
| } | |
| std::optional<int64_t> DecodedFramesHistory::GetLastDecodedFrameId() const { | |
| return last_decoded_frame_; | |
| } | |
| std::optional<uint32_t> DecodedFramesHistory::GetLastDecodedFrameTimestamp() | |
| const { | |
| return last_decoded_frame_timestamp_; | |
| } | |
| int DecodedFramesHistory::FrameIdToIndex(int64_t frame_id) const { | |
| int m = frame_id % buffer_.size(); | |
| return m >= 0 ? m : m + buffer_.size(); | |
| } | |
| } // namespace video_coding | |
| } // namespace webrtc |