summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/api/video/frame_buffer_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/libwebrtc/api/video/frame_buffer_unittest.cc393
1 files changed, 393 insertions, 0 deletions
diff --git a/third_party/libwebrtc/api/video/frame_buffer_unittest.cc b/third_party/libwebrtc/api/video/frame_buffer_unittest.cc
new file mode 100644
index 0000000000..92e2f67540
--- /dev/null
+++ b/third_party/libwebrtc/api/video/frame_buffer_unittest.cc
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "api/video/frame_buffer.h"
+
+#include <vector>
+
+#include "api/video/encoded_frame.h"
+#include "test/fake_encoded_frame.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+#include "test/scoped_key_value_config.h"
+
+namespace webrtc {
+namespace {
+
+using ::testing::ElementsAre;
+using ::testing::Eq;
+using ::testing::IsEmpty;
+using ::testing::Matches;
+
+MATCHER_P(FrameWithId, id, "") {
+ return Matches(Eq(id))(arg->Id());
+}
+
+TEST(FrameBuffer3Test, RejectInvalidRefs) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+ // Ref must be less than the id of this frame.
+ EXPECT_FALSE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(0).Id(0).Refs({0}).AsLast().Build()));
+ EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt));
+
+ // Duplicate ids are also invalid.
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_FALSE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(2).Refs({1, 1}).AsLast().Build()));
+ EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
+}
+
+TEST(FrameBuffer3Test, LastContinuousUpdatesOnInsertedFrames) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+ EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt));
+ EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
+
+ EXPECT_TRUE(
+ buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build()));
+ EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
+ EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).AsLast().Build()));
+ EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(2));
+ EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(2));
+}
+
+TEST(FrameBuffer3Test, LastContinuousFrameReordering) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(30).Id(3).Refs({2}).AsLast().Build()));
+ EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build()));
+ EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(3));
+}
+
+TEST(FrameBuffer3Test, LastContinuousTemporalUnit) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+
+ EXPECT_TRUE(
+ buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build()));
+ EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).AsLast().Build()));
+ EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(2));
+}
+
+TEST(FrameBuffer3Test, LastContinuousTemporalUnitReordering) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+
+ EXPECT_TRUE(
+ buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(3).Refs({1}).Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(4).Refs({2, 3}).AsLast().Build()));
+ EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).AsLast().Build()));
+ EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(4));
+}
+
+TEST(FrameBuffer3Test, NextDecodable) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+
+ EXPECT_THAT(buffer.DecodableTemporalUnitsInfo(), Eq(absl::nullopt));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->next_rtp_timestamp, Eq(10U));
+}
+
+TEST(FrameBuffer3Test, AdvanceNextDecodableOnExtraction) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(2).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(30).Id(3).Refs({2}).AsLast().Build()));
+ EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->next_rtp_timestamp, Eq(10U));
+
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(1)));
+ EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->next_rtp_timestamp, Eq(20U));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(2)));
+ EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->next_rtp_timestamp, Eq(30U));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(3)));
+}
+
+TEST(FrameBuffer3Test, AdvanceLastDecodableOnExtraction) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(30).Id(3).Refs({1}).AsLast().Build()));
+ EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->last_rtp_timestamp, Eq(10U));
+
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(1)));
+ EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->last_rtp_timestamp, Eq(30U));
+}
+
+TEST(FrameBuffer3Test, FrameUpdatesNextDecodable) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(2).AsLast().Build()));
+ EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->next_rtp_timestamp, Eq(20U));
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->next_rtp_timestamp, Eq(10U));
+}
+
+TEST(FrameBuffer3Test, KeyframeClearsFullBuffer) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/5, /*max_decode_history=*/10,
+ field_trials);
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(30).Id(3).Refs({2}).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(40).Id(4).Refs({3}).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(50).Id(5).Refs({4}).AsLast().Build()));
+ EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(5));
+
+ // Frame buffer is full
+ EXPECT_FALSE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(60).Id(6).Refs({5}).AsLast().Build()));
+ EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(5));
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(70).Id(7).AsLast().Build()));
+ EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(7));
+}
+
+TEST(FrameBuffer3Test, DropNextDecodableTemporalUnit) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(30).Id(3).Refs({1}).AsLast().Build()));
+
+ buffer.ExtractNextDecodableTemporalUnit();
+ buffer.DropNextDecodableTemporalUnit();
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(3)));
+}
+
+TEST(FrameBuffer3Test, OldFramesAreIgnored) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build()));
+
+ buffer.ExtractNextDecodableTemporalUnit();
+ buffer.ExtractNextDecodableTemporalUnit();
+
+ EXPECT_FALSE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_FALSE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(30).Id(3).Refs({1}).AsLast().Build()));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(3)));
+}
+
+TEST(FrameBuffer3Test, ReturnFullTemporalUnitKSVC) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+ EXPECT_TRUE(
+ buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(3).Refs({2}).AsLast().Build()));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(1), FrameWithId(2), FrameWithId(3)));
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(4).Refs({3}).AsLast().Build()));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(4)));
+}
+
+TEST(FrameBuffer3Test, InterleavedStream) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(30).Id(3).Refs({1}).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(40).Id(4).Refs({2}).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(50).Id(5).Refs({3}).AsLast().Build()));
+
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(1)));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(2)));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(3)));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(4)));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(5)));
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(70).Id(7).Refs({5}).AsLast().Build()));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(7)));
+ EXPECT_FALSE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(60).Id(6).Refs({4}).AsLast().Build()));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty());
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(90).Id(9).Refs({7}).AsLast().Build()));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(9)));
+}
+
+TEST(FrameBuffer3Test, LegacyFrameIdJumpBehavior) {
+ {
+ test::ScopedKeyValueConfig field_trials(
+ "WebRTC-LegacyFrameIdJumpBehavior/Disabled/");
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(3).AsLast().Build()));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(3)));
+ EXPECT_FALSE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(30).Id(2).AsLast().Build()));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty());
+ }
+
+ {
+ // WebRTC-LegacyFrameIdJumpBehavior is disabled by default.
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(3).AsLast().Build()));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(3)));
+ EXPECT_FALSE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(30).Id(2).Refs({1}).AsLast().Build()));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty());
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(40).Id(1).AsLast().Build()));
+ EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
+ ElementsAre(FrameWithId(1)));
+ }
+}
+
+TEST(FrameBuffer3Test, TotalNumberOfContinuousTemporalUnits) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+ EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(0));
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).Build()));
+ EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(40).Id(4).Refs({2}).Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(40).Id(5).Refs({3, 4}).AsLast().Build()));
+ EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
+
+ // Reordered
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(3).Refs({2}).AsLast().Build()));
+ EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(3));
+}
+
+TEST(FrameBuffer3Test, TotalNumberOfDroppedFrames) {
+ test::ScopedKeyValueConfig field_trials;
+ FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
+ field_trials);
+ EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0));
+
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(20).Id(3).Refs({2}).AsLast().Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(40).Id(4).Refs({1}).Build()));
+ EXPECT_TRUE(buffer.InsertFrame(
+ test::FakeFrameBuilder().Time(40).Id(5).Refs({4}).AsLast().Build()));
+
+ buffer.ExtractNextDecodableTemporalUnit();
+ EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0));
+
+ buffer.DropNextDecodableTemporalUnit();
+ EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(2));
+
+ buffer.ExtractNextDecodableTemporalUnit();
+ EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(2));
+}
+
+} // namespace
+} // namespace webrtc