[Unified Plan] Clear RtpSender "SSRC" when the SDP has no send streams

This fixes a crash that occurs with this sequence of events:
1. AddTrack. SetLocalDescription(CreateOffer())
2. RemoveTrack. SetLocalDescription(CreateOffer())
3. AddTrack.

When AddTrack is called again it re-uses the RtpTransceiver/
RtpSender and try to configure the underlying MediaChannel. But the
MediaChannel would DCHECK since the send stream had been destroyed
by the SLD in 2. and would not get created until SLD is called
again.

Bug: webrtc:9401
Change-Id: I4b5572886e17263aaa4ce0408663444d72e09243
Reviewed-on: https://webrtc-review.googlesource.com/83420
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Commit-Queue: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23605}
This commit is contained in:
Steve Anton 2018-06-13 11:32:27 -07:00 committed by Commit Bot
parent f7d7e90c5e
commit 60b6c1dfa9
2 changed files with 42 additions and 0 deletions

View File

@ -2113,6 +2113,12 @@ RTCError PeerConnection::ApplyLocalDescription(
streams[0].stream_ids());
transceiver->internal()->sender_internal()->SetSsrc(
streams[0].first_ssrc());
} else {
// 0 is a special value meaning "this sender has no associated send
// stream". Need to call this so the sender won't attempt to configure
// a no longer existing stream and run into DCHECKs in the lower
// layers.
transceiver->internal()->sender_internal()->SetSsrc(0);
}
}
} else {

View File

@ -1219,6 +1219,42 @@ TEST_F(PeerConnectionRtpTestUnifiedPlan,
EXPECT_FALSE(caller->observer()->negotiation_needed());
}
// Test that setting offers that add/remove/add a track repeatedly without
// setting the appropriate answer in between works.
// These are regression tests for bugs.webrtc.org/9401
TEST_F(PeerConnectionRtpTestUnifiedPlan, AddRemoveAddTrackOffersWorksAudio) {
auto caller = CreatePeerConnection();
auto sender1 = caller->AddAudioTrack("audio1");
ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
caller->pc()->RemoveTrack(sender1);
ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
// This will re-use the transceiver created by the first AddTrack.
auto sender2 = caller->AddAudioTrack("audio2");
ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
EXPECT_EQ(1u, caller->pc()->GetTransceivers().size());
EXPECT_EQ(sender1, sender2);
}
TEST_F(PeerConnectionRtpTestUnifiedPlan, AddRemoveAddTrackOffersWorksVideo) {
auto caller = CreatePeerConnection();
auto sender1 = caller->AddVideoTrack("video1");
ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
caller->pc()->RemoveTrack(sender1);
ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
// This will re-use the transceiver created by the first AddTrack.
auto sender2 = caller->AddVideoTrack("video2");
ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
EXPECT_EQ(1u, caller->pc()->GetTransceivers().size());
EXPECT_EQ(sender1, sender2);
}
// Test that OnRenegotiationNeeded is fired if SetDirection is called on an
// active RtpTransceiver with a new direction.
TEST_F(PeerConnectionRtpTestUnifiedPlan,