Skip network transmission in RtpSenderEgress for untransmitted packets.

When packet->allow_sending() is false, skip adding send-time header
extensions and skip transmitting to the network transport, but still
store the packet in RtpPacketHistory if it is marked as retransmittable.

Bug: webrtc:564720400
Change-Id: Ie627f5b44d34b6eb44b481212e4c95094928f2f4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/505760
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#48752}
diff --git a/modules/rtp_rtcp/BUILD.gn b/modules/rtp_rtcp/BUILD.gn
index b871280..542331a 100644
--- a/modules/rtp_rtcp/BUILD.gn
+++ b/modules/rtp_rtcp/BUILD.gn
@@ -376,6 +376,7 @@
     "../../rtc_base:timeutils",
     "../../rtc_base/containers:flat_map",
     "../../rtc_base/experiments:field_trial_parser",
+    "../../rtc_base/experiments:retransmit_flushed_packets_settings",
     "../../rtc_base/synchronization:mutex",
     "../../rtc_base/system:no_unique_address",
     "../../rtc_base/task_utils:repeating_task",
diff --git a/modules/rtp_rtcp/source/rtp_packet_history.cc b/modules/rtp_rtcp/source/rtp_packet_history.cc
index f215424..5cda7d6 100644
--- a/modules/rtp_rtcp/source/rtp_packet_history.cc
+++ b/modules/rtp_rtcp/source/rtp_packet_history.cc
@@ -42,12 +42,12 @@
 RtpPacketHistory::StoredPacket::StoredPacket(
     std::unique_ptr<RtpPacketToSend> packet,
     Timestamp send_time,
-    uint64_t insert_order)
+    uint64_t insert_order,
+    Timestamp earliest_allowed_retransmission)
     : packet_(std::move(packet)),
-      pending_transmission_(false),
+      earliest_allowed_retransmission_(earliest_allowed_retransmission),
       send_time_(send_time),
-      insert_order_(insert_order),
-      times_retransmitted_(0) {}
+      insert_order_(insert_order) {}
 
 RtpPacketHistory::StoredPacket::StoredPacket(StoredPacket&&) = default;
 RtpPacketHistory::StoredPacket& RtpPacketHistory::StoredPacket::operator=(
@@ -62,6 +62,7 @@
                                    PaddingMode padding_mode)
     : clock_(&env.clock()),
       padding_mode_(padding_mode),
+      retransmit_flushed_packets_settings_(env.field_trials()),
       number_to_store_(0),
       mode_(StorageMode::kDisabled),
       rtt_(TimeDelta::MinusInfinity()),
@@ -109,6 +110,13 @@
   RTC_DCHECK(packet->allow_retransmission());
   CullOldPackets();
 
+  Timestamp earliest_allowed_retransmission = Timestamp::MinusInfinity();
+  if (!packet->allow_sending()) {
+    TimeDelta rtt = rtt_ >= TimeDelta::Zero() ? rtt_ : kDefaultRtt;
+    earliest_allowed_retransmission =
+        send_time + retransmit_flushed_packets_settings_.rtt_multiplier() * rtt;
+  }
+
   // Store packet.
   const uint16_t rtp_seq_no = packet->SequenceNumber();
   int packet_index = GetPacketIndex(rtp_seq_no);
@@ -146,7 +154,8 @@
   }
 
   packet_history_[packet_index] =
