diff options
Diffstat (limited to 'modules/rtp_rtcp/source/rtp_rtcp_impl2_unittest.cc')
-rw-r--r-- | modules/rtp_rtcp/source/rtp_rtcp_impl2_unittest.cc | 497 |
1 files changed, 356 insertions, 141 deletions
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl2_unittest.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl2_unittest.cc index 40a002a116..5deb12d465 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl2_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl2_unittest.cc @@ -10,18 +10,22 @@ #include "modules/rtp_rtcp/source/rtp_rtcp_impl2.h" +#include <deque> #include <map> #include <memory> #include <set> +#include <utility> #include "absl/types/optional.h" #include "api/transport/field_trial_based_config.h" +#include "api/units/time_delta.h" #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "modules/rtp_rtcp/source/rtcp_packet.h" #include "modules/rtp_rtcp/source/rtcp_packet/nack.h" #include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "modules/rtp_rtcp/source/rtp_rtcp_interface.h" #include "modules/rtp_rtcp/source/rtp_sender_video.h" +#include "rtc_base/logging.h" #include "rtc_base/rate_limiter.h" #include "rtc_base/strings/string_builder.h" #include "test/gmock.h" @@ -31,6 +35,7 @@ #include "test/run_loop.h" #include "test/time_controller/simulated_time_controller.h" +using ::testing::AllOf; using ::testing::ElementsAre; using ::testing::Eq; using ::testing::Field; @@ -41,15 +46,24 @@ using ::testing::SizeIs; namespace webrtc { namespace { -const uint32_t kSenderSsrc = 0x12345; -const uint32_t kReceiverSsrc = 0x23456; -const int64_t kOneWayNetworkDelayMs = 100; -const uint8_t kBaseLayerTid = 0; -const uint8_t kHigherLayerTid = 1; -const uint16_t kSequenceNumber = 100; -const uint8_t kPayloadType = 100; -const int kWidth = 320; -const int kHeight = 100; +constexpr uint32_t kSenderSsrc = 0x12345; +constexpr uint32_t kReceiverSsrc = 0x23456; +constexpr TimeDelta kOneWayNetworkDelay = TimeDelta::Millis(100); +constexpr uint8_t kBaseLayerTid = 0; +constexpr uint8_t kHigherLayerTid = 1; +constexpr uint16_t kSequenceNumber = 100; +constexpr uint8_t kPayloadType = 100; +constexpr int kWidth = 320; +constexpr int kHeight = 100; +constexpr int kCaptureTimeMsToRtpTimestamp = 90; // 90 kHz clock. +constexpr TimeDelta kDefaultReportInterval = TimeDelta::Millis(1000); + +// RTP header extension ids. +enum : int { + kAbsoluteSendTimeExtensionId = 1, + kTransportSequenceNumberExtensionId, + kTransmissionOffsetExtensionId, +}; class RtcpRttStatsTestImpl : public RtcpRttStats { public: @@ -61,53 +75,79 @@ class RtcpRttStatsTestImpl : public RtcpRttStats { int64_t rtt_ms_; }; -class SendTransport : public Transport { +// TODO(bugs.webrtc.org/11581): remove inheritance once the ModuleRtpRtcpImpl2 +// Module/ProcessThread dependency is gone. +class SendTransport : public Transport, + public sim_time_impl::SimulatedSequenceRunner { public: - SendTransport() + SendTransport(TimeDelta delay, GlobalSimulatedTimeController* time_controller) : receiver_(nullptr), - time_controller_(nullptr), - delay_ms_(0), + time_controller_(time_controller), + delay_(delay), rtp_packets_sent_(0), - rtcp_packets_sent_(0) {} + rtcp_packets_sent_(0), + last_packet_(&header_extensions_) { + time_controller_->Register(this); + } + + ~SendTransport() { time_controller_->Unregister(this); } void SetRtpRtcpModule(ModuleRtpRtcpImpl2* receiver) { receiver_ = receiver; } - void SimulateNetworkDelay(int64_t delay_ms, TimeController* time_controller) { - time_controller_ = time_controller; - delay_ms_ = delay_ms; - } + void SimulateNetworkDelay(TimeDelta delay) { delay_ = delay; } bool SendRtp(const uint8_t* data, size_t len, const PacketOptions& options) override { - RTPHeader header; - std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::CreateForTest()); - EXPECT_TRUE(parser->Parse(static_cast<const uint8_t*>(data), len, &header)); + EXPECT_TRUE(last_packet_.Parse(data, len)); ++rtp_packets_sent_; - last_rtp_header_ = header; return true; } bool SendRtcp(const uint8_t* data, size_t len) override { test::RtcpPacketParser parser; parser.Parse(data, len); last_nack_list_ = parser.nack()->packet_ids(); - - if (time_controller_) { - time_controller_->AdvanceTime(TimeDelta::Millis(delay_ms_)); - } - EXPECT_TRUE(receiver_); - receiver_->IncomingRtcpPacket(data, len); + Timestamp current_time = time_controller_->GetClock()->CurrentTime(); + Timestamp delivery_time = current_time + delay_; + rtcp_packets_.push_back( + Packet{delivery_time, std::vector<uint8_t>(data, data + len)}); ++rtcp_packets_sent_; + RunReady(current_time); return true; } + // sim_time_impl::SimulatedSequenceRunner + Timestamp GetNextRunTime() const override { + if (!rtcp_packets_.empty()) + return rtcp_packets_.front().send_time; + return Timestamp::PlusInfinity(); + } + void RunReady(Timestamp at_time) override { + while (!rtcp_packets_.empty() && + rtcp_packets_.front().send_time <= at_time) { + Packet packet = std::move(rtcp_packets_.front()); + rtcp_packets_.pop_front(); + EXPECT_TRUE(receiver_); + receiver_->IncomingRtcpPacket(packet.data.data(), packet.data.size()); + } + } + TaskQueueBase* GetAsTaskQueue() override { + return reinterpret_cast<TaskQueueBase*>(this); + } + size_t NumRtcpSent() { return rtcp_packets_sent_; } ModuleRtpRtcpImpl2* receiver_; - TimeController* time_controller_; - int64_t delay_ms_; + GlobalSimulatedTimeController* const time_controller_; + TimeDelta delay_; int rtp_packets_sent_; size_t rtcp_packets_sent_; - RTPHeader last_rtp_header_; std::vector<uint16_t> last_nack_list_; + RtpHeaderExtensionMap header_extensions_; + RtpPacketReceived last_packet_; + struct Packet { + Timestamp send_time; + std::vector<uint8_t> data; + }; + std::deque<Packet> rtcp_packets_; }; struct TestConfig { @@ -147,29 +187,43 @@ class FieldTrialConfig : public WebRtcKeyValueConfig { double max_padding_factor_; }; -class RtpRtcpModule : public RtcpPacketTypeCounterObserver { +class RtpRtcpModule : public RtcpPacketTypeCounterObserver, + public SendPacketObserver { public: - RtpRtcpModule(TimeController* time_controller, + struct SentPacket { + SentPacket(uint16_t packet_id, int64_t capture_time_ms, uint32_t ssrc) + : packet_id(packet_id), capture_time_ms(capture_time_ms), ssrc(ssrc) {} + uint16_t packet_id; + int64_t capture_time_ms; + uint32_t ssrc; + }; + + RtpRtcpModule(GlobalSimulatedTimeController* time_controller, + ProcessThread* process_thread, bool is_sender, const FieldTrialConfig& trials) - : is_sender_(is_sender), + : time_controller_(time_controller), + is_sender_(is_sender), trials_(trials), + process_thread_(process_thread), receive_statistics_( ReceiveStatistics::Create(time_controller->GetClock())), - time_controller_(time_controller) { + transport_(kOneWayNetworkDelay, time_controller) { CreateModuleImpl(); - transport_.SimulateNetworkDelay(kOneWayNetworkDelayMs, time_controller); } + ~RtpRtcpModule() { process_thread_->DeRegisterModule(impl_.get()); } + + TimeController* const time_controller_; const bool is_sender_; const FieldTrialConfig& trials_; + ProcessThread* const process_thread_; RtcpPacketTypeCounter packets_sent_; RtcpPacketTypeCounter packets_received_; std::unique_ptr<ReceiveStatistics> receive_statistics_; SendTransport transport_; RtcpRttStatsTestImpl rtt_stats_; std::unique_ptr<ModuleRtpRtcpImpl2> impl_; - int rtcp_report_interval_ms_ = 0; void RtcpPacketTypesCounterUpdated( uint32_t ssrc, @@ -177,6 +231,16 @@ class RtpRtcpModule : public RtcpPacketTypeCounterObserver { counter_map_[ssrc] = packet_counter; } + void OnSendPacket(uint16_t packet_id, + int64_t capture_time_ms, + uint32_t ssrc) override { + last_sent_packet_.emplace(packet_id, capture_time_ms, ssrc); + } + + absl::optional<SentPacket> last_sent_packet() const { + return last_sent_packet_; + } + RtcpPacketTypeCounter RtcpSent() { // RTCP counters for remote SSRC. return counter_map_[is_sender_ ? kReceiverSsrc : kSenderSsrc]; @@ -187,14 +251,22 @@ class RtpRtcpModule : public RtcpPacketTypeCounterObserver { return counter_map_[impl_->SSRC()]; } int RtpSent() { return transport_.rtp_packets_sent_; } - uint16_t LastRtpSequenceNumber() { - return transport_.last_rtp_header_.sequenceNumber; - } + uint16_t LastRtpSequenceNumber() { return last_packet().SequenceNumber(); } std::vector<uint16_t> LastNackListSent() { return transport_.last_nack_list_; } - void SetRtcpReportIntervalAndReset(int rtcp_report_interval_ms) { - rtcp_report_interval_ms_ = rtcp_report_interval_ms; + void SetRtcpReportIntervalAndReset(TimeDelta rtcp_report_interval) { + rtcp_report_interval_ = rtcp_report_interval; + CreateModuleImpl(); + } + const RtpPacketReceived& last_packet() { return transport_.last_packet_; } + void RegisterHeaderExtension(absl::string_view uri, int id) { + impl_->RegisterRtpHeaderExtension(uri, id); + transport_.header_extensions_.RegisterByUri(id, uri); + transport_.last_packet_.IdentifyExtensions(transport_.header_extensions_); + } + void ReinintWithFec(VideoFecGenerator* fec_generator) { + fec_generator_ = fec_generator; CreateModuleImpl(); } @@ -207,19 +279,25 @@ class RtpRtcpModule : public RtcpPacketTypeCounterObserver { config.receive_statistics = receive_statistics_.get(); config.rtcp_packet_type_counter_observer = this; config.rtt_stats = &rtt_stats_; - config.rtcp_report_interval_ms = rtcp_report_interval_ms_; + config.rtcp_report_interval_ms = rtcp_report_interval_.ms(); config.local_media_ssrc = is_sender_ ? kSenderSsrc : kReceiverSsrc; config.need_rtp_packet_infos = true; config.non_sender_rtt_measurement = true; config.field_trials = &trials_; - + config.send_packet_observer = this; + config.fec_generator = fec_generator_; + if (impl_) + process_thread_->DeRegisterModule(impl_.get()); impl_.reset(new ModuleRtpRtcpImpl2(config)); + process_thread_->RegisterModule(impl_.get(), RTC_FROM_HERE); impl_->SetRemoteSSRC(is_sender_ ? kReceiverSsrc : kSenderSsrc); impl_->SetRTCPStatus(RtcpMode::kCompound); } - TimeController* const time_controller_; std::map<uint32_t, RtcpPacketTypeCounter> counter_map_; + absl::optional<SentPacket> last_sent_packet_; + VideoFecGenerator* fec_generator_ = nullptr; + TimeDelta rtcp_report_interval_ = kDefaultReportInterval; }; } // namespace @@ -228,12 +306,20 @@ class RtpRtcpImpl2Test : public ::testing::TestWithParam<TestConfig> { RtpRtcpImpl2Test() : time_controller_(Timestamp::Micros(133590000000000)), field_trials_(FieldTrialConfig::GetFromTestConfig(GetParam())), + process_thread_( + time_controller_.CreateProcessThread("RtpRtcpImpl2Test")), sender_(&time_controller_, + process_thread_.get(), /*is_sender=*/true, field_trials_), receiver_(&time_controller_, + process_thread_.get(), /*is_sender=*/false, - field_trials_) {} + field_trials_) { + process_thread_->Start(); + } + + ~RtpRtcpImpl2Test() { process_thread_->Stop(); } void SetUp() override { // Send module. @@ -256,20 +342,50 @@ class RtpRtcpImpl2Test : public ::testing::TestWithParam<TestConfig> { receiver_.transport_.SetRtpRtcpModule(sender_.impl_.get()); } - void AdvanceTimeMs(int64_t milliseconds) { - time_controller_.AdvanceTime(TimeDelta::Millis(milliseconds)); + void AdvanceTime(TimeDelta duration) { + time_controller_.AdvanceTime(duration); + } + + void ReinitWithFec(VideoFecGenerator* fec_generator, + absl::optional<int> red_payload_type) { + sender_.ReinintWithFec(fec_generator); + EXPECT_EQ(0, sender_.impl_->SetSendingStatus(true)); + sender_.impl_->SetSendingMediaStatus(true); + sender_.impl_->SetSequenceNumber(kSequenceNumber); + sender_.impl_->SetStorePacketsStatus(true, 100); + receiver_.transport_.SetRtpRtcpModule(sender_.impl_.get()); + + RTPSenderVideo::Config video_config; + video_config.clock = time_controller_.GetClock(); + video_config.rtp_sender = sender_.impl_->RtpSender(); + video_config.field_trials = &field_trials_; + video_config.fec_overhead_bytes = fec_generator->MaxPacketOverhead(); + video_config.fec_type = fec_generator->GetFecType(); + video_config.red_payload_type = red_payload_type; + sender_video_ = std::make_unique<RTPSenderVideo>(video_config); } GlobalSimulatedTimeController time_controller_; FieldTrialConfig field_trials_; + std::unique_ptr<ProcessThread> process_thread_; RtpRtcpModule sender_; std::unique_ptr<RTPSenderVideo> sender_video_; RtpRtcpModule receiver_; bool SendFrame(const RtpRtcpModule* module, RTPSenderVideo* sender, + uint8_t tid) { + int64_t now_ms = time_controller_.GetClock()->TimeInMilliseconds(); + return SendFrame( + module, sender, tid, + static_cast<uint32_t>(now_ms * kCaptureTimeMsToRtpTimestamp), now_ms); + } + + bool SendFrame(const RtpRtcpModule* module, + RTPSenderVideo* sender, uint8_t tid, - uint32_t rtp_timestamp) { + uint32_t rtp_timestamp, + int64_t capture_time_ms) { RTPVideoHeaderVP8 vp8_header = {}; vp8_header.temporalIdx = tid; RTPVideoHeader rtp_video_header; @@ -288,9 +404,9 @@ class RtpRtcpImpl2Test : public ::testing::TestWithParam<TestConfig> { const uint8_t payload[100] = {0}; bool success = module->impl_->OnSendingRtpFrame(0, 0, kPayloadType, true); - success &= - sender->SendVideo(kPayloadType, VideoCodecType::kVideoCodecVP8, - rtp_timestamp, 0, payload, rtp_video_header, 0); + success &= sender->SendVideo(kPayloadType, VideoCodecType::kVideoCodecVP8, + rtp_timestamp, capture_time_ms, payload, + rtp_video_header, 0); return success; } @@ -311,17 +427,17 @@ class RtpRtcpImpl2Test : public ::testing::TestWithParam<TestConfig> { TEST_P(RtpRtcpImpl2Test, RetransmitsAllLayers) { // Send frames. EXPECT_EQ(0, sender_.RtpSent()); - EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, - /*timestamp=*/0)); // kSequenceNumber - EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kHigherLayerTid, - /*timestamp=*/0)); // kSequenceNumber + 1 - EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kNoTemporalIdx, - /*timestamp=*/0)); // kSequenceNumber + 2 + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), + kBaseLayerTid)); // kSequenceNumber + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), + kHigherLayerTid)); // kSequenceNumber + 1 + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), + kNoTemporalIdx)); // kSequenceNumber + 2 EXPECT_EQ(3, sender_.RtpSent()); EXPECT_EQ(kSequenceNumber + 2, sender_.LastRtpSequenceNumber()); // Min required delay until retransmit = 5 + RTT ms (RTT = 0). - AdvanceTimeMs(5); + AdvanceTime(TimeDelta::Millis(5)); // Frame with kBaseLayerTid re-sent. IncomingRtcpNack(&sender_, kSequenceNumber); @@ -346,14 +462,14 @@ TEST_P(RtpRtcpImpl2Test, Rtt) { receiver_.receive_statistics_->OnRtpPacket(packet); // Send Frame before sending an SR. - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); // Sender module should send an SR. EXPECT_EQ(0, sender_.impl_->SendRTCP(kRtcpReport)); + AdvanceTime(kOneWayNetworkDelay); // Receiver module should send a RR with a response to the last received SR. - AdvanceTimeMs(1000); EXPECT_EQ(0, receiver_.impl_->SendRTCP(kRtcpReport)); + AdvanceTime(kOneWayNetworkDelay); // Verify RTT. int64_t rtt; @@ -362,10 +478,10 @@ TEST_P(RtpRtcpImpl2Test, Rtt) { int64_t max_rtt; EXPECT_EQ( 0, sender_.impl_->RTT(kReceiverSsrc, &rtt, &avg_rtt, &min_rtt, &max_rtt)); - EXPECT_NEAR(2 * kOneWayNetworkDelayMs, rtt, 1); - EXPECT_NEAR(2 * kOneWayNetworkDelayMs, avg_rtt, 1); - EXPECT_NEAR(2 * kOneWayNetworkDelayMs, min_rtt, 1); - EXPECT_NEAR(2 * kOneWayNetworkDelayMs, max_rtt, 1); + EXPECT_NEAR(2 * kOneWayNetworkDelay.ms(), rtt, 1); + EXPECT_NEAR(2 * kOneWayNetworkDelay.ms(), avg_rtt, 1); + EXPECT_NEAR(2 * kOneWayNetworkDelay.ms(), min_rtt, 1); + EXPECT_NEAR(2 * kOneWayNetworkDelay.ms(), max_rtt, 1); // No RTT from other ssrc. EXPECT_EQ(-1, sender_.impl_->RTT(kReceiverSsrc + 1, &rtt, &avg_rtt, &min_rtt, @@ -374,11 +490,11 @@ TEST_P(RtpRtcpImpl2Test, Rtt) { // Verify RTT from rtt_stats config. EXPECT_EQ(0, sender_.rtt_stats_.LastProcessedRtt()); EXPECT_EQ(0, sender_.impl_->rtt_ms()); - AdvanceTimeMs(1000); + AdvanceTime(TimeDelta::Millis(1000)); - EXPECT_NEAR(2 * kOneWayNetworkDelayMs, sender_.rtt_stats_.LastProcessedRtt(), - 1); - EXPECT_NEAR(2 * kOneWayNetworkDelayMs, sender_.impl_->rtt_ms(), 1); + EXPECT_NEAR(2 * kOneWayNetworkDelay.ms(), + sender_.rtt_stats_.LastProcessedRtt(), 1); + EXPECT_NEAR(2 * kOneWayNetworkDelay.ms(), sender_.impl_->rtt_ms(), 1); } TEST_P(RtpRtcpImpl2Test, RttForReceiverOnly) { @@ -386,40 +502,35 @@ TEST_P(RtpRtcpImpl2Test, RttForReceiverOnly) { EXPECT_EQ(0, receiver_.impl_->SendRTCP(kRtcpReport)); // Sender module should send a response to the last received RTRR (DLRR). - AdvanceTimeMs(1000); + AdvanceTime(TimeDelta::Millis(1000)); // Send Frame before sending a SR. - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); EXPECT_EQ(0, sender_.impl_->SendRTCP(kRtcpReport)); // Verify RTT. EXPECT_EQ(0, receiver_.rtt_stats_.LastProcessedRtt()); EXPECT_EQ(0, receiver_.impl_->rtt_ms()); - AdvanceTimeMs(1000); - EXPECT_NEAR(2 * kOneWayNetworkDelayMs, + AdvanceTime(TimeDelta::Millis(1000)); + EXPECT_NEAR(2 * kOneWayNetworkDelay.ms(), receiver_.rtt_stats_.LastProcessedRtt(), 1); - EXPECT_NEAR(2 * kOneWayNetworkDelayMs, receiver_.impl_->rtt_ms(), 1); + EXPECT_NEAR(2 * kOneWayNetworkDelay.ms(), receiver_.impl_->rtt_ms(), 1); } TEST_P(RtpRtcpImpl2Test, NoSrBeforeMedia) { // Ignore fake transport delays in this test. - sender_.transport_.SimulateNetworkDelay(0, &time_controller_); - receiver_.transport_.SimulateNetworkDelay(0, &time_controller_); - - sender_.impl_->Process(); - EXPECT_EQ(-1, sender_.RtcpSent().first_packet_time_ms); + sender_.transport_.SimulateNetworkDelay(TimeDelta::Millis(0)); + receiver_.transport_.SimulateNetworkDelay(TimeDelta::Millis(0)); + // Move ahead to the instant a rtcp is expected. // Verify no SR is sent before media has been sent, RR should still be sent // from the receiving module though. - AdvanceTimeMs(2000); + AdvanceTime(kDefaultReportInterval / 2); int64_t current_time = time_controller_.GetClock()->TimeInMilliseconds(); - sender_.impl_->Process(); - receiver_.impl_->Process(); EXPECT_EQ(-1, sender_.RtcpSent().first_packet_time_ms); EXPECT_EQ(receiver_.RtcpSent().first_packet_time_ms, current_time); - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + // RTCP should be triggered by the RTP send. + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); EXPECT_EQ(sender_.RtcpSent().first_packet_time_ms, current_time); } @@ -433,6 +544,7 @@ TEST_P(RtpRtcpImpl2Test, RtcpPacketTypeCounter_Nack) { const uint16_t kNackLength = 1; uint16_t nack_list[kNackLength] = {123}; EXPECT_EQ(0, receiver_.impl_->SendNACK(nack_list, kNackLength)); + AdvanceTime(kOneWayNetworkDelay); EXPECT_EQ(1U, receiver_.RtcpSent().nack_packets); EXPECT_GT(receiver_.RtcpSent().first_packet_time_ms, -1); @@ -490,8 +602,7 @@ TEST_P(RtpRtcpImpl2Test, SendsInitialNackList) { uint16_t nack_list[kNackLength] = {123}; EXPECT_EQ(0U, sender_.RtcpSent().nack_packets); // Send Frame before sending a compound RTCP that starts with SR. - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); EXPECT_EQ(0, sender_.impl_->SendNACK(nack_list, kNackLength)); EXPECT_EQ(1U, sender_.RtcpSent().nack_packets); EXPECT_THAT(sender_.LastNackListSent(), ElementsAre(123)); @@ -503,8 +614,7 @@ TEST_P(RtpRtcpImpl2Test, SendsExtendedNackList) { uint16_t nack_list[kNackLength] = {123}; EXPECT_EQ(0U, sender_.RtcpSent().nack_packets); // Send Frame before sending a compound RTCP that starts with SR. - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); EXPECT_EQ(0, sender_.impl_->SendNACK(nack_list, kNackLength)); EXPECT_EQ(1U, sender_.RtcpSent().nack_packets); EXPECT_THAT(sender_.LastNackListSent(), ElementsAre(123)); @@ -523,33 +633,32 @@ TEST_P(RtpRtcpImpl2Test, SendsExtendedNackList) { } TEST_P(RtpRtcpImpl2Test, ReSendsNackListAfterRttMs) { - sender_.transport_.SimulateNetworkDelay(0, &time_controller_); + sender_.transport_.SimulateNetworkDelay(TimeDelta::Millis(0)); // Send module sends a NACK. const uint16_t kNackLength = 2; uint16_t nack_list[kNackLength] = {123, 125}; EXPECT_EQ(0U, sender_.RtcpSent().nack_packets); // Send Frame before sending a compound RTCP that starts with SR. - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); EXPECT_EQ(0, sender_.impl_->SendNACK(nack_list, kNackLength)); EXPECT_EQ(1U, sender_.RtcpSent().nack_packets); EXPECT_THAT(sender_.LastNackListSent(), ElementsAre(123, 125)); // Same list not re-send, rtt interval has not passed. - const int kStartupRttMs = 100; - AdvanceTimeMs(kStartupRttMs); + const TimeDelta kStartupRtt = TimeDelta::Millis(100); + AdvanceTime(kStartupRtt); EXPECT_EQ(0, sender_.impl_->SendNACK(nack_list, kNackLength)); EXPECT_EQ(1U, sender_.RtcpSent().nack_packets); // Rtt interval passed, full list sent. - AdvanceTimeMs(1); + AdvanceTime(TimeDelta::Millis(1)); EXPECT_EQ(0, sender_.impl_->SendNACK(nack_list, kNackLength)); EXPECT_EQ(2U, sender_.RtcpSent().nack_packets); EXPECT_THAT(sender_.LastNackListSent(), ElementsAre(123, 125)); } TEST_P(RtpRtcpImpl2Test, UniqueNackRequests) { - receiver_.transport_.SimulateNetworkDelay(0, &time_controller_); + receiver_.transport_.SimulateNetworkDelay(TimeDelta::Millis(0)); EXPECT_EQ(0U, receiver_.RtcpSent().nack_packets); EXPECT_EQ(0U, receiver_.RtcpSent().nack_requests); EXPECT_EQ(0U, receiver_.RtcpSent().unique_nack_requests); @@ -571,8 +680,8 @@ TEST_P(RtpRtcpImpl2Test, UniqueNackRequests) { EXPECT_EQ(100, sender_.RtcpReceived().UniqueNackRequestsInPercent()); // Receive module sends new request with duplicated packets. - const int kStartupRttMs = 100; - AdvanceTimeMs(kStartupRttMs + 1); + const TimeDelta kStartupRtt = TimeDelta::Millis(100); + AdvanceTime(kStartupRtt + TimeDelta::Millis(1)); const uint16_t kNackLength2 = 4; uint16_t nack_list2[kNackLength2] = {11, 18, 20, 21}; EXPECT_EQ(0, receiver_.impl_->SendNACK(nack_list2, kNackLength2)); @@ -589,52 +698,43 @@ TEST_P(RtpRtcpImpl2Test, UniqueNackRequests) { } TEST_P(RtpRtcpImpl2Test, ConfigurableRtcpReportInterval) { - const int kVideoReportInterval = 3000; + const TimeDelta kVideoReportInterval = TimeDelta::Millis(3000); // Recreate sender impl with new configuration, and redo setup. sender_.SetRtcpReportIntervalAndReset(kVideoReportInterval); SetUp(); - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); // Initial state - sender_.impl_->Process(); EXPECT_EQ(sender_.RtcpSent().first_packet_time_ms, -1); EXPECT_EQ(0u, sender_.transport_.NumRtcpSent()); // Move ahead to the last ms before a rtcp is expected, no action. - AdvanceTimeMs(kVideoReportInterval / 2 - 1); - sender_.impl_->Process(); + AdvanceTime(kVideoReportInterval / 2 - TimeDelta::Millis(1)); EXPECT_EQ(sender_.RtcpSent().first_packet_time_ms, -1); EXPECT_EQ(sender_.transport_.NumRtcpSent(), 0u); // Move ahead to the first rtcp. Send RTCP. - AdvanceTimeMs(1); - sender_.impl_->Process(); + AdvanceTime(TimeDelta::Millis(1)); EXPECT_GT(sender_.RtcpSent().first_packet_time_ms, -1); EXPECT_EQ(sender_.transport_.NumRtcpSent(), 1u); - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); // Move ahead to the last possible second before second rtcp is expected. - AdvanceTimeMs(kVideoReportInterval * 1 / 2 - 1); - sender_.impl_->Process(); + AdvanceTime(kVideoReportInterval * 1 / 2 - TimeDelta::Millis(1)); EXPECT_EQ(sender_.transport_.NumRtcpSent(), 1u); // Move ahead into the range of second rtcp, the second rtcp may be sent. - AdvanceTimeMs(1); - sender_.impl_->Process(); + AdvanceTime(TimeDelta::Millis(1)); EXPECT_GE(sender_.transport_.NumRtcpSent(), 1u); - AdvanceTimeMs(kVideoReportInterval / 2); - sender_.impl_->Process(); + AdvanceTime(kVideoReportInterval / 2); EXPECT_GE(sender_.transport_.NumRtcpSent(), 1u); // Move out the range of second rtcp, the second rtcp must have been sent. - AdvanceTimeMs(kVideoReportInterval / 2); - sender_.impl_->Process(); + AdvanceTime(kVideoReportInterval / 2); EXPECT_EQ(sender_.transport_.NumRtcpSent(), 2u); } @@ -656,7 +756,7 @@ TEST_P(RtpRtcpImpl2Test, StoresPacketInfoForSentPackets) { packet.set_first_packet_of_frame(true); packet.SetMarker(true); sender_.impl_->TrySendPacket(&packet, pacing_info); - AdvanceTimeMs(1); + AdvanceTime(TimeDelta::Millis(1)); std::vector<RtpSequenceNumberMap::Info> seqno_info = sender_.impl_->GetSentRtpPacketInfos(std::vector<uint16_t>{1}); @@ -681,7 +781,7 @@ TEST_P(RtpRtcpImpl2Test, StoresPacketInfoForSentPackets) { packet.SetMarker(true); sender_.impl_->TrySendPacket(&packet, pacing_info); - AdvanceTimeMs(1); + AdvanceTime(TimeDelta::Millis(1)); seqno_info = sender_.impl_->GetSentRtpPacketInfos(std::vector<uint16_t>{2, 3, 4}); @@ -708,10 +808,10 @@ TEST_P(RtpRtcpImpl2Test, SenderReportStatsNotAvailable) { // Checks that the sender report stats are available if an RTCP SR was sent. TEST_P(RtpRtcpImpl2Test, SenderReportStatsAvailable) { // Send a frame in order to send an SR. - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); // Send an SR. ASSERT_THAT(sender_.impl_->SendRTCP(kRtcpReport), Eq(0)); + AdvanceTime(kOneWayNetworkDelay); EXPECT_THAT(receiver_.impl_->GetSenderReportStats(), Not(Eq(absl::nullopt))); } @@ -759,14 +859,15 @@ TEST_P(RtpRtcpImpl2Test, SenderReportStatsCheckStatsFromLastReport) { TEST_P(RtpRtcpImpl2Test, SenderReportStatsCount) { using SenderReportStats = RtpRtcpInterface::SenderReportStats; // Send a frame in order to send an SR. - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); // Send the first SR. ASSERT_THAT(sender_.impl_->SendRTCP(kRtcpReport), Eq(0)); + AdvanceTime(kOneWayNetworkDelay); EXPECT_THAT(receiver_.impl_->GetSenderReportStats(), Optional(Field(&SenderReportStats::reports_count, Eq(1u)))); // Send the second SR. ASSERT_THAT(sender_.impl_->SendRTCP(kRtcpReport), Eq(0)); + AdvanceTime(kOneWayNetworkDelay); EXPECT_THAT(receiver_.impl_->GetSenderReportStats(), Optional(Field(&SenderReportStats::reports_count, Eq(2u)))); } @@ -775,10 +876,10 @@ TEST_P(RtpRtcpImpl2Test, SenderReportStatsCount) { // SR was sent. TEST_P(RtpRtcpImpl2Test, SenderReportStatsArrivalTimestampSet) { // Send a frame in order to send an SR. - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); // Send an SR. ASSERT_THAT(sender_.impl_->SendRTCP(kRtcpReport), Eq(0)); + AdvanceTime(kOneWayNetworkDelay); auto stats = receiver_.impl_->GetSenderReportStats(); ASSERT_THAT(stats, Not(Eq(absl::nullopt))); EXPECT_TRUE(stats->last_arrival_timestamp.Valid()); @@ -789,14 +890,14 @@ TEST_P(RtpRtcpImpl2Test, SenderReportStatsArrivalTimestampSet) { TEST_P(RtpRtcpImpl2Test, SenderReportStatsPacketByteCounters) { using SenderReportStats = RtpRtcpInterface::SenderReportStats; // Send a frame in order to send an SR. - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); ASSERT_THAT(sender_.transport_.rtp_packets_sent_, Gt(0)); // Advance time otherwise the RTCP SR report will not include any packets // generated by `SendFrame()`. - AdvanceTimeMs(1); + AdvanceTime(TimeDelta::Millis(1)); // Send an SR. ASSERT_THAT(sender_.impl_->SendRTCP(kRtcpReport), Eq(0)); + AdvanceTime(kOneWayNetworkDelay); EXPECT_THAT(receiver_.impl_->GetSenderReportStats(), Optional(AllOf(Field(&SenderReportStats::packets_sent, Gt(0u)), Field(&SenderReportStats::bytes_sent, Gt(0u))))); @@ -804,8 +905,7 @@ TEST_P(RtpRtcpImpl2Test, SenderReportStatsPacketByteCounters) { TEST_P(RtpRtcpImpl2Test, SendingVideoAdvancesSequenceNumber) { const uint16_t sequence_number = sender_.impl_->SequenceNumber(); - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); ASSERT_THAT(sender_.transport_.rtp_packets_sent_, Gt(0)); EXPECT_EQ(sequence_number + 1, sender_.impl_->SequenceNumber()); } @@ -813,8 +913,7 @@ TEST_P(RtpRtcpImpl2Test, SendingVideoAdvancesSequenceNumber) { TEST_P(RtpRtcpImpl2Test, SequenceNumberNotAdvancedWhenNotSending) { const uint16_t sequence_number = sender_.impl_->SequenceNumber(); sender_.impl_->SetSendingMediaStatus(false); - EXPECT_FALSE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_FALSE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); ASSERT_THAT(sender_.transport_.rtp_packets_sent_, Eq(0)); EXPECT_EQ(sequence_number, sender_.impl_->SequenceNumber()); } @@ -825,8 +924,7 @@ TEST_P(RtpRtcpImpl2Test, PaddingNotAllowedInMiddleOfFrame) { // Can't send padding before media. EXPECT_THAT(sender_.impl_->GeneratePadding(kPaddingSize), SizeIs(0u)); - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, /*timestamp=*/0)); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); // Padding is now ok. EXPECT_THAT(sender_.impl_->GeneratePadding(kPaddingSize), SizeIs(Gt(0u))); @@ -859,12 +957,12 @@ TEST_P(RtpRtcpImpl2Test, PaddingNotAllowedInMiddleOfFrame) { TEST_P(RtpRtcpImpl2Test, PaddingTimestampMatchesMedia) { constexpr size_t kPaddingSize = 100; - uint32_t kTimestamp = 123; + const uint32_t kTimestamp = 123; - EXPECT_TRUE( - SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, kTimestamp)); - EXPECT_EQ(sender_.transport_.last_rtp_header_.timestamp, kTimestamp); - uint16_t media_seq = sender_.transport_.last_rtp_header_.sequenceNumber; + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, + kTimestamp, /*capture_time_ms=*/0)); + EXPECT_EQ(sender_.last_packet().Timestamp(), kTimestamp); + uint16_t media_seq = sender_.last_packet().SequenceNumber(); // Generate and send padding. auto padding = sender_.impl_->GeneratePadding(kPaddingSize); @@ -874,8 +972,125 @@ TEST_P(RtpRtcpImpl2Test, PaddingTimestampMatchesMedia) { } // Verify we sent a new packet, but with the same timestamp. - EXPECT_NE(sender_.transport_.last_rtp_header_.sequenceNumber, media_seq); - EXPECT_EQ(sender_.transport_.last_rtp_header_.timestamp, kTimestamp); + EXPECT_NE(sender_.last_packet().SequenceNumber(), media_seq); + EXPECT_EQ(sender_.last_packet().Timestamp(), kTimestamp); +} + +TEST_P(RtpRtcpImpl2Test, AssignsTransportSequenceNumber) { + sender_.RegisterHeaderExtension(TransportSequenceNumber::kUri, + kTransportSequenceNumberExtensionId); + + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); + uint16_t first_transport_seq = 0; + EXPECT_TRUE(sender_.last_packet().GetExtension<TransportSequenceNumber>( + &first_transport_seq)); + + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); + uint16_t second_transport_seq = 0; + EXPECT_TRUE(sender_.last_packet().GetExtension<TransportSequenceNumber>( + &second_transport_seq)); + + EXPECT_EQ(first_transport_seq + 1, second_transport_seq); +} + +TEST_P(RtpRtcpImpl2Test, AssignsAbsoluteSendTime) { + sender_.RegisterHeaderExtension(AbsoluteSendTime::kUri, + kAbsoluteSendTimeExtensionId); + + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); + EXPECT_NE(sender_.last_packet().GetExtension<AbsoluteSendTime>(), 0u); +} + +TEST_P(RtpRtcpImpl2Test, AssignsTransmissionTimeOffset) { + sender_.RegisterHeaderExtension(TransmissionOffset::kUri, + kTransmissionOffsetExtensionId); + + constexpr TimeDelta kOffset = TimeDelta::Millis(100); + // Transmission offset is calculated from difference between capture time + // and send time. + int64_t capture_time_ms = time_controller_.GetClock()->TimeInMilliseconds(); + time_controller_.AdvanceTime(kOffset); + + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid, + /*timestamp=*/0, capture_time_ms)); + EXPECT_EQ(sender_.last_packet().GetExtension<TransmissionOffset>(), + kOffset.ms() * kCaptureTimeMsToRtpTimestamp); +} + +TEST_P(RtpRtcpImpl2Test, PropagatesSentPacketInfo) { + sender_.RegisterHeaderExtension(TransportSequenceNumber::kUri, + kTransportSequenceNumberExtensionId); + int64_t now_ms = time_controller_.GetClock()->TimeInMilliseconds(); + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); + EXPECT_THAT( + sender_.last_sent_packet(), + Optional( + AllOf(Field(&RtpRtcpModule::SentPacket::packet_id, + Eq(sender_.last_packet() + .GetExtension<TransportSequenceNumber>())), + Field(&RtpRtcpModule::SentPacket::capture_time_ms, Eq(now_ms)), + Field(&RtpRtcpModule::SentPacket::ssrc, Eq(kSenderSsrc))))); +} + +TEST_P(RtpRtcpImpl2Test, GeneratesFlexfec) { + constexpr int kFlexfecPayloadType = 118; + constexpr uint32_t kFlexfecSsrc = 17; + const char kNoMid[] = ""; + const std::vector<RtpExtension> kNoRtpExtensions; + const std::vector<RtpExtensionSize> kNoRtpExtensionSizes; + + // Make sure FlexFec sequence numbers start at a different point than media. + const uint16_t fec_start_seq = sender_.impl_->SequenceNumber() + 100; + RtpState start_state; + start_state.sequence_number = fec_start_seq; + FlexfecSender flexfec_sender(kFlexfecPayloadType, kFlexfecSsrc, kSenderSsrc, + kNoMid, kNoRtpExtensions, kNoRtpExtensionSizes, + &start_state, time_controller_.GetClock()); + ReinitWithFec(&flexfec_sender, /*red_payload_type=*/absl::nullopt); + + // Parameters selected to generate a single FEC packet per media packet. + FecProtectionParams params; + params.fec_rate = 15; + params.max_fec_frames = 1; + params.fec_mask_type = kFecMaskRandom; + sender_.impl_->SetFecProtectionParams(params, params); + + // Send a one packet frame, expect one media packet and one FEC packet. + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); + ASSERT_THAT(sender_.transport_.rtp_packets_sent_, Eq(2)); + + const RtpPacketReceived& fec_packet = sender_.last_packet(); + EXPECT_EQ(fec_packet.SequenceNumber(), fec_start_seq); + EXPECT_EQ(fec_packet.Ssrc(), kFlexfecSsrc); + EXPECT_EQ(fec_packet.PayloadType(), kFlexfecPayloadType); +} + +TEST_P(RtpRtcpImpl2Test, GeneratesUlpfec) { + constexpr int kUlpfecPayloadType = 118; + constexpr int kRedPayloadType = 119; + UlpfecGenerator ulpfec_sender(kRedPayloadType, kUlpfecPayloadType, + time_controller_.GetClock()); + ReinitWithFec(&ulpfec_sender, kRedPayloadType); + + // Parameters selected to generate a single FEC packet per media packet. + FecProtectionParams params; + params.fec_rate = 15; + params.max_fec_frames = 1; + params.fec_mask_type = kFecMaskRandom; + sender_.impl_->SetFecProtectionParams(params, params); + + // Send a one packet frame, expect one media packet and one FEC packet. + EXPECT_TRUE(SendFrame(&sender_, sender_video_.get(), kBaseLayerTid)); + ASSERT_THAT(sender_.transport_.rtp_packets_sent_, Eq(2)); + + // Ulpfec is sent on the media ssrc, sharing the sequene number series. + const RtpPacketReceived& fec_packet = sender_.last_packet(); + EXPECT_EQ(fec_packet.SequenceNumber(), kSequenceNumber + 1); + EXPECT_EQ(fec_packet.Ssrc(), kSenderSsrc); + // The packets are encapsulated in RED packets, check that and that the RED + // header (first byte of payload) indicates the desired FEC payload type. + EXPECT_EQ(fec_packet.PayloadType(), kRedPayloadType); + EXPECT_EQ(fec_packet.payload()[0], kUlpfecPayloadType); } INSTANTIATE_TEST_SUITE_P(WithAndWithoutOverhead, |