From 09408115cda7e4203cdc06413c0240958b167814 Mon Sep 17 00:00:00 2001 From: Sebastian Jansson Date: Tue, 24 Apr 2018 14:41:22 +0200 Subject: [PATCH] Moving demux from FakeNetworkPipe to DirectTransport. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL moves the responsibility for demuxing from FakeNetworkPipe to DirectTransport. This makes the interface for FakeNetworkPipe more consistent. It exposes fewer different interfaces for different usages. It also means that any time degradations applied to the packets due in FakeNetworkPipe in tests will now be propagated to Call in a more realistic manner. Previously the time was set to uninitialized which meant that Call filled in values based on the system clock. Bug: webrtc:9054 Change-Id: Ie534062f5ae9ad992c06b19e43804138a35702f0 Reviewed-on: https://webrtc-review.googlesource.com/64260 Commit-Queue: Sebastian Jansson Reviewed-by: Christoffer Rodbro Reviewed-by: Stefan Holmer Reviewed-by: Erik Språng Cr-Commit-Position: refs/heads/master@{#23017} --- call/BUILD.gn | 1 - call/fake_network_pipe.cc | 65 ++------ call/fake_network_pipe.h | 41 +---- call/test/fake_network_pipe_unittest.cc | 194 +++++++++++------------- test/BUILD.gn | 2 + test/direct_transport.cc | 53 ++++--- test/direct_transport.h | 20 ++- test/direct_transport_unittest.cc | 30 ++++ test/layer_filtering_transport.cc | 8 +- test/layer_filtering_transport.h | 4 +- test/rtp_rtcp_observer.h | 9 +- 11 files changed, 196 insertions(+), 231 deletions(-) create mode 100644 test/direct_transport_unittest.cc diff --git a/call/BUILD.gn b/call/BUILD.gn index ffb38ee9e3..1924e26780 100644 --- a/call/BUILD.gn +++ b/call/BUILD.gn @@ -240,7 +240,6 @@ rtc_source_set("fake_network") { "..:webrtc_common", "../api:transport_api", "../modules:module_api", - "../modules/rtp_rtcp", "../rtc_base:rtc_base_approved", "../rtc_base:sequenced_task_checker", "../system_wrappers", diff --git a/call/fake_network_pipe.cc b/call/fake_network_pipe.cc index 6562f549e1..e3f5393e35 100644 --- a/call/fake_network_pipe.cc +++ b/call/fake_network_pipe.cc @@ -18,7 +18,6 @@ #include "call/call.h" #include "call/fake_network_pipe.h" -#include "modules/rtp_rtcp/include/rtp_header_parser.h" #include "rtc_base/logging.h" #include "system_wrappers/include/clock.h" @@ -69,52 +68,21 @@ NetworkPacket& NetworkPacket::operator=(NetworkPacket&& o) { return *this; } -DemuxerImpl::DemuxerImpl(const std::map& payload_type_map) - : packet_receiver_(nullptr), payload_type_map_(payload_type_map) {} - -void DemuxerImpl::SetReceiver(PacketReceiver* receiver) { - packet_receiver_ = receiver; -} - -void DemuxerImpl::DeliverPacket(const NetworkPacket* packet, - const PacketTime& packet_time) { - // No packet receiver means that this demuxer will terminate the flow of - // packets. - if (!packet_receiver_) - return; - const uint8_t* const packet_data = packet->data(); - const size_t packet_length = packet->data_length(); - MediaType media_type = MediaType::ANY; - if (!RtpHeaderParser::IsRtcp(packet_data, packet_length)) { - RTC_CHECK_GE(packet_length, 2); - const uint8_t payload_type = packet_data[1] & 0x7f; - std::map::const_iterator it = - payload_type_map_.find(payload_type); - RTC_CHECK(it != payload_type_map_.end()) - << "payload type " << static_cast(payload_type) << " unknown."; - media_type = it->second; - } - packet_receiver_->DeliverPacket( - media_type, rtc::CopyOnWriteBuffer(packet_data, packet_length), - packet_time); -} - FakeNetworkPipe::FakeNetworkPipe(Clock* clock, const FakeNetworkPipe::Config& config) : FakeNetworkPipe(clock, config, nullptr, 1) {} FakeNetworkPipe::FakeNetworkPipe(Clock* clock, const FakeNetworkPipe::Config& config, - std::unique_ptr demuxer) - : FakeNetworkPipe(clock, config, std::move(demuxer), 1) {} + PacketReceiver* receiver) + : FakeNetworkPipe(clock, config, receiver, 1) {} FakeNetworkPipe::FakeNetworkPipe(Clock* clock, const FakeNetworkPipe::Config& config, - std::unique_ptr demuxer, + PacketReceiver* receiver, uint64_t seed) : clock_(clock), - demuxer_(std::move(demuxer)), - receiver_(nullptr), + receiver_(receiver), transport_(nullptr), random_(seed), clock_offset_ms_(0), @@ -150,8 +118,6 @@ FakeNetworkPipe::~FakeNetworkPipe() = default; void FakeNetworkPipe::SetReceiver(PacketReceiver* receiver) { rtc::CritScope crit(&config_lock_); - if (demuxer_) - demuxer_->SetReceiver(receiver); receiver_ = receiver; } @@ -209,13 +175,6 @@ void FakeNetworkPipe::SetConfig(const FakeNetworkPipe::Config& config) { } } -void FakeNetworkPipe::SendPacket(const uint8_t* data, size_t data_length) { - RTC_DCHECK(HasDemuxer()); - PacketTime packet_time(clock_->TimeInMicroseconds(), 0); - EnqueuePacket(rtc::CopyOnWriteBuffer(data, data_length), rtc::nullopt, false, - MediaType::ANY, packet_time); -} - bool FakeNetworkPipe::EnqueuePacket(rtc::CopyOnWriteBuffer packet, rtc::Optional options, bool is_rtcp, @@ -389,14 +348,13 @@ void FakeNetworkPipe::Process() { void FakeNetworkPipe::DeliverPacket(NetworkPacket* packet) { if (transport_) { RTC_DCHECK(!receiver_); - RTC_DCHECK(!demuxer_); if (packet->is_rtcp()) { transport_->SendRtcp(packet->data(), packet->data_length()); } else { transport_->SendRtp(packet->data(), packet->data_length(), packet->packet_options()); } - } else { + } else if (receiver_) { PacketTime packet_time = packet->packet_time(); if (packet_time.timestamp != -1) { int64_t queue_time = packet->arrival_time() - packet->send_time(); @@ -404,12 +362,8 @@ void FakeNetworkPipe::DeliverPacket(NetworkPacket* packet) { packet_time.timestamp += (queue_time * 1000); packet_time.timestamp += (clock_offset_ms_ * 1000); } - if (demuxer_) { - demuxer_->DeliverPacket(packet, packet_time); - } else if (receiver_) { - receiver_->DeliverPacket(packet->media_type(), - std::move(*packet->raw_packet()), packet_time); - } + receiver_->DeliverPacket(packet->media_type(), + std::move(*packet->raw_packet()), packet_time); } } @@ -423,10 +377,9 @@ bool FakeNetworkPipe::HasTransport() const { rtc::CritScope crit(&config_lock_); return transport_ != nullptr; } - -bool FakeNetworkPipe::HasDemuxer() const { +bool FakeNetworkPipe::HasReceiver() const { rtc::CritScope crit(&config_lock_); - return demuxer_ != nullptr; + return receiver_ != nullptr; } void FakeNetworkPipe::DeliverPacketWithLock(NetworkPacket* packet) { diff --git a/call/fake_network_pipe.h b/call/fake_network_pipe.h index 3c6cfdd6b1..7331068d2a 100644 --- a/call/fake_network_pipe.h +++ b/call/fake_network_pipe.h @@ -82,29 +82,6 @@ class NetworkPacket { rtc::Optional packet_time_; }; -class Demuxer { - public: - virtual ~Demuxer() = default; - virtual void SetReceiver(PacketReceiver* receiver) = 0; - virtual void DeliverPacket(const NetworkPacket* packet, - const PacketTime& packet_time) = 0; -}; - -// This class doesn't have any internal thread safety, so caller must make sure -// SetReceiver and DeliverPacket aren't called in a racy manner. -class DemuxerImpl final : public Demuxer { - public: - explicit DemuxerImpl(const std::map& payload_type_map); - - void SetReceiver(PacketReceiver* receiver) override; - void DeliverPacket(const NetworkPacket* packet, - const PacketTime& packet_time) override; - - private: - PacketReceiver* packet_receiver_; - const std::map payload_type_map_; - RTC_DISALLOW_COPY_AND_ASSIGN(DemuxerImpl); -}; // Class faking a network link. This is a simple and naive solution just faking // capacity and adding an extra transport delay in addition to the capacity @@ -130,16 +107,14 @@ class FakeNetworkPipe : public Transport, public PacketReceiver, public Module { int avg_burst_loss_length = -1; }; - // Use this constructor if you plan to insert packets using DeliverPacket(). + // Use these constructors if you plan to insert packets using DeliverPacket(). FakeNetworkPipe(Clock* clock, const FakeNetworkPipe::Config& config); - - // Use these constructors if you plan to insert packets using SendPacket(). FakeNetworkPipe(Clock* clock, const FakeNetworkPipe::Config& config, - std::unique_ptr demuxer); + PacketReceiver* receiver); FakeNetworkPipe(Clock* clock, const FakeNetworkPipe::Config& config, - std::unique_ptr demuxer, + PacketReceiver* receiver, uint64_t seed); // Use this constructor if you plan to insert packets using SendRt[c?]p(). @@ -154,12 +129,7 @@ class FakeNetworkPipe : public Transport, public PacketReceiver, public Module { // Sets a new configuration. This won't affect packets already in the pipe. void SetConfig(const FakeNetworkPipe::Config& config); - // Sends a new packet to the link. When/if packets are delivered, they will - // be passed to the receiver instance given in SetReceiver(). This method - // should only be used if a Demuxer was provided in the constructor. - void SendPacket(const uint8_t* packet, size_t packet_length); - - // Must not be called in parallel with SendPacket or Process. + // Must not be called in parallel with DeliverPacket or Process. void SetReceiver(PacketReceiver* receiver); // Implements Transport interface. When/if packets are delivered, they will @@ -214,12 +184,11 @@ class FakeNetworkPipe : public Transport, public PacketReceiver, public Module { void DeliverPacket(NetworkPacket* packet) RTC_EXCLUSIVE_LOCKS_REQUIRED(config_lock_); bool HasTransport() const; - bool HasDemuxer() const; + bool HasReceiver() const; Clock* const clock_; // |config_lock| guards the mostly constant things like the callbacks. rtc::CriticalSection config_lock_; - const std::unique_ptr demuxer_ RTC_GUARDED_BY(config_lock_); PacketReceiver* receiver_ RTC_GUARDED_BY(config_lock_); Transport* const transport_ RTC_GUARDED_BY(config_lock_); diff --git a/call/test/fake_network_pipe_unittest.cc b/call/test/fake_network_pipe_unittest.cc index e63b7ed762..14288c6f6e 100644 --- a/call/test/fake_network_pipe_unittest.cc +++ b/call/test/fake_network_pipe_unittest.cc @@ -25,36 +25,27 @@ using ::testing::Invoke; namespace webrtc { -class TestDemuxer : public Demuxer { - public: - void IncomingPacket(NetworkPacket* packet) { - DeliverPacket(packet, PacketTime()); - } - - MOCK_METHOD1(SetReceiver, void(PacketReceiver* receiver)); - MOCK_METHOD2(DeliverPacket, - void(const NetworkPacket* packet, - const PacketTime& packet_time)); -}; - -class ReorderTestDemuxer : public TestDemuxer { - public: - void DeliverPacket(const NetworkPacket* packet, - const PacketTime& packet_time) override { - RTC_DCHECK_GE(packet->data_length(), sizeof(int)); - int seq_num; - memcpy(&seq_num, packet->data(), sizeof(int)); - delivered_sequence_numbers_.push_back(seq_num); - } - std::vector delivered_sequence_numbers_; -}; - class MockReceiver : public PacketReceiver { public: MOCK_METHOD3(DeliverPacket, DeliveryStatus(MediaType, rtc::CopyOnWriteBuffer, const PacketTime&)); + virtual ~MockReceiver() = default; +}; + +class ReorderTestReceiver : public MockReceiver { + public: + DeliveryStatus DeliverPacket(MediaType media_type, + rtc::CopyOnWriteBuffer packet, + const PacketTime& packet_time) override { + RTC_DCHECK_GE(packet.size(), sizeof(int)); + int seq_num; + memcpy(&seq_num, packet.data(), sizeof(int)); + delivered_sequence_numbers_.push_back(seq_num); + return DeliveryStatus::DELIVERY_OK; + } + std::vector delivered_sequence_numbers_; }; class FakeNetworkPipeTest : public ::testing::Test { @@ -69,7 +60,8 @@ class FakeNetworkPipeTest : public ::testing::Test { // Set a sequence number for the packets by // using the first bytes in the packet. memcpy(packet.get(), &i, sizeof(int)); - pipe->SendPacket(packet.get(), packet_size); + rtc::CopyOnWriteBuffer buffer(packet.get(), packet_size); + pipe->DeliverPacket(MediaType::ANY, buffer, PacketTime()); } } @@ -85,9 +77,9 @@ TEST_F(FakeNetworkPipeTest, CapacityTest) { FakeNetworkPipe::Config config; config.queue_length_packets = 20; config.link_capacity_kbps = 80; - TestDemuxer* demuxer = new TestDemuxer(); - std::unique_ptr pipe(new FakeNetworkPipe( - &fake_clock_, config, std::unique_ptr(demuxer))); + MockReceiver receiver; + std::unique_ptr pipe( + new FakeNetworkPipe(&fake_clock_, config, &receiver)); // Add 10 packets of 1000 bytes, = 80 kb, and verify it takes one second to // get through the pipe. @@ -100,22 +92,22 @@ TEST_F(FakeNetworkPipeTest, CapacityTest) { PacketTimeMs(config.link_capacity_kbps, kPacketSize); // Time haven't increased yet, so we souldn't get any packets. - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); pipe->Process(); // Advance enough time to release one packet. fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); pipe->Process(); // Release all but one packet fake_clock_.AdvanceTimeMilliseconds(9 * kPacketTimeMs - 1); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(8); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(8); pipe->Process(); // And the last one. fake_clock_.AdvanceTimeMilliseconds(1); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); pipe->Process(); } @@ -125,9 +117,9 @@ TEST_F(FakeNetworkPipeTest, ExtraDelayTest) { config.queue_length_packets = 20; config.queue_delay_ms = 100; config.link_capacity_kbps = 80; - TestDemuxer* demuxer = new TestDemuxer(); - std::unique_ptr pipe(new FakeNetworkPipe( - &fake_clock_, config, std::unique_ptr(demuxer))); + MockReceiver receiver; + std::unique_ptr pipe( + new FakeNetworkPipe(&fake_clock_, config, &receiver)); const int kNumPackets = 2; const int kPacketSize = 1000; @@ -139,17 +131,17 @@ TEST_F(FakeNetworkPipeTest, ExtraDelayTest) { // Increase more than kPacketTimeMs, but not more than the extra delay. fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); pipe->Process(); // Advance the network delay to get the first packet. fake_clock_.AdvanceTimeMilliseconds(config.queue_delay_ms); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); pipe->Process(); // Advance one more kPacketTimeMs to get the last packet. fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); pipe->Process(); } @@ -159,9 +151,9 @@ TEST_F(FakeNetworkPipeTest, QueueLengthTest) { FakeNetworkPipe::Config config; config.queue_length_packets = 2; config.link_capacity_kbps = 80; - TestDemuxer* demuxer = new TestDemuxer(); - std::unique_ptr pipe(new FakeNetworkPipe( - &fake_clock_, config, std::unique_ptr(demuxer))); + MockReceiver receiver; + std::unique_ptr pipe( + new FakeNetworkPipe(&fake_clock_, config, &receiver)); const int kPacketSize = 1000; const int kPacketTimeMs = @@ -173,7 +165,7 @@ TEST_F(FakeNetworkPipeTest, QueueLengthTest) { // Increase time enough to deliver all three packets, verify only two are // delivered. fake_clock_.AdvanceTimeMilliseconds(3 * kPacketTimeMs); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(2); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(2); pipe->Process(); } @@ -183,9 +175,9 @@ TEST_F(FakeNetworkPipeTest, StatisticsTest) { config.queue_length_packets = 2; config.queue_delay_ms = 20; config.link_capacity_kbps = 80; - TestDemuxer* demuxer = new TestDemuxer(); - std::unique_ptr pipe(new FakeNetworkPipe( - &fake_clock_, config, std::unique_ptr(demuxer))); + MockReceiver receiver; + std::unique_ptr pipe( + new FakeNetworkPipe(&fake_clock_, config, &receiver)); const int kPacketSize = 1000; const int kPacketTimeMs = @@ -196,7 +188,7 @@ TEST_F(FakeNetworkPipeTest, StatisticsTest) { fake_clock_.AdvanceTimeMilliseconds(3 * kPacketTimeMs + config.queue_delay_ms); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(2); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(2); pipe->Process(); // Packet 1: kPacketTimeMs + config.queue_delay_ms, @@ -213,9 +205,9 @@ TEST_F(FakeNetworkPipeTest, ChangingCapacityWithEmptyPipeTest) { FakeNetworkPipe::Config config; config.queue_length_packets = 20; config.link_capacity_kbps = 80; - TestDemuxer* demuxer = new TestDemuxer(); - std::unique_ptr pipe(new FakeNetworkPipe( - &fake_clock_, config, std::unique_ptr(demuxer))); + MockReceiver receiver; + std::unique_ptr pipe( + new FakeNetworkPipe(&fake_clock_, config, &receiver)); // Add 10 packets of 1000 bytes, = 80 kb, and verify it takes one second to // get through the pipe. @@ -227,13 +219,13 @@ TEST_F(FakeNetworkPipeTest, ChangingCapacityWithEmptyPipeTest) { int packet_time_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize); // Time hasn't increased yet, so we souldn't get any packets. - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); pipe->Process(); // Advance time in steps to release one packet at a time. for (int i = 0; i < kNumPackets; ++i) { fake_clock_.AdvanceTimeMilliseconds(packet_time_ms); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); pipe->Process(); } @@ -249,20 +241,20 @@ TEST_F(FakeNetworkPipeTest, ChangingCapacityWithEmptyPipeTest) { packet_time_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize); // Time hasn't increased yet, so we souldn't get any packets. - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); pipe->Process(); // Advance time in steps to release one packet at a time. for (int i = 0; i < kNumPackets; ++i) { fake_clock_.AdvanceTimeMilliseconds(packet_time_ms); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); pipe->Process(); } // Check that all the packets were sent. EXPECT_EQ(static_cast(2 * kNumPackets), pipe->SentPackets()); fake_clock_.AdvanceTimeMilliseconds(pipe->TimeUntilNextProcess()); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); pipe->Process(); } @@ -272,9 +264,9 @@ TEST_F(FakeNetworkPipeTest, ChangingCapacityWithPacketsInPipeTest) { FakeNetworkPipe::Config config; config.queue_length_packets = 20; config.link_capacity_kbps = 80; - TestDemuxer* demuxer = new TestDemuxer(); - std::unique_ptr pipe(new FakeNetworkPipe( - &fake_clock_, config, std::unique_ptr(demuxer))); + MockReceiver receiver; + std::unique_ptr pipe( + new FakeNetworkPipe(&fake_clock_, config, &receiver)); // Add 10 packets of 1000 bytes, = 80 kb. const int kNumPackets = 10; @@ -296,27 +288,27 @@ TEST_F(FakeNetworkPipeTest, ChangingCapacityWithPacketsInPipeTest) { int packet_time_2_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize); // Time hasn't increased yet, so we souldn't get any packets. - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); pipe->Process(); // Advance time in steps to release one packet at a time. for (int i = 0; i < kNumPackets; ++i) { fake_clock_.AdvanceTimeMilliseconds(packet_time_1_ms); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); pipe->Process(); } // Advance time in steps to release one packet at a time. for (int i = 0; i < kNumPackets; ++i) { fake_clock_.AdvanceTimeMilliseconds(packet_time_2_ms); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); pipe->Process(); } // Check that all the packets were sent. EXPECT_EQ(static_cast(2 * kNumPackets), pipe->SentPackets()); fake_clock_.AdvanceTimeMilliseconds(pipe->TimeUntilNextProcess()); - EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); pipe->Process(); } @@ -327,9 +319,9 @@ TEST_F(FakeNetworkPipeTest, DisallowReorderingThenAllowReordering) { config.link_capacity_kbps = 800; config.queue_delay_ms = 100; config.delay_standard_deviation_ms = 10; - ReorderTestDemuxer* demuxer = new ReorderTestDemuxer(); - std::unique_ptr pipe(new FakeNetworkPipe( - &fake_clock_, config, std::unique_ptr(demuxer))); + ReorderTestReceiver receiver; + std::unique_ptr pipe( + new FakeNetworkPipe(&fake_clock_, config, &receiver)); const uint32_t kNumPackets = 100; const int kPacketSize = 10; @@ -338,9 +330,9 @@ TEST_F(FakeNetworkPipeTest, DisallowReorderingThenAllowReordering) { pipe->Process(); // Confirm that all packets have been delivered in order. - EXPECT_EQ(kNumPackets, demuxer->delivered_sequence_numbers_.size()); + EXPECT_EQ(kNumPackets, receiver.delivered_sequence_numbers_.size()); int last_seq_num = -1; - for (int seq_num : demuxer->delivered_sequence_numbers_) { + for (int seq_num : receiver.delivered_sequence_numbers_) { EXPECT_GT(seq_num, last_seq_num); last_seq_num = seq_num; } @@ -349,15 +341,15 @@ TEST_F(FakeNetworkPipeTest, DisallowReorderingThenAllowReordering) { pipe->SetConfig(config); SendPackets(pipe.get(), kNumPackets, kPacketSize); fake_clock_.AdvanceTimeMilliseconds(1000); - demuxer->delivered_sequence_numbers_.clear(); + receiver.delivered_sequence_numbers_.clear(); pipe->Process(); // Confirm that all packets have been delivered // and that reordering has occured. - EXPECT_EQ(kNumPackets, demuxer->delivered_sequence_numbers_.size()); + EXPECT_EQ(kNumPackets, receiver.delivered_sequence_numbers_.size()); bool reordering_has_occured = false; last_seq_num = -1; - for (int seq_num : demuxer->delivered_sequence_numbers_) { + for (int seq_num : receiver.delivered_sequence_numbers_) { if (last_seq_num > seq_num) { reordering_has_occured = true; break; @@ -377,26 +369,26 @@ TEST_F(FakeNetworkPipeTest, BurstLoss) { config.queue_length_packets = kNumPackets; config.loss_percent = kLossPercent; config.avg_burst_loss_length = kAvgBurstLength; - ReorderTestDemuxer* demuxer = new ReorderTestDemuxer(); - std::unique_ptr pipe(new FakeNetworkPipe( - &fake_clock_, config, std::unique_ptr(demuxer))); + ReorderTestReceiver receiver; + std::unique_ptr pipe( + new FakeNetworkPipe(&fake_clock_, config, &receiver)); SendPackets(pipe.get(), kNumPackets, kPacketSize); fake_clock_.AdvanceTimeMilliseconds(1000); pipe->Process(); // Check that the average loss is |kLossPercent| percent. - int lost_packets = kNumPackets - demuxer->delivered_sequence_numbers_.size(); + int lost_packets = kNumPackets - receiver.delivered_sequence_numbers_.size(); double loss_fraction = lost_packets / static_cast(kNumPackets); EXPECT_NEAR(kLossPercent / 100.0, loss_fraction, 0.05); // Find the number of bursts that has occurred. - size_t received_packets = demuxer->delivered_sequence_numbers_.size(); + size_t received_packets = receiver.delivered_sequence_numbers_.size(); int num_bursts = 0; for (size_t i = 0; i < received_packets - 1; ++i) { - int diff = demuxer->delivered_sequence_numbers_[i + 1] - - demuxer->delivered_sequence_numbers_[i]; + int diff = receiver.delivered_sequence_numbers_[i + 1] - + receiver.delivered_sequence_numbers_[i]; if (diff > 1) ++num_bursts; } @@ -408,41 +400,27 @@ TEST_F(FakeNetworkPipeTest, BurstLoss) { TEST_F(FakeNetworkPipeTest, SetReceiver) { FakeNetworkPipe::Config config; - TestDemuxer* demuxer = new TestDemuxer(); - std::unique_ptr pipe(new FakeNetworkPipe( - &fake_clock_, config, std::unique_ptr(demuxer))); - MockReceiver packet_receiver; - EXPECT_CALL(*demuxer, SetReceiver(&packet_receiver)).Times(1); - pipe->SetReceiver(&packet_receiver); -} + config.link_capacity_kbps = 800; + MockReceiver receiver; + std::unique_ptr pipe( + new FakeNetworkPipe(&fake_clock_, config, &receiver)); -TEST(DemuxerImplTest, Demuxing) { - constexpr uint8_t kVideoPayloadType = 100; - constexpr uint8_t kAudioPayloadType = 101; - constexpr int64_t kTimeNow = 12345; - constexpr int64_t kArrivalTime = kTimeNow - 1; - constexpr size_t kPacketSize = 10; - DemuxerImpl demuxer({{kVideoPayloadType, MediaType::VIDEO}, - {kAudioPayloadType, MediaType::AUDIO}}); + const int kPacketSize = 1000; + const int kPacketTimeMs = + PacketTimeMs(config.link_capacity_kbps, kPacketSize); + SendPackets(pipe.get(), 1, kPacketSize); + fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); + pipe->Process(); - MockReceiver mock_receiver; - demuxer.SetReceiver(&mock_receiver); + MockReceiver new_receiver; + pipe->SetReceiver(&new_receiver); - rtc::CopyOnWriteBuffer data(kPacketSize); - data[1] = kVideoPayloadType; - std::unique_ptr packet( - new NetworkPacket(data, kTimeNow, kArrivalTime, rtc::nullopt, false, - MediaType::ANY, rtc::nullopt)); - EXPECT_CALL(mock_receiver, DeliverPacket(MediaType::VIDEO, _, _)) - .WillOnce(Return(PacketReceiver::DELIVERY_OK)); - demuxer.DeliverPacket(packet.get(), PacketTime()); - - data[1] = kAudioPayloadType; - packet.reset(new NetworkPacket(data, kTimeNow, kArrivalTime, rtc::nullopt, - false, MediaType::ANY, rtc::nullopt)); - EXPECT_CALL(mock_receiver, DeliverPacket(MediaType::AUDIO, _, _)) - .WillOnce(Return(PacketReceiver::DELIVERY_OK)); - demuxer.DeliverPacket(packet.get(), PacketTime()); + SendPackets(pipe.get(), 1, kPacketSize); + fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs); + EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); + EXPECT_CALL(new_receiver, DeliverPacket(_, _, _)).Times(1); + pipe->Process(); } } // namespace webrtc diff --git a/test/BUILD.gn b/test/BUILD.gn index ece4003acb..c69ad08eb8 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -310,6 +310,7 @@ if (rtc_include_tests) { rtc_test("test_support_unittests") { deps = [ + ":direct_transport", ":fileutils", ":perf_test", ":rtp_test_utils", @@ -325,6 +326,7 @@ if (rtc_include_tests) { "//testing/gtest", ] sources = [ + "direct_transport_unittest.cc", "frame_generator_unittest.cc", "rtp_file_reader_unittest.cc", "rtp_file_writer_unittest.cc", diff --git a/test/direct_transport.cc b/test/direct_transport.cc index 971130fe9e..4b2fd0463e 100644 --- a/test/direct_transport.cc +++ b/test/direct_transport.cc @@ -10,6 +10,7 @@ #include "test/direct_transport.h" #include "call/call.h" +#include "modules/rtp_rtcp/include/rtp_header_parser.h" #include "rtc_base/ptr_util.h" #include "system_wrappers/include/clock.h" #include "test/single_threaded_task_queue.h" @@ -17,6 +18,23 @@ namespace webrtc { namespace test { +Demuxer::Demuxer(const std::map& payload_type_map) + : payload_type_map_(payload_type_map) {} + +MediaType Demuxer::GetMediaType(const uint8_t* packet_data, + const size_t packet_length) const { + if (!RtpHeaderParser::IsRtcp(packet_data, packet_length)) { + RTC_CHECK_GE(packet_length, 2); + const uint8_t payload_type = packet_data[1] & 0x7f; + std::map::const_iterator it = + payload_type_map_.find(payload_type); + RTC_CHECK(it != payload_type_map_.end()) + << "payload type " << static_cast(payload_type) << " unknown."; + return it->second; + } + return MediaType::ANY; +} + DirectTransport::DirectTransport( SingleThreadedTaskQueueForTesting* task_queue, Call* send_call, @@ -32,31 +50,23 @@ DirectTransport::DirectTransport( const FakeNetworkPipe::Config& config, Call* send_call, const std::map& payload_type_map) - : DirectTransport( - task_queue, - config, - send_call, - std::unique_ptr(new DemuxerImpl(payload_type_map))) { -} - -DirectTransport::DirectTransport(SingleThreadedTaskQueueForTesting* task_queue, - const FakeNetworkPipe::Config& config, - Call* send_call, - std::unique_ptr demuxer) : send_call_(send_call), clock_(Clock::GetRealTimeClock()), task_queue_(task_queue), - fake_network_(rtc::MakeUnique(clock_, config, - std::move(demuxer))) { + demuxer_(payload_type_map), + fake_network_(rtc::MakeUnique(clock_, config)) { Start(); } -DirectTransport::DirectTransport(SingleThreadedTaskQueueForTesting* task_queue, - std::unique_ptr pipe, - Call* send_call) +DirectTransport::DirectTransport( + SingleThreadedTaskQueueForTesting* task_queue, + std::unique_ptr pipe, + Call* send_call, + const std::map& payload_type_map) : send_call_(send_call), clock_(Clock::GetRealTimeClock()), task_queue_(task_queue), + demuxer_(payload_type_map), fake_network_(std::move(pipe)) { Start(); } @@ -94,15 +104,22 @@ bool DirectTransport::SendRtp(const uint8_t* data, clock_->TimeInMilliseconds()); send_call_->OnSentPacket(sent_packet); } - fake_network_->SendPacket(data, length); + SendPacket(data, length); return true; } bool DirectTransport::SendRtcp(const uint8_t* data, size_t length) { - fake_network_->SendPacket(data, length); + SendPacket(data, length); return true; } +void DirectTransport::SendPacket(const uint8_t* data, size_t length) { + MediaType media_type = demuxer_.GetMediaType(data, length); + int64_t send_time = clock_->TimeInMicroseconds(); + fake_network_->DeliverPacket(media_type, rtc::CopyOnWriteBuffer(data, length), + PacketTime(send_time, -1)); +} + int DirectTransport::GetAverageDelayMs() { return fake_network_->AverageDelay(); } diff --git a/test/direct_transport.h b/test/direct_transport.h index d61282aae7..2d473073e9 100644 --- a/test/direct_transport.h +++ b/test/direct_transport.h @@ -27,6 +27,15 @@ class Clock; class PacketReceiver; namespace test { +class Demuxer { + public: + explicit Demuxer(const std::map& payload_type_map); + ~Demuxer() = default; + MediaType GetMediaType(const uint8_t* packet_data, + const size_t packet_length) const; + const std::map payload_type_map_; + RTC_DISALLOW_COPY_AND_ASSIGN(Demuxer); +}; // Objects of this class are expected to be allocated and destroyed on the // same task-queue - the one that's passed in via the constructor. @@ -42,12 +51,9 @@ class DirectTransport : public Transport { const std::map& payload_type_map); DirectTransport(SingleThreadedTaskQueueForTesting* task_queue, - const FakeNetworkPipe::Config& config, + std::unique_ptr pipe, Call* send_call, - std::unique_ptr demuxer); - - DirectTransport(SingleThreadedTaskQueueForTesting* task_queue, - std::unique_ptr pipe, Call* send_call); + const std::map& payload_type_map); ~DirectTransport() override; @@ -69,6 +75,7 @@ class DirectTransport : public Transport { private: void SendPackets(); + void SendPacket(const uint8_t* data, size_t length); void Start(); Call* const send_call_; @@ -78,7 +85,8 @@ class DirectTransport : public Transport { SingleThreadedTaskQueueForTesting::TaskId next_scheduled_task_ RTC_GUARDED_BY(&sequence_checker_); - std::unique_ptr fake_network_; + const Demuxer demuxer_; + const std::unique_ptr fake_network_; rtc::SequencedTaskChecker sequence_checker_; }; diff --git a/test/direct_transport_unittest.cc b/test/direct_transport_unittest.cc new file mode 100644 index 0000000000..d35c4a4c03 --- /dev/null +++ b/test/direct_transport_unittest.cc @@ -0,0 +1,30 @@ +/* + * 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 "test/direct_transport.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { +TEST(DemuxerTest, Demuxing) { + constexpr uint8_t kVideoPayloadType = 100; + constexpr uint8_t kAudioPayloadType = 101; + constexpr size_t kPacketSize = 10; + Demuxer demuxer({{kVideoPayloadType, MediaType::VIDEO}, + {kAudioPayloadType, MediaType::AUDIO}}); + + uint8_t data[kPacketSize]; + memset(data, 0, kPacketSize); + data[1] = kVideoPayloadType; + EXPECT_EQ(demuxer.GetMediaType(data, kPacketSize), MediaType::VIDEO); + data[1] = kAudioPayloadType; + EXPECT_EQ(demuxer.GetMediaType(data, kPacketSize), MediaType::AUDIO); +} +} // namespace test +} // namespace webrtc diff --git a/test/layer_filtering_transport.cc b/test/layer_filtering_transport.cc index 4cf1ccadf4..c28110ca04 100644 --- a/test/layer_filtering_transport.cc +++ b/test/layer_filtering_transport.cc @@ -48,9 +48,10 @@ LayerFilteringTransport::LayerFilteringTransport( uint8_t vp9_video_payload_type, int selected_tl, int selected_sl, + const std::map& payload_type_map, uint32_t ssrc_to_filter_min, uint32_t ssrc_to_filter_max) - : DirectTransport(task_queue, std::move(pipe), send_call), + : DirectTransport(task_queue, std::move(pipe), send_call, payload_type_map), vp8_video_payload_type_(vp8_video_payload_type), vp9_video_payload_type_(vp9_video_payload_type), selected_tl_(selected_tl), @@ -84,8 +85,9 @@ LayerFilteringTransport::LayerFilteringTransport( uint8_t vp8_video_payload_type, uint8_t vp9_video_payload_type, int selected_tl, - int selected_sl) - : DirectTransport(task_queue, std::move(pipe), send_call), + int selected_sl, + const std::map& payload_type_map) + : DirectTransport(task_queue, std::move(pipe), send_call, payload_type_map), vp8_video_payload_type_(vp8_video_payload_type), vp9_video_payload_type_(vp9_video_payload_type), selected_tl_(selected_tl), diff --git a/test/layer_filtering_transport.h b/test/layer_filtering_transport.h index b63dc29fab..8835b89463 100644 --- a/test/layer_filtering_transport.h +++ b/test/layer_filtering_transport.h @@ -48,6 +48,7 @@ class LayerFilteringTransport : public test::DirectTransport { uint8_t vp9_video_payload_type, int selected_tl, int selected_sl, + const std::map& payload_type_map, uint32_t ssrc_to_filter_min, uint32_t ssrc_to_filter_max); LayerFilteringTransport(SingleThreadedTaskQueueForTesting* task_queue, @@ -56,7 +57,8 @@ class LayerFilteringTransport : public test::DirectTransport { uint8_t vp8_video_payload_type, uint8_t vp9_video_payload_type, int selected_tl, - int selected_sl); + int selected_sl, + const std::map& payload_type_map); bool DiscardedLastPacket() const; bool SendRtp(const uint8_t* data, size_t length, diff --git a/test/rtp_rtcp_observer.h b/test/rtp_rtcp_observer.h index 5163d2248e..1f213b475c 100644 --- a/test/rtp_rtcp_observer.h +++ b/test/rtp_rtcp_observer.h @@ -106,10 +106,15 @@ class PacketTransport : public test::DirectTransport { transport_type_(transport_type) {} PacketTransport(SingleThreadedTaskQueueForTesting* task_queue, - Call* send_call, RtpRtcpObserver* observer, + Call* send_call, + RtpRtcpObserver* observer, TransportType transport_type, + const std::map& payload_type_map, std::unique_ptr nw_pipe) - : test::DirectTransport(task_queue, std::move(nw_pipe), send_call), + : test::DirectTransport(task_queue, + std::move(nw_pipe), + send_call, + payload_type_map), observer_(observer), transport_type_(transport_type) {}