-      StoredPacket(std::move(packet), send_time, packets_inserted_++);
+      StoredPacket(std::move(packet), send_time, packets_inserted_++,
+                   earliest_allowed_retransmission);
 }
 
 std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetPacketAndMarkAsPending(
@@ -186,6 +195,7 @@
       encapsulate(*packet->packet_);
   if (encapsulated_packet) {
     packet->pending_transmission_ = true;
+    encapsulated_packet->set_allow_sending(true);
   }
 
   return encapsulated_packet;
@@ -234,8 +244,11 @@
 
 bool RtpPacketHistory::VerifyRtt(
     const RtpPacketHistory::StoredPacket& packet) const {
-  if (packet.times_retransmitted() > 0 &&
-      clock_->CurrentTime() - packet.send_time() < rtt_) {
+  const Timestamp now = clock_->CurrentTime();
+  if (now < packet.earliest_allowed_retransmission()) {
+    return false;
+  }
+  if (packet.times_retransmitted() > 0 && now - packet.send_time() < rtt_) {
     // This packet has already been retransmitted once, and the time since
     // that even is lower than on RTT. Ignore request as this packet is
     // likely already in the network pipe.
@@ -261,7 +274,12 @@
   }
   if (padding_mode_ == PaddingMode::kRecentLargePacket &&
       large_payload_packet_) {
-    return encapsulate(*large_payload_packet_);
+    std::unique_ptr<RtpPacketToSend> padding_packet =
+        encapsulate(*large_payload_packet_);
+    if (padding_packet != nullptr) {
+      padding_packet->set_allow_sending(true);
+    }
+    return padding_packet;
   }
 
   StoredPacket* best_packet = nullptr;
@@ -293,6 +311,7 @@
     return nullptr;
   }
 
+  padding_packet->set_allow_sending(true);
   best_packet->set_send_time(clock_->CurrentTime());
   best_packet->IncrementTimesRetransmitted();
   return padding_packet;
diff --git a/modules/rtp_rtcp/source/rtp_packet_history.h b/modules/rtp_rtcp/source/rtp_packet_history.h
index 9a8c882..c49766e 100644
--- a/modules/rtp_rtcp/source/rtp_packet_history.h
+++ b/modules/rtp_rtcp/source/rtp_packet_history.h
@@ -24,6 +24,7 @@
 #include "api/units/timestamp.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
+#include "rtc_base/experiments/retransmit_flushed_packets_settings.h"
 #include "rtc_base/synchronization/mutex.h"
 #include "rtc_base/thread_annotations.h"
 
@@ -55,6 +56,9 @@
   static constexpr int kMinPacketDurationRtt = 3;
   // With kStoreAndCull, always remove packets after 3x max(1000ms, 3x rtt).
   static constexpr int kPacketCullingDelayFactor = 3;
+  // Default RTT used when calculating earliest allowed retransmission for
+  // packets not allowed sending if no RTT has been set yet.
+  static constexpr TimeDelta kDefaultRtt = TimeDelta::Millis(200);
 
   RtpPacketHistory(const Environment& env, PaddingMode padding_mode);
 
@@ -128,7 +132,8 @@
     StoredPacket() = default;
     StoredPacket(std::unique_ptr<RtpPacketToSend> packet,
                  Timestamp send_time,
-                 uint64_t insert_order);
+                 uint64_t insert_order,
+                 Timestamp earliest_allowed_retransmission);
     StoredPacket(StoredPacket&&);
     StoredPacket& operator=(StoredPacket&&);
     ~StoredPacket();
@@ -141,21 +146,27 @@
     Timestamp send_time() const { return send_time_; }
     void set_send_time(Timestamp value) { send_time_ = value; }
 
+    Timestamp earliest_allowed_retransmission() const {
+      return earliest_allowed_retransmission_;
+    }
+
     // The actual packet.
     std::unique_ptr<RtpPacketToSend> packet_;
 
     // True if the packet is currently in the pacer queue pending transmission.
-    bool pending_transmission_;
+    bool pending_transmission_ = false;
 
    private:
+    // Do not restrict retransmission by default.
+    Timestamp earliest_allowed_retransmission_ = Timestamp::MinusInfinity();
     Timestamp send_time_ = Timestamp::Zero();
 
     // Unique number per StoredPacket, incremented by one for each added
     // packet. Used to sort on insert order.
-    uint64_t insert_order_;
+    uint64_t insert_order_ = 0;
 
     // Number of times RE-transmitted, ie excluding the first transmission.
-    size_t times_retransmitted_;
+    size_t times_retransmitted_ = 0;
   };
 
   // Helper method to check if packet has too recently been sent.
@@ -174,6 +185,9 @@
 
   Clock* const clock_;
   const PaddingMode padding_mode_;
+  // TODO(bugs.webrtc.org/564720400): Either remove or make permanent once
+  // experiment is concluded.
+  const RetransmitFlushedPacketsSettings retransmit_flushed_packets_settings_;
   mutable Mutex lock_;
   size_t number_to_store_ RTC_GUARDED_BY(lock_);
   StorageMode mode_ RTC_GUARDED_BY(lock_);
