Remove pending packets from the pacer when an RTP module is removed.
This CL adds functionality to remove packets matching a given SSRC from
the pacer queue, and calls that with any SSRCs used by an RTP module
when that module is removed.
Bug: chromium:1395081
Change-Id: I13c0285ddca600e784ad04a806727a508ede6dcc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/287124
Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38880}
diff --git a/call/rtp_video_sender_unittest.cc b/call/rtp_video_sender_unittest.cc
index a8595e3..da2bed6 100644
--- a/call/rtp_video_sender_unittest.cc
+++ b/call/rtp_video_sender_unittest.cc
@@ -1098,4 +1098,81 @@
}
}
+TEST(RtpVideoSenderTest, ClearsPendingPacketsOnInactivation) {
+ RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
+ test.SetActiveModules({true});
+
+ RtpHeaderExtensionMap extensions;
+ extensions.Register<RtpDependencyDescriptorExtension>(
+ kDependencyDescriptorExtensionId);
+ std::vector<RtpPacket> sent_packets;
+ ON_CALL(test.transport(), SendRtp)
+ .WillByDefault([&](const uint8_t* packet, size_t length,
+ const PacketOptions& options) {
+ sent_packets.emplace_back(&extensions);
+ EXPECT_TRUE(sent_packets.back().Parse(packet, length));
+ return true;
+ });
+
+ // Set a very low bitrate.
+ test.router()->OnBitrateUpdated(
+ CreateBitrateAllocationUpdate(/*rate_bps=*/30'000),
+ /*framerate=*/30);
+
+ // Create and send a large keyframe.
+ const size_t kImageSizeBytes = 10000;
+ constexpr uint8_t kPayload[kImageSizeBytes] = {'a'};
+ EncodedImage encoded_image;
+ encoded_image.SetTimestamp(1);
+ encoded_image.capture_time_ms_ = 2;
+ encoded_image._frameType = VideoFrameType::kVideoFrameKey;
+ encoded_image.SetEncodedData(
+ EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
+ EXPECT_EQ(test.router()
+ ->OnEncodedImage(encoded_image, /*codec_specific=*/nullptr)
+ .error,
+ EncodedImageCallback::Result::OK);
+
+ // Advance time a small amount, check that sent data is only part of the
+ // image.
+ test.AdvanceTime(TimeDelta::Millis(5));
+ DataSize transmittedPayload = DataSize::Zero();
+ for (const RtpPacket& packet : sent_packets) {
+ transmittedPayload += DataSize::Bytes(packet.payload_size());
+ // Make sure we don't see the end of the frame.
+ EXPECT_FALSE(packet.Marker());
+ }
+ EXPECT_GT(transmittedPayload, DataSize::Zero());
+ EXPECT_LT(transmittedPayload, DataSize::Bytes(kImageSizeBytes / 4));
+
+ // Record the RTP timestamp of the first frame.
+ const uint32_t first_frame_timestamp = sent_packets[0].Timestamp();
+ sent_packets.clear();
+
+ // Disable the sending module and advance time slightly. No packets should be
+ // sent.
+ test.SetActiveModules({false});
+ test.AdvanceTime(TimeDelta::Millis(20));
+ EXPECT_TRUE(sent_packets.empty());
+
+ // Reactive the send module - any packets should have been removed, so nothing
+ // should be transmitted.
+ test.SetActiveModules({true});
+ test.AdvanceTime(TimeDelta::Millis(33));
+ EXPECT_TRUE(sent_packets.empty());
+
+ // Send a new frame.
+ encoded_image.SetTimestamp(3);
+ encoded_image.capture_time_ms_ = 4;
+ EXPECT_EQ(test.router()
+ ->OnEncodedImage(encoded_image, /*codec_specific=*/nullptr)
+ .error,
+ EncodedImageCallback::Result::OK);
+ test.AdvanceTime(TimeDelta::Millis(33));
+
+ // Advance time, check we get new packets - but only for the second frame.
+ EXPECT_FALSE(sent_packets.empty());
+ EXPECT_NE(sent_packets[0].Timestamp(), first_frame_timestamp);
+}
+
} // namespace webrtc