diff --git a/call/BUILD.gn b/call/BUILD.gn index 72d9d1a22d..95483c266c 100644 --- a/call/BUILD.gn +++ b/call/BUILD.gn @@ -444,6 +444,8 @@ rtc_library("fake_network") { "../api:sequence_checker", "../api:simulated_network_api", "../api:transport_api", + "../api/units:timestamp", + "../modules/rtp_rtcp:rtp_rtcp_format", "../rtc_base:checks", "../rtc_base:logging", "../rtc_base:macromagic", @@ -672,6 +674,8 @@ if (rtc_include_tests) { "../api:simulated_network_api", "../api/units:data_rate", "../api/units:time_delta", + "../modules/rtp_rtcp:rtp_rtcp_format", + "../rtc_base:checks", "../system_wrappers", "../test:test_support", "//testing/gtest", diff --git a/call/degraded_call.cc b/call/degraded_call.cc index 445a1e90c2..50349c1086 100644 --- a/call/degraded_call.cc +++ b/call/degraded_call.cc @@ -14,6 +14,7 @@ #include #include "absl/strings/string_view.h" +#include "api/sequence_checker.h" #include "modules/rtp_rtcp/source/rtp_util.h" #include "rtc_base/event.h" @@ -128,54 +129,6 @@ bool DegradedCall::FakeNetworkPipeTransportAdapter::SendRtcp( return true; } -DegradedCall::ThreadedPacketReceiver::ThreadedPacketReceiver( - webrtc::TaskQueueBase* worker_thread, - webrtc::TaskQueueBase* network_thread, - rtc::scoped_refptr call_alive, - webrtc::PacketReceiver* receiver) - : worker_thread_(worker_thread), - network_thread_(network_thread), - call_alive_(std::move(call_alive)), - receiver_(receiver) {} - -DegradedCall::ThreadedPacketReceiver::~ThreadedPacketReceiver() = default; - -PacketReceiver::DeliveryStatus -DegradedCall::ThreadedPacketReceiver::DeliverPacket( - MediaType media_type, - rtc::CopyOnWriteBuffer packet, - int64_t packet_time_us) { - // `Call::DeliverPacket` expects RTCP packets to be delivered from the - // network thread and RTP packets to be delivered from the worker thread. - // Because `FakeNetworkPipe` queues packets, the thread used when this packet - // is delivered to `DegradedCall::DeliverPacket` may differ from the thread - // used when this packet is delivered to - // `ThreadedPacketReceiver::DeliverPacket`. To solve this problem, always - // make sure that packets are sent in the correct thread. - if (IsRtcpPacket(packet)) { - if (!network_thread_->IsCurrent()) { - network_thread_->PostTask( - SafeTask(call_alive_, [receiver = receiver_, media_type, - packet = std::move(packet), packet_time_us]() { - receiver->DeliverPacket(media_type, std::move(packet), - packet_time_us); - })); - return DELIVERY_OK; - } - } else { - if (!worker_thread_->IsCurrent()) { - worker_thread_->PostTask([receiver = receiver_, media_type, - packet = std::move(packet), packet_time_us]() { - receiver->DeliverPacket(media_type, std::move(packet), packet_time_us); - }); - return DELIVERY_OK; - } - } - - return receiver_->DeliverPacket(media_type, std::move(packet), - packet_time_us); -} - DegradedCall::DegradedCall( std::unique_ptr call, const std::vector& send_configs, @@ -193,10 +146,7 @@ DegradedCall::DegradedCall( receive_simulated_network_ = network.get(); receive_pipe_ = std::make_unique(clock_, std::move(network)); - packet_receiver_ = std::make_unique( - call_->worker_thread(), call_->network_thread(), call_alive_, - call_->Receiver()); - receive_pipe_->SetReceiver(packet_receiver_.get()); + receive_pipe_->SetReceiver(call_->Receiver()); if (receive_configs_.size() > 1) { call_->network_thread()->PostDelayedTask( SafeTask(call_alive_, [this] { UpdateReceiveNetworkConfig(); }), @@ -400,6 +350,7 @@ PacketReceiver::DeliveryStatus DegradedCall::DeliverPacket( MediaType media_type, rtc::CopyOnWriteBuffer packet, int64_t packet_time_us) { + RTC_DCHECK_RUN_ON(&received_packet_sequence_checker_); PacketReceiver::DeliveryStatus status = receive_pipe_->DeliverPacket( media_type, std::move(packet), packet_time_us); // This is not optimal, but there are many places where there are thread @@ -414,7 +365,18 @@ PacketReceiver::DeliveryStatus DegradedCall::DeliverPacket( return status; } +void DegradedCall::DeliverRtpPacket( + MediaType media_type, + RtpPacketReceived packet, + OnUndemuxablePacketHandler undemuxable_packet_handler) { + RTC_DCHECK_RUN_ON(&received_packet_sequence_checker_); + receive_pipe_->DeliverRtpPacket(media_type, std::move(packet), + std::move(undemuxable_packet_handler)); + receive_pipe_->Process(); +} + void DegradedCall::DeliverRtcpPacket(rtc::CopyOnWriteBuffer packet) { + RTC_DCHECK_RUN_ON(&received_packet_sequence_checker_); receive_pipe_->DeliverRtcpPacket(std::move(packet)); receive_pipe_->Process(); } diff --git a/call/degraded_call.h b/call/degraded_call.h index bff93e20ce..6a22b69e4a 100644 --- a/call/degraded_call.h +++ b/call/degraded_call.h @@ -116,6 +116,10 @@ class DegradedCall : public Call, private PacketReceiver { DeliveryStatus DeliverPacket(MediaType media_type, rtc::CopyOnWriteBuffer packet, int64_t packet_time_us) override; + void DeliverRtpPacket( + MediaType media_type, + RtpPacketReceived packet, + OnUndemuxablePacketHandler undemuxable_packet_handler) override; void DeliverRtcpPacket(rtc::CopyOnWriteBuffer packet) override; private: @@ -148,25 +152,6 @@ class DegradedCall : public Call, private PacketReceiver { absl::optional next_process_ms_ RTC_GUARDED_BY(&task_queue_); }; - class ThreadedPacketReceiver : public PacketReceiver { - public: - ThreadedPacketReceiver(webrtc::TaskQueueBase* worker_thread, - webrtc::TaskQueueBase* network_thread, - rtc::scoped_refptr call_alive, - PacketReceiver* receiver); - ~ThreadedPacketReceiver() override; - - DeliveryStatus DeliverPacket(MediaType media_type, - rtc::CopyOnWriteBuffer packet, - int64_t packet_time_us) override; - - private: - webrtc::TaskQueueBase* const worker_thread_; - webrtc::TaskQueueBase* const network_thread_; - rtc::scoped_refptr call_alive_; - webrtc::PacketReceiver* const receiver_; - }; - // For audio/video send stream, a TransportAdapter instance is used to // intercept packets to be sent, and put them into a common FakeNetworkPipe // in such as way that they will eventually (unless dropped) be forwarded to @@ -212,8 +197,9 @@ class DegradedCall : public Call, private PacketReceiver { size_t receive_config_index_; const std::vector receive_configs_; SimulatedNetwork* receive_simulated_network_; - std::unique_ptr receive_pipe_; - std::unique_ptr packet_receiver_; + SequenceChecker received_packet_sequence_checker_; + std::unique_ptr receive_pipe_ + RTC_GUARDED_BY(received_packet_sequence_checker_); }; } // namespace webrtc diff --git a/call/fake_network_pipe.cc b/call/fake_network_pipe.cc index 60650640c8..76adfe3cf0 100644 --- a/call/fake_network_pipe.cc +++ b/call/fake_network_pipe.cc @@ -18,6 +18,8 @@ #include #include "api/media_types.h" +#include "api/units/timestamp.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "rtc_base/checks.h" #include "rtc_base/logging.h" #include "system_wrappers/include/clock.h" @@ -45,6 +47,19 @@ NetworkPacket::NetworkPacket(rtc::CopyOnWriteBuffer packet, packet_time_us_(packet_time_us), transport_(transport) {} +NetworkPacket::NetworkPacket(RtpPacketReceived packet_received, + MediaType media_type, + int64_t send_time, + int64_t arrival_time) + : packet_(packet_received.Buffer()), + send_time_(send_time), + arrival_time_(arrival_time), + is_rtcp_(false), + media_type_(media_type), + packet_time_us_(packet_received.arrival_time().us()), + packet_received_(std::move(packet_received)), + transport_(nullptr) {} + NetworkPacket::NetworkPacket(NetworkPacket&& o) : packet_(std::move(o.packet_)), send_time_(o.send_time_), @@ -53,6 +68,7 @@ NetworkPacket::NetworkPacket(NetworkPacket&& o) is_rtcp_(o.is_rtcp_), media_type_(o.media_type_), packet_time_us_(o.packet_time_us_), + packet_received_(std::move(o.packet_received_)), transport_(o.transport_) {} NetworkPacket::~NetworkPacket() = default; @@ -65,6 +81,7 @@ NetworkPacket& NetworkPacket::operator=(NetworkPacket&& o) { is_rtcp_ = o.is_rtcp_; media_type_ = o.media_type_; packet_time_us_ = o.packet_time_us_; + packet_received_ = o.packet_received_; transport_ = o.transport_; return *this; @@ -184,6 +201,16 @@ PacketReceiver::DeliveryStatus FakeNetworkPipe::DeliverPacket( : PacketReceiver::DELIVERY_PACKET_ERROR; } +void FakeNetworkPipe::DeliverRtpPacket( + MediaType media_type, + RtpPacketReceived packet, + OnUndemuxablePacketHandler undemuxable_packet_handler) { + MutexLock lock(&process_lock_); + int64_t time_now_us = clock_->TimeInMicroseconds(); + EnqueuePacket( + NetworkPacket(std::move(packet), media_type, time_now_us, time_now_us)); +} + void FakeNetworkPipe::DeliverRtcpPacket(rtc::CopyOnWriteBuffer packet) { EnqueuePacket(std::move(packet), absl::nullopt, true, MediaType::ANY, absl::nullopt); @@ -352,8 +379,25 @@ void FakeNetworkPipe::DeliverNetworkPacket(NetworkPacket* packet) { packet_time_us += queue_time_us; packet_time_us += (clock_offset_ms_ * 1000); } - receiver_->DeliverPacket(packet->media_type(), - std::move(*packet->raw_packet()), packet_time_us); + if (packet->is_rtcp()) { + receiver_->DeliverRtcpPacket(std::move(*packet->raw_packet())); + } else if (packet->packet_received()) { + packet->packet_received()->set_arrival_time( + Timestamp::Micros(packet_time_us)); + receiver_->DeliverRtpPacket( + packet->media_type(), *packet->packet_received(), + [](const RtpPacketReceived& packet) { + RTC_LOG(LS_WARNING) + << "Unexpected failed demuxing packet in FakeNetworkPipe, " + "Ssrc: " + << packet.Ssrc() << " seq : " << packet.SequenceNumber(); + return false; + }); + } else { + receiver_->DeliverPacket(packet->media_type(), + std::move(*packet->raw_packet()), + packet_time_us); + } } } diff --git a/call/fake_network_pipe.h b/call/fake_network_pipe.h index 3a6cb05643..198615cb79 100644 --- a/call/fake_network_pipe.h +++ b/call/fake_network_pipe.h @@ -21,8 +21,8 @@ #include "api/call/transport.h" #include "api/test/simulated_network.h" -#include "call/call.h" #include "call/simulated_packet_receiver.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "rtc_base/synchronization/mutex.h" #include "rtc_base/thread_annotations.h" @@ -43,6 +43,11 @@ class NetworkPacket { absl::optional packet_time_us, Transport* transport); + NetworkPacket(RtpPacketReceived packet, + MediaType media_type, + int64_t send_time, + int64_t arrival_time); + // Disallow copy constructor and copy assignment (no deep copies of `data_`). NetworkPacket(const NetworkPacket&) = delete; ~NetworkPacket(); @@ -65,6 +70,9 @@ class NetworkPacket { bool is_rtcp() const { return is_rtcp_; } MediaType media_type() const { return media_type_; } absl::optional packet_time_us() const { return packet_time_us_; } + absl::optional packet_received() const { + return packet_received_; + } Transport* transport() const { return transport_; } private: @@ -83,6 +91,7 @@ class NetworkPacket { // network pipe. MediaType media_type_; absl::optional packet_time_us_; + absl::optional packet_received_; Transport* transport_; }; @@ -142,19 +151,20 @@ class FakeNetworkPipe : public SimulatedPacketReceiverInterface { // Implements the PacketReceiver interface. When/if packets are delivered, // they will be passed directly to the receiver instance given in - // SetReceiver(), without passing through a Demuxer. The receive time - // will be increased by the amount of time the packet spent in the - // fake network pipe. + // SetReceiver(). The receive time will be increased by the amount of time the + // packet spent in the fake network pipe. + void DeliverRtpPacket( + MediaType media_type, + RtpPacketReceived packet, + OnUndemuxablePacketHandler undemuxable_packet_handler) override; + void DeliverRtcpPacket(rtc::CopyOnWriteBuffer packet) override; + + // TODO(perkj, https://bugs.webrtc.org/7135): Remove once implementations + // dont use it. PacketReceiver::DeliveryStatus DeliverPacket(MediaType media_type, rtc::CopyOnWriteBuffer packet, int64_t packet_time_us) override; - void DeliverRtcpPacket(rtc::CopyOnWriteBuffer packet) override; - - // TODO(bugs.webrtc.org/9584): Needed to inherit the alternative signature for - // this method. - using PacketReceiver::DeliverPacket; - // Processes the network queues and trigger PacketReceiver::IncomingPacket for // packets ready to be delivered. void Process() override; diff --git a/call/fake_network_pipe_unittest.cc b/call/fake_network_pipe_unittest.cc index 60c26e335b..9c4e6d926f 100644 --- a/call/fake_network_pipe_unittest.cc +++ b/call/fake_network_pipe_unittest.cc @@ -14,33 +14,46 @@ #include #include "call/simulated_network.h" +#include "modules/rtp_rtcp/include/rtp_header_extension_map.h" +#include "modules/rtp_rtcp/source/rtp_header_extensions.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" +#include "rtc_base/checks.h" #include "system_wrappers/include/clock.h" #include "test/gmock.h" #include "test/gtest.h" using ::testing::_; +using ::testing::Property; +using ::testing::WithArg; namespace webrtc { - class MockReceiver : public PacketReceiver { public: MOCK_METHOD(DeliveryStatus, DeliverPacket, (MediaType, rtc::CopyOnWriteBuffer, int64_t), (override)); + MOCK_METHOD(void, + DeliverRtcpPacket, + (rtc::CopyOnWriteBuffer packet), + (override)); + MOCK_METHOD(void, + DeliverRtpPacket, + (MediaType media_type, + RtpPacketReceived packet, + OnUndemuxablePacketHandler undemuxable_packet_handler), + (override)); virtual ~MockReceiver() = default; }; class ReorderTestReceiver : public MockReceiver { public: - DeliveryStatus DeliverPacket(MediaType media_type, - rtc::CopyOnWriteBuffer packet, - int64_t /* packet_time_us */) override { + void DeliverRtpPacket( + MediaType media_type, + RtpPacketReceived packet, + OnUndemuxablePacketHandler undemuxable_packet_handler) 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; + delivered_sequence_numbers_.push_back(packet.SequenceNumber()); } std::vector delivered_sequence_numbers_; }; @@ -52,13 +65,15 @@ class FakeNetworkPipeTest : public ::testing::Test { protected: void SendPackets(FakeNetworkPipe* pipe, int number_packets, int packet_size) { RTC_DCHECK_GE(packet_size, sizeof(int)); - std::unique_ptr packet(new uint8_t[packet_size]); for (int i = 0; i < number_packets; ++i) { - // Set a sequence number for the packets by - // using the first bytes in the packet. - memcpy(packet.get(), &i, sizeof(int)); - rtc::CopyOnWriteBuffer buffer(packet.get(), packet_size); - pipe->DeliverPacket(MediaType::ANY, buffer, /* packet_time_us */ -1); + RtpPacketReceived packet; + constexpr size_t kFixedHeaderSize = 12; + packet.AllocatePayload(packet_size - kFixedHeaderSize); + packet.SetSequenceNumber(i); + packet.set_arrival_time(fake_clock_.CurrentTime()); + RTC_DCHECK_EQ(packet.Buffer().size(), packet_size); + pipe->DeliverRtpPacket(MediaType::ANY, std::move(packet), + [](const RtpPacketReceived&) { return false; }); } } @@ -90,22 +105,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(receiver, DeliverPacket(_, _, _)).Times(0); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(0); pipe->Process(); // Advance enough time to release one packet. fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(1); pipe->Process(); // Release all but one packet fake_clock_.AdvanceTimeMilliseconds(9 * kPacketTimeMs - 1); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(8); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(8); pipe->Process(); // And the last one. fake_clock_.AdvanceTimeMilliseconds(1); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(1); pipe->Process(); } @@ -130,17 +145,17 @@ TEST_F(FakeNetworkPipeTest, ExtraDelayTest) { // Increase more than kPacketTimeMs, but not more than the extra delay. fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(0); pipe->Process(); // Advance the network delay to get the first packet. fake_clock_.AdvanceTimeMilliseconds(config.queue_delay_ms); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(1); pipe->Process(); // Advance one more kPacketTimeMs to get the last packet. fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(1); pipe->Process(); } @@ -165,7 +180,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(receiver, DeliverPacket(_, _, _)).Times(2); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(2); pipe->Process(); } @@ -189,7 +204,7 @@ TEST_F(FakeNetworkPipeTest, StatisticsTest) { fake_clock_.AdvanceTimeMilliseconds(3 * kPacketTimeMs + config.queue_delay_ms); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(2); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(2); pipe->Process(); // Packet 1: kPacketTimeMs + config.queue_delay_ms, @@ -222,13 +237,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(receiver, DeliverPacket(_, _, _)).Times(0); + EXPECT_CALL(receiver, DeliverRtpPacket).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(receiver, DeliverPacket(_, _, _)).Times(1); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(1); pipe->Process(); } @@ -244,13 +259,13 @@ 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(receiver, DeliverPacket(_, _, _)).Times(0); + EXPECT_CALL(receiver, DeliverRtpPacket).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(receiver, DeliverPacket(_, _, _)).Times(1); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(1); pipe->Process(); } @@ -258,7 +273,7 @@ TEST_F(FakeNetworkPipeTest, ChangingCapacityWithEmptyPipeTest) { EXPECT_EQ(static_cast(2 * kNumPackets), pipe->SentPackets()); EXPECT_FALSE(pipe->TimeUntilNextProcess().has_value()); fake_clock_.AdvanceTimeMilliseconds(1000); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(0); pipe->Process(); } @@ -280,14 +295,14 @@ TEST_F(FakeNetworkPipeTest, ChangingCapacityWithPacketsInPipeTest) { SendPackets(pipe.get(), kNumPackets, kPacketSize); // Time hasn't increased yet, so we souldn't get any packets. - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(0); pipe->Process(); // Advance time in steps to release half of the packets one at a time. int step_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize); for (int i = 0; i < kNumPackets / 2; ++i) { fake_clock_.AdvanceTimeMilliseconds(step_ms); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(1); pipe->Process(); } @@ -299,7 +314,7 @@ TEST_F(FakeNetworkPipeTest, ChangingCapacityWithPacketsInPipeTest) { step_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize); for (int i = 0; i < kNumPackets / 2; ++i) { fake_clock_.AdvanceTimeMilliseconds(step_ms); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(1); pipe->Process(); } @@ -307,7 +322,7 @@ TEST_F(FakeNetworkPipeTest, ChangingCapacityWithPacketsInPipeTest) { EXPECT_EQ(static_cast(kNumPackets), pipe->SentPackets()); EXPECT_FALSE(pipe->TimeUntilNextProcess().has_value()); fake_clock_.AdvanceTimeMilliseconds(1000); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(0); pipe->Process(); } @@ -413,7 +428,7 @@ TEST_F(FakeNetworkPipeTest, SetReceiver) { PacketTimeMs(config.link_capacity_kbps, kPacketSize); SendPackets(pipe.get(), 1, kPacketSize); fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(1); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(1); pipe->Process(); MockReceiver new_receiver; @@ -421,8 +436,51 @@ TEST_F(FakeNetworkPipeTest, SetReceiver) { SendPackets(pipe.get(), 1, kPacketSize); fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs); - EXPECT_CALL(receiver, DeliverPacket(_, _, _)).Times(0); - EXPECT_CALL(new_receiver, DeliverPacket(_, _, _)).Times(1); + EXPECT_CALL(receiver, DeliverRtpPacket).Times(0); + EXPECT_CALL(new_receiver, DeliverRtpPacket).Times(1); + pipe->Process(); +} + +TEST_F(FakeNetworkPipeTest, DeliverRtpPacketPropagatesExtensions) { + BuiltInNetworkBehaviorConfig config; + config.queue_delay_ms = 100; + MockReceiver receiver; + auto simulated_network = std::make_unique(config); + std::unique_ptr pipe(new FakeNetworkPipe( + &fake_clock_, std::move(simulated_network), &receiver)); + RtpHeaderExtensionMap extension_map; + extension_map.Register(/*id=*/7); + + RtpPacketReceived packet(&extension_map, fake_clock_.CurrentTime()); + packet.SetExtension(123); + pipe->DeliverRtpPacket(MediaType::VIDEO, std::move(packet), + [](const RtpPacketReceived&) { return false; }); + + // Advance the network delay to get the first packet. + fake_clock_.AdvanceTimeMilliseconds(config.queue_delay_ms); + EXPECT_CALL(receiver, DeliverRtpPacket(MediaType::VIDEO, _, _)) + .WillOnce(WithArg<1>([](RtpPacketReceived packet) { + EXPECT_EQ(packet.GetExtension(), 123); + })); + pipe->Process(); +} + +TEST_F(FakeNetworkPipeTest, DeliverRtcpPacket) { + BuiltInNetworkBehaviorConfig config; + config.queue_delay_ms = 100; + MockReceiver receiver; + auto simulated_network = std::make_unique(config); + std::unique_ptr pipe(new FakeNetworkPipe( + &fake_clock_, std::move(simulated_network), &receiver)); + + rtc::CopyOnWriteBuffer buffer(100); + memset(buffer.MutableData(), 0, 100); + pipe->DeliverRtcpPacket(std::move(buffer)); + + // Advance the network delay to get the first packet. + fake_clock_.AdvanceTimeMilliseconds(config.queue_delay_ms); + EXPECT_CALL(receiver, + DeliverRtcpPacket(Property(&rtc::CopyOnWriteBuffer::size, 100))); pipe->Process(); }