diff --git a/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc b/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc
index a265483..453bffd1 100644
--- a/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc
@@ -41,6 +41,8 @@
 using StorageMode = RtpPacketHistory::StorageMode;
 
 using ::testing::AllOf;
+using ::testing::IsNull;
+using ::testing::NotNull;
 using ::testing::Pointee;
 using ::testing::Property;
 
@@ -723,4 +725,97 @@
       Pointee(Property(&RtpPacketToSend::SequenceNumber, sequence_number)));
 }
 
+TEST_P(RtpPacketHistoryTest,
+       DisallowsRetransmissionOfPacketNotAllowedSendingBeforeMultiplierRtt) {
+  constexpr TimeDelta kRtt = TimeDelta::Millis(100);
+  hist_.SetStorePacketsStatus(RtpPacketHistory::StorageMode::kStoreAndCull, 10);
+  hist_.SetRtt(kRtt);
+
+  Timestamp now = fake_clock_.CurrentTime();
+  std::unique_ptr<RtpPacketToSend> packet = CreatePacket(kStartSeqNum);
+  packet->set_allow_sending(false);
+  hist_.PutRtpPacket(std::move(packet), now);
+
+  fake_clock_.AdvanceTime(2 * kRtt - TimeDelta::Millis(1));
+  EXPECT_FALSE(hist_.GetPacketState(kStartSeqNum));
+  EXPECT_THAT(hist_.GetPacketAndMarkAsPending(kStartSeqNum), IsNull());
+}
+
+TEST_P(RtpPacketHistoryTest,
+       AllowsRetransmissionOfPacketNotAllowedSendingAtMultiplierRtt) {
+  constexpr TimeDelta kRtt = TimeDelta::Millis(100);
+  hist_.SetStorePacketsStatus(RtpPacketHistory::StorageMode::kStoreAndCull, 10);
+  hist_.SetRtt(kRtt);
+
+  Timestamp now = fake_clock_.CurrentTime();
+  std::unique_ptr<RtpPacketToSend> packet = CreatePacket(kStartSeqNum);
+  packet->set_allow_sending(false);
+  hist_.PutRtpPacket(std::move(packet), now);
+
+  fake_clock_.AdvanceTime(2 * kRtt);
+  EXPECT_TRUE(hist_.GetPacketState(kStartSeqNum));
+  std::unique_ptr<RtpPacketToSend> retransmitted_packet =
+      hist_.GetPacketAndMarkAsPending(kStartSeqNum);
+  ASSERT_THAT(retransmitted_packet, NotNull());
+  EXPECT_EQ(retransmitted_packet->SequenceNumber(), kStartSeqNum);
+  EXPECT_TRUE(retransmitted_packet->allow_sending());
+}
+
+TEST_P(RtpPacketHistoryTest, PacketNotAllowedSendingUsesDefaultRttIfNoneSet) {
+  hist_.SetStorePacketsStatus(RtpPacketHistory::StorageMode::kStoreAndCull, 10);
+
+  Timestamp now = fake_clock_.CurrentTime();
+  std::unique_ptr<RtpPacketToSend> packet = CreatePacket(kStartSeqNum);
+  packet->set_allow_sending(false);
+  hist_.PutRtpPacket(std::move(packet), now);
+
+  // Before 2 * kDefaultRtt (400ms), retransmission is not allowed.
+  fake_clock_.AdvanceTime(2 * RtpPacketHistory::kDefaultRtt -
+                          TimeDelta::Millis(1));
+  EXPECT_FALSE(hist_.GetPacketState(kStartSeqNum));
+  EXPECT_THAT(hist_.GetPacketAndMarkAsPending(kStartSeqNum), IsNull());
+
+  // At/after 2 * kDefaultRtt, retransmission is allowed.
+  fake_clock_.AdvanceTime(TimeDelta::Millis(1));
+  EXPECT_TRUE(hist_.GetPacketState(kStartSeqNum));
+  std::unique_ptr<RtpPacketToSend> default_rtt_packet =
+      hist_.GetPacketAndMarkAsPending(kStartSeqNum);
+  ASSERT_THAT(default_rtt_packet, NotNull());
+  EXPECT_EQ(default_rtt_packet->SequenceNumber(), kStartSeqNum);
+  EXPECT_TRUE(default_rtt_packet->allow_sending());
+}
+
+TEST_P(RtpPacketHistoryTest,
+       PacketNotAllowedSendingRespectsCustomRttMultiplier) {
+  constexpr TimeDelta kRtt = TimeDelta::Millis(100);
+  Environment env = CreateTestEnvironment({
+      .field_trials =
+          "WebRTC-RetransmitFlushedPackets/Enabled,rtt_multiplier:3.0/",
+      .time = &fake_clock_,
+  });
+  RtpPacketHistory history(env, GetParam());
+  history.SetStorePacketsStatus(RtpPacketHistory::StorageMode::kStoreAndCull,
+                                10);
+  history.SetRtt(kRtt);
+
+  Timestamp now = fake_clock_.CurrentTime();
+  std::unique_ptr<RtpPacketToSend> packet = CreatePacket(kStartSeqNum);
+  packet->set_allow_sending(false);
+  history.PutRtpPacket(std::move(packet), now);
+
+  // Before 3 * RTT (300ms), retransmission is not allowed.
+  fake_clock_.AdvanceTime(3 * kRtt - TimeDelta::Millis(1));
+  EXPECT_FALSE(history.GetPacketState(kStartSeqNum));
+  EXPECT_THAT(history.GetPacketAndMarkAsPending(kStartSeqNum), IsNull());
+
+  // At 3 * RTT, retransmission is allowed.
+  fake_clock_.AdvanceTime(TimeDelta::Millis(1));
+  EXPECT_TRUE(history.GetPacketState(kStartSeqNum));
+  std::unique_ptr<RtpPacketToSend> custom_multiplier_packet =
+      history.GetPacketAndMarkAsPending(kStartSeqNum);
+  ASSERT_THAT(custom_multiplier_packet, NotNull());
+  EXPECT_EQ(custom_multiplier_packet->SequenceNumber(), kStartSeqNum);
+  EXPECT_TRUE(custom_multiplier_packet->allow_sending());
+}
+
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_sender_egress.cc b/modules/rtp_rtcp/source/rtp_sender_egress.cc
index d4d39c2..8feb4f1 100644
--- a/modules/rtp_rtcp/source/rtp_sender_egress.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_egress.cc
@@ -49,6 +49,11 @@
 constexpr TimeDelta kBitrateStatisticsWindow = TimeDelta::Seconds(1);
 constexpr size_t kRtpSequenceNumberMapMaxEntries = 1 << 13;
 constexpr TimeDelta kUpdateInterval = kBitrateStatisticsWindow;
