Add test::FakeEncodedFrame for testing

Change-Id: I1c8fabe5caf2c723487ec1cd71a379e922026a9d
Bug: webrtc:13996
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/260001
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Evan Shrubsole <eshr@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36654}
This commit is contained in:
Evan Shrubsole
2022-04-26 10:09:04 +02:00
committed by WebRTC LUCI CQ
parent 65dcc47b8b
commit a0ee64c57e
9 changed files with 602 additions and 414 deletions

View File

@ -1279,6 +1279,7 @@ if (rtc_include_tests) {
"../../system_wrappers", "../../system_wrappers",
"../../system_wrappers:field_trial", "../../system_wrappers:field_trial",
"../../system_wrappers:metrics", "../../system_wrappers:metrics",
"../../test:fake_encoded_frame",
"../../test:fake_video_codecs", "../../test:fake_video_codecs",
"../../test:field_trial", "../../test:field_trial",
"../../test:fileutils", "../../test:fileutils",

View File

@ -12,6 +12,7 @@
#include <vector> #include <vector>
#include "api/video/encoded_frame.h" #include "api/video/encoded_frame.h"
#include "test/fake_encoded_frame.h"
#include "test/field_trial.h" #include "test/field_trial.h"
#include "test/gmock.h" #include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
@ -29,67 +30,19 @@ MATCHER_P(FrameWithId, id, "") {
return Matches(Eq(id))(arg->Id()); return Matches(Eq(id))(arg->Id());
} }
class FakeEncodedFrame : public EncodedFrame {
public:
int64_t ReceivedTime() const override { return 0; }
int64_t RenderTime() const override { return 0; }
};
class Builder {
public:
Builder& Time(uint32_t rtp_timestamp) {
rtp_timestamp_ = rtp_timestamp;
return *this;
}
Builder& Id(int64_t frame_id) {
frame_id_ = frame_id;
return *this;
}
Builder& AsLast() {
last_spatial_layer_ = true;
return *this;
}
Builder& Refs(const std::vector<int64_t>& references) {
references_ = references;
return *this;
}
std::unique_ptr<FakeEncodedFrame> Build() {
RTC_CHECK_LE(references_.size(), EncodedFrame::kMaxFrameReferences);
RTC_CHECK(rtp_timestamp_.has_value());
RTC_CHECK(frame_id_.has_value());
auto frame = std::make_unique<FakeEncodedFrame>();
frame->SetTimestamp(*rtp_timestamp_);
frame->SetId(*frame_id_);
frame->is_last_spatial_layer = last_spatial_layer_;
for (int64_t ref : references_) {
frame->references[frame->num_references] = ref;
frame->num_references++;
}
return frame;
}
private:
absl::optional<uint32_t> rtp_timestamp_;
absl::optional<int64_t> frame_id_;
bool last_spatial_layer_ = false;
std::vector<int64_t> references_;
};
TEST(FrameBuffer3Test, RejectInvalidRefs) { TEST(FrameBuffer3Test, RejectInvalidRefs) {
test::ScopedKeyValueConfig field_trials; test::ScopedKeyValueConfig field_trials;
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
// Ref must be less than the id of this frame. // Ref must be less than the id of this frame.
buffer.InsertFrame(Builder().Time(0).Id(0).Refs({0}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(0).Id(0).Refs({0}).AsLast().Build());
EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt)); EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt));
// Duplicate ids are also invalid. // Duplicate ids are also invalid.
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1, 1}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(20).Id(2).Refs({1, 1}).AsLast().Build());
EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1)); EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
} }
@ -100,11 +53,12 @@ TEST(FrameBuffer3Test, LastContinuousUpdatesOnInsertedFrames) {
EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt)); EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt));
EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt)); EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
buffer.InsertFrame(Builder().Time(10).Id(1).Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build());
EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1)); EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt)); EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).AsLast().Build());
EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(2)); EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(2));
EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(2)); EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(2));
} }
@ -114,11 +68,13 @@ TEST(FrameBuffer3Test, LastContinuousFrameReordering) {
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(30).Id(3).Refs({2}).AsLast().Build());
EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1)); EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build());
EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(3)); EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(3));
} }
@ -127,9 +83,10 @@ TEST(FrameBuffer3Test, LastContinuousTemporalUnit) {
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(10).Id(1).Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build());
EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt)); EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).AsLast().Build());
EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(2)); EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(2));
} }
@ -138,12 +95,14 @@ TEST(FrameBuffer3Test, LastContinuousTemporalUnitReordering) {
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(10).Id(1).Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build());
buffer.InsertFrame(Builder().Time(20).Id(3).Refs({1}).Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(20).Id(3).Refs({1}).Build());
buffer.InsertFrame(Builder().Time(20).Id(4).Refs({2, 3}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(20).Id(4).Refs({2, 3}).AsLast().Build());
EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt)); EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt));
buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).AsLast().Build());
EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(4)); EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(4));
} }
@ -154,7 +113,7 @@ TEST(FrameBuffer3Test, NextDecodable) {
EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(),
Eq(absl::nullopt)); Eq(absl::nullopt));
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U)); EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U));
} }
@ -163,9 +122,10 @@ TEST(FrameBuffer3Test, AdvanceNextDecodableOnExtraction) {
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
buffer.InsertFrame(Builder().Time(20).Id(2).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(20).Id(2).AsLast().Build());
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(30).Id(3).Refs({2}).AsLast().Build());
EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U)); EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U));
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
@ -183,9 +143,11 @@ TEST(FrameBuffer3Test, AdvanceLastDecodableOnExtraction) {
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build()); buffer.InsertFrame(
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build()); test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build());
buffer.InsertFrame(
test::FakeFrameBuilder().Time(30).Id(3).Refs({1}).AsLast().Build());
EXPECT_THAT(buffer.LastDecodableTemporalUnitRtpTimestamp(), Eq(10U)); EXPECT_THAT(buffer.LastDecodableTemporalUnitRtpTimestamp(), Eq(10U));
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
@ -198,10 +160,10 @@ TEST(FrameBuffer3Test, FrameUpdatesNextDecodable) {
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(20).Id(2).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(20).Id(2).AsLast().Build());
EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(20U)); EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(20U));
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U)); EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U));
} }
@ -209,18 +171,23 @@ TEST(FrameBuffer3Test, KeyframeClearsFullBuffer) {
test::ScopedKeyValueConfig field_trials; test::ScopedKeyValueConfig field_trials;
FrameBuffer buffer(/*max_frame_slots=*/5, /*max_decode_history=*/10, FrameBuffer buffer(/*max_frame_slots=*/5, /*max_decode_history=*/10,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build()); buffer.InsertFrame(
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build()); test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build());
buffer.InsertFrame(Builder().Time(40).Id(4).Refs({3}).AsLast().Build()); buffer.InsertFrame(
buffer.InsertFrame(Builder().Time(50).Id(5).Refs({4}).AsLast().Build()); test::FakeFrameBuilder().Time(30).Id(3).Refs({2}).AsLast().Build());
buffer.InsertFrame(
test::FakeFrameBuilder().Time(40).Id(4).Refs({3}).AsLast().Build());
buffer.InsertFrame(
test::FakeFrameBuilder().Time(50).Id(5).Refs({4}).AsLast().Build());
EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(5)); EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(5));
// Frame buffer is full // Frame buffer is full
buffer.InsertFrame(Builder().Time(60).Id(6).Refs({5}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(60).Id(6).Refs({5}).AsLast().Build());
EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(5)); EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(5));
buffer.InsertFrame(Builder().Time(70).Id(7).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(70).Id(7).AsLast().Build());
EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(7)); EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(7));
} }
@ -228,9 +195,11 @@ TEST(FrameBuffer3Test, DropNextDecodableTemporalUnit) {
test::ScopedKeyValueConfig field_trials; test::ScopedKeyValueConfig field_trials;
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build()); buffer.InsertFrame(
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build()); test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build());
buffer.InsertFrame(
test::FakeFrameBuilder().Time(30).Id(3).Refs({1}).AsLast().Build());
buffer.ExtractNextDecodableTemporalUnit(); buffer.ExtractNextDecodableTemporalUnit();
buffer.DropNextDecodableTemporalUnit(); buffer.DropNextDecodableTemporalUnit();
@ -242,15 +211,18 @@ TEST(FrameBuffer3Test, OldFramesAreIgnored) {
test::ScopedKeyValueConfig field_trials; test::ScopedKeyValueConfig field_trials;
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build());
buffer.ExtractNextDecodableTemporalUnit(); buffer.ExtractNextDecodableTemporalUnit();
buffer.ExtractNextDecodableTemporalUnit(); buffer.ExtractNextDecodableTemporalUnit();
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build()); buffer.InsertFrame(
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build()); test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build());
buffer.InsertFrame(
test::FakeFrameBuilder().Time(30).Id(3).Refs({1}).AsLast().Build());
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
ElementsAre(FrameWithId(3))); ElementsAre(FrameWithId(3)));
@ -260,13 +232,15 @@ TEST(FrameBuffer3Test, ReturnFullTemporalUnitKSVC) {
test::ScopedKeyValueConfig field_trials; test::ScopedKeyValueConfig field_trials;
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(10).Id(1).Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build());
buffer.InsertFrame(Builder().Time(10).Id(2).Refs({1}).Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).Build());
buffer.InsertFrame(Builder().Time(10).Id(3).Refs({2}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(10).Id(3).Refs({2}).AsLast().Build());
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
ElementsAre(FrameWithId(1), FrameWithId(2), FrameWithId(3))); ElementsAre(FrameWithId(1), FrameWithId(2), FrameWithId(3)));
buffer.InsertFrame(Builder().Time(20).Id(4).Refs({3}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(20).Id(4).Refs({3}).AsLast().Build());
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
ElementsAre(FrameWithId(4))); ElementsAre(FrameWithId(4)));
} }
@ -275,11 +249,15 @@ TEST(FrameBuffer3Test, InterleavedStream) {
test::ScopedKeyValueConfig field_trials; test::ScopedKeyValueConfig field_trials;
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build()); buffer.InsertFrame(
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build()); test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build());
buffer.InsertFrame(Builder().Time(40).Id(4).Refs({2}).AsLast().Build()); buffer.InsertFrame(
buffer.InsertFrame(Builder().Time(50).Id(5).Refs({3}).AsLast().Build()); test::FakeFrameBuilder().Time(30).Id(3).Refs({1}).AsLast().Build());
buffer.InsertFrame(
test::FakeFrameBuilder().Time(40).Id(4).Refs({2}).AsLast().Build());
buffer.InsertFrame(
test::FakeFrameBuilder().Time(50).Id(5).Refs({3}).AsLast().Build());
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
ElementsAre(FrameWithId(1))); ElementsAre(FrameWithId(1)));
@ -292,12 +270,15 @@ TEST(FrameBuffer3Test, InterleavedStream) {
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
ElementsAre(FrameWithId(5))); ElementsAre(FrameWithId(5)));
buffer.InsertFrame(Builder().Time(70).Id(7).Refs({5}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(70).Id(7).Refs({5}).AsLast().Build());
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
ElementsAre(FrameWithId(7))); ElementsAre(FrameWithId(7)));
buffer.InsertFrame(Builder().Time(60).Id(6).Refs({4}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(60).Id(6).Refs({4}).AsLast().Build());
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty()); EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty());
buffer.InsertFrame(Builder().Time(90).Id(9).Refs({7}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(90).Id(9).Refs({7}).AsLast().Build());
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
ElementsAre(FrameWithId(9))); ElementsAre(FrameWithId(9)));
} }
@ -309,10 +290,12 @@ TEST(FrameBuffer3Test, LegacyFrameIdJumpBehavior) {
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(20).Id(3).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(20).Id(3).AsLast().Build());
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
ElementsAre(FrameWithId(3))); ElementsAre(FrameWithId(3)));
buffer.InsertFrame(Builder().Time(30).Id(2).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(30).Id(2).AsLast().Build());
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty()); EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty());
} }
@ -322,12 +305,15 @@ TEST(FrameBuffer3Test, LegacyFrameIdJumpBehavior) {
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
field_trials); field_trials);
buffer.InsertFrame(Builder().Time(20).Id(3).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(20).Id(3).AsLast().Build());
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
ElementsAre(FrameWithId(3))); ElementsAre(FrameWithId(3)));
buffer.InsertFrame(Builder().Time(30).Id(2).Refs({1}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(30).Id(2).Refs({1}).AsLast().Build());
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty()); EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty());
buffer.InsertFrame(Builder().Time(40).Id(1).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(40).Id(1).AsLast().Build());
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
ElementsAre(FrameWithId(1))); ElementsAre(FrameWithId(1)));
} }
@ -339,18 +325,20 @@ TEST(FrameBuffer3Test, TotalNumberOfContinuousTemporalUnits) {
field_trials); field_trials);
EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(0)); EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(0));
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1)); EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).Build());
EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1)); EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
buffer.InsertFrame(Builder().Time(40).Id(4).Refs({2}).Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(40).Id(4).Refs({2}).Build());
buffer.InsertFrame(Builder().Time(40).Id(5).Refs({3, 4}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(40).Id(5).Refs({3, 4}).AsLast().Build());
EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1)); EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
// Reordered // Reordered
buffer.InsertFrame(Builder().Time(20).Id(3).Refs({2}).AsLast().Build()); buffer.InsertFrame(
test::FakeFrameBuilder().Time(20).Id(3).Refs({2}).AsLast().Build());
EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(3)); EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(3));
} }
@ -360,11 +348,13 @@ TEST(FrameBuffer3Test, TotalNumberOfDroppedFrames) {
field_trials); field_trials);
EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0)); EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0));
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).Build());
buffer.InsertFrame(Builder().Time(20).Id(3).Refs({2}).AsLast().Build()); buffer.InsertFrame(
buffer.InsertFrame(Builder().Time(40).Id(4).Refs({1}).Build()); test::FakeFrameBuilder().Time(20).Id(3).Refs({2}).AsLast().Build());
buffer.InsertFrame(Builder().Time(40).Id(5).Refs({4}).AsLast().Build()); buffer.InsertFrame(test::FakeFrameBuilder().Time(40).Id(4).Refs({1}).Build());
buffer.InsertFrame(
test::FakeFrameBuilder().Time(40).Id(5).Refs({4}).AsLast().Build());
buffer.ExtractNextDecodableTemporalUnit(); buffer.ExtractNextDecodableTemporalUnit();
EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0)); EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0));

View File

@ -1120,3 +1120,18 @@ rtc_library("call_config_utils") {
"../rtc_base:rtc_json", "../rtc_base:rtc_json",
] ]
} }
rtc_library("fake_encoded_frame") {
testonly = true
sources = [
"fake_encoded_frame.cc",
"fake_encoded_frame.h",
]
deps = [
":test_support",
"../api:rtp_packet_info",
"../api/video:encoded_frame",
"../api/video:video_rtp_headers",
]
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}

135
test/fake_encoded_frame.cc Normal file
View File

@ -0,0 +1,135 @@
/*
* Copyright (c) 2022 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 "test/fake_encoded_frame.h"
namespace webrtc::test {
void PrintTo(const EncodedFrame& frame,
std::ostream* os) /* no-presubmit-check TODO(webrtc:8982) */ {
*os << "EncodedFrame with id=" << frame.Id() << " rtp=" << frame.Timestamp()
<< " size=" << frame.size() << " refs=[";
for (size_t ref = 0; ref < frame.num_references; ++ref) {
*os << frame.references[ref] << ",";
}
*os << "]";
}
int64_t FakeEncodedFrame::ReceivedTime() const {
return received_time_;
}
int64_t FakeEncodedFrame::RenderTime() const {
return _renderTimeMs;
}
void FakeEncodedFrame::SetReceivedTime(int64_t received_time) {
received_time_ = received_time;
}
void FakeEncodedFrame::SetPayloadType(int payload_type) {
_payloadType = payload_type;
}
FakeFrameBuilder& FakeFrameBuilder::Time(uint32_t rtp_timestamp) {
rtp_timestamp_ = rtp_timestamp;
return *this;
}
FakeFrameBuilder& FakeFrameBuilder::Id(int64_t frame_id) {
frame_id_ = frame_id;
return *this;
}
FakeFrameBuilder& FakeFrameBuilder::AsLast() {
last_spatial_layer_ = true;
return *this;
}
FakeFrameBuilder& FakeFrameBuilder::Refs(
const std::vector<int64_t>& references) {
references_ = references;
return *this;
}
FakeFrameBuilder& FakeFrameBuilder::PlayoutDelay(
VideoPlayoutDelay playout_delay) {
playout_delay_ = playout_delay;
return *this;
}
FakeFrameBuilder& FakeFrameBuilder::SpatialLayer(int spatial_layer) {
spatial_layer_ = spatial_layer;
return *this;
}
FakeFrameBuilder& FakeFrameBuilder::ReceivedTime(Timestamp receive_time) {
received_time_ = receive_time;
return *this;
}
FakeFrameBuilder& FakeFrameBuilder::Size(size_t size) {
size_ = size;
return *this;
}
std::unique_ptr<FakeEncodedFrame> FakeFrameBuilder::Build() {
RTC_CHECK_LE(references_.size(), EncodedFrame::kMaxFrameReferences);
auto frame = std::make_unique<FakeEncodedFrame>();
frame->is_last_spatial_layer = last_spatial_layer_;
frame->SetEncodedData(EncodedImageBuffer::Create(size_));
if (rtp_timestamp_)
frame->SetTimestamp(*rtp_timestamp_);
if (frame_id_)
frame->SetId(*frame_id_);
if (playout_delay_)
frame->SetPlayoutDelay(*playout_delay_);
for (int64_t ref : references_) {
frame->references[frame->num_references] = ref;
frame->num_references++;
}
if (spatial_layer_)
frame->SetSpatialIndex(spatial_layer_);
if (received_time_)
frame->SetReceivedTime(received_time_->ms());
if (payload_type_)
frame->SetPayloadType(*payload_type_);
if (ntp_time_)
frame->ntp_time_ms_ = ntp_time_->ms();
if (rotation_)
frame->rotation_ = *rotation_;
if (packet_infos_)
frame->SetPacketInfos(*packet_infos_);
return frame;
}
FakeFrameBuilder& FakeFrameBuilder::PayloadType(int payload_type) {
payload_type_ = payload_type;
return *this;
}
FakeFrameBuilder& FakeFrameBuilder::NtpTime(Timestamp ntp_time) {
ntp_time_ = ntp_time;
return *this;
}
FakeFrameBuilder& FakeFrameBuilder::Rotation(VideoRotation rotation) {
rotation_ = rotation;
return *this;
}
FakeFrameBuilder& FakeFrameBuilder::PacketInfos(RtpPacketInfos packet_infos) {
packet_infos_ = packet_infos;
return *this;
}
} // namespace webrtc::test

84
test/fake_encoded_frame.h Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2022 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.
*/
#ifndef TEST_FAKE_ENCODED_FRAME_H_
#define TEST_FAKE_ENCODED_FRAME_H_
#include <memory>
#include <ostream> // no-presubmit-check TODO(webrtc:8982)
#include <vector>
#include "api/rtp_packet_infos.h"
#include "api/video/encoded_frame.h"
#include "api/video/video_rotation.h"
#include "test/gmock.h"
namespace webrtc::test {
// For test printing.
void PrintTo(const EncodedFrame& frame,
std::ostream* os); // no-presubmit-check TODO(webrtc:8982)
class FakeEncodedFrame : public EncodedFrame {
public:
// Always 10ms delay and on time.
int64_t ReceivedTime() const override;
int64_t RenderTime() const override;
// Setters for protected variables.
void SetReceivedTime(int64_t received_time);
void SetPayloadType(int payload_type);
private:
int64_t received_time_;
};
MATCHER_P(WithId, id, "") {
return ::testing::Matches(::testing::Eq(id))(arg.Id());
}
MATCHER_P(FrameWithSize, id, "") {
return ::testing::Matches(::testing::Eq(id))(arg.size());
}
class FakeFrameBuilder {
public:
FakeFrameBuilder& Time(uint32_t rtp_timestamp);
FakeFrameBuilder& Id(int64_t frame_id);
FakeFrameBuilder& AsLast();
FakeFrameBuilder& Refs(const std::vector<int64_t>& references);
FakeFrameBuilder& PlayoutDelay(VideoPlayoutDelay playout_delay);
FakeFrameBuilder& SpatialLayer(int spatial_layer);
FakeFrameBuilder& ReceivedTime(Timestamp receive_time);
FakeFrameBuilder& Size(size_t size);
FakeFrameBuilder& PayloadType(int payload_type);
FakeFrameBuilder& NtpTime(Timestamp ntp_time);
FakeFrameBuilder& Rotation(VideoRotation rotation);
FakeFrameBuilder& PacketInfos(RtpPacketInfos packet_infos);
std::unique_ptr<FakeEncodedFrame> Build();
private:
absl::optional<uint32_t> rtp_timestamp_;
absl::optional<int64_t> frame_id_;
absl::optional<VideoPlayoutDelay> playout_delay_;
absl::optional<int> spatial_layer_;
absl::optional<Timestamp> received_time_;
absl::optional<int> payload_type_;
absl::optional<Timestamp> ntp_time_;
absl::optional<VideoRotation> rotation_;
absl::optional<RtpPacketInfos> packet_infos_;
std::vector<int64_t> references_;
bool last_spatial_layer_ = false;
size_t size_ = 10;
};
} // namespace webrtc::test
#endif // TEST_FAKE_ENCODED_FRAME_H_

View File

@ -950,6 +950,7 @@ if (rtc_include_tests) {
"../system_wrappers:metrics", "../system_wrappers:metrics",
"../test:direct_transport", "../test:direct_transport",
"../test:encoder_settings", "../test:encoder_settings",
"../test:fake_encoded_frame",
"../test:fake_video_codecs", "../test:fake_video_codecs",
"../test:field_trial", "../test:field_trial",
"../test:fileutils", "../test:fileutils",
@ -965,7 +966,6 @@ if (rtc_include_tests) {
"../test:video_test_common", "../test:video_test_common",
"../test/time_controller", "../test/time_controller",
"adaptation:video_adaptation", "adaptation:video_adaptation",
"//testing/gtest",
] ]
absl_deps = [ absl_deps = [
"//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/algorithm:container",

View File

@ -28,6 +28,7 @@
#include "api/video/video_timing.h" #include "api/video/video_timing.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/event.h" #include "rtc_base/event.h"
#include "test/fake_encoded_frame.h"
#include "test/gmock.h" #include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
#include "test/run_loop.h" #include "test/run_loop.h"
@ -51,16 +52,6 @@ using ::testing::VariantWith;
namespace webrtc { namespace webrtc {
// For test printing.
void PrintTo(const EncodedFrame& frame, std::ostream* os) {
*os << "EncodedFrame with id=" << frame.Id() << " rtp=" << frame.Timestamp()
<< " size=" << frame.size() << " refs=[";
for (size_t ref = 0; ref < frame.num_references; ++ref) {
*os << frame.references[ref] << ",";
}
*os << "]";
}
namespace { namespace {
constexpr size_t kFrameSize = 10; constexpr size_t kFrameSize = 10;
@ -69,28 +60,6 @@ constexpr TimeDelta kFps30Delay = 1 / Frequency::Hertz(30);
const VideoPlayoutDelay kZeroPlayoutDelay = {0, 0}; const VideoPlayoutDelay kZeroPlayoutDelay = {0, 0};
constexpr Timestamp kClockStart = Timestamp::Millis(1000); constexpr Timestamp kClockStart = Timestamp::Millis(1000);
class FakeEncodedFrame : public EncodedFrame {
public:
// Always 10ms delay and on time.
int64_t ReceivedTime() const override { return received_time_; }
int64_t RenderTime() const override { return _renderTimeMs; }
void SetReceivedTime(int64_t received_time) {
received_time_ = received_time;
}
private:
int64_t received_time_;
};
MATCHER_P(WithId, id, "") {
return Matches(Eq(id))(arg.Id());
}
MATCHER_P(FrameWithSize, id, "") {
return Matches(Eq(id))(arg.size());
}
auto TimedOut() { auto TimedOut() {
return Optional(VariantWith<TimeDelta>(_)); return Optional(VariantWith<TimeDelta>(_));
} }
@ -99,80 +68,17 @@ auto Frame(testing::Matcher<EncodedFrame> m) {
return Optional(VariantWith<std::unique_ptr<EncodedFrame>>(Pointee(m))); return Optional(VariantWith<std::unique_ptr<EncodedFrame>>(Pointee(m)));
} }
class Builder { std::unique_ptr<test::FakeEncodedFrame> WithReceiveTimeFromRtpTimestamp(
public: std::unique_ptr<test::FakeEncodedFrame> frame) {
Builder& Time(uint32_t rtp_timestamp) { if (frame->Timestamp() == 0) {
rtp_timestamp_ = rtp_timestamp; frame->SetReceivedTime(kClockStart.ms());
return *this; } else {
frame->SetReceivedTime(
TimeDelta::Seconds(frame->Timestamp() / 90000.0).ms() +
kClockStart.ms());
} }
Builder& Id(int64_t frame_id) { return frame;
frame_id_ = frame_id; }
return *this;
}
Builder& AsLast() {
last_spatial_layer_ = true;
return *this;
}
Builder& Refs(const std::vector<int64_t>& references) {
references_ = references;
return *this;
}
Builder& PlayoutDelay(VideoPlayoutDelay playout_delay) {
playout_delay_ = playout_delay;
return *this;
}
Builder& SpatialLayer(int spatial_layer) {
spatial_layer_ = spatial_layer;
return *this;
}
Builder& ReceivedTime(Timestamp receive_time) {
received_time_ = receive_time;
return *this;
}
std::unique_ptr<FakeEncodedFrame> Build() {
RTC_CHECK_LE(references_.size(), EncodedFrame::kMaxFrameReferences);
RTC_CHECK(rtp_timestamp_);
RTC_CHECK(frame_id_);
auto frame = std::make_unique<FakeEncodedFrame>();
frame->SetTimestamp(*rtp_timestamp_);
frame->SetId(*frame_id_);
frame->is_last_spatial_layer = last_spatial_layer_;
frame->SetEncodedData(EncodedImageBuffer::Create(kFrameSize));
if (playout_delay_)
frame->SetPlayoutDelay(*playout_delay_);
for (int64_t ref : references_) {
frame->references[frame->num_references] = ref;
frame->num_references++;
}
if (spatial_layer_) {
frame->SetSpatialIndex(spatial_layer_);
}
if (received_time_) {
frame->SetReceivedTime(received_time_->ms());
} else {
if (*rtp_timestamp_ == 0)
frame->SetReceivedTime(kClockStart.ms());
frame->SetReceivedTime(
TimeDelta::Seconds(*rtp_timestamp_ / 90000.0).ms() +
kClockStart.ms());
}
return frame;
}
private:
absl::optional<uint32_t> rtp_timestamp_;
absl::optional<int64_t> frame_id_;
absl::optional<VideoPlayoutDelay> playout_delay_;
absl::optional<int> spatial_layer_;
absl::optional<Timestamp> received_time_;
bool last_spatial_layer_ = false;
std::vector<int64_t> references_;
};
class VCMReceiveStatisticsCallbackMock : public VCMReceiveStatisticsCallback { class VCMReceiveStatisticsCallbackMock : public VCMReceiveStatisticsCallback {
public: public:
@ -349,19 +255,20 @@ TEST_P(FrameBufferProxyTest, KeyFramesAreScheduled) {
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
time_controller_.AdvanceTime(TimeDelta::Millis(50)); time_controller_.AdvanceTime(TimeDelta::Millis(50));
auto frame = Builder().Id(0).Time(0).AsLast().Build(); auto frame = test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build();
proxy_->InsertFrame(std::move(frame)); proxy_->InsertFrame(std::move(frame));
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
} }
TEST_P(FrameBufferProxyTest, DeltaFrameTimeoutAfterKeyframeExtracted) { TEST_P(FrameBufferProxyTest, DeltaFrameTimeoutAfterKeyframeExtracted) {
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
time_controller_.AdvanceTime(TimeDelta::Millis(50)); time_controller_.AdvanceTime(TimeDelta::Millis(50));
auto frame = Builder().Id(0).Time(0).AsLast().Build(); auto frame = test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build();
proxy_->InsertFrame(std::move(frame)); proxy_->InsertFrame(std::move(frame));
EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForKeyframe), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForKeyframe),
Frame(test::WithId(0)));
StartNextDecode(); StartNextDecode();
time_controller_.AdvanceTime(TimeDelta::Millis(50)); time_controller_.AdvanceTime(TimeDelta::Millis(50));
@ -376,44 +283,64 @@ TEST_P(FrameBufferProxyTest, DeltaFrameTimeoutAfterKeyframeExtracted) {
TEST_P(FrameBufferProxyTest, DependantFramesAreScheduled) { TEST_P(FrameBufferProxyTest, DependantFramesAreScheduled) {
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
StartNextDecode(); StartNextDecode();
time_controller_.AdvanceTime(kFps30Delay); time_controller_.AdvanceTime(kFps30Delay);
proxy_->InsertFrame( proxy_->InsertFrame(test::FakeFrameBuilder()
Builder().Id(1).Time(kFps30Rtp).AsLast().Refs({0}).Build()); .Id(1)
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(1))); .Time(kFps30Rtp)
.AsLast()
.Refs({0})
.Build());
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(1)));
} }
TEST_P(FrameBufferProxyTest, SpatialLayersAreScheduled) { TEST_P(FrameBufferProxyTest, SpatialLayersAreScheduled) {
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
proxy_->InsertFrame(Builder().Id(0).SpatialLayer(0).Time(0).Build()); proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
proxy_->InsertFrame(Builder().Id(1).SpatialLayer(1).Time(0).Build()); test::FakeFrameBuilder().Id(0).SpatialLayer(0).Time(0).Build()));
proxy_->InsertFrame(Builder().Id(2).SpatialLayer(2).Time(0).AsLast().Build()); proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), test::FakeFrameBuilder().Id(1).SpatialLayer(1).Time(0).Build()));
Frame(AllOf(WithId(0), FrameWithSize(3 * kFrameSize)))); proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
test::FakeFrameBuilder().Id(2).SpatialLayer(2).Time(0).AsLast().Build()));
EXPECT_THAT(
WaitForFrameOrTimeout(TimeDelta::Zero()),
Frame(AllOf(test::WithId(0), test::FrameWithSize(3 * kFrameSize))));
proxy_->InsertFrame(Builder().Id(3).Time(kFps30Rtp).SpatialLayer(0).Build()); proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
proxy_->InsertFrame(Builder().Id(4).Time(kFps30Rtp).SpatialLayer(1).Build()); test::FakeFrameBuilder().Id(3).Time(kFps30Rtp).SpatialLayer(0).Build()));
proxy_->InsertFrame( proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
Builder().Id(5).Time(kFps30Rtp).SpatialLayer(2).AsLast().Build()); test::FakeFrameBuilder().Id(4).Time(kFps30Rtp).SpatialLayer(1).Build()));
proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(test::FakeFrameBuilder()
.Id(5)
.Time(kFps30Rtp)
.SpatialLayer(2)
.AsLast()
.Build()));
StartNextDecode(); StartNextDecode();
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay * 10), EXPECT_THAT(
Frame(AllOf(WithId(3), FrameWithSize(3 * kFrameSize)))); WaitForFrameOrTimeout(kFps30Delay * 10),
Frame(AllOf(test::WithId(3), test::FrameWithSize(3 * kFrameSize))));
} }
TEST_P(FrameBufferProxyTest, OutstandingFrameTasksAreCancelledAfterDeletion) { TEST_P(FrameBufferProxyTest, OutstandingFrameTasksAreCancelledAfterDeletion) {
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build()); proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build()));
// Get keyframe. Delta frame should now be scheduled. // Get keyframe. Delta frame should now be scheduled.
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
StartNextDecode(); StartNextDecode();
proxy_->InsertFrame( proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(test::FakeFrameBuilder()
Builder().Id(1).Time(kFps30Rtp).AsLast().Refs({0}).Build()); .Id(1)
.Time(kFps30Rtp)
.AsLast()
.Refs({0})
.Build()));
proxy_->StopOnWorker(); proxy_->StopOnWorker();
// Wait for 2x max wait time. Since we stopped, this should cause no timeouts // Wait for 2x max wait time. Since we stopped, this should cause no timeouts
// or frame-ready callbacks. // or frame-ready callbacks.
@ -424,20 +351,24 @@ TEST_P(FrameBufferProxyTest, FramesWaitForDecoderToComplete) {
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
// Start with a keyframe. // Start with a keyframe.
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
ResetLastResult(); ResetLastResult();
// Insert a delta frame. // Insert a delta frame.
proxy_->InsertFrame( proxy_->InsertFrame(test::FakeFrameBuilder()
Builder().Id(1).Time(kFps30Rtp).AsLast().Refs({0}).Build()); .Id(1)
.Time(kFps30Rtp)
.AsLast()
.Refs({0})
.Build());
// Advancing time should not result in a frame since the scheduler has not // Advancing time should not result in a frame since the scheduler has not
// been signalled that we are ready. // been signalled that we are ready.
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Eq(absl::nullopt)); EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Eq(absl::nullopt));
// Signal ready. // Signal ready.
StartNextDecode(); StartNextDecode();
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(1))); EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(1)));
} }
TEST_P(FrameBufferProxyTest, LateFrameDropped) { TEST_P(FrameBufferProxyTest, LateFrameDropped) {
@ -445,22 +376,30 @@ TEST_P(FrameBufferProxyTest, LateFrameDropped) {
// F1 // F1
// / // /
// F0 --> F2 // F0 --> F2
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
// Start with a keyframe. // Start with a keyframe.
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
StartNextDecode(); StartNextDecode();
// Simulate late F1 which arrives after F2. // Simulate late F1 which arrives after F2.
time_controller_.AdvanceTime(kFps30Delay * 2); time_controller_.AdvanceTime(kFps30Delay * 2);
proxy_->InsertFrame( proxy_->InsertFrame(test::FakeFrameBuilder()
Builder().Id(2).Time(2 * kFps30Rtp).AsLast().Refs({0}).Build()); .Id(2)
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(2))); .Time(2 * kFps30Rtp)
.AsLast()
.Refs({0})
.Build());
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(2)));
StartNextDecode(); StartNextDecode();
proxy_->InsertFrame( proxy_->InsertFrame(test::FakeFrameBuilder()
Builder().Id(1).Time(1 * kFps30Rtp).AsLast().Refs({0}).Build()); .Id(1)
.Time(1 * kFps30Rtp)
.AsLast()
.Refs({0})
.Build());
// Confirm frame 1 is never scheduled by timing out. // Confirm frame 1 is never scheduled by timing out.
EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), TimedOut()); EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), TimedOut());
} }
@ -470,40 +409,53 @@ TEST_P(FrameBufferProxyTest, FramesFastForwardOnSystemHalt) {
// F1 // F1
// / // /
// F0 --> F2 // F0 --> F2
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
// Start with a keyframe. // Start with a keyframe.
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
time_controller_.AdvanceTime(kFps30Delay); time_controller_.AdvanceTime(kFps30Delay);
proxy_->InsertFrame( proxy_->InsertFrame(test::FakeFrameBuilder()
Builder().Id(1).Time(kFps30Rtp).AsLast().Refs({0}).Build()); .Id(1)
.Time(kFps30Rtp)
.AsLast()
.Refs({0})
.Build());
time_controller_.AdvanceTime(kFps30Delay); time_controller_.AdvanceTime(kFps30Delay);
proxy_->InsertFrame( proxy_->InsertFrame(test::FakeFrameBuilder()
Builder().Id(2).Time(2 * kFps30Rtp).AsLast().Refs({0}).Build()); .Id(2)
.Time(2 * kFps30Rtp)
.AsLast()
.Refs({0})
.Build());
// Halting time should result in F1 being skipped. // Halting time should result in F1 being skipped.
time_controller_.AdvanceTime(kFps30Delay * 2); time_controller_.AdvanceTime(kFps30Delay * 2);
StartNextDecode(); StartNextDecode();
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(2))); EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(2)));
EXPECT_EQ(dropped_frames(), 1); EXPECT_EQ(dropped_frames(), 1);
} }
TEST_P(FrameBufferProxyTest, ForceKeyFrame) { TEST_P(FrameBufferProxyTest, ForceKeyFrame) {
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
// Initial keyframe. // Initial keyframe.
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
// F2 is the next keyframe, and should be extracted since a keyframe was // F2 is the next keyframe, and should be extracted since a keyframe was
// forced. // forced.
proxy_->InsertFrame(test::FakeFrameBuilder()
.Id(1)
.Time(kFps30Rtp)
.AsLast()
.Refs({0})
.Build());
proxy_->InsertFrame( proxy_->InsertFrame(
Builder().Id(1).Time(kFps30Rtp).AsLast().Refs({0}).Build()); test::FakeFrameBuilder().Id(2).Time(kFps30Rtp * 2).AsLast().Build());
proxy_->InsertFrame(Builder().Id(2).Time(kFps30Rtp * 2).AsLast().Build());
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay * 3), Frame(WithId(2))); EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay * 3), Frame(test::WithId(2)));
} }
TEST_P(FrameBufferProxyTest, SlowDecoderDropsTemporalLayers) { TEST_P(FrameBufferProxyTest, SlowDecoderDropsTemporalLayers) {
@ -513,40 +465,60 @@ TEST_P(FrameBufferProxyTest, SlowDecoderDropsTemporalLayers) {
// F1 --> F3 --> F5 // F1 --> F3 --> F5
// / / / // / / /
// F0 --> F2 --> F4 // F0 --> F2 --> F4
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
// Keyframe received. // Keyframe received.
// Don't start next decode until slow delay. // Don't start next decode until slow delay.
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
time_controller_.AdvanceTime(kFps30Delay); time_controller_.AdvanceTime(kFps30Delay);
proxy_->InsertFrame( proxy_->InsertFrame(test::FakeFrameBuilder()
Builder().Id(1).Time(1 * kFps30Rtp).Refs({0}).AsLast().Build()); .Id(1)
.Time(1 * kFps30Rtp)
.Refs({0})
.AsLast()
.Build());
time_controller_.AdvanceTime(kFps30Delay); time_controller_.AdvanceTime(kFps30Delay);
proxy_->InsertFrame( proxy_->InsertFrame(test::FakeFrameBuilder()
Builder().Id(2).Time(2 * kFps30Rtp).Refs({0}).AsLast().Build()); .Id(2)
.Time(2 * kFps30Rtp)
.Refs({0})
.AsLast()
.Build());
// Simulate decode taking 3x FPS rate. // Simulate decode taking 3x FPS rate.
time_controller_.AdvanceTime(kFps30Delay * 1.5); time_controller_.AdvanceTime(kFps30Delay * 1.5);
StartNextDecode(); StartNextDecode();
// F2 is the best frame since decoding was so slow that F1 is too old. // F2 is the best frame since decoding was so slow that F1 is too old.
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay * 2), Frame(WithId(2))); EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay * 2), Frame(test::WithId(2)));
EXPECT_EQ(dropped_frames(), 1); EXPECT_EQ(dropped_frames(), 1);
time_controller_.AdvanceTime(kFps30Delay / 2); time_controller_.AdvanceTime(kFps30Delay / 2);
proxy_->InsertFrame( proxy_->InsertFrame(test::FakeFrameBuilder()
Builder().Id(3).Time(3 * kFps30Rtp).Refs({1, 2}).AsLast().Build()); .Id(3)
.Time(3 * kFps30Rtp)
.Refs({1, 2})
.AsLast()
.Build());
time_controller_.AdvanceTime(kFps30Delay / 2); time_controller_.AdvanceTime(kFps30Delay / 2);
proxy_->InsertFrame( proxy_->InsertFrame(test::FakeFrameBuilder()
Builder().Id(4).Time(4 * kFps30Rtp).Refs({2}).AsLast().Build()); .Id(4)
.Time(4 * kFps30Rtp)
.Refs({2})
.AsLast()
.Build());
time_controller_.AdvanceTime(kFps30Delay / 2); time_controller_.AdvanceTime(kFps30Delay / 2);
// F4 is the best frame since decoding was so slow that F1 is too old. // F4 is the best frame since decoding was so slow that F1 is too old.
time_controller_.AdvanceTime(kFps30Delay); time_controller_.AdvanceTime(kFps30Delay);
StartNextDecode(); StartNextDecode();
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(4))); EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(4)));
proxy_->InsertFrame( proxy_->InsertFrame(test::FakeFrameBuilder()
Builder().Id(5).Time(5 * kFps30Rtp).Refs({3, 4}).AsLast().Build()); .Id(5)
.Time(5 * kFps30Rtp)
.Refs({3, 4})
.AsLast()
.Build());
time_controller_.AdvanceTime(kFps30Delay / 2); time_controller_.AdvanceTime(kFps30Delay / 2);
// F5 is not decodable since F4 was decoded, so a timeout is expected. // F5 is not decodable since F4 was decoded, so a timeout is expected.
@ -563,20 +535,29 @@ TEST_P(FrameBufferProxyTest, SlowDecoderDropsTemporalLayers) {
TEST_P(FrameBufferProxyTest, NewFrameInsertedWhileWaitingToReleaseFrame) { TEST_P(FrameBufferProxyTest, NewFrameInsertedWhileWaitingToReleaseFrame) {
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
// Initial keyframe. // Initial keyframe.
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build()); proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build()));
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
time_controller_.AdvanceTime(kFps30Delay / 2); time_controller_.AdvanceTime(kFps30Delay / 2);
proxy_->InsertFrame( proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(test::FakeFrameBuilder()
Builder().Id(1).Time(kFps30Rtp).Refs({0}).AsLast().Build()); .Id(1)
.Time(kFps30Rtp)
.Refs({0})
.AsLast()
.Build()));
StartNextDecode(); StartNextDecode();
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Eq(absl::nullopt)); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Eq(absl::nullopt));
// Scheduler is waiting to deliver Frame 1 now. Insert Frame 2. Frame 1 should // Scheduler is waiting to deliver Frame 1 now. Insert Frame 2. Frame 1 should
// be delivered still. // be delivered still.
proxy_->InsertFrame( proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(test::FakeFrameBuilder()
Builder().Id(2).Time(kFps30Rtp * 2).Refs({0}).AsLast().Build()); .Id(2)
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(1))); .Time(kFps30Rtp * 2)
.Refs({0})
.AsLast()
.Build()));
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(1)));
} }
TEST_P(FrameBufferProxyTest, SameFrameNotScheduledTwice) { TEST_P(FrameBufferProxyTest, SameFrameNotScheduledTwice) {
@ -592,34 +573,40 @@ TEST_P(FrameBufferProxyTest, SameFrameNotScheduledTwice) {
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
// First keyframe. // First keyframe.
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build()); proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Millis(15)), Frame(WithId(0))); test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build()));
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Millis(15)),
Frame(test::WithId(0)));
StartNextDecode(); StartNextDecode();
// Warmup VCMTiming for 30fps. // Warmup VCMTiming for 30fps.
for (int i = 1; i <= 30; ++i) { for (int i = 1; i <= 30; ++i) {
proxy_->InsertFrame(Builder().Id(i).Time(i * kFps30Rtp).AsLast().Build()); proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(i))); test::FakeFrameBuilder().Id(i).Time(i * kFps30Rtp).AsLast().Build()));
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(i)));
StartNextDecode(); StartNextDecode();
} }
// F2 arrives and is scheduled. // F2 arrives and is scheduled.
proxy_->InsertFrame(Builder().Id(32).Time(32 * kFps30Rtp).AsLast().Build()); proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
test::FakeFrameBuilder().Id(32).Time(32 * kFps30Rtp).AsLast().Build()));
// F3 arrives before F2 is extracted. // F3 arrives before F2 is extracted.
time_controller_.AdvanceTime(kFps30Delay); time_controller_.AdvanceTime(kFps30Delay);
proxy_->InsertFrame(Builder().Id(33).Time(33 * kFps30Rtp).AsLast().Build()); proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
test::FakeFrameBuilder().Id(33).Time(33 * kFps30Rtp).AsLast().Build()));
// F1 arrives and is fast-forwarded since it is too late. // F1 arrives and is fast-forwarded since it is too late.
// F2 is already scheduled and should not be rescheduled. // F2 is already scheduled and should not be rescheduled.
time_controller_.AdvanceTime(kFps30Delay / 2); time_controller_.AdvanceTime(kFps30Delay / 2);
proxy_->InsertFrame(Builder().Id(31).Time(31 * kFps30Rtp).AsLast().Build()); proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
test::FakeFrameBuilder().Id(31).Time(31 * kFps30Rtp).AsLast().Build()));
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(32))); EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(32)));
StartNextDecode(); StartNextDecode();
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(33))); EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(33)));
StartNextDecode(); StartNextDecode();
EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), TimedOut()); EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), TimedOut());
EXPECT_EQ(dropped_frames(), 1); EXPECT_EQ(dropped_frames(), 1);
@ -633,8 +620,8 @@ TEST_P(FrameBufferProxyTest, TestStatsCallback) {
// Fake timing having received decoded frame. // Fake timing having received decoded frame.
timing_.StopDecodeTimer(TimeDelta::Millis(1), clock_->CurrentTime()); timing_.StopDecodeTimer(TimeDelta::Millis(1), clock_->CurrentTime());
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
// Flush stats posted on the decode queue. // Flush stats posted on the decode queue.
time_controller_.AdvanceTime(TimeDelta::Zero()); time_controller_.AdvanceTime(TimeDelta::Zero());
@ -646,8 +633,8 @@ TEST_P(FrameBufferProxyTest, FrameCompleteCalledOnceForDuplicateFrame) {
.Times(1); .Times(1);
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
// Flush stats posted on the decode queue. // Flush stats posted on the decode queue.
time_controller_.AdvanceTime(TimeDelta::Zero()); time_controller_.AdvanceTime(TimeDelta::Zero());
} }
@ -658,8 +645,8 @@ TEST_P(FrameBufferProxyTest, FrameCompleteCalledOnceForSingleTemporalUnit) {
// `OnCompleteFrame` should not be called for the first two frames since they // `OnCompleteFrame` should not be called for the first two frames since they
// do not complete the temporal layer. // do not complete the temporal layer.
EXPECT_CALL(stats_callback_, OnCompleteFrame(_, _, _)).Times(0); EXPECT_CALL(stats_callback_, OnCompleteFrame(_, _, _)).Times(0);
proxy_->InsertFrame(Builder().Id(0).Time(0).Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).Build());
proxy_->InsertFrame(Builder().Id(1).Time(0).Refs({0}).Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(1).Time(0).Refs({0}).Build());
time_controller_.AdvanceTime(TimeDelta::Zero()); time_controller_.AdvanceTime(TimeDelta::Zero());
// Flush stats posted on the decode queue. // Flush stats posted on the decode queue.
::testing::Mock::VerifyAndClearExpectations(&stats_callback_); ::testing::Mock::VerifyAndClearExpectations(&stats_callback_);
@ -669,7 +656,8 @@ TEST_P(FrameBufferProxyTest, FrameCompleteCalledOnceForSingleTemporalUnit) {
EXPECT_CALL(stats_callback_, EXPECT_CALL(stats_callback_,
OnCompleteFrame(false, kFrameSize, VideoContentType::UNSPECIFIED)) OnCompleteFrame(false, kFrameSize, VideoContentType::UNSPECIFIED))
.Times(1); .Times(1);
proxy_->InsertFrame(Builder().Id(2).Time(0).Refs({0, 1}).AsLast().Build()); proxy_->InsertFrame(
test::FakeFrameBuilder().Id(2).Time(0).Refs({0, 1}).AsLast().Build());
// Flush stats posted on the decode queue. // Flush stats posted on the decode queue.
time_controller_.AdvanceTime(TimeDelta::Zero()); time_controller_.AdvanceTime(TimeDelta::Zero());
} }
@ -684,8 +672,9 @@ TEST_P(FrameBufferProxyTest, FrameCompleteCalledOnceForCompleteTemporalUnit) {
// do not complete the temporal layer. Frame 1 arrives later, at which time // do not complete the temporal layer. Frame 1 arrives later, at which time
// this frame can finally be considered complete. // this frame can finally be considered complete.
EXPECT_CALL(stats_callback_, OnCompleteFrame(_, _, _)).Times(0); EXPECT_CALL(stats_callback_, OnCompleteFrame(_, _, _)).Times(0);
proxy_->InsertFrame(Builder().Id(0).Time(0).Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).Build());
proxy_->InsertFrame(Builder().Id(2).Time(0).Refs({0, 1}).AsLast().Build()); proxy_->InsertFrame(
test::FakeFrameBuilder().Id(2).Time(0).Refs({0, 1}).AsLast().Build());
time_controller_.AdvanceTime(TimeDelta::Zero()); time_controller_.AdvanceTime(TimeDelta::Zero());
// Flush stats posted on the decode queue. // Flush stats posted on the decode queue.
::testing::Mock::VerifyAndClearExpectations(&stats_callback_); ::testing::Mock::VerifyAndClearExpectations(&stats_callback_);
@ -693,7 +682,7 @@ TEST_P(FrameBufferProxyTest, FrameCompleteCalledOnceForCompleteTemporalUnit) {
EXPECT_CALL(stats_callback_, EXPECT_CALL(stats_callback_,
OnCompleteFrame(false, kFrameSize, VideoContentType::UNSPECIFIED)) OnCompleteFrame(false, kFrameSize, VideoContentType::UNSPECIFIED))
.Times(1); .Times(1);
proxy_->InsertFrame(Builder().Id(1).Time(0).Refs({0}).Build()); proxy_->InsertFrame(test::FakeFrameBuilder().Id(1).Time(0).Refs({0}).Build());
// Flush stats posted on the decode queue. // Flush stats posted on the decode queue.
time_controller_.AdvanceTime(TimeDelta::Zero()); time_controller_.AdvanceTime(TimeDelta::Zero());
} }
@ -711,23 +700,23 @@ TEST_P(FrameBufferProxyTest, NextFrameWithOldTimestamp) {
// First keyframe. The receive time must be explicitly set in this test since // First keyframe. The receive time must be explicitly set in this test since
// the RTP derived time used in all tests does not work when the long pause // the RTP derived time used in all tests does not work when the long pause
// happens later in the test. // happens later in the test.
proxy_->InsertFrame(Builder() proxy_->InsertFrame(test::FakeFrameBuilder()
.Id(0) .Id(0)
.Time(kBaseRtp) .Time(kBaseRtp)
.ReceivedTime(clock_->CurrentTime()) .ReceivedTime(clock_->CurrentTime())
.AsLast() .AsLast()
.Build()); .Build());
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(0)));
// 1 more frame to warmup VCMTiming for 30fps. // 1 more frame to warmup VCMTiming for 30fps.
StartNextDecode(); StartNextDecode();
proxy_->InsertFrame(Builder() proxy_->InsertFrame(test::FakeFrameBuilder()
.Id(1) .Id(1)
.Time(kBaseRtp + kFps30Rtp) .Time(kBaseRtp + kFps30Rtp)
.ReceivedTime(clock_->CurrentTime()) .ReceivedTime(clock_->CurrentTime())
.AsLast() .AsLast()
.Build()); .Build());
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(1))); EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(1)));
// Pause the stream for such a long time it incurs an RTP timestamp rollover // Pause the stream for such a long time it incurs an RTP timestamp rollover
// by over half. // by over half.
@ -746,7 +735,7 @@ TEST_P(FrameBufferProxyTest, NextFrameWithOldTimestamp) {
EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), Eq(absl::nullopt)); EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), Eq(absl::nullopt));
time_controller_.AdvanceTime(kRolloverDelay - kMaxWaitForFrame); time_controller_.AdvanceTime(kRolloverDelay - kMaxWaitForFrame);
StartNextDecode(); StartNextDecode();
proxy_->InsertFrame(Builder() proxy_->InsertFrame(test::FakeFrameBuilder()
.Id(2) .Id(2)
.Time(kRolloverRtp) .Time(kRolloverRtp)
.ReceivedTime(clock_->CurrentTime()) .ReceivedTime(clock_->CurrentTime())
@ -754,7 +743,7 @@ TEST_P(FrameBufferProxyTest, NextFrameWithOldTimestamp) {
.Build()); .Build());
// FrameBuffer2 drops the frame, while FrameBuffer3 will continue the stream. // FrameBuffer2 drops the frame, while FrameBuffer3 will continue the stream.
if (!IsFrameBuffer2Enabled(field_trials_)) { if (!IsFrameBuffer2Enabled(field_trials_)) {
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(2))); EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(2)));
} else { } else {
EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), TimedOut()); EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), TimedOut());
} }
@ -776,22 +765,22 @@ TEST_P(LowLatencyFrameBufferProxyTest,
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
timing_.set_min_playout_delay(TimeDelta::Zero()); timing_.set_min_playout_delay(TimeDelta::Zero());
timing_.set_max_playout_delay(TimeDelta::Millis(10)); timing_.set_max_playout_delay(TimeDelta::Millis(10));
auto frame = Builder().Id(0).Time(0).AsLast().Build(); auto frame = test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build();
// Playout delay of 0 implies low-latency rendering. // Playout delay of 0 implies low-latency rendering.
frame->SetPlayoutDelay({0, 10}); frame->SetPlayoutDelay({0, 10});
proxy_->InsertFrame(std::move(frame)); proxy_->InsertFrame(std::move(frame));
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
// Delta frame would normally wait here, but should decode at the pacing rate // Delta frame would normally wait here, but should decode at the pacing rate
// in low-latency mode. // in low-latency mode.
StartNextDecode(); StartNextDecode();
frame = Builder().Id(1).Time(kFps30Rtp).AsLast().Build(); frame = test::FakeFrameBuilder().Id(1).Time(kFps30Rtp).AsLast().Build();
frame->SetPlayoutDelay({0, 10}); frame->SetPlayoutDelay({0, 10});
proxy_->InsertFrame(std::move(frame)); proxy_->InsertFrame(std::move(frame));
// Pacing is set to 16ms in the field trial so we should not decode yet. // Pacing is set to 16ms in the field trial so we should not decode yet.
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Eq(absl::nullopt)); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Eq(absl::nullopt));
time_controller_.AdvanceTime(TimeDelta::Millis(16)); time_controller_.AdvanceTime(TimeDelta::Millis(16));
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(1))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(1)));
} }
TEST_P(LowLatencyFrameBufferProxyTest, ZeroPlayoutDelayFullQueue) { TEST_P(LowLatencyFrameBufferProxyTest, ZeroPlayoutDelayFullQueue) {
@ -799,15 +788,16 @@ TEST_P(LowLatencyFrameBufferProxyTest, ZeroPlayoutDelayFullQueue) {
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
timing_.set_min_playout_delay(TimeDelta::Zero()); timing_.set_min_playout_delay(TimeDelta::Zero());
timing_.set_max_playout_delay(TimeDelta::Millis(10)); timing_.set_max_playout_delay(TimeDelta::Millis(10));
auto frame = Builder().Id(0).Time(0).AsLast().Build(); auto frame = test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build();
// Playout delay of 0 implies low-latency rendering. // Playout delay of 0 implies low-latency rendering.
frame->SetPlayoutDelay({0, 10}); frame->SetPlayoutDelay({0, 10});
proxy_->InsertFrame(std::move(frame)); proxy_->InsertFrame(std::move(frame));
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
// Queue up 5 frames (configured max queue size for 0-playout delay pacing). // Queue up 5 frames (configured max queue size for 0-playout delay pacing).
for (int id = 1; id <= 6; ++id) { for (int id = 1; id <= 6; ++id) {
frame = Builder().Id(id).Time(kFps30Rtp * id).AsLast().Build(); frame =
test::FakeFrameBuilder().Id(id).Time(kFps30Rtp * id).AsLast().Build();
frame->SetPlayoutDelay({0, 10}); frame->SetPlayoutDelay({0, 10});
proxy_->InsertFrame(std::move(frame)); proxy_->InsertFrame(std::move(frame));
} }
@ -815,7 +805,7 @@ TEST_P(LowLatencyFrameBufferProxyTest, ZeroPlayoutDelayFullQueue) {
// The queue is at its max size for zero playout delay pacing, so the pacing // The queue is at its max size for zero playout delay pacing, so the pacing
// should be ignored and the next frame should be decoded instantly. // should be ignored and the next frame should be decoded instantly.
StartNextDecode(); StartNextDecode();
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(1))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(1)));
} }
TEST_P(LowLatencyFrameBufferProxyTest, MinMaxDelayZeroLowLatencyMode) { TEST_P(LowLatencyFrameBufferProxyTest, MinMaxDelayZeroLowLatencyMode) {
@ -823,21 +813,21 @@ TEST_P(LowLatencyFrameBufferProxyTest, MinMaxDelayZeroLowLatencyMode) {
StartNextDecodeForceKeyframe(); StartNextDecodeForceKeyframe();
timing_.set_min_playout_delay(TimeDelta::Zero()); timing_.set_min_playout_delay(TimeDelta::Zero());
timing_.set_max_playout_delay(TimeDelta::Zero()); timing_.set_max_playout_delay(TimeDelta::Zero());
auto frame = Builder().Id(0).Time(0).AsLast().Build(); auto frame = test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build();
// Playout delay of 0 implies low-latency rendering. // Playout delay of 0 implies low-latency rendering.
frame->SetPlayoutDelay({0, 0}); frame->SetPlayoutDelay({0, 0});
proxy_->InsertFrame(std::move(frame)); proxy_->InsertFrame(std::move(frame));
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
// Delta frame would normally wait here, but should decode at the pacing rate // Delta frame would normally wait here, but should decode at the pacing rate
// in low-latency mode. // in low-latency mode.
StartNextDecode(); StartNextDecode();
frame = Builder().Id(1).Time(kFps30Rtp).AsLast().Build(); frame = test::FakeFrameBuilder().Id(1).Time(kFps30Rtp).AsLast().Build();
frame->SetPlayoutDelay({0, 0}); frame->SetPlayoutDelay({0, 0});
proxy_->InsertFrame(std::move(frame)); proxy_->InsertFrame(std::move(frame));
// The min/max=0 version of low-latency rendering will result in a large // The min/max=0 version of low-latency rendering will result in a large
// negative decode wait time, so the frame should be ready right away. // negative decode wait time, so the frame should be ready right away.
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(1))); EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(1)));
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(

View File

@ -34,6 +34,7 @@
#include "rtc_base/event.h" #include "rtc_base/event.h"
#include "system_wrappers/include/clock.h" #include "system_wrappers/include/clock.h"
#include "test/fake_decoder.h" #include "test/fake_decoder.h"
#include "test/fake_encoded_frame.h"
#include "test/gmock.h" #include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
#include "test/mock_transport.h" #include "test/mock_transport.h"
@ -59,19 +60,6 @@ using ::testing::WithoutArgs;
constexpr int kDefaultTimeOutMs = 50; constexpr int kDefaultTimeOutMs = 50;
class FrameObjectFake : public EncodedFrame {
public:
void SetPayloadType(uint8_t payload_type) { _payloadType = payload_type; }
void SetRotation(const VideoRotation& rotation) { rotation_ = rotation; }
void SetNtpTime(int64_t ntp_time_ms) { ntp_time_ms_ = ntp_time_ms; }
int64_t ReceivedTime() const override { return 0; }
int64_t RenderTime() const override { return _renderTimeMs; }
};
} // namespace } // namespace
class VideoReceiveStream2Test : public ::testing::Test { class VideoReceiveStream2Test : public ::testing::Test {
@ -159,8 +147,8 @@ TEST_F(VideoReceiveStream2Test, CreateFrameFromH264FmtpSpropAndIdr) {
TEST_F(VideoReceiveStream2Test, PlayoutDelay) { TEST_F(VideoReceiveStream2Test, PlayoutDelay) {
const VideoPlayoutDelay kPlayoutDelayMs = {123, 321}; const VideoPlayoutDelay kPlayoutDelayMs = {123, 321};
std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake()); std::unique_ptr<test::FakeEncodedFrame> test_frame =
test_frame->SetId(0); test::FakeFrameBuilder().Id(0).AsLast().Build();
test_frame->SetPlayoutDelay(kPlayoutDelayMs); test_frame->SetPlayoutDelay(kPlayoutDelayMs);
video_receive_stream_->OnCompleteFrame(std::move(test_frame)); video_receive_stream_->OnCompleteFrame(std::move(test_frame));
@ -196,8 +184,8 @@ TEST_F(VideoReceiveStream2Test, PlayoutDelayPreservesDefaultMaxValue) {
timing_->GetTimings().max_playout_delay; timing_->GetTimings().max_playout_delay;
const VideoPlayoutDelay kPlayoutDelayMs = {123, -1}; const VideoPlayoutDelay kPlayoutDelayMs = {123, -1};
std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake()); std::unique_ptr<test::FakeEncodedFrame> test_frame =
test_frame->SetId(0); test::FakeFrameBuilder().Id(0).AsLast().Build();
test_frame->SetPlayoutDelay(kPlayoutDelayMs); test_frame->SetPlayoutDelay(kPlayoutDelayMs);
video_receive_stream_->OnCompleteFrame(std::move(test_frame)); video_receive_stream_->OnCompleteFrame(std::move(test_frame));
@ -214,8 +202,8 @@ TEST_F(VideoReceiveStream2Test, PlayoutDelayPreservesDefaultMinValue) {
timing_->GetTimings().min_playout_delay; timing_->GetTimings().min_playout_delay;
const VideoPlayoutDelay kPlayoutDelayMs = {-1, 321}; const VideoPlayoutDelay kPlayoutDelayMs = {-1, 321};
std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake()); std::unique_ptr<test::FakeEncodedFrame> test_frame =
test_frame->SetId(0); test::FakeFrameBuilder().Id(0).AsLast().Build();
test_frame->SetPlayoutDelay(kPlayoutDelayMs); test_frame->SetPlayoutDelay(kPlayoutDelayMs);
video_receive_stream_->OnCompleteFrame(std::move(test_frame)); video_receive_stream_->OnCompleteFrame(std::move(test_frame));
@ -229,21 +217,21 @@ TEST_F(VideoReceiveStream2Test, PlayoutDelayPreservesDefaultMinValue) {
TEST_F(VideoReceiveStream2Test, MaxCompositionDelayNotSetByDefault) { TEST_F(VideoReceiveStream2Test, MaxCompositionDelayNotSetByDefault) {
// Default with no playout delay set. // Default with no playout delay set.
std::unique_ptr<FrameObjectFake> test_frame0(new FrameObjectFake()); std::unique_ptr<test::FakeEncodedFrame> test_frame0 =
test_frame0->SetId(0); test::FakeFrameBuilder().Id(0).AsLast().Build();
video_receive_stream_->OnCompleteFrame(std::move(test_frame0)); video_receive_stream_->OnCompleteFrame(std::move(test_frame0));
EXPECT_FALSE(timing_->MaxCompositionDelayInFrames()); EXPECT_FALSE(timing_->MaxCompositionDelayInFrames());
// Max composition delay not set for playout delay 0,0. // Max composition delay not set for playout delay 0,0.
std::unique_ptr<FrameObjectFake> test_frame1(new FrameObjectFake()); std::unique_ptr<test::FakeEncodedFrame> test_frame1 =
test_frame1->SetId(1); test::FakeFrameBuilder().Id(1).AsLast().Build();
test_frame1->SetPlayoutDelay({0, 0}); test_frame1->SetPlayoutDelay({0, 0});
video_receive_stream_->OnCompleteFrame(std::move(test_frame1)); video_receive_stream_->OnCompleteFrame(std::move(test_frame1));
EXPECT_FALSE(timing_->MaxCompositionDelayInFrames()); EXPECT_FALSE(timing_->MaxCompositionDelayInFrames());
// Max composition delay not set for playout delay X,Y, where X,Y>0. // Max composition delay not set for playout delay X,Y, where X,Y>0.
std::unique_ptr<FrameObjectFake> test_frame2(new FrameObjectFake()); std::unique_ptr<test::FakeEncodedFrame> test_frame2 =
test_frame2->SetId(2); test::FakeFrameBuilder().Id(2).AsLast().Build();
test_frame2->SetPlayoutDelay({10, 30}); test_frame2->SetPlayoutDelay({10, 30});
video_receive_stream_->OnCompleteFrame(std::move(test_frame2)); video_receive_stream_->OnCompleteFrame(std::move(test_frame2));
EXPECT_FALSE(timing_->MaxCompositionDelayInFrames()); EXPECT_FALSE(timing_->MaxCompositionDelayInFrames());
@ -253,8 +241,8 @@ TEST_F(VideoReceiveStream2Test, MaxCompositionDelaySetFromMaxPlayoutDelay) {
// Max composition delay set if playout delay X,Y, where X=0,Y>0. // Max composition delay set if playout delay X,Y, where X=0,Y>0.
const VideoPlayoutDelay kPlayoutDelayMs = {0, 50}; const VideoPlayoutDelay kPlayoutDelayMs = {0, 50};
const int kExpectedMaxCompositionDelayInFrames = 3; // ~50 ms at 60 fps. const int kExpectedMaxCompositionDelayInFrames = 3; // ~50 ms at 60 fps.
std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake()); std::unique_ptr<test::FakeEncodedFrame> test_frame =
test_frame->SetId(0); test::FakeFrameBuilder().Id(0).AsLast().Build();
test_frame->SetPlayoutDelay(kPlayoutDelayMs); test_frame->SetPlayoutDelay(kPlayoutDelayMs);
video_receive_stream_->OnCompleteFrame(std::move(test_frame)); video_receive_stream_->OnCompleteFrame(std::move(test_frame));
EXPECT_EQ(kExpectedMaxCompositionDelayInFrames, EXPECT_EQ(kExpectedMaxCompositionDelayInFrames,
@ -321,24 +309,29 @@ class VideoReceiveStream2TestWithFakeDecoder : public ::testing::Test {
}; };
TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesNtpTime) { TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesNtpTime) {
const int64_t kNtpTimestamp = 12345; const Timestamp kNtpTimestamp = Timestamp::Millis(12345);
auto test_frame = std::make_unique<FrameObjectFake>(); std::unique_ptr<test::FakeEncodedFrame> test_frame =
test_frame->SetPayloadType(99); test::FakeFrameBuilder()
test_frame->SetId(0); .Id(0)
test_frame->SetNtpTime(kNtpTimestamp); .PayloadType(99)
.NtpTime(kNtpTimestamp)
.AsLast()
.Build();
video_receive_stream_->Start(); video_receive_stream_->Start();
video_receive_stream_->OnCompleteFrame(std::move(test_frame)); video_receive_stream_->OnCompleteFrame(std::move(test_frame));
EXPECT_TRUE(fake_renderer_.WaitForRenderedFrame(kDefaultTimeOutMs)); EXPECT_TRUE(fake_renderer_.WaitForRenderedFrame(kDefaultTimeOutMs));
EXPECT_EQ(kNtpTimestamp, fake_renderer_.ntp_time_ms()); EXPECT_EQ(kNtpTimestamp.ms(), fake_renderer_.ntp_time_ms());
} }
TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesRotation) { TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesRotation) {
const webrtc::VideoRotation kRotation = webrtc::kVideoRotation_180; const webrtc::VideoRotation kRotation = webrtc::kVideoRotation_180;
auto test_frame = std::make_unique<FrameObjectFake>(); std::unique_ptr<test::FakeEncodedFrame> test_frame = test::FakeFrameBuilder()
test_frame->SetPayloadType(99); .Id(0)
test_frame->SetId(0); .PayloadType(99)
test_frame->SetRotation(kRotation); .Rotation(kRotation)
.AsLast()
.Build();
video_receive_stream_->Start(); video_receive_stream_->Start();
video_receive_stream_->OnCompleteFrame(std::move(test_frame)); video_receive_stream_->OnCompleteFrame(std::move(test_frame));
@ -348,11 +341,13 @@ TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesRotation) {
} }
TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesPacketInfos) { TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesPacketInfos) {
auto test_frame = std::make_unique<FrameObjectFake>();
test_frame->SetPayloadType(99);
test_frame->SetId(0);
RtpPacketInfos packet_infos = CreatePacketInfos(3); RtpPacketInfos packet_infos = CreatePacketInfos(3);
test_frame->SetPacketInfos(packet_infos); auto test_frame = test::FakeFrameBuilder()
.Id(0)
.PayloadType(99)
.PacketInfos(packet_infos)
.AsLast()
.Build();
video_receive_stream_->Start(); video_receive_stream_->Start();
video_receive_stream_->OnCompleteFrame(std::move(test_frame)); video_receive_stream_->OnCompleteFrame(std::move(test_frame));
@ -367,9 +362,8 @@ TEST_F(VideoReceiveStream2TestWithFakeDecoder, RenderedFrameUpdatesGetSources) {
constexpr uint32_t kRtpTimestamp = 12345; constexpr uint32_t kRtpTimestamp = 12345;
// Prepare one video frame with per-packet information. // Prepare one video frame with per-packet information.
auto test_frame = std::make_unique<FrameObjectFake>(); auto test_frame =
test_frame->SetPayloadType(99); test::FakeFrameBuilder().Id(0).PayloadType(99).AsLast().Build();
test_frame->SetId(0);
RtpPacketInfos packet_infos; RtpPacketInfos packet_infos;
{ {
RtpPacketInfos::vector_type infos; RtpPacketInfos::vector_type infos;
@ -439,22 +433,21 @@ TEST_F(VideoReceiveStream2TestWithFakeDecoder, RenderedFrameUpdatesGetSources) {
} }
} }
std::unique_ptr<FrameObjectFake> MakeFrameWithResolution( std::unique_ptr<test::FakeEncodedFrame> MakeFrameWithResolution(
VideoFrameType frame_type, VideoFrameType frame_type,
int picture_id, int picture_id,
int width, int width,
int height) { int height) {
auto frame = std::make_unique<FrameObjectFake>(); auto frame =
frame->SetPayloadType(99); test::FakeFrameBuilder().Id(picture_id).PayloadType(99).AsLast().Build();
frame->SetId(picture_id);
frame->SetFrameType(frame_type); frame->SetFrameType(frame_type);
frame->_encodedWidth = width; frame->_encodedWidth = width;
frame->_encodedHeight = height; frame->_encodedHeight = height;
return frame; return frame;
} }
std::unique_ptr<FrameObjectFake> MakeFrame(VideoFrameType frame_type, std::unique_ptr<test::FakeEncodedFrame> MakeFrame(VideoFrameType frame_type,
int picture_id) { int picture_id) {
return MakeFrameWithResolution(frame_type, picture_id, 320, 240); return MakeFrameWithResolution(frame_type, picture_id, 320, 240);
} }

View File

@ -14,6 +14,7 @@
#include "api/video/i420_buffer.h" #include "api/video/i420_buffer.h"
#include "api/video_codecs/video_decoder.h" #include "api/video_codecs/video_decoder.h"
#include "test/fake_encoded_frame.h"
#include "test/gmock.h" #include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
#include "test/scoped_key_value_config.h" #include "test/scoped_key_value_config.h"
@ -22,7 +23,6 @@
namespace webrtc { namespace webrtc {
namespace { namespace {
using ::testing::_; using ::testing::_;
using ::testing::ByMove;
using ::testing::NiceMock; using ::testing::NiceMock;
using ::testing::Return; using ::testing::Return;
@ -127,35 +127,6 @@ class FakeVideoDecoderFactory : public VideoDecoderFactory {
NiceMock<StubVideoDecoder> av1_decoder_; NiceMock<StubVideoDecoder> av1_decoder_;
}; };
class FakeEncodedFrame : public EncodedFrame {
public:
int64_t ReceivedTime() const override { return 0; }
int64_t RenderTime() const override { return 0; }
// Setters for protected variables.
void SetPayloadType(int payload_type) { _payloadType = payload_type; }
};
class FrameBuilder {
public:
FrameBuilder() : frame_(std::make_unique<FakeEncodedFrame>()) {}
FrameBuilder& WithPayloadType(int payload_type) {
frame_->SetPayloadType(payload_type);
return *this;
}
FrameBuilder& WithPictureId(int picture_id) {
frame_->SetId(picture_id);
return *this;
}
std::unique_ptr<FakeEncodedFrame> Build() { return std::move(frame_); }
private:
std::unique_ptr<FakeEncodedFrame> frame_;
};
class VideoStreamDecoderImplTest : public ::testing::Test { class VideoStreamDecoderImplTest : public ::testing::Test {
public: public:
VideoStreamDecoderImplTest() VideoStreamDecoderImplTest()
@ -179,7 +150,8 @@ class VideoStreamDecoderImplTest : public ::testing::Test {
}; };
TEST_F(VideoStreamDecoderImplTest, InsertAndDecodeFrame) { TEST_F(VideoStreamDecoderImplTest, InsertAndDecodeFrame) {
video_stream_decoder_.OnFrame(FrameBuilder().WithPayloadType(1).Build()); video_stream_decoder_.OnFrame(
test::FakeFrameBuilder().PayloadType(1).AsLast().Build());
EXPECT_CALL(callbacks_, OnDecodedFrame); EXPECT_CALL(callbacks_, OnDecodedFrame);
time_controller_.AdvanceTime(TimeDelta::Millis(1)); time_controller_.AdvanceTime(TimeDelta::Millis(1));
} }
@ -190,7 +162,8 @@ TEST_F(VideoStreamDecoderImplTest, NonDecodableStateWaitingForKeyframe) {
} }
TEST_F(VideoStreamDecoderImplTest, NonDecodableStateWaitingForDeltaFrame) { TEST_F(VideoStreamDecoderImplTest, NonDecodableStateWaitingForDeltaFrame) {
video_stream_decoder_.OnFrame(FrameBuilder().WithPayloadType(1).Build()); video_stream_decoder_.OnFrame(
test::FakeFrameBuilder().PayloadType(1).AsLast().Build());
EXPECT_CALL(callbacks_, OnDecodedFrame); EXPECT_CALL(callbacks_, OnDecodedFrame);
time_controller_.AdvanceTime(TimeDelta::Millis(1)); time_controller_.AdvanceTime(TimeDelta::Millis(1));
EXPECT_CALL(callbacks_, OnNonDecodableState); EXPECT_CALL(callbacks_, OnNonDecodableState);
@ -198,7 +171,8 @@ TEST_F(VideoStreamDecoderImplTest, NonDecodableStateWaitingForDeltaFrame) {
} }
TEST_F(VideoStreamDecoderImplTest, InsertAndDecodeFrameWithKeyframeRequest) { TEST_F(VideoStreamDecoderImplTest, InsertAndDecodeFrameWithKeyframeRequest) {
video_stream_decoder_.OnFrame(FrameBuilder().WithPayloadType(1).Build()); video_stream_decoder_.OnFrame(
test::FakeFrameBuilder().PayloadType(1).AsLast().Build());
EXPECT_CALL(decoder_factory_.Vp8Decoder(), DecodeCall) EXPECT_CALL(decoder_factory_.Vp8Decoder(), DecodeCall)
.WillOnce(Return(WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME)); .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME));
EXPECT_CALL(callbacks_, OnDecodedFrame); EXPECT_CALL(callbacks_, OnDecodedFrame);
@ -207,7 +181,12 @@ TEST_F(VideoStreamDecoderImplTest, InsertAndDecodeFrameWithKeyframeRequest) {
} }
TEST_F(VideoStreamDecoderImplTest, FailToInitDecoder) { TEST_F(VideoStreamDecoderImplTest, FailToInitDecoder) {
video_stream_decoder_.OnFrame(FrameBuilder().WithPayloadType(1).Build()); video_stream_decoder_.OnFrame(
test::FakeFrameBuilder()
.ReceivedTime(time_controller_.GetClock()->CurrentTime())
.PayloadType(1)
.AsLast()
.Build());
ON_CALL(decoder_factory_.Vp8Decoder(), Configure) ON_CALL(decoder_factory_.Vp8Decoder(), Configure)
.WillByDefault(Return(false)); .WillByDefault(Return(false));
EXPECT_CALL(callbacks_, OnNonDecodableState); EXPECT_CALL(callbacks_, OnNonDecodableState);
@ -215,7 +194,8 @@ TEST_F(VideoStreamDecoderImplTest, FailToInitDecoder) {
} }
TEST_F(VideoStreamDecoderImplTest, FailToDecodeFrame) { TEST_F(VideoStreamDecoderImplTest, FailToDecodeFrame) {
video_stream_decoder_.OnFrame(FrameBuilder().WithPayloadType(1).Build()); video_stream_decoder_.OnFrame(
test::FakeFrameBuilder().PayloadType(1).AsLast().Build());
ON_CALL(decoder_factory_.Vp8Decoder(), DecodeCall) ON_CALL(decoder_factory_.Vp8Decoder(), DecodeCall)
.WillByDefault(Return(WEBRTC_VIDEO_CODEC_ERROR)); .WillByDefault(Return(WEBRTC_VIDEO_CODEC_ERROR));
EXPECT_CALL(callbacks_, OnNonDecodableState); EXPECT_CALL(callbacks_, OnNonDecodableState);
@ -225,13 +205,13 @@ TEST_F(VideoStreamDecoderImplTest, FailToDecodeFrame) {
TEST_F(VideoStreamDecoderImplTest, ChangeFramePayloadType) { TEST_F(VideoStreamDecoderImplTest, ChangeFramePayloadType) {
constexpr TimeDelta kFrameInterval = TimeDelta::Millis(1000 / 60); constexpr TimeDelta kFrameInterval = TimeDelta::Millis(1000 / 60);
video_stream_decoder_.OnFrame( video_stream_decoder_.OnFrame(
FrameBuilder().WithPayloadType(1).WithPictureId(0).Build()); test::FakeFrameBuilder().PayloadType(1).Id(0).AsLast().Build());
EXPECT_CALL(decoder_factory_.Vp8Decoder(), DecodeCall); EXPECT_CALL(decoder_factory_.Vp8Decoder(), DecodeCall);
EXPECT_CALL(callbacks_, OnDecodedFrame); EXPECT_CALL(callbacks_, OnDecodedFrame);
time_controller_.AdvanceTime(kFrameInterval); time_controller_.AdvanceTime(kFrameInterval);
video_stream_decoder_.OnFrame( video_stream_decoder_.OnFrame(
FrameBuilder().WithPayloadType(2).WithPictureId(1).Build()); test::FakeFrameBuilder().PayloadType(2).Id(1).AsLast().Build());
EXPECT_CALL(decoder_factory_.Av1Decoder(), DecodeCall); EXPECT_CALL(decoder_factory_.Av1Decoder(), DecodeCall);
EXPECT_CALL(callbacks_, OnDecodedFrame); EXPECT_CALL(callbacks_, OnDecodedFrame);
time_controller_.AdvanceTime(kFrameInterval); time_controller_.AdvanceTime(kFrameInterval);