blob: 27a25f2309c49d5b499bb38f1bd1119292bf2aa6 [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"
Jonas Orelande02f9ee2022-03-25 12:43:14 +010018#include "test/scoped_key_value_config.h"
philipelceac5d52021-12-07 18:13:09 +010019
20namespace webrtc {
21namespace {
22
23using ::testing::ElementsAre;
24using ::testing::Eq;
25using ::testing::IsEmpty;
26using ::testing::Matches;
27
28MATCHER_P(FrameWithId, id, "") {
29 return Matches(Eq(id))(arg->Id());
30}
31
32class FakeEncodedFrame : public EncodedFrame {
33 public:
34 int64_t ReceivedTime() const override { return 0; }
35 int64_t RenderTime() const override { return 0; }
36};
37
38class Builder {
39 public:
40 Builder& Time(uint32_t rtp_timestamp) {
41 rtp_timestamp_ = rtp_timestamp;
42 return *this;
43 }
44 Builder& Id(int64_t frame_id) {
45 frame_id_ = frame_id;
46 return *this;
47 }
48 Builder& AsLast() {
49 last_spatial_layer_ = true;
50 return *this;
51 }
52 Builder& Refs(const std::vector<int64_t>& references) {
53 references_ = references;
54 return *this;
55 }
56
57 std::unique_ptr<FakeEncodedFrame> Build() {
58 RTC_CHECK_LE(references_.size(), EncodedFrame::kMaxFrameReferences);
59 RTC_CHECK(rtp_timestamp_.has_value());
60 RTC_CHECK(frame_id_.has_value());
61
62 auto frame = std::make_unique<FakeEncodedFrame>();
63 frame->SetTimestamp(*rtp_timestamp_);
64 frame->SetId(*frame_id_);
65 frame->is_last_spatial_layer = last_spatial_layer_;
66
67 for (int64_t ref : references_) {
68 frame->references[frame->num_references] = ref;
69 frame->num_references++;
70 }
71
72 return frame;
73 }
74
75 private:
76 absl::optional<uint32_t> rtp_timestamp_;
77 absl::optional<int64_t> frame_id_;
78 bool last_spatial_layer_ = false;
79 std::vector<int64_t> references_;
80};
81
82TEST(FrameBuffer3Test, RejectInvalidRefs) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +010083 test::ScopedKeyValueConfig field_trials;
84 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
85 field_trials);
philipelceac5d52021-12-07 18:13:09 +010086 // Ref must be less than the id of this frame.
87 buffer.InsertFrame(Builder().Time(0).Id(0).Refs({0}).AsLast().Build());
88 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt));
89
90 // Duplicate ids are also invalid.
91 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
92 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1, 1}).AsLast().Build());
93 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
94}
95
96TEST(FrameBuffer3Test, LastContinuousUpdatesOnInsertedFrames) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +010097 test::ScopedKeyValueConfig field_trials;
98 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
99 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100100 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt));
101 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
102
103 buffer.InsertFrame(Builder().Time(10).Id(1).Build());
104 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
105 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
106
107 buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).AsLast().Build());
108 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(2));
109 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(2));
110}
111
112TEST(FrameBuffer3Test, LastContinuousFrameReordering) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100113 test::ScopedKeyValueConfig field_trials;
114 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
115 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100116
117 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
118 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build());
119 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
120
121 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
122 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(3));
123}
124
125TEST(FrameBuffer3Test, LastContinuousTemporalUnit) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100126 test::ScopedKeyValueConfig field_trials;
127 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
128 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100129
130 buffer.InsertFrame(Builder().Time(10).Id(1).Build());
131 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
132 buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).AsLast().Build());
133 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(2));
134}
135
136TEST(FrameBuffer3Test, LastContinuousTemporalUnitReordering) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100137 test::ScopedKeyValueConfig field_trials;
138 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
139 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100140
141 buffer.InsertFrame(Builder().Time(10).Id(1).Build());
142 buffer.InsertFrame(Builder().Time(20).Id(3).Refs({1}).Build());
143 buffer.InsertFrame(Builder().Time(20).Id(4).Refs({2, 3}).AsLast().Build());
144 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
145
146 buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).AsLast().Build());
147 EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(4));
148}
149
150TEST(FrameBuffer3Test, NextDecodable) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100151 test::ScopedKeyValueConfig field_trials;
152 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
153 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100154
155 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(),
156 Eq(absl::nullopt));
157 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
158 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U));
159}
160
161TEST(FrameBuffer3Test, AdvanceNextDecodableOnExtraction) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100162 test::ScopedKeyValueConfig field_trials;
163 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
164 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100165
166 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
167 buffer.InsertFrame(Builder().Time(20).Id(2).AsLast().Build());
168 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build());
169 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U));
170
171 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
172 ElementsAre(FrameWithId(1)));
173 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(20U));
174 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
175 ElementsAre(FrameWithId(2)));
176 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(30U));
177 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
178 ElementsAre(FrameWithId(3)));
179}
180
181TEST(FrameBuffer3Test, AdvanceLastDecodableOnExtraction) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100182 test::ScopedKeyValueConfig field_trials;
183 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
184 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100185
186 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
187 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
188 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
189 EXPECT_THAT(buffer.LastDecodableTemporalUnitRtpTimestamp(), Eq(10U));
190
191 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
192 ElementsAre(FrameWithId(1)));
193 EXPECT_THAT(buffer.LastDecodableTemporalUnitRtpTimestamp(), Eq(30U));
194}
195
196TEST(FrameBuffer3Test, FrameUpdatesNextDecodable) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100197 test::ScopedKeyValueConfig field_trials;
198 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
199 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100200
201 buffer.InsertFrame(Builder().Time(20).Id(2).AsLast().Build());
202 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(20U));
203
204 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
205 EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U));
206}
207
208TEST(FrameBuffer3Test, KeyframeClearsFullBuffer) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100209 test::ScopedKeyValueConfig field_trials;
210 FrameBuffer buffer(/*max_frame_slots=*/5, /*max_decode_history=*/10,
211 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100212 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
213 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
214 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build());
215 buffer.InsertFrame(Builder().Time(40).Id(4).Refs({3}).AsLast().Build());
216 buffer.InsertFrame(Builder().Time(50).Id(5).Refs({4}).AsLast().Build());
217 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(5));
218
219 // Frame buffer is full
220 buffer.InsertFrame(Builder().Time(60).Id(6).Refs({5}).AsLast().Build());
221 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(5));
222
223 buffer.InsertFrame(Builder().Time(70).Id(7).AsLast().Build());
224 EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(7));
225}
226
227TEST(FrameBuffer3Test, DropNextDecodableTemporalUnit) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100228 test::ScopedKeyValueConfig field_trials;
229 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
230 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100231 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
232 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
233 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
234
235 buffer.ExtractNextDecodableTemporalUnit();
236 buffer.DropNextDecodableTemporalUnit();
237 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
238 ElementsAre(FrameWithId(3)));
239}
240
241TEST(FrameBuffer3Test, OldFramesAreIgnored) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100242 test::ScopedKeyValueConfig field_trials;
243 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
244 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100245 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
246 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
247
248 buffer.ExtractNextDecodableTemporalUnit();
249 buffer.ExtractNextDecodableTemporalUnit();
250
251 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
252 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
253 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
254
255 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
256 ElementsAre(FrameWithId(3)));
257}
258
259TEST(FrameBuffer3Test, ReturnFullTemporalUnitKSVC) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100260 test::ScopedKeyValueConfig field_trials;
261 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
262 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100263 buffer.InsertFrame(Builder().Time(10).Id(1).Build());
264 buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).Build());
265 buffer.InsertFrame(Builder().Time(10).Id(3).Refs({2}).AsLast().Build());
266 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
267 ElementsAre(FrameWithId(1), FrameWithId(2), FrameWithId(3)));
268
269 buffer.InsertFrame(Builder().Time(20).Id(4).Refs({3}).AsLast().Build());
270 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
271 ElementsAre(FrameWithId(4)));
272}
273
274TEST(FrameBuffer3Test, InterleavedStream) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100275 test::ScopedKeyValueConfig field_trials;
276 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
277 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100278 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
279 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
280 buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
281 buffer.InsertFrame(Builder().Time(40).Id(4).Refs({2}).AsLast().Build());
282 buffer.InsertFrame(Builder().Time(50).Id(5).Refs({3}).AsLast().Build());
283
284 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
285 ElementsAre(FrameWithId(1)));
286 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
287 ElementsAre(FrameWithId(2)));
288 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
289 ElementsAre(FrameWithId(3)));
290 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
291 ElementsAre(FrameWithId(4)));
292 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
293 ElementsAre(FrameWithId(5)));
294
295 buffer.InsertFrame(Builder().Time(70).Id(7).Refs({5}).AsLast().Build());
296 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
297 ElementsAre(FrameWithId(7)));
298 buffer.InsertFrame(Builder().Time(60).Id(6).Refs({4}).AsLast().Build());
299 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty());
300 buffer.InsertFrame(Builder().Time(90).Id(9).Refs({7}).AsLast().Build());
301 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
302 ElementsAre(FrameWithId(9)));
303}
304
305TEST(FrameBuffer3Test, LegacyFrameIdJumpBehavior) {
306 {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100307 test::ScopedKeyValueConfig field_trials(
Evan Shrubsoleb39fce82022-01-21 14:51:18 +0100308 "WebRTC-LegacyFrameIdJumpBehavior/Disabled/");
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100309 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
310 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100311
312 buffer.InsertFrame(Builder().Time(20).Id(3).AsLast().Build());
313 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
314 ElementsAre(FrameWithId(3)));
315 buffer.InsertFrame(Builder().Time(30).Id(2).AsLast().Build());
316 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty());
317 }
318
319 {
Evan Shrubsoleb39fce82022-01-21 14:51:18 +0100320 // WebRTC-LegacyFrameIdJumpBehavior is disabled by default.
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100321 test::ScopedKeyValueConfig field_trials;
322 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
323 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100324
325 buffer.InsertFrame(Builder().Time(20).Id(3).AsLast().Build());
326 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
327 ElementsAre(FrameWithId(3)));
328 buffer.InsertFrame(Builder().Time(30).Id(2).Refs({1}).AsLast().Build());
329 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty());
330 buffer.InsertFrame(Builder().Time(40).Id(1).AsLast().Build());
331 EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
332 ElementsAre(FrameWithId(1)));
333 }
334}
335
336TEST(FrameBuffer3Test, TotalNumberOfContinuousTemporalUnits) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100337 test::ScopedKeyValueConfig field_trials;
338 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
339 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100340 EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(0));
341
342 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
343 EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
344
345 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).Build());
346 EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
347
348 buffer.InsertFrame(Builder().Time(40).Id(4).Refs({2}).Build());
349 buffer.InsertFrame(Builder().Time(40).Id(5).Refs({3, 4}).AsLast().Build());
350 EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
351
352 // Reordered
353 buffer.InsertFrame(Builder().Time(20).Id(3).Refs({2}).AsLast().Build());
354 EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(3));
355}
356
357TEST(FrameBuffer3Test, TotalNumberOfDroppedFrames) {
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100358 test::ScopedKeyValueConfig field_trials;
359 FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
360 field_trials);
philipelceac5d52021-12-07 18:13:09 +0100361 EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0));
362
363 buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
364 buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).Build());
365 buffer.InsertFrame(Builder().Time(20).Id(3).Refs({2}).AsLast().Build());
366 buffer.InsertFrame(Builder().Time(40).Id(4).Refs({1}).Build());
367 buffer.InsertFrame(Builder().Time(40).Id(5).Refs({4}).AsLast().Build());
368
369 buffer.ExtractNextDecodableTemporalUnit();
370 EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0));
371
372 buffer.DropNextDecodableTemporalUnit();
373 EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(2));
374
375 buffer.ExtractNextDecodableTemporalUnit();
376 EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(2));
377}
378
379} // namespace
380} // namespace webrtc