blob: 786465c92c03543b8e3b312ec116fcfd26ed2b0a [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#include "modules/video_coding/frame_buffer3.h"
11
12#include <vector>
13
14#include "api/video/encoded_frame.h"
15#include "test/field_trial.h"
16#include "test/gmock.h"
17#include "test/gtest.h"
18
19namespace webrtc {
20namespace {
21
22using ::testing::ElementsAre;
23using ::testing::Eq;
24using ::testing::IsEmpty;
25using ::testing::Matches;
26
27MATCHER_P(FrameWithId, id, "") {
28 return Matches(Eq(id))(arg->Id());
29}
30
31class FakeEncodedFrame : public EncodedFrame {
32 public:
33 int64_t ReceivedTime() const override { return 0; }
34 int64_t RenderTime() const override { return 0; }
35};
36
37class Builder {
38 public:
39 Builder& Time(uint32_t rtp_timestamp) {
40 rtp_timestamp_ = rtp_timestamp;
41 return *this;
42 }
43 Builder& Id(int64_t frame_id) {
44 frame_id_ = frame_id;
45 return *this;
46 }
47 Builder& AsLast() {
48 last_spatial_layer_ = true;
49 return *this;
50 }
51 Builder& Refs(const std::vector<int64_t>& references) {
52 references_ = references;
53 return *this;
54 }
55
56 std::unique_ptr<FakeEncodedFrame> Build() {
57 RTC_CHECK_LE(references_.size(), EncodedFrame::kMaxFrameReferences);
58 RTC_CHECK(rtp_timestamp_.has_value());
59 RTC_CHECK(frame_id_.has_value());
60
61 auto frame = std::make_unique<FakeEncodedFrame>();
62 frame->SetTimestamp(*rtp_timestamp_);
63 frame->SetId(*frame_id_);
64 frame->is_last_spatial_layer = last_spatial_layer_;
65
66 for (int64_t ref : references_) {
67 frame->references[frame->num_references] = ref;
68 frame->num_references++;
69 }
70
71 return frame;
72 }
73
74 private:
75 absl::optional<uint32_t> rtp_timestamp_;
76 absl::optional<int64_t> frame_id_;
77 bool last_spatial_layer_ = false;
78 std::vector<int64_t> references_;
79};
80
81TEST(FrameBuffer3Test, RejectInvalidRefs) {
82 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
83 // Ref must be less than the id of this frame.
84 buffer.InsertFrame(Builder().Time(0).Id(0).Refs({0}).AsLast().Build());
85 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt));
86
87 // Duplicate ids are also invalid.
88 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
89 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1, 1}).AsLast().Build());
90 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
91}
92
93TEST(FrameBuffer3Test, LastContinuousUpdatesOnInsertedFrames) {
94 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
95 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt));
96 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
97
98 buffer.InsertFrame(Builder().Time(10).Id(1).Build());
99 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
100 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
101
102 buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).AsLast().Build());
103 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(2));
104 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(2));
105}
106
107TEST(FrameBuffer3Test, LastContinuousFrameReordering) {
108 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
109
110 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
111 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build());
112 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
113
114 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
115 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(3));
116}
117
118TEST(FrameBuffer3Test, LastContinuousTemporalUnit) {
119 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
120
121 buffer.InsertFrame(Builder().Time(10).Id(1).Build());
122 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
123 buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).AsLast().Build());
124 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(2));
125}
126
127TEST(FrameBuffer3Test, LastContinuousTemporalUnitReordering) {
128 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
129
130 buffer.InsertFrame(Builder().Time(10).Id(1).Build());
131 buffer.InsertFrame(Builder().Time(20).Id(3).Refs({1}).Build());
132 buffer.InsertFrame(Builder().Time(20).Id(4).Refs({2, 3}).AsLast().Build());
133 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
134
135 buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).AsLast().Build());
136 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(4));
137}
138
139TEST(FrameBuffer3Test, NextDecodable) {
140 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
141
142 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(),
143 Eq(absl::nullopt));
144 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
145 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U));
146}
147
148TEST(FrameBuffer3Test, AdvanceNextDecodableOnExtraction) {
149 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
150
151 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
152 buffer.InsertFrame(Builder().Time(20).Id(2).AsLast().Build());
153 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build());
154 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U));
155
156 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
157 ElementsAre(FrameWithId(1)));
158 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(20U));
159 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
160 ElementsAre(FrameWithId(2)));
161 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(30U));
162 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
163 ElementsAre(FrameWithId(3)));
164}
165
166TEST(FrameBuffer3Test, AdvanceLastDecodableOnExtraction) {
167 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
168
169 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
170 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
171 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
172 EXPECT_THAT(buffer.LastDecodableTemporalUnitRtpTimestamp(), Eq(10U));
173
174 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
175 ElementsAre(FrameWithId(1)));
176 EXPECT_THAT(buffer.LastDecodableTemporalUnitRtpTimestamp(), Eq(30U));
177}
178
179TEST(FrameBuffer3Test, FrameUpdatesNextDecodable) {
180 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
181
182 buffer.InsertFrame(Builder().Time(20).Id(2).AsLast().Build());
183 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(20U));
184
185 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
186 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U));
187}
188
189TEST(FrameBuffer3Test, KeyframeClearsFullBuffer) {
190 FrameBuffer buffer(/*max_frame_slots=*/5, /*max_decode_history=*/10);
191 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
192 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
193 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build());
194 buffer.InsertFrame(Builder().Time(40).Id(4).Refs({3}).AsLast().Build());
195 buffer.InsertFrame(Builder().Time(50).Id(5).Refs({4}).AsLast().Build());
196 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(5));
197
198 // Frame buffer is full
199 buffer.InsertFrame(Builder().Time(60).Id(6).Refs({5}).AsLast().Build());
200 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(5));
201
202 buffer.InsertFrame(Builder().Time(70).Id(7).AsLast().Build());
203 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(7));
204}
205
206TEST(FrameBuffer3Test, DropNextDecodableTemporalUnit) {
207 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
208 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
209 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
210 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
211
212 buffer.ExtractNextDecodableTemporalUnit();
213 buffer.DropNextDecodableTemporalUnit();
214 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
215 ElementsAre(FrameWithId(3)));
216}
217
218TEST(FrameBuffer3Test, OldFramesAreIgnored) {
219 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
220 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
221 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
222
223 buffer.ExtractNextDecodableTemporalUnit();
224 buffer.ExtractNextDecodableTemporalUnit();
225
226 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
227 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
228 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
229
230 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
231 ElementsAre(FrameWithId(3)));
232}
233
234TEST(FrameBuffer3Test, ReturnFullTemporalUnitKSVC) {
235 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
236 buffer.InsertFrame(Builder().Time(10).Id(1).Build());
237 buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).Build());
238 buffer.InsertFrame(Builder().Time(10).Id(3).Refs({2}).AsLast().Build());
239 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
240 ElementsAre(FrameWithId(1), FrameWithId(2), FrameWithId(3)));
241
242 buffer.InsertFrame(Builder().Time(20).Id(4).Refs({3}).AsLast().Build());
243 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
244 ElementsAre(FrameWithId(4)));
245}
246
247TEST(FrameBuffer3Test, InterleavedStream) {
248 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
249 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
250 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
251 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
252 buffer.InsertFrame(Builder().Time(40).Id(4).Refs({2}).AsLast().Build());
253 buffer.InsertFrame(Builder().Time(50).Id(5).Refs({3}).AsLast().Build());
254
255 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
256 ElementsAre(FrameWithId(1)));
257 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
258 ElementsAre(FrameWithId(2)));
259 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
260 ElementsAre(FrameWithId(3)));
261 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
262 ElementsAre(FrameWithId(4)));
263 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
264 ElementsAre(FrameWithId(5)));
265
266 buffer.InsertFrame(Builder().Time(70).Id(7).Refs({5}).AsLast().Build());
267 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
268 ElementsAre(FrameWithId(7)));
269 buffer.InsertFrame(Builder().Time(60).Id(6).Refs({4}).AsLast().Build());
270 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty());
271 buffer.InsertFrame(Builder().Time(90).Id(9).Refs({7}).AsLast().Build());
272 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
273 ElementsAre(FrameWithId(9)));
274}
275
276TEST(FrameBuffer3Test, LegacyFrameIdJumpBehavior) {
277 {
278 // WebRTC-LegacyFrameIdJumpBehavior is disabled by default.
279 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
280
281 buffer.InsertFrame(Builder().Time(20).Id(3).AsLast().Build());
282 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
283 ElementsAre(FrameWithId(3)));
284 buffer.InsertFrame(Builder().Time(30).Id(2).AsLast().Build());
285 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty());
286 }
287
288 {
289 test::ScopedFieldTrials field_trial(
290 "WebRTC-LegacyFrameIdJumpBehavior/Enabled/");
291 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
292
293 buffer.InsertFrame(Builder().Time(20).Id(3).AsLast().Build());
294 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
295 ElementsAre(FrameWithId(3)));
296 buffer.InsertFrame(Builder().Time(30).Id(2).Refs({1}).AsLast().Build());
297 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty());
298 buffer.InsertFrame(Builder().Time(40).Id(1).AsLast().Build());
299 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
300 ElementsAre(FrameWithId(1)));
301 }
302}
303
304TEST(FrameBuffer3Test, TotalNumberOfContinuousTemporalUnits) {
305 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
306 EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(0));
307
308 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
309 EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
310
311 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).Build());
312 EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
313
314 buffer.InsertFrame(Builder().Time(40).Id(4).Refs({2}).Build());
315 buffer.InsertFrame(Builder().Time(40).Id(5).Refs({3, 4}).AsLast().Build());
316 EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
317
318 // Reordered
319 buffer.InsertFrame(Builder().Time(20).Id(3).Refs({2}).AsLast().Build());
320 EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(3));
321}
322
323TEST(FrameBuffer3Test, TotalNumberOfDroppedFrames) {
324 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100);
325 EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0));
326
327 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
328 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).Build());
329 buffer.InsertFrame(Builder().Time(20).Id(3).Refs({2}).AsLast().Build());
330 buffer.InsertFrame(Builder().Time(40).Id(4).Refs({1}).Build());
331 buffer.InsertFrame(Builder().Time(40).Id(5).Refs({4}).AsLast().Build());
332
333 buffer.ExtractNextDecodableTemporalUnit();
334 EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0));
335
336 buffer.DropNextDecodableTemporalUnit();
337 EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(2));
338
339 buffer.ExtractNextDecodableTemporalUnit();
340 EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(2));
341}
342
343} // namespace
344} // namespace webrtc