blob: d02a99749a2f36954f82faeeee7487b8ceb47582 [file] [log] [blame]
philipelceac5d52021-12-07 18:13:09 +01001/*
2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "modules/video_coding/frame_buffer3.h"
12
13#include <algorithm>
14#include <iterator>
15#include <queue>
16#include <utility>
17
18#include "absl/algorithm/container.h"
19#include "absl/container/inlined_vector.h"
20#include "rtc_base/logging.h"
21#include "rtc_base/numerics/sequence_number_util.h"
22#include "system_wrappers/include/field_trial.h"
23
24namespace webrtc {
25namespace {
26bool ValidReferences(const EncodedFrame& frame) {
27 // All references must point backwards, and duplicates are not allowed.
28 for (size_t i = 0; i < frame.num_references; ++i) {
29 if (frame.references[i] >= frame.Id())
30 return false;
31
32 for (size_t j = i + 1; j < frame.num_references; ++j) {
33 if (frame.references[i] == frame.references[j])
34 return false;
35 }
36 }
37
38 return true;
39}
40
41// Since FrameBuffer::FrameInfo is private it can't be used in the function
42// signature, hence the FrameIteratorT type.
43template <typename FrameIteratorT>
44rtc::ArrayView<const int64_t> GetReferences(const FrameIteratorT& it) {
45 return {it->second.encoded_frame->references,
46 std::min<size_t>(it->second.encoded_frame->num_references,
47 EncodedFrame::kMaxFrameReferences)};
48}
49
50template <typename FrameIteratorT>
51int64_t GetFrameId(const FrameIteratorT& it) {
52 return it->first;
53}
54
55template <typename FrameIteratorT>
56int64_t GetTimestamp(const FrameIteratorT& it) {
57 return it->second.encoded_frame->Timestamp();
58}
59
60template <typename FrameIteratorT>
61bool IsLastFrameInTemporalUnit(const FrameIteratorT& it) {
62 return it->second.encoded_frame->is_last_spatial_layer;
63}
64} // namespace
65
66FrameBuffer::FrameBuffer(int max_size, int max_decode_history)
67 : legacy_frame_id_jump_behavior_(
Evan Shrubsoleb39fce82022-01-21 14:51:18 +010068 !field_trial::IsDisabled("WebRTC-LegacyFrameIdJumpBehavior")),
philipelceac5d52021-12-07 18:13:09 +010069 max_size_(max_size),
70 decoded_frame_history_(max_decode_history) {}
71
72void FrameBuffer::InsertFrame(std::unique_ptr<EncodedFrame> frame) {
73 if (!ValidReferences(*frame)) {
74 RTC_DLOG(LS_WARNING) << "Frame " << frame->Id()
75 << " has invalid references, dropping frame.";
76 return;
77 }
78
79 if (frame->Id() <= decoded_frame_history_.GetLastDecodedFrameId()) {
80 if (legacy_frame_id_jump_behavior_ && frame->is_keyframe() &&
81 AheadOf(frame->Timestamp(),
82 *decoded_frame_history_.GetLastDecodedFrameTimestamp())) {
83 RTC_DLOG(LS_WARNING)
84 << "Keyframe " << frame->Id()
85 << " has newer timestamp but older picture id, clearing buffer.";
86 Clear();
87 } else {
88 // Already decoded past this frame.
89 return;
90 }
91 }
92
93 if (frames_.size() == max_size_) {
94 if (frame->is_keyframe()) {
95 RTC_DLOG(LS_WARNING) << "Keyframe " << frame->Id()
96 << " inserted into full buffer, clearing buffer.";
97 Clear();
98 } else {
99 // No space for this frame.
100 return;
101 }
102 }
103
104 const int64_t frame_id = frame->Id();
105 auto insert_res = frames_.emplace(frame_id, FrameInfo{std::move(frame)});
106 if (!insert_res.second) {
107 // Frame has already been inserted.
108 return;
109 }
110
111 if (frames_.size() == max_size_) {
112 RTC_DLOG(LS_WARNING) << "Frame " << frame_id
113 << " inserted, buffer is now full.";
114 }
115
116 PropagateContinuity(insert_res.first);
117 FindNextAndLastDecodableTemporalUnit();
118}
119
120absl::InlinedVector<std::unique_ptr<EncodedFrame>, 4>
121FrameBuffer::ExtractNextDecodableTemporalUnit() {
122 absl::InlinedVector<std::unique_ptr<EncodedFrame>, 4> res;
123 if (!next_decodable_temporal_unit_) {
124 return res;
125 }
126
127 auto end_it = std::next(next_decodable_temporal_unit_->last_frame);
128 for (auto it = next_decodable_temporal_unit_->first_frame; it != end_it;
129 ++it) {
130 decoded_frame_history_.InsertDecoded(GetFrameId(it), GetTimestamp(it));
131 res.push_back(std::move(it->second.encoded_frame));
132 }
133
134 DropNextDecodableTemporalUnit();
135 return res;
136}
137
138void FrameBuffer::DropNextDecodableTemporalUnit() {
139 if (!next_decodable_temporal_unit_) {
140 return;
141 }
142
143 auto end_it = std::next(next_decodable_temporal_unit_->last_frame);
144 num_dropped_frames_ += std::count_if(
145 frames_.begin(), end_it,
146 [](const auto& f) { return f.second.encoded_frame != nullptr; });
147
148 frames_.erase(frames_.begin(), end_it);
149 FindNextAndLastDecodableTemporalUnit();
150}
151
152absl::optional<int64_t> FrameBuffer::LastContinuousFrameId() const {
153 return last_continuous_frame_id_;
154}
155
156absl::optional<int64_t> FrameBuffer::LastContinuousTemporalUnitFrameId() const {
157 return last_continuous_temporal_unit_frame_id_;
158}
159
160absl::optional<uint32_t> FrameBuffer::NextDecodableTemporalUnitRtpTimestamp()
161 const {
162 if (!next_decodable_temporal_unit_) {
163 return absl::nullopt;
164 }
165 return GetTimestamp(next_decodable_temporal_unit_->first_frame);
166}
167
168absl::optional<uint32_t> FrameBuffer::LastDecodableTemporalUnitRtpTimestamp()
169 const {
170 return last_decodable_temporal_unit_timestamp_;
171}
172
173int FrameBuffer::GetTotalNumberOfContinuousTemporalUnits() const {
174 return num_continuous_temporal_units_;
175}
176int FrameBuffer::GetTotalNumberOfDroppedFrames() const {
177 return num_dropped_frames_;
178}
179
Evan Shrubsole9a999052021-12-12 15:27:00 +0100180size_t FrameBuffer::CurrentSize() const {
181 return frames_.size();
182}
183
philipelceac5d52021-12-07 18:13:09 +0100184bool FrameBuffer::IsContinuous(const FrameIterator& it) const {
185 for (int64_t reference : GetReferences(it)) {
186 if (decoded_frame_history_.WasDecoded(reference)) {
187 continue;
188 }
189
190 auto reference_frame_it = frames_.find(reference);
191 if (reference_frame_it != frames_.end() &&
192 reference_frame_it->second.continuous) {
193 continue;
194 }
195
196 return false;
197 }
198
199 return true;
200}
201
202void FrameBuffer::PropagateContinuity(const FrameIterator& frame_it) {
203 for (auto it = frame_it; it != frames_.end(); ++it) {
204 if (!it->second.continuous) {
205 if (IsContinuous(it)) {
206 it->second.continuous = true;
207 if (last_continuous_frame_id_ < GetFrameId(it)) {
208 last_continuous_frame_id_ = GetFrameId(it);
209 }
210 if (IsLastFrameInTemporalUnit(it)) {
211 num_continuous_temporal_units_++;
212 if (last_continuous_temporal_unit_frame_id_ < GetFrameId(it)) {
213 last_continuous_temporal_unit_frame_id_ = GetFrameId(it);
214 }
215 }
216 }
217 }
218 }
219}
220
221void FrameBuffer::FindNextAndLastDecodableTemporalUnit() {
222 next_decodable_temporal_unit_.reset();
223 last_decodable_temporal_unit_timestamp_.reset();
224
225 if (!last_continuous_temporal_unit_frame_id_) {
226 return;
227 }
228
229 FrameIterator first_frame_it = frames_.begin();
230 FrameIterator last_frame_it = frames_.begin();
231 absl::InlinedVector<int64_t, 4> frames_in_temporal_unit;
232 for (auto frame_it = frames_.begin(); frame_it != frames_.end();) {
233 if (GetFrameId(frame_it) > *last_continuous_temporal_unit_frame_id_) {
234 break;
235 }
236
237 if (GetTimestamp(frame_it) != GetTimestamp(first_frame_it)) {
238 frames_in_temporal_unit.clear();
239 first_frame_it = frame_it;
240 }
241
242 frames_in_temporal_unit.push_back(GetFrameId(frame_it));
243
244 last_frame_it = frame_it++;
245
246 if (IsLastFrameInTemporalUnit(last_frame_it)) {
247 bool temporal_unit_decodable = true;
248 for (auto it = first_frame_it; it != frame_it && temporal_unit_decodable;
249 ++it) {
250 for (int64_t reference : GetReferences(it)) {
251 if (!decoded_frame_history_.WasDecoded(reference) &&
252 !absl::c_linear_search(frames_in_temporal_unit, reference)) {
253 // A frame in the temporal unit has a non-decoded reference outside
254 // the temporal unit, so it's not yet ready to be decoded.
255 temporal_unit_decodable = false;
256 break;
257 }
258 }
259 }
260
261 if (temporal_unit_decodable) {
262 if (!next_decodable_temporal_unit_) {
263 next_decodable_temporal_unit_ = {first_frame_it, last_frame_it};
264 }
265
266 last_decodable_temporal_unit_timestamp_ = GetTimestamp(first_frame_it);
267 }
268 }
269 }
270}
271
272void FrameBuffer::Clear() {
273 frames_.clear();
274 next_decodable_temporal_unit_.reset();
275 last_decodable_temporal_unit_timestamp_.reset();
276 last_continuous_frame_id_.reset();
277 last_continuous_temporal_unit_frame_id_.reset();
278 decoded_frame_history_.Clear();
279}
280
281} // namespace webrtc