+
+bool IsMediaPacket(std::optional<RtpPacketMediaType> packet_type) {
+  return packet_type == RtpPacketMediaType::kVideo ||
+         packet_type == RtpPacketMediaType::kAudio;
+}
 }  // namespace
 
 RtpSenderEgress::NonPacedPacketSender::NonPacedPacketSender(
@@ -93,12 +98,10 @@
   if (packet->Ssrc() != sender_->FlexFecSsrc()) {
     sequencer_->Sequence(*packet);
   }
-  if (!packet->SetExtension<TransportSequenceNumber>(
-          ++transport_sequence_number_)) {
+  if (packet->allow_sending() && !packet->SetExtension<TransportSequenceNumber>(
+                                     ++transport_sequence_number_)) {
     --transport_sequence_number_;
   }
-  packet->ReserveExtension<TransmissionOffset>();
-  packet->ReserveExtension<AbsoluteSendTime>();
 }
 
 RtpSenderEgress::RtpSenderEgress(const Environment& env,
@@ -220,35 +223,45 @@
   // In case of VideoTimingExtension, since it's present not in every packet,
   // data after rtp header may be corrupted if these packets are protected by
   // the FEC.
-  if (packet->HasExtension<TransmissionOffset>() &&
-      packet->capture_time() > Timestamp::Zero()) {
-    TimeDelta diff = now - packet->capture_time();
-    packet->SetExtension<TransmissionOffset>(kTimestampTicksPerMs * diff.ms());
-  }
-  if (packet->HasExtension<AbsoluteSendTime>()) {
-    packet->SetExtension<AbsoluteSendTime>(AbsoluteSendTime::To24Bits(
-        env_.clock().ConvertTimestampToNtpTime(now)));
-  }
-  if (packet->HasExtension<TransportSequenceNumber>() &&
-      packet->transport_sequence_number()) {
-    packet->SetExtension<TransportSequenceNumber>(
-        *packet->transport_sequence_number() & 0xFFFF);
-  }
-
-  if (packet->HasExtension<VideoTimingExtension>()) {
-    if (populate_network2_timestamp_) {
-      packet->set_network2_time(now);
-    } else {
-      packet->set_pacer_exit_time(now);
+  if (packet->allow_sending()) {
+    if (packet->HasExtension<TransmissionOffset>() &&
+        packet->capture_time() > Timestamp::Zero()) {
+      TimeDelta diff = now - packet->capture_time();
+      packet->SetExtension<TransmissionOffset>(kTimestampTicksPerMs *
+                                               diff.ms());
     }
-  }
+    if (packet->HasExtension<AbsoluteSendTime>()) {
+      packet->SetExtension<AbsoluteSendTime>(AbsoluteSendTime::To24Bits(
+          env_.clock().ConvertTimestampToNtpTime(now)));
+    }
+    if (packet->HasExtension<TransportSequenceNumber>() &&
+        packet->transport_sequence_number()) {
+      packet->SetExtension<TransportSequenceNumber>(
+          *packet->transport_sequence_number() & 0xFFFF);
+    }
 
-  auto compound_packet =
-      Packet{.rtp_packet = std::move(packet), .info = pacing_info, .now = now};
-  if (enable_send_packet_batching_ && !is_audio_) {
-    packets_to_send_.push_back(std::move(compound_packet));
-  } else {
-    CompleteSendPacket(compound_packet, false);
+    if (packet->HasExtension<VideoTimingExtension>()) {
+      if (populate_network2_timestamp_) {
+        packet->set_network2_time(now);
+      } else {
+        packet->set_pacer_exit_time(now);
+      }
+    }
+
+    auto compound_packet = Packet{
+        .rtp_packet = std::move(packet), .info = pacing_info, .now = now};
+    if (enable_send_packet_batching_ && !is_audio_) {
+      packets_to_send_.push_back(std::move(compound_packet));
+    } else {
+      CompleteSendPacket(compound_packet, false);
+    }
+  } else if (IsMediaPacket(packet->packet_type()) &&
+             packet->allow_retransmission()) {
+    // TODO(bugs.webrtc.org/564720400): Either remove or make permanent skipping
+    // network transmission if allow_sending is false.
+    //
+    // Packet should not be sent, just put it in the packet history.
+    packet_history_->PutRtpPacket(std::move(packet), now);
   }
 }
 
@@ -265,11 +278,11 @@
   RTC_DCHECK_RUN_ON(worker_queue_);
   auto& [packet, pacing_info, now] = compound_packet;
   RTC_CHECK(packet);
+  RTC_DCHECK(packet->allow_sending());
 
   PacketOptions options;
   options.included_in_allocation = force_part_of_allocation_;
-  options.is_media = packet->packet_type() == RtpPacketMediaType::kAudio ||
-                     packet->packet_type() == RtpPacketMediaType::kVideo;
+  options.is_media = IsMediaPacket(packet->packet_type());
 
   // Set Packet id from transport sequence number header extension if it is
   // used. The source of the header extension is
diff --git a/modules/rtp_rtcp/source/rtp_sender_egress_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_egress_unittest.cc
index 68476ca..676cef0 100644
--- a/modules/rtp_rtcp/source/rtp_sender_egress_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_egress_unittest.cc
@@ -17,6 +17,7 @@
 #include <optional>
 #include <span>
 #include <utility>
+#include <vector>
 
 #include "api/call/transport.h"
 #include "api/environment/environment.h"
@@ -29,6 +30,7 @@
 #include "modules/rtp_rtcp/include/flexfec_sender.h"
 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/packet_sequencer.h"
 #include "modules/rtp_rtcp/source/rtp_header_extension_size.h"
 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
 #include "modules/rtp_rtcp/source/rtp_packet_history.h"
@@ -49,7 +51,9 @@
 using ::testing::Eq;
 using ::testing::Field;
 using ::testing::InSequence;
+using ::testing::IsNull;
 using ::testing::NiceMock;
+using ::testing::NotNull;
 
 constexpr Timestamp kStartTime = Timestamp::Millis(123456789);
 constexpr int kDefaultPayloadType = 100;
@@ -510,6 +514,140 @@
   EXPECT_TRUE(packet_history_.GetPacketState(packet_sequence_number));
 }
 
+TEST_F(RtpSenderEgressTest, PacketWithAllowSendingFalseNotSentToNetwork) {
+  std::unique_ptr<RtpSenderEgress> sender = CreateRtpSenderEgress();
+
+  std::unique_ptr<RtpPacketToSend> packet = BuildRtpPacket();
+  packet->set_allow_retransmission(true);
+  packet->set_allow_sending(false);
+
+  // Transport and observer should NOT receive the packet.
+  EXPECT_CALL(transport_, SentRtp).Times(0);
+  EXPECT_CALL(send_packet_observer_, OnSendPacket).Times(0);
+
+  sender->SendPacket(std::move(packet), PacedPacketInfo());
+
+  EXPECT_FALSE(transport_.last_packet().has_value());
+}
+
+TEST_F(RtpSenderEgressTest,
+       PacketWithAllowSendingFalseStoredInHistoryWithDelayedRetransmission) {
+  std::unique_ptr<RtpSenderEgress> sender = CreateRtpSenderEgress();
+  const TimeDelta kRtt = TimeDelta::Millis(100);
+  packet_history_.SetRtt(kRtt);
+  packet_history_.SetStorePacketsStatus(
+      RtpPacketHistory::StorageMode::kStoreAndCull, 10);
+
+  std::unique_ptr<RtpPacketToSend> packet = BuildRtpPacket();
+  packet->set_allow_retransmission(true);
+  packet->set_allow_sending(false);
+  packet->set_transport_sequence_number(42);
+  const uint16_t packet_sequence_number = packet->SequenceNumber();
+
+  sender->SendPacket(std::move(packet), PacedPacketInfo());
+
+  // Before 2 * RTT, retransmission is not allowed.
+  time_controller_.AdvanceTime(2 * kRtt - TimeDelta::Millis(1));
+  EXPECT_FALSE(packet_history_.GetPacketState(packet_sequence_number));
+  EXPECT_THAT(packet_history_.GetPacketAndMarkAsPending(packet_sequence_number),
+              IsNull());
+
+  // At/after 2 * RTT, retransmission IS allowed.
+  time_controller_.AdvanceTime(TimeDelta::Millis(1));
+  EXPECT_TRUE(packet_history_.GetPacketState(packet_sequence_number));
+  std::unique_ptr<RtpPacketToSend> retransmit =
+      packet_history_.GetPacketAndMarkAsPending(packet_sequence_number);
+  ASSERT_THAT(retransmit, NotNull());
+  EXPECT_THAT(retransmit->SequenceNumber(), packet_sequence_number);
+  EXPECT_THAT(retransmit->allow_sending(), true);
+  EXPECT_THAT(retransmit->HasExtension<AbsoluteSendTime>(), false);
+  EXPECT_THAT(retransmit->HasExtension<TransportSequenceNumber>(), false);
+
+  // Send the retransmitted packet and verify it is sent to the network.
+  retransmit->set_packet_type(RtpPacketMediaType::kRetransmission);
+  retransmit->set_retransmitted_sequence_number(packet_sequence_number);
+  EXPECT_CALL(transport_, SentRtp);
+  sender->SendPacket(std::move(retransmit), PacedPacketInfo());
+  EXPECT_TRUE(transport_.last_packet().has_value());
+}
+
+TEST_F(RtpSenderEgressTest,
+       PacketWithAllowSendingFalseUsesDefaultRttIfNoneSet) {
+  std::unique_ptr<RtpSenderEgress> sender = CreateRtpSenderEgress();
+  packet_history_.SetStorePacketsStatus(
+      RtpPacketHistory::StorageMode::kStoreAndCull, 10);
+
+  std::unique_ptr<RtpPacketToSend> packet = BuildRtpPacket();
+  packet->set_allow_retransmission(true);
+  packet->set_allow_sending(false);
+  const uint16_t packet_sequence_number = packet->SequenceNumber();
+
+  sender->SendPacket(std::move(packet), PacedPacketInfo());
+
+  // Before 2 * kDefaultRtt (400ms), retransmission is not allowed.
+  time_controller_.AdvanceTime(2 * RtpPacketHistory::kDefaultRtt -
+                               TimeDelta::Millis(1));
+  EXPECT_FALSE(packet_history_.GetPacketState(packet_sequence_number));
+  EXPECT_THAT(packet_history_.GetPacketAndMarkAsPending(packet_sequence_number),
+              IsNull());
+
+  // At/after 2 * kDefaultRtt, retransmission is allowed.
+  time_controller_.AdvanceTime(TimeDelta::Millis(1));
+  std::unique_ptr<RtpPacketToSend> retransmitted_packet =
+      packet_history_.GetPacketAndMarkAsPending(packet_sequence_number);
+  ASSERT_THAT(retransmitted_packet, NotNull());
+  EXPECT_EQ(retransmitted_packet->SequenceNumber(), packet_sequence_number);
+  EXPECT_TRUE(retransmitted_packet->allow_sending());
+}
+
+TEST_F(
+    RtpSenderEgressTest,
+    NonPacedPacketSenderDoesNotIncrementTransportSeqWhenAllowSendingIsFalse) {
+  header_extensions_.RegisterByUri(kTransportSequenceNumberExtensionId,
+                                   TransportSequenceNumber::Uri());
+  std::unique_ptr<RtpSenderEgress> sender = CreateRtpSenderEgress();
+  packet_history_.SetStorePacketsStatus(
+      RtpPacketHistory::StorageMode::kStoreAndCull, 10);
+
+  PacketSequencer sequencer(kSsrc, kRtxSsrc,
+                            /*require_marker_before_media_padding=*/false,
+                            &env_.clock());
+  sequencer.set_media_sequence_number(kStartSequenceNumber);
+  RtpSenderEgress::NonPacedPacketSender non_paced_sender(
+      *time_controller_.GetMainThread(), sender.get(), &sequencer);
+
+  std::unique_ptr<RtpPacketToSend> untransmitted_packet = BuildRtpPacket();
+  untransmitted_packet->set_allow_retransmission(true);
+  untransmitted_packet->set_allow_sending(false);
+
+  EXPECT_CALL(transport_, SentRtp).Times(0);
+  std::vector<std::unique_ptr<RtpPacketToSend>> packets;
+  packets.push_back(std::move(untransmitted_packet));
+  non_paced_sender.EnqueuePackets(std::move(packets));
+
+  time_controller_.AdvanceTime(2 * RtpPacketHistory::kDefaultRtt);
+  std::unique_ptr<RtpPacketToSend> stored_packet =
+      packet_history_.GetPacketAndMarkAsPending(kStartSequenceNumber);
+  ASSERT_THAT(stored_packet, NotNull());
+
+  // Enqueue a normal packet and verify the transport sequence number starts at
+  // 1 (was not incremented for the untransmitted packet).
+  std::unique_ptr<RtpPacketToSend> transmitted_packet = BuildRtpPacket();
+  transmitted_packet->set_allow_sending(true);
+
+  EXPECT_CALL(transport_, SentRtp);
+  packets.clear();
+  packets.push_back(std::move(transmitted_packet));
+  non_paced_sender.EnqueuePackets(std::move(packets));
+
+  ASSERT_TRUE(transport_.last_packet().has_value());
+  EXPECT_EQ(transport_.last_packet()->packet.SequenceNumber(),
+            kStartSequenceNumber + 1);
+  EXPECT_EQ(
+      transport_.last_packet()->packet.GetExtension<TransportSequenceNumber>(),
+      1u);
+}
+
 TEST_F(RtpSenderEgressTest, DoesNotPutNonMediaInHistory) {
   std::unique_ptr<RtpSenderEgress> sender = CreateRtpSenderEgress();
   packet_history_.SetStorePacketsStatus(