Fix potential deadlock in VideoSendStreamTests.
The synchronously waiting SendTask() helper method should never be
called from within OnSendRtp() as that risks a deadlock with the
shutdown of the test.
This CL reverts an earlier disabling which did not correctly identify
the root cause.
Bug: webrtc:13291
Change-Id: Ia3c3417e0cbfb7011bb2439a52f976b946adad78
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/235721
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35244}
diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc
index b0394f8..16b7f09 100644
--- a/video/video_send_stream_tests.cc
+++ b/video/video_send_stream_tests.cc
@@ -1458,14 +1458,7 @@
//
// Note that the test starts at "high" bitrate and does not ramp up to "higher"
// bitrate since no receiver block or remb is sent in the initial phase.
-// TODO(bugs.webrtc.org/13294): Fix flakiness or replace with scenario test.
-#if defined(WEBRTC_MAC)
-#define MAYBE_MinTransmitBitrateRespectsRemb \
- DISABLED_MinTransmitBitrateRespectsRemb
-#else
-#define MAYBE_MinTransmitBitrateRespectsRemb MinTransmitBitrateRespectsRemb
-#endif
-TEST_F(VideoSendStreamTest, MAYBE_MinTransmitBitrateRespectsRemb) {
+TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
static const int kMinTransmitBitrateBps = 400000;
static const int kHighBitrateBps = 150000;
static const int kRembBitrateBps = 80000;
@@ -1490,27 +1483,29 @@
return DROP_PACKET;
RtpPacket rtp_packet;
- if (!rtp_packet.Parse(packet, length))
- return DROP_PACKET;
+ RTC_CHECK(rtp_packet.Parse(packet, length));
+ const uint32_t ssrc = rtp_packet.Ssrc();
RTC_DCHECK(stream_);
- VideoSendStream::Stats stats;
- SendTask(RTC_FROM_HERE, task_queue_,
- [&]() { stats = stream_->GetStats(); });
- if (!stats.substreams.empty()) {
- EXPECT_EQ(1u, stats.substreams.size());
- int total_bitrate_bps =
- stats.substreams.begin()->second.total_bitrate_bps;
- test::PrintResult("bitrate_stats_", "min_transmit_bitrate_low_remb",
- "bitrate_bps", static_cast<size_t>(total_bitrate_bps),
- "bps", false);
- if (total_bitrate_bps > kHighBitrateBps) {
- rtp_rtcp_->SetRemb(kRembBitrateBps, {rtp_packet.Ssrc()});
- bitrate_capped_ = true;
- } else if (bitrate_capped_ &&
- total_bitrate_bps < kRembRespectedBitrateBps) {
- observation_complete_.Set();
+
+ task_queue_->PostTask(ToQueuedTask([this, ssrc]() {
+ VideoSendStream::Stats stats = stream_->GetStats();
+ if (!stats.substreams.empty()) {
+ EXPECT_EQ(1u, stats.substreams.size());
+ int total_bitrate_bps =
+ stats.substreams.begin()->second.total_bitrate_bps;
+ test::PrintResult(
+ "bitrate_stats_", "min_transmit_bitrate_low_remb", "bitrate_bps",
+ static_cast<size_t>(total_bitrate_bps), "bps", false);
+ if (total_bitrate_bps > kHighBitrateBps) {
+ rtp_rtcp_->SetRemb(kRembBitrateBps, {ssrc});
+ bitrate_capped_ = true;
+ } else if (bitrate_capped_ &&
+ total_bitrate_bps < kRembRespectedBitrateBps) {
+ observation_complete_.Set();
+ }
}
- }
+ }));
+
// Packets don't have to be delivered since the test is the receiver.
return DROP_PACKET;
}
@@ -3893,54 +3888,55 @@
}
Action OnSendRtp(const uint8_t* packet, size_t length) override {
- MutexLock lock(&mutex_);
+ task_queue_->PostTask(ToQueuedTask([this]() {
+ MutexLock lock(&mutex_);
- auto internal_send_peer = test::VideoSendStreamPeer(send_stream_);
- float pacing_factor =
- internal_send_peer.GetPacingFactorOverride().value_or(0.0f);
- float expected_pacing_factor = 1.1; // Strict pacing factor.
- VideoSendStream::Stats stats;
- SendTask(RTC_FROM_HERE, task_queue_,
- [&stats, stream = send_stream_]() { stats = stream->GetStats(); });
- if (stats.content_type == webrtc::VideoContentType::SCREENSHARE) {
- expected_pacing_factor = 1.0f; // Currently used pacing factor in ALR.
- }
-
- EXPECT_NEAR(expected_pacing_factor, pacing_factor, 1e-6);
-
- // Wait until at least kMinPacketsToSend packets to be sent, so that
- // some frames would be encoded.
- if (++packets_sent_ < kMinPacketsToSend)
- return SEND_PACKET;
-
- if (state_ != StreamState::kAfterSwitchBack) {
- // We've sent kMinPacketsToSend packets, switch the content type and move
- // move to the next state.
- // Note that we need to recreate the stream if changing content type.
- packets_sent_ = 0;
- if (encoder_config_.content_type ==
- VideoEncoderConfig::ContentType::kRealtimeVideo) {
- encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
- } else {
- encoder_config_.content_type =
- VideoEncoderConfig::ContentType::kRealtimeVideo;
+ auto internal_send_peer = test::VideoSendStreamPeer(send_stream_);
+ float pacing_factor =
+ internal_send_peer.GetPacingFactorOverride().value_or(0.0f);
+ float expected_pacing_factor = 1.1; // Strict pacing factor.
+ VideoSendStream::Stats stats = send_stream_->GetStats();
+ if (stats.content_type == webrtc::VideoContentType::SCREENSHARE) {
+ expected_pacing_factor = 1.0f; // Currently used pacing factor in ALR.
}
- switch (state_) {
- case StreamState::kBeforeSwitch:
- state_ = StreamState::kInScreenshare;
- break;
- case StreamState::kInScreenshare:
- state_ = StreamState::kAfterSwitchBack;
- break;
- case StreamState::kAfterSwitchBack:
- RTC_NOTREACHED();
- break;
- }
- content_switch_event_.Set();
- return SEND_PACKET;
- }
- observation_complete_.Set();
+ EXPECT_NEAR(expected_pacing_factor, pacing_factor, 1e-6);
+
+ // Wait until at least kMinPacketsToSend packets to be sent, so that
+ // some frames would be encoded.
+ if (++packets_sent_ < kMinPacketsToSend)
+ return;
+
+ if (state_ != StreamState::kAfterSwitchBack) {
+ // We've sent kMinPacketsToSend packets, switch the content type and
+ // move move to the next state. Note that we need to recreate the stream
+ // if changing content type.
+ packets_sent_ = 0;
+ if (encoder_config_.content_type ==
+ VideoEncoderConfig::ContentType::kRealtimeVideo) {
+ encoder_config_.content_type =
+ VideoEncoderConfig::ContentType::kScreen;
+ } else {
+ encoder_config_.content_type =
+ VideoEncoderConfig::ContentType::kRealtimeVideo;
+ }
+ switch (state_) {
+ case StreamState::kBeforeSwitch:
+ state_ = StreamState::kInScreenshare;
+ break;
+ case StreamState::kInScreenshare:
+ state_ = StreamState::kAfterSwitchBack;
+ break;
+ case StreamState::kAfterSwitchBack:
+ RTC_NOTREACHED();
+ break;
+ }
+ content_switch_event_.Set();
+ return;
+ }
+ observation_complete_.Set();
+ }));
+
return SEND_PACKET;
}