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