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