aboutsummaryrefslogtreecommitdiff
path: root/video
diff options
context:
space:
mode:
Diffstat (limited to 'video')
-rw-r--r--video/BUILD.gn1
-rw-r--r--video/end_to_end_tests/receive_time_tests.cc141
2 files changed, 142 insertions, 0 deletions
diff --git a/video/BUILD.gn b/video/BUILD.gn
index 56ff9e66cb..1400814c0e 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -329,6 +329,7 @@ if (rtc_include_tests) {
"end_to_end_tests/multi_stream_tests.cc",
"end_to_end_tests/network_state_tests.cc",
"end_to_end_tests/probing_tests.cc",
+ "end_to_end_tests/receive_time_tests.cc",
"end_to_end_tests/retransmission_tests.cc",
"end_to_end_tests/rtp_rtcp_tests.cc",
"end_to_end_tests/ssrc_tests.cc",
diff --git a/video/end_to_end_tests/receive_time_tests.cc b/video/end_to_end_tests/receive_time_tests.cc
new file mode 100644
index 0000000000..9e025cb553
--- /dev/null
+++ b/video/end_to_end_tests/receive_time_tests.cc
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2018 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 "rtc_base/criticalsection.h"
+#include "rtc_base/timeutils.h"
+#include "test/call_test.h"
+#include "test/field_trial.h"
+#include "test/rtcp_packet_parser.h"
+
+namespace webrtc {
+namespace {
+
+// This tester simulates a series of clock reset events where different offsets
+// are added to the receive time. It detects jumps in the resulting reported
+// receive times of more than 200 ms.
+class ReportedReceiveTimeTester : public test::EndToEndTest {
+ public:
+ struct TimeJump {
+ int64_t at_send_time_ms;
+ int64_t add_offset_ms;
+ static constexpr int64_t kStop = 0;
+ };
+
+ ReportedReceiveTimeTester()
+ : EndToEndTest(test::CallTest::kDefaultTimeoutMs) {
+ // These should be let trough without correction and filtered if correction
+ // is enabled.
+ jumps_.push({500, 2000});
+ jumps_.push({1000, -400});
+ jumps_.push({1500, 2000000});
+ jumps_.push({1700, TimeJump::kStop});
+ }
+ bool JumpInReportedTimes() { return jump_in_reported_times_; }
+
+ protected:
+ Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
+ test::RtcpPacketParser parser;
+ EXPECT_TRUE(parser.Parse(data, length));
+ const auto& fb = parser.transport_feedback();
+ if (fb->num_packets() > 0) {
+ int64_t arrival_time_us = fb->GetBaseTimeUs();
+ for (const auto& pkt : fb->GetReceivedPackets()) {
+ arrival_time_us += pkt.delta_us();
+ if (last_arrival_time_us_ != 0) {
+ int64_t delta_us = arrival_time_us - last_arrival_time_us_;
+ rtc::CritScope crit(&send_times_crit_);
+ if (send_times_us_.size() >= 2) {
+ int64_t ground_truth_delta_us =
+ send_times_us_[1] - send_times_us_[0];
+ send_times_us_.pop_front();
+ int64_t delta_diff_ms = (delta_us - ground_truth_delta_us) / 1000;
+ if (std::abs(delta_diff_ms) > 200) {
+ jump_in_reported_times_ = true;
+ observation_complete_.Set();
+ }
+ }
+ }
+ last_arrival_time_us_ = arrival_time_us;
+ }
+ }
+ return SEND_PACKET;
+ }
+ Action OnSendRtp(const uint8_t* data, size_t length) override {
+ {
+ rtc::CritScope crit(&send_times_crit_);
+ send_times_us_.push_back(rtc::TimeMicros());
+ }
+ int64_t now_ms = rtc::TimeMillis();
+ if (!first_send_time_ms_)
+ first_send_time_ms_ = now_ms;
+ int64_t send_time_ms = now_ms - first_send_time_ms_;
+ if (send_time_ms >= jumps_.front().at_send_time_ms) {
+ if (jumps_.front().add_offset_ms == TimeJump::kStop) {
+ observation_complete_.Set();
+ jumps_.pop();
+ return SEND_PACKET;
+ }
+ clock_offset_ms_ += jumps_.front().add_offset_ms;
+ send_transport_->SetClockOffset(clock_offset_ms_);
+ jumps_.pop();
+ }
+ return SEND_PACKET;
+ }
+ test::PacketTransport* CreateSendTransport(
+ test::SingleThreadedTaskQueueForTesting* task_queue,
+ Call* sender_call) override {
+ return send_transport_ = new test::PacketTransport(
+ task_queue, sender_call, this, test::PacketTransport::kSender,
+ test::CallTest::payload_type_map_, FakeNetworkPipe::Config());
+ }
+ void PerformTest() override {
+ observation_complete_.Wait(test::CallTest::kDefaultTimeoutMs);
+ }
+ size_t GetNumVideoStreams() const override { return 1; }
+ size_t GetNumAudioStreams() const override { return 0; }
+
+ private:
+ int64_t last_arrival_time_us_ = 0;
+ int64_t first_send_time_ms_ = 0;
+ rtc::CriticalSection send_times_crit_;
+ std::deque<int64_t> send_times_us_ RTC_GUARDED_BY(send_times_crit_);
+ bool jump_in_reported_times_ = false;
+ test::PacketTransport* send_transport_;
+ int64_t clock_offset_ms_ = 0;
+ std::queue<TimeJump> jumps_;
+};
+} // namespace
+
+class ReceiveTimeEndToEndTest : public test::CallTest {
+ public:
+ ReceiveTimeEndToEndTest() {}
+
+ virtual ~ReceiveTimeEndToEndTest() {}
+};
+
+TEST_F(ReceiveTimeEndToEndTest, ReceiveTimeJumpsWithoutFieldTrial) {
+ // Without the field trial, the jumps in clock offset should be let trough and
+ // be detected.
+ ReportedReceiveTimeTester test;
+ RunBaseTest(&test);
+ EXPECT_TRUE(test.JumpInReportedTimes());
+}
+
+TEST_F(ReceiveTimeEndToEndTest, ReceiveTimeSteadyWithFieldTrial) {
+ // Since all the added jumps by the tester are outside the interval of -100 ms
+ // to 1000 ms, they should all be filtered by the field trial below, and no
+ // jumps should be detected.
+ test::ScopedFieldTrials field_trial(
+ "WebRTC-BweReceiveTimeCorrection/Enabled,-100,1000/");
+ ReportedReceiveTimeTester test;
+ RunBaseTest(&test);
+ EXPECT_FALSE(test.JumpInReportedTimes());
+}
+} // namespace webrtc