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:
committed by
WebRTC LUCI CQ
parent
65dcc47b8b
commit
a0ee64c57e
@ -1279,6 +1279,7 @@ if (rtc_include_tests) {
|
||||
"../../system_wrappers",
|
||||
"../../system_wrappers:field_trial",
|
||||
"../../system_wrappers:metrics",
|
||||
"../../test:fake_encoded_frame",
|
||||
"../../test:fake_video_codecs",
|
||||
"../../test:field_trial",
|
||||
"../../test:fileutils",
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "api/video/encoded_frame.h"
|
||||
#include "test/fake_encoded_frame.h"
|
||||
#include "test/field_trial.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
@ -29,67 +30,19 @@ MATCHER_P(FrameWithId, 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::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.
|
||||
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));
|
||||
|
||||
// Duplicate ids are also invalid.
|
||||
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1, 1}).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(
|
||||
test::FakeFrameBuilder().Time(20).Id(2).Refs({1, 1}).AsLast().Build());
|
||||
EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1));
|
||||
}
|
||||
|
||||
@ -100,11 +53,12 @@ TEST(FrameBuffer3Test, LastContinuousUpdatesOnInsertedFrames) {
|
||||
EXPECT_THAT(buffer.LastContinuousFrameId(), 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.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.LastContinuousTemporalUnitFrameId(), Eq(2));
|
||||
}
|
||||
@ -114,11 +68,13 @@ TEST(FrameBuffer3Test, LastContinuousFrameReordering) {
|
||||
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
|
||||
field_trials);
|
||||
|
||||
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(
|
||||
test::FakeFrameBuilder().Time(30).Id(3).Refs({2}).AsLast().Build());
|
||||
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));
|
||||
}
|
||||
|
||||
@ -127,9 +83,10 @@ TEST(FrameBuffer3Test, LastContinuousTemporalUnit) {
|
||||
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
|
||||
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));
|
||||
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));
|
||||
}
|
||||
|
||||
@ -138,12 +95,14 @@ TEST(FrameBuffer3Test, LastContinuousTemporalUnitReordering) {
|
||||
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
|
||||
field_trials);
|
||||
|
||||
buffer.InsertFrame(Builder().Time(10).Id(1).Build());
|
||||
buffer.InsertFrame(Builder().Time(20).Id(3).Refs({1}).Build());
|
||||
buffer.InsertFrame(Builder().Time(20).Id(4).Refs({2, 3}).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(20).Id(3).Refs({1}).Build());
|
||||
buffer.InsertFrame(
|
||||
test::FakeFrameBuilder().Time(20).Id(4).Refs({2, 3}).AsLast().Build());
|
||||
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));
|
||||
}
|
||||
|
||||
@ -154,7 +113,7 @@ TEST(FrameBuffer3Test, NextDecodable) {
|
||||
|
||||
EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(),
|
||||
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));
|
||||
}
|
||||
|
||||
@ -163,9 +122,10 @@ TEST(FrameBuffer3Test, AdvanceNextDecodableOnExtraction) {
|
||||
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
|
||||
field_trials);
|
||||
|
||||
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(20).Id(2).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(20).Id(2).AsLast().Build());
|
||||
buffer.InsertFrame(
|
||||
test::FakeFrameBuilder().Time(30).Id(3).Refs({2}).AsLast().Build());
|
||||
EXPECT_THAT(buffer.NextDecodableTemporalUnitRtpTimestamp(), Eq(10U));
|
||||
|
||||
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
|
||||
@ -183,9 +143,11 @@ TEST(FrameBuffer3Test, AdvanceLastDecodableOnExtraction) {
|
||||
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
|
||||
field_trials);
|
||||
|
||||
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(
|
||||
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.ExtractNextDecodableTemporalUnit(),
|
||||
@ -198,10 +160,10 @@ TEST(FrameBuffer3Test, FrameUpdatesNextDecodable) {
|
||||
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
|
||||
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));
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
@ -209,18 +171,23 @@ TEST(FrameBuffer3Test, KeyframeClearsFullBuffer) {
|
||||
test::ScopedKeyValueConfig field_trials;
|
||||
FrameBuffer buffer(/*max_frame_slots=*/5, /*max_decode_history=*/10,
|
||||
field_trials);
|
||||
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({2}).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(40).Id(4).Refs({3}).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(50).Id(5).Refs({4}).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(
|
||||
test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build());
|
||||
buffer.InsertFrame(
|
||||
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));
|
||||
|
||||
// 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));
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
@ -228,9 +195,11 @@ TEST(FrameBuffer3Test, DropNextDecodableTemporalUnit) {
|
||||
test::ScopedKeyValueConfig field_trials;
|
||||
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
|
||||
field_trials);
|
||||
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(
|
||||
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.DropNextDecodableTemporalUnit();
|
||||
@ -242,15 +211,18 @@ TEST(FrameBuffer3Test, OldFramesAreIgnored) {
|
||||
test::ScopedKeyValueConfig field_trials;
|
||||
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
|
||||
field_trials);
|
||||
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(
|
||||
test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build());
|
||||
|
||||
buffer.ExtractNextDecodableTemporalUnit();
|
||||
buffer.ExtractNextDecodableTemporalUnit();
|
||||
|
||||
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(
|
||||
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(),
|
||||
ElementsAre(FrameWithId(3)));
|
||||
@ -260,13 +232,15 @@ TEST(FrameBuffer3Test, ReturnFullTemporalUnitKSVC) {
|
||||
test::ScopedKeyValueConfig field_trials;
|
||||
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
|
||||
field_trials);
|
||||
buffer.InsertFrame(Builder().Time(10).Id(1).Build());
|
||||
buffer.InsertFrame(Builder().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(1).Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).Build());
|
||||
buffer.InsertFrame(
|
||||
test::FakeFrameBuilder().Time(10).Id(3).Refs({2}).AsLast().Build());
|
||||
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
|
||||
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(),
|
||||
ElementsAre(FrameWithId(4)));
|
||||
}
|
||||
@ -275,11 +249,15 @@ TEST(FrameBuffer3Test, InterleavedStream) {
|
||||
test::ScopedKeyValueConfig field_trials;
|
||||
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
|
||||
field_trials);
|
||||
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(30).Id(3).Refs({1}).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(40).Id(4).Refs({2}).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(50).Id(5).Refs({3}).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(
|
||||
test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build());
|
||||
buffer.InsertFrame(
|
||||
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(),
|
||||
ElementsAre(FrameWithId(1)));
|
||||
@ -292,12 +270,15 @@ TEST(FrameBuffer3Test, InterleavedStream) {
|
||||
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
|
||||
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(),
|
||||
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());
|
||||
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(),
|
||||
ElementsAre(FrameWithId(9)));
|
||||
}
|
||||
@ -309,10 +290,12 @@ TEST(FrameBuffer3Test, LegacyFrameIdJumpBehavior) {
|
||||
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
|
||||
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(),
|
||||
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());
|
||||
}
|
||||
|
||||
@ -322,12 +305,15 @@ TEST(FrameBuffer3Test, LegacyFrameIdJumpBehavior) {
|
||||
FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100,
|
||||
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(),
|
||||
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());
|
||||
buffer.InsertFrame(Builder().Time(40).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(
|
||||
test::FakeFrameBuilder().Time(40).Id(1).AsLast().Build());
|
||||
EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(),
|
||||
ElementsAre(FrameWithId(1)));
|
||||
}
|
||||
@ -339,18 +325,20 @@ TEST(FrameBuffer3Test, TotalNumberOfContinuousTemporalUnits) {
|
||||
field_trials);
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
buffer.InsertFrame(Builder().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(4).Refs({2}).Build());
|
||||
buffer.InsertFrame(
|
||||
test::FakeFrameBuilder().Time(40).Id(5).Refs({3, 4}).AsLast().Build());
|
||||
EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1));
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
@ -360,11 +348,13 @@ TEST(FrameBuffer3Test, TotalNumberOfDroppedFrames) {
|
||||
field_trials);
|
||||
EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0));
|
||||
|
||||
buffer.InsertFrame(Builder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(20).Id(2).Refs({1}).Build());
|
||||
buffer.InsertFrame(Builder().Time(20).Id(3).Refs({2}).AsLast().Build());
|
||||
buffer.InsertFrame(Builder().Time(40).Id(4).Refs({1}).Build());
|
||||
buffer.InsertFrame(Builder().Time(40).Id(5).Refs({4}).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build());
|
||||
buffer.InsertFrame(test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).Build());
|
||||
buffer.InsertFrame(
|
||||
test::FakeFrameBuilder().Time(20).Id(3).Refs({2}).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();
|
||||
EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0));
|
||||
|
||||
@ -1120,3 +1120,18 @@ rtc_library("call_config_utils") {
|
||||
"../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
135
test/fake_encoded_frame.cc
Normal 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
84
test/fake_encoded_frame.h
Normal 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_
|
||||
@ -950,6 +950,7 @@ if (rtc_include_tests) {
|
||||
"../system_wrappers:metrics",
|
||||
"../test:direct_transport",
|
||||
"../test:encoder_settings",
|
||||
"../test:fake_encoded_frame",
|
||||
"../test:fake_video_codecs",
|
||||
"../test:field_trial",
|
||||
"../test:fileutils",
|
||||
@ -965,7 +966,6 @@ if (rtc_include_tests) {
|
||||
"../test:video_test_common",
|
||||
"../test/time_controller",
|
||||
"adaptation:video_adaptation",
|
||||
"//testing/gtest",
|
||||
]
|
||||
absl_deps = [
|
||||
"//third_party/abseil-cpp/absl/algorithm:container",
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "api/video/video_timing.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/event.h"
|
||||
#include "test/fake_encoded_frame.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
#include "test/run_loop.h"
|
||||
@ -51,16 +52,6 @@ using ::testing::VariantWith;
|
||||
|
||||
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 {
|
||||
|
||||
constexpr size_t kFrameSize = 10;
|
||||
@ -69,28 +60,6 @@ constexpr TimeDelta kFps30Delay = 1 / Frequency::Hertz(30);
|
||||
const VideoPlayoutDelay kZeroPlayoutDelay = {0, 0};
|
||||
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() {
|
||||
return Optional(VariantWith<TimeDelta>(_));
|
||||
}
|
||||
@ -99,80 +68,17 @@ auto Frame(testing::Matcher<EncodedFrame> m) {
|
||||
return Optional(VariantWith<std::unique_ptr<EncodedFrame>>(Pointee(m)));
|
||||
}
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
Builder& Time(uint32_t rtp_timestamp) {
|
||||
rtp_timestamp_ = rtp_timestamp;
|
||||
return *this;
|
||||
std::unique_ptr<test::FakeEncodedFrame> WithReceiveTimeFromRtpTimestamp(
|
||||
std::unique_ptr<test::FakeEncodedFrame> frame) {
|
||||
if (frame->Timestamp() == 0) {
|
||||
frame->SetReceivedTime(kClockStart.ms());
|
||||
} else {
|
||||
frame->SetReceivedTime(
|
||||
TimeDelta::Seconds(frame->Timestamp() / 90000.0).ms() +
|
||||
kClockStart.ms());
|
||||
}
|
||||
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;
|
||||
}
|
||||
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_;
|
||||
};
|
||||
return frame;
|
||||
}
|
||||
|
||||
class VCMReceiveStatisticsCallbackMock : public VCMReceiveStatisticsCallback {
|
||||
public:
|
||||
@ -349,19 +255,20 @@ TEST_P(FrameBufferProxyTest, KeyFramesAreScheduled) {
|
||||
StartNextDecodeForceKeyframe();
|
||||
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));
|
||||
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
|
||||
}
|
||||
|
||||
TEST_P(FrameBufferProxyTest, DeltaFrameTimeoutAfterKeyframeExtracted) {
|
||||
StartNextDecodeForceKeyframe();
|
||||
|
||||
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));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForKeyframe), Frame(WithId(0)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForKeyframe),
|
||||
Frame(test::WithId(0)));
|
||||
|
||||
StartNextDecode();
|
||||
time_controller_.AdvanceTime(TimeDelta::Millis(50));
|
||||
@ -376,44 +283,64 @@ TEST_P(FrameBufferProxyTest, DeltaFrameTimeoutAfterKeyframeExtracted) {
|
||||
|
||||
TEST_P(FrameBufferProxyTest, DependantFramesAreScheduled) {
|
||||
StartNextDecodeForceKeyframe();
|
||||
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0)));
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
|
||||
|
||||
StartNextDecode();
|
||||
|
||||
time_controller_.AdvanceTime(kFps30Delay);
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(1).Time(kFps30Rtp).AsLast().Refs({0}).Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(1)));
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(1)
|
||||
.Time(kFps30Rtp)
|
||||
.AsLast()
|
||||
.Refs({0})
|
||||
.Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(1)));
|
||||
}
|
||||
|
||||
TEST_P(FrameBufferProxyTest, SpatialLayersAreScheduled) {
|
||||
StartNextDecodeForceKeyframe();
|
||||
proxy_->InsertFrame(Builder().Id(0).SpatialLayer(0).Time(0).Build());
|
||||
proxy_->InsertFrame(Builder().Id(1).SpatialLayer(1).Time(0).Build());
|
||||
proxy_->InsertFrame(Builder().Id(2).SpatialLayer(2).Time(0).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()),
|
||||
Frame(AllOf(WithId(0), FrameWithSize(3 * kFrameSize))));
|
||||
proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
|
||||
test::FakeFrameBuilder().Id(0).SpatialLayer(0).Time(0).Build()));
|
||||
proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
|
||||
test::FakeFrameBuilder().Id(1).SpatialLayer(1).Time(0).Build()));
|
||||
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(Builder().Id(4).Time(kFps30Rtp).SpatialLayer(1).Build());
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(5).Time(kFps30Rtp).SpatialLayer(2).AsLast().Build());
|
||||
proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
|
||||
test::FakeFrameBuilder().Id(3).Time(kFps30Rtp).SpatialLayer(0).Build()));
|
||||
proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
|
||||
test::FakeFrameBuilder().Id(4).Time(kFps30Rtp).SpatialLayer(1).Build()));
|
||||
proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(test::FakeFrameBuilder()
|
||||
.Id(5)
|
||||
.Time(kFps30Rtp)
|
||||
.SpatialLayer(2)
|
||||
.AsLast()
|
||||
.Build()));
|
||||
|
||||
StartNextDecode();
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay * 10),
|
||||
Frame(AllOf(WithId(3), FrameWithSize(3 * kFrameSize))));
|
||||
EXPECT_THAT(
|
||||
WaitForFrameOrTimeout(kFps30Delay * 10),
|
||||
Frame(AllOf(test::WithId(3), test::FrameWithSize(3 * kFrameSize))));
|
||||
}
|
||||
|
||||
TEST_P(FrameBufferProxyTest, OutstandingFrameTasksAreCancelledAfterDeletion) {
|
||||
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.
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
|
||||
|
||||
StartNextDecode();
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(1).Time(kFps30Rtp).AsLast().Refs({0}).Build());
|
||||
proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(test::FakeFrameBuilder()
|
||||
.Id(1)
|
||||
.Time(kFps30Rtp)
|
||||
.AsLast()
|
||||
.Refs({0})
|
||||
.Build()));
|
||||
proxy_->StopOnWorker();
|
||||
// Wait for 2x max wait time. Since we stopped, this should cause no timeouts
|
||||
// or frame-ready callbacks.
|
||||
@ -424,20 +351,24 @@ TEST_P(FrameBufferProxyTest, FramesWaitForDecoderToComplete) {
|
||||
StartNextDecodeForceKeyframe();
|
||||
|
||||
// Start with a keyframe.
|
||||
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0)));
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
|
||||
|
||||
ResetLastResult();
|
||||
// Insert a delta frame.
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(1).Time(kFps30Rtp).AsLast().Refs({0}).Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(1)
|
||||
.Time(kFps30Rtp)
|
||||
.AsLast()
|
||||
.Refs({0})
|
||||
.Build());
|
||||
|
||||
// Advancing time should not result in a frame since the scheduler has not
|
||||
// been signalled that we are ready.
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Eq(absl::nullopt));
|
||||
// Signal ready.
|
||||
StartNextDecode();
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(1)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(1)));
|
||||
}
|
||||
|
||||
TEST_P(FrameBufferProxyTest, LateFrameDropped) {
|
||||
@ -445,22 +376,30 @@ TEST_P(FrameBufferProxyTest, LateFrameDropped) {
|
||||
// F1
|
||||
// /
|
||||
// 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.
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
|
||||
|
||||
StartNextDecode();
|
||||
|
||||
// Simulate late F1 which arrives after F2.
|
||||
time_controller_.AdvanceTime(kFps30Delay * 2);
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(2).Time(2 * kFps30Rtp).AsLast().Refs({0}).Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(2)));
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(2)
|
||||
.Time(2 * kFps30Rtp)
|
||||
.AsLast()
|
||||
.Refs({0})
|
||||
.Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(2)));
|
||||
|
||||
StartNextDecode();
|
||||
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(1).Time(1 * kFps30Rtp).AsLast().Refs({0}).Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(1)
|
||||
.Time(1 * kFps30Rtp)
|
||||
.AsLast()
|
||||
.Refs({0})
|
||||
.Build());
|
||||
// Confirm frame 1 is never scheduled by timing out.
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), TimedOut());
|
||||
}
|
||||
@ -470,40 +409,53 @@ TEST_P(FrameBufferProxyTest, FramesFastForwardOnSystemHalt) {
|
||||
// F1
|
||||
// /
|
||||
// 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.
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
|
||||
|
||||
time_controller_.AdvanceTime(kFps30Delay);
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(1).Time(kFps30Rtp).AsLast().Refs({0}).Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(1)
|
||||
.Time(kFps30Rtp)
|
||||
.AsLast()
|
||||
.Refs({0})
|
||||
.Build());
|
||||
time_controller_.AdvanceTime(kFps30Delay);
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(2).Time(2 * kFps30Rtp).AsLast().Refs({0}).Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(2)
|
||||
.Time(2 * kFps30Rtp)
|
||||
.AsLast()
|
||||
.Refs({0})
|
||||
.Build());
|
||||
|
||||
// Halting time should result in F1 being skipped.
|
||||
time_controller_.AdvanceTime(kFps30Delay * 2);
|
||||
StartNextDecode();
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(2)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(2)));
|
||||
EXPECT_EQ(dropped_frames(), 1);
|
||||
}
|
||||
|
||||
TEST_P(FrameBufferProxyTest, ForceKeyFrame) {
|
||||
StartNextDecodeForceKeyframe();
|
||||
// Initial keyframe.
|
||||
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0)));
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
|
||||
|
||||
StartNextDecodeForceKeyframe();
|
||||
|
||||
// F2 is the next keyframe, and should be extracted since a keyframe was
|
||||
// forced.
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(1)
|
||||
.Time(kFps30Rtp)
|
||||
.AsLast()
|
||||
.Refs({0})
|
||||
.Build());
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(1).Time(kFps30Rtp).AsLast().Refs({0}).Build());
|
||||
proxy_->InsertFrame(Builder().Id(2).Time(kFps30Rtp * 2).AsLast().Build());
|
||||
test::FakeFrameBuilder().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) {
|
||||
@ -513,40 +465,60 @@ TEST_P(FrameBufferProxyTest, SlowDecoderDropsTemporalLayers) {
|
||||
// F1 --> F3 --> F5
|
||||
// / / /
|
||||
// F0 --> F2 --> F4
|
||||
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
|
||||
// Keyframe received.
|
||||
// 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);
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(1).Time(1 * kFps30Rtp).Refs({0}).AsLast().Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(1)
|
||||
.Time(1 * kFps30Rtp)
|
||||
.Refs({0})
|
||||
.AsLast()
|
||||
.Build());
|
||||
time_controller_.AdvanceTime(kFps30Delay);
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(2).Time(2 * kFps30Rtp).Refs({0}).AsLast().Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(2)
|
||||
.Time(2 * kFps30Rtp)
|
||||
.Refs({0})
|
||||
.AsLast()
|
||||
.Build());
|
||||
|
||||
// Simulate decode taking 3x FPS rate.
|
||||
time_controller_.AdvanceTime(kFps30Delay * 1.5);
|
||||
StartNextDecode();
|
||||
// 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);
|
||||
time_controller_.AdvanceTime(kFps30Delay / 2);
|
||||
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(3).Time(3 * kFps30Rtp).Refs({1, 2}).AsLast().Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(3)
|
||||
.Time(3 * kFps30Rtp)
|
||||
.Refs({1, 2})
|
||||
.AsLast()
|
||||
.Build());
|
||||
time_controller_.AdvanceTime(kFps30Delay / 2);
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(4).Time(4 * kFps30Rtp).Refs({2}).AsLast().Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(4)
|
||||
.Time(4 * kFps30Rtp)
|
||||
.Refs({2})
|
||||
.AsLast()
|
||||
.Build());
|
||||
time_controller_.AdvanceTime(kFps30Delay / 2);
|
||||
|
||||
// F4 is the best frame since decoding was so slow that F1 is too old.
|
||||
time_controller_.AdvanceTime(kFps30Delay);
|
||||
StartNextDecode();
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(4)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(4)));
|
||||
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(5).Time(5 * kFps30Rtp).Refs({3, 4}).AsLast().Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(5)
|
||||
.Time(5 * kFps30Rtp)
|
||||
.Refs({3, 4})
|
||||
.AsLast()
|
||||
.Build());
|
||||
time_controller_.AdvanceTime(kFps30Delay / 2);
|
||||
|
||||
// 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) {
|
||||
StartNextDecodeForceKeyframe();
|
||||
// Initial keyframe.
|
||||
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0)));
|
||||
proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
|
||||
test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build()));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
|
||||
|
||||
time_controller_.AdvanceTime(kFps30Delay / 2);
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(1).Time(kFps30Rtp).Refs({0}).AsLast().Build());
|
||||
proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(test::FakeFrameBuilder()
|
||||
.Id(1)
|
||||
.Time(kFps30Rtp)
|
||||
.Refs({0})
|
||||
.AsLast()
|
||||
.Build()));
|
||||
StartNextDecode();
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Eq(absl::nullopt));
|
||||
|
||||
// Scheduler is waiting to deliver Frame 1 now. Insert Frame 2. Frame 1 should
|
||||
// be delivered still.
|
||||
proxy_->InsertFrame(
|
||||
Builder().Id(2).Time(kFps30Rtp * 2).Refs({0}).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(1)));
|
||||
proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(test::FakeFrameBuilder()
|
||||
.Id(2)
|
||||
.Time(kFps30Rtp * 2)
|
||||
.Refs({0})
|
||||
.AsLast()
|
||||
.Build()));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(1)));
|
||||
}
|
||||
|
||||
TEST_P(FrameBufferProxyTest, SameFrameNotScheduledTwice) {
|
||||
@ -592,34 +573,40 @@ TEST_P(FrameBufferProxyTest, SameFrameNotScheduledTwice) {
|
||||
StartNextDecodeForceKeyframe();
|
||||
|
||||
// First keyframe.
|
||||
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Millis(15)), Frame(WithId(0)));
|
||||
proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
|
||||
test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build()));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Millis(15)),
|
||||
Frame(test::WithId(0)));
|
||||
|
||||
StartNextDecode();
|
||||
|
||||
// Warmup VCMTiming for 30fps.
|
||||
for (int i = 1; i <= 30; ++i) {
|
||||
proxy_->InsertFrame(Builder().Id(i).Time(i * kFps30Rtp).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(i)));
|
||||
proxy_->InsertFrame(WithReceiveTimeFromRtpTimestamp(
|
||||
test::FakeFrameBuilder().Id(i).Time(i * kFps30Rtp).AsLast().Build()));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(i)));
|
||||
StartNextDecode();
|
||||
}
|
||||
|
||||
// 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.
|
||||
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.
|
||||
// F2 is already scheduled and should not be rescheduled.
|
||||
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();
|
||||
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(33)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(33)));
|
||||
StartNextDecode();
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), TimedOut());
|
||||
EXPECT_EQ(dropped_frames(), 1);
|
||||
@ -633,8 +620,8 @@ TEST_P(FrameBufferProxyTest, TestStatsCallback) {
|
||||
// Fake timing having received decoded frame.
|
||||
timing_.StopDecodeTimer(TimeDelta::Millis(1), clock_->CurrentTime());
|
||||
StartNextDecodeForceKeyframe();
|
||||
proxy_->InsertFrame(Builder().Id(0).Time(0).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(0)));
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0)));
|
||||
|
||||
// Flush stats posted on the decode queue.
|
||||
time_controller_.AdvanceTime(TimeDelta::Zero());
|
||||
@ -646,8 +633,8 @@ TEST_P(FrameBufferProxyTest, FrameCompleteCalledOnceForDuplicateFrame) {
|
||||
.Times(1);
|
||||
|
||||
StartNextDecodeForceKeyframe();
|
||||
proxy_->InsertFrame(Builder().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());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).AsLast().Build());
|
||||
// Flush stats posted on the decode queue.
|
||||
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
|
||||
// do not complete the temporal layer.
|
||||
EXPECT_CALL(stats_callback_, OnCompleteFrame(_, _, _)).Times(0);
|
||||
proxy_->InsertFrame(Builder().Id(0).Time(0).Build());
|
||||
proxy_->InsertFrame(Builder().Id(1).Time(0).Refs({0}).Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder().Id(1).Time(0).Refs({0}).Build());
|
||||
time_controller_.AdvanceTime(TimeDelta::Zero());
|
||||
// Flush stats posted on the decode queue.
|
||||
::testing::Mock::VerifyAndClearExpectations(&stats_callback_);
|
||||
@ -669,7 +656,8 @@ TEST_P(FrameBufferProxyTest, FrameCompleteCalledOnceForSingleTemporalUnit) {
|
||||
EXPECT_CALL(stats_callback_,
|
||||
OnCompleteFrame(false, kFrameSize, VideoContentType::UNSPECIFIED))
|
||||
.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.
|
||||
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
|
||||
// this frame can finally be considered complete.
|
||||
EXPECT_CALL(stats_callback_, OnCompleteFrame(_, _, _)).Times(0);
|
||||
proxy_->InsertFrame(Builder().Id(0).Time(0).Build());
|
||||
proxy_->InsertFrame(Builder().Id(2).Time(0).Refs({0, 1}).AsLast().Build());
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder().Id(0).Time(0).Build());
|
||||
proxy_->InsertFrame(
|
||||
test::FakeFrameBuilder().Id(2).Time(0).Refs({0, 1}).AsLast().Build());
|
||||
time_controller_.AdvanceTime(TimeDelta::Zero());
|
||||
// Flush stats posted on the decode queue.
|
||||
::testing::Mock::VerifyAndClearExpectations(&stats_callback_);
|
||||
@ -693,7 +682,7 @@ TEST_P(FrameBufferProxyTest, FrameCompleteCalledOnceForCompleteTemporalUnit) {
|
||||
EXPECT_CALL(stats_callback_,
|
||||
OnCompleteFrame(false, kFrameSize, VideoContentType::UNSPECIFIED))
|
||||
.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.
|
||||
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
|
||||
// the RTP derived time used in all tests does not work when the long pause
|
||||
// happens later in the test.
|
||||
proxy_->InsertFrame(Builder()
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(0)
|
||||
.Time(kBaseRtp)
|
||||
.ReceivedTime(clock_->CurrentTime())
|
||||
.AsLast()
|
||||
.Build());
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(0)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(0)));
|
||||
|
||||
// 1 more frame to warmup VCMTiming for 30fps.
|
||||
StartNextDecode();
|
||||
proxy_->InsertFrame(Builder()
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(1)
|
||||
.Time(kBaseRtp + kFps30Rtp)
|
||||
.ReceivedTime(clock_->CurrentTime())
|
||||
.AsLast()
|
||||
.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
|
||||
// by over half.
|
||||
@ -746,7 +735,7 @@ TEST_P(FrameBufferProxyTest, NextFrameWithOldTimestamp) {
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), Eq(absl::nullopt));
|
||||
time_controller_.AdvanceTime(kRolloverDelay - kMaxWaitForFrame);
|
||||
StartNextDecode();
|
||||
proxy_->InsertFrame(Builder()
|
||||
proxy_->InsertFrame(test::FakeFrameBuilder()
|
||||
.Id(2)
|
||||
.Time(kRolloverRtp)
|
||||
.ReceivedTime(clock_->CurrentTime())
|
||||
@ -754,7 +743,7 @@ TEST_P(FrameBufferProxyTest, NextFrameWithOldTimestamp) {
|
||||
.Build());
|
||||
// FrameBuffer2 drops the frame, while FrameBuffer3 will continue the stream.
|
||||
if (!IsFrameBuffer2Enabled(field_trials_)) {
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(WithId(2)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(2)));
|
||||
} else {
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), TimedOut());
|
||||
}
|
||||
@ -776,22 +765,22 @@ TEST_P(LowLatencyFrameBufferProxyTest,
|
||||
StartNextDecodeForceKeyframe();
|
||||
timing_.set_min_playout_delay(TimeDelta::Zero());
|
||||
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.
|
||||
frame->SetPlayoutDelay({0, 10});
|
||||
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
|
||||
// in low-latency mode.
|
||||
StartNextDecode();
|
||||
frame = Builder().Id(1).Time(kFps30Rtp).AsLast().Build();
|
||||
frame = test::FakeFrameBuilder().Id(1).Time(kFps30Rtp).AsLast().Build();
|
||||
frame->SetPlayoutDelay({0, 10});
|
||||
proxy_->InsertFrame(std::move(frame));
|
||||
// Pacing is set to 16ms in the field trial so we should not decode yet.
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Eq(absl::nullopt));
|
||||
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) {
|
||||
@ -799,15 +788,16 @@ TEST_P(LowLatencyFrameBufferProxyTest, ZeroPlayoutDelayFullQueue) {
|
||||
StartNextDecodeForceKeyframe();
|
||||
timing_.set_min_playout_delay(TimeDelta::Zero());
|
||||
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.
|
||||
frame->SetPlayoutDelay({0, 10});
|
||||
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).
|
||||
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});
|
||||
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
|
||||
// should be ignored and the next frame should be decoded instantly.
|
||||
StartNextDecode();
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(1)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(1)));
|
||||
}
|
||||
|
||||
TEST_P(LowLatencyFrameBufferProxyTest, MinMaxDelayZeroLowLatencyMode) {
|
||||
@ -823,21 +813,21 @@ TEST_P(LowLatencyFrameBufferProxyTest, MinMaxDelayZeroLowLatencyMode) {
|
||||
StartNextDecodeForceKeyframe();
|
||||
timing_.set_min_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.
|
||||
frame->SetPlayoutDelay({0, 0});
|
||||
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
|
||||
// in low-latency mode.
|
||||
StartNextDecode();
|
||||
frame = Builder().Id(1).Time(kFps30Rtp).AsLast().Build();
|
||||
frame = test::FakeFrameBuilder().Id(1).Time(kFps30Rtp).AsLast().Build();
|
||||
frame->SetPlayoutDelay({0, 0});
|
||||
proxy_->InsertFrame(std::move(frame));
|
||||
// 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.
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(WithId(1)));
|
||||
EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(1)));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#include "rtc_base/event.h"
|
||||
#include "system_wrappers/include/clock.h"
|
||||
#include "test/fake_decoder.h"
|
||||
#include "test/fake_encoded_frame.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
#include "test/mock_transport.h"
|
||||
@ -59,19 +60,6 @@ using ::testing::WithoutArgs;
|
||||
|
||||
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
|
||||
|
||||
class VideoReceiveStream2Test : public ::testing::Test {
|
||||
@ -159,8 +147,8 @@ TEST_F(VideoReceiveStream2Test, CreateFrameFromH264FmtpSpropAndIdr) {
|
||||
|
||||
TEST_F(VideoReceiveStream2Test, PlayoutDelay) {
|
||||
const VideoPlayoutDelay kPlayoutDelayMs = {123, 321};
|
||||
std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
|
||||
test_frame->SetId(0);
|
||||
std::unique_ptr<test::FakeEncodedFrame> test_frame =
|
||||
test::FakeFrameBuilder().Id(0).AsLast().Build();
|
||||
test_frame->SetPlayoutDelay(kPlayoutDelayMs);
|
||||
|
||||
video_receive_stream_->OnCompleteFrame(std::move(test_frame));
|
||||
@ -196,8 +184,8 @@ TEST_F(VideoReceiveStream2Test, PlayoutDelayPreservesDefaultMaxValue) {
|
||||
timing_->GetTimings().max_playout_delay;
|
||||
const VideoPlayoutDelay kPlayoutDelayMs = {123, -1};
|
||||
|
||||
std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
|
||||
test_frame->SetId(0);
|
||||
std::unique_ptr<test::FakeEncodedFrame> test_frame =
|
||||
test::FakeFrameBuilder().Id(0).AsLast().Build();
|
||||
test_frame->SetPlayoutDelay(kPlayoutDelayMs);
|
||||
|
||||
video_receive_stream_->OnCompleteFrame(std::move(test_frame));
|
||||
@ -214,8 +202,8 @@ TEST_F(VideoReceiveStream2Test, PlayoutDelayPreservesDefaultMinValue) {
|
||||
timing_->GetTimings().min_playout_delay;
|
||||
const VideoPlayoutDelay kPlayoutDelayMs = {-1, 321};
|
||||
|
||||
std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
|
||||
test_frame->SetId(0);
|
||||
std::unique_ptr<test::FakeEncodedFrame> test_frame =
|
||||
test::FakeFrameBuilder().Id(0).AsLast().Build();
|
||||
test_frame->SetPlayoutDelay(kPlayoutDelayMs);
|
||||
|
||||
video_receive_stream_->OnCompleteFrame(std::move(test_frame));
|
||||
@ -229,21 +217,21 @@ TEST_F(VideoReceiveStream2Test, PlayoutDelayPreservesDefaultMinValue) {
|
||||
|
||||
TEST_F(VideoReceiveStream2Test, MaxCompositionDelayNotSetByDefault) {
|
||||
// Default with no playout delay set.
|
||||
std::unique_ptr<FrameObjectFake> test_frame0(new FrameObjectFake());
|
||||
test_frame0->SetId(0);
|
||||
std::unique_ptr<test::FakeEncodedFrame> test_frame0 =
|
||||
test::FakeFrameBuilder().Id(0).AsLast().Build();
|
||||
video_receive_stream_->OnCompleteFrame(std::move(test_frame0));
|
||||
EXPECT_FALSE(timing_->MaxCompositionDelayInFrames());
|
||||
|
||||
// Max composition delay not set for playout delay 0,0.
|
||||
std::unique_ptr<FrameObjectFake> test_frame1(new FrameObjectFake());
|
||||
test_frame1->SetId(1);
|
||||
std::unique_ptr<test::FakeEncodedFrame> test_frame1 =
|
||||
test::FakeFrameBuilder().Id(1).AsLast().Build();
|
||||
test_frame1->SetPlayoutDelay({0, 0});
|
||||
video_receive_stream_->OnCompleteFrame(std::move(test_frame1));
|
||||
EXPECT_FALSE(timing_->MaxCompositionDelayInFrames());
|
||||
|
||||
// Max composition delay not set for playout delay X,Y, where X,Y>0.
|
||||
std::unique_ptr<FrameObjectFake> test_frame2(new FrameObjectFake());
|
||||
test_frame2->SetId(2);
|
||||
std::unique_ptr<test::FakeEncodedFrame> test_frame2 =
|
||||
test::FakeFrameBuilder().Id(2).AsLast().Build();
|
||||
test_frame2->SetPlayoutDelay({10, 30});
|
||||
video_receive_stream_->OnCompleteFrame(std::move(test_frame2));
|
||||
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.
|
||||
const VideoPlayoutDelay kPlayoutDelayMs = {0, 50};
|
||||
const int kExpectedMaxCompositionDelayInFrames = 3; // ~50 ms at 60 fps.
|
||||
std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
|
||||
test_frame->SetId(0);
|
||||
std::unique_ptr<test::FakeEncodedFrame> test_frame =
|
||||
test::FakeFrameBuilder().Id(0).AsLast().Build();
|
||||
test_frame->SetPlayoutDelay(kPlayoutDelayMs);
|
||||
video_receive_stream_->OnCompleteFrame(std::move(test_frame));
|
||||
EXPECT_EQ(kExpectedMaxCompositionDelayInFrames,
|
||||
@ -321,24 +309,29 @@ class VideoReceiveStream2TestWithFakeDecoder : public ::testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesNtpTime) {
|
||||
const int64_t kNtpTimestamp = 12345;
|
||||
auto test_frame = std::make_unique<FrameObjectFake>();
|
||||
test_frame->SetPayloadType(99);
|
||||
test_frame->SetId(0);
|
||||
test_frame->SetNtpTime(kNtpTimestamp);
|
||||
const Timestamp kNtpTimestamp = Timestamp::Millis(12345);
|
||||
std::unique_ptr<test::FakeEncodedFrame> test_frame =
|
||||
test::FakeFrameBuilder()
|
||||
.Id(0)
|
||||
.PayloadType(99)
|
||||
.NtpTime(kNtpTimestamp)
|
||||
.AsLast()
|
||||
.Build();
|
||||
|
||||
video_receive_stream_->Start();
|
||||
video_receive_stream_->OnCompleteFrame(std::move(test_frame));
|
||||
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) {
|
||||
const webrtc::VideoRotation kRotation = webrtc::kVideoRotation_180;
|
||||
auto test_frame = std::make_unique<FrameObjectFake>();
|
||||
test_frame->SetPayloadType(99);
|
||||
test_frame->SetId(0);
|
||||
test_frame->SetRotation(kRotation);
|
||||
std::unique_ptr<test::FakeEncodedFrame> test_frame = test::FakeFrameBuilder()
|
||||
.Id(0)
|
||||
.PayloadType(99)
|
||||
.Rotation(kRotation)
|
||||
.AsLast()
|
||||
.Build();
|
||||
|
||||
video_receive_stream_->Start();
|
||||
video_receive_stream_->OnCompleteFrame(std::move(test_frame));
|
||||
@ -348,11 +341,13 @@ TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesRotation) {
|
||||
}
|
||||
|
||||
TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesPacketInfos) {
|
||||
auto test_frame = std::make_unique<FrameObjectFake>();
|
||||
test_frame->SetPayloadType(99);
|
||||
test_frame->SetId(0);
|
||||
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_->OnCompleteFrame(std::move(test_frame));
|
||||
@ -367,9 +362,8 @@ TEST_F(VideoReceiveStream2TestWithFakeDecoder, RenderedFrameUpdatesGetSources) {
|
||||
constexpr uint32_t kRtpTimestamp = 12345;
|
||||
|
||||
// Prepare one video frame with per-packet information.
|
||||
auto test_frame = std::make_unique<FrameObjectFake>();
|
||||
test_frame->SetPayloadType(99);
|
||||
test_frame->SetId(0);
|
||||
auto test_frame =
|
||||
test::FakeFrameBuilder().Id(0).PayloadType(99).AsLast().Build();
|
||||
RtpPacketInfos packet_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,
|
||||
int picture_id,
|
||||
int width,
|
||||
int height) {
|
||||
auto frame = std::make_unique<FrameObjectFake>();
|
||||
frame->SetPayloadType(99);
|
||||
frame->SetId(picture_id);
|
||||
auto frame =
|
||||
test::FakeFrameBuilder().Id(picture_id).PayloadType(99).AsLast().Build();
|
||||
frame->SetFrameType(frame_type);
|
||||
frame->_encodedWidth = width;
|
||||
frame->_encodedHeight = height;
|
||||
return frame;
|
||||
}
|
||||
|
||||
std::unique_ptr<FrameObjectFake> MakeFrame(VideoFrameType frame_type,
|
||||
int picture_id) {
|
||||
std::unique_ptr<test::FakeEncodedFrame> MakeFrame(VideoFrameType frame_type,
|
||||
int picture_id) {
|
||||
return MakeFrameWithResolution(frame_type, picture_id, 320, 240);
|
||||
}
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
#include "api/video/i420_buffer.h"
|
||||
#include "api/video_codecs/video_decoder.h"
|
||||
#include "test/fake_encoded_frame.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
#include "test/scoped_key_value_config.h"
|
||||
@ -22,7 +23,6 @@
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
using ::testing::_;
|
||||
using ::testing::ByMove;
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::Return;
|
||||
|
||||
@ -127,35 +127,6 @@ class FakeVideoDecoderFactory : public VideoDecoderFactory {
|
||||
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 {
|
||||
public:
|
||||
VideoStreamDecoderImplTest()
|
||||
@ -179,7 +150,8 @@ class VideoStreamDecoderImplTest : public ::testing::Test {
|
||||
};
|
||||
|
||||
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);
|
||||
time_controller_.AdvanceTime(TimeDelta::Millis(1));
|
||||
}
|
||||
@ -190,7 +162,8 @@ TEST_F(VideoStreamDecoderImplTest, NonDecodableStateWaitingForKeyframe) {
|
||||
}
|
||||
|
||||
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);
|
||||
time_controller_.AdvanceTime(TimeDelta::Millis(1));
|
||||
EXPECT_CALL(callbacks_, OnNonDecodableState);
|
||||
@ -198,7 +171,8 @@ TEST_F(VideoStreamDecoderImplTest, NonDecodableStateWaitingForDeltaFrame) {
|
||||
}
|
||||
|
||||
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)
|
||||
.WillOnce(Return(WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME));
|
||||
EXPECT_CALL(callbacks_, OnDecodedFrame);
|
||||
@ -207,7 +181,12 @@ TEST_F(VideoStreamDecoderImplTest, InsertAndDecodeFrameWithKeyframeRequest) {
|
||||
}
|
||||
|
||||
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)
|
||||
.WillByDefault(Return(false));
|
||||
EXPECT_CALL(callbacks_, OnNonDecodableState);
|
||||
@ -215,7 +194,8 @@ TEST_F(VideoStreamDecoderImplTest, FailToInitDecoder) {
|
||||
}
|
||||
|
||||
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)
|
||||
.WillByDefault(Return(WEBRTC_VIDEO_CODEC_ERROR));
|
||||
EXPECT_CALL(callbacks_, OnNonDecodableState);
|
||||
@ -225,13 +205,13 @@ TEST_F(VideoStreamDecoderImplTest, FailToDecodeFrame) {
|
||||
TEST_F(VideoStreamDecoderImplTest, ChangeFramePayloadType) {
|
||||
constexpr TimeDelta kFrameInterval = TimeDelta::Millis(1000 / 60);
|
||||
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(callbacks_, OnDecodedFrame);
|
||||
time_controller_.AdvanceTime(kFrameInterval);
|
||||
|
||||
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(callbacks_, OnDecodedFrame);
|
||||
time_controller_.AdvanceTime(kFrameInterval);
|
||||
|
||||
Reference in New Issue
Block a user