/* * Copyright (c) 2012 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 "modules/pacing/paced_sender.h" #include #include #include #include #include #include "modules/pacing/packet_router.h" #include "modules/utility/include/mock/mock_process_thread.h" #include "system_wrappers/include/clock.h" #include "system_wrappers/include/field_trial.h" #include "test/field_trial.h" #include "test/gmock.h" #include "test/gtest.h" using ::testing::_; using ::testing::Return; using ::testing::SaveArg; namespace { constexpr uint32_t kAudioSsrc = 12345; constexpr uint32_t kVideoSsrc = 234565; constexpr uint32_t kVideoRtxSsrc = 34567; constexpr uint32_t kFlexFecSsrc = 45678; constexpr size_t kDefaultPacketSize = 234; } // namespace namespace webrtc { namespace test { // Mock callback implementing the raw api. class MockCallback : public PacketRouter { public: MOCK_METHOD2(SendPacket, void(std::unique_ptr packet, const PacedPacketInfo& cluster_info)); MOCK_METHOD1( GeneratePadding, std::vector>(size_t target_size_bytes)); }; class PacedSenderTest : public ::testing::TestWithParam { public: PacedSenderTest() : clock_(0), paced_module_(nullptr) {} void SetUp() override { EXPECT_CALL(process_thread_, RegisterModule) .WillOnce(SaveArg<0>(&paced_module_)); pacer_ = std::make_unique(&clock_, &callback_, nullptr, nullptr, &process_thread_); EXPECT_CALL(process_thread_, DeRegisterModule(paced_module_)).Times(1); } protected: std::unique_ptr BuildRtpPacket(RtpPacketToSend::Type type) { auto packet = std::make_unique(nullptr); packet->set_packet_type(type); switch (type) { case RtpPacketToSend::Type::kAudio: packet->SetSsrc(kAudioSsrc); break; case RtpPacketToSend::Type::kVideo: packet->SetSsrc(kVideoSsrc); break; case RtpPacketToSend::Type::kRetransmission: case RtpPacketToSend::Type::kPadding: packet->SetSsrc(kVideoRtxSsrc); break; case RtpPacketToSend::Type::kForwardErrorCorrection: packet->SetSsrc(kFlexFecSsrc); break; } packet->SetPayloadSize(kDefaultPacketSize); return packet; } SimulatedClock clock_; MockCallback callback_; MockProcessThread process_thread_; Module* paced_module_; std::unique_ptr pacer_; }; TEST_P(PacedSenderTest, PacesPackets) { // Insert a number of packets, covering one second. static constexpr size_t kPacketsToSend = 42; pacer_->SetPacingRates(DataRate::bps(kDefaultPacketSize * 8 * kPacketsToSend), DataRate::Zero()); std::vector> packets; for (size_t i = 0; i < kPacketsToSend; ++i) { packets.emplace_back(BuildRtpPacket(RtpPacketToSend::Type::kVideo)); } pacer_->EnqueuePackets(std::move(packets)); // Expect all of them to be sent. size_t packets_sent = 0; clock_.AdvanceTimeMilliseconds(paced_module_->TimeUntilNextProcess()); EXPECT_CALL(callback_, SendPacket) .WillRepeatedly( [&](std::unique_ptr packet, const PacedPacketInfo& cluster_info) { ++packets_sent; }); const Timestamp start_time = clock_.CurrentTime(); while (packets_sent < kPacketsToSend) { clock_.AdvanceTimeMilliseconds(paced_module_->TimeUntilNextProcess()); paced_module_->Process(); } // Packets should be sent over a period of close to 1s. Expect a little lower // than this since initial probing is a bit quicker. TimeDelta duration = clock_.CurrentTime() - start_time; EXPECT_GT(duration, TimeDelta::ms(900)); } INSTANTIATE_TEST_SUITE_P( WithAndWithoutDynamicProcess, PacedSenderTest, ::testing::Values(PacingController::ProcessMode::kPeriodic, PacingController::ProcessMode::kDynamic)); } // namespace test } // namespace webrtc