Fix SDP stream ID mismatch issue when a track's stream changes.
The example that brought up this issue was: 1. Do offer/answer exchange. 2. Later, remove the audio/video stream. 3. Add back a new stream, that contains only the audio track. 4. Do new offer/answer. The new offer didn't have the new stream ID, but code elsewhere was expecting one. As a result, the send stream is never hooked up to the audio track, and audio packets aren't sent. BUG=chromium:611708 Review-Url: https://codereview.webrtc.org/2810733003 Cr-Commit-Position: refs/heads/master@{#17709}
This commit is contained in:
parent
0c99514240
commit
2f425aa6b5
@ -252,6 +252,13 @@ const StreamParams* GetStream(const StreamParamsVec& streams,
|
||||
return found == streams.end() ? nullptr : &(*found);
|
||||
}
|
||||
|
||||
template <class Condition>
|
||||
StreamParams* GetStream(StreamParamsVec& streams, Condition condition) {
|
||||
StreamParamsVec::iterator found =
|
||||
std::find_if(streams.begin(), streams.end(), condition);
|
||||
return found == streams.end() ? nullptr : &(*found);
|
||||
}
|
||||
|
||||
inline const StreamParams* GetStreamBySsrc(const StreamParamsVec& streams,
|
||||
uint32_t ssrc) {
|
||||
return GetStream(streams,
|
||||
@ -261,6 +268,14 @@ inline const StreamParams* GetStreamBySsrc(const StreamParamsVec& streams,
|
||||
inline const StreamParams* GetStreamByIds(const StreamParamsVec& streams,
|
||||
const std::string& groupid,
|
||||
const std::string& id) {
|
||||
return GetStream(streams, [&groupid, &id](const StreamParams& sp) {
|
||||
return sp.groupid == groupid && sp.id == id;
|
||||
});
|
||||
}
|
||||
|
||||
inline StreamParams* GetStreamByIds(StreamParamsVec& streams,
|
||||
const std::string& groupid,
|
||||
const std::string& id) {
|
||||
return GetStream(streams,
|
||||
[&groupid, &id](const StreamParams& sp) {
|
||||
return sp.groupid == groupid && sp.id == id;
|
||||
|
||||
@ -448,8 +448,7 @@ static bool AddStreamParams(MediaType media_type,
|
||||
if (stream_it->type != media_type)
|
||||
continue; // Wrong media type.
|
||||
|
||||
const StreamParams* param =
|
||||
GetStreamByIds(*current_streams, "", stream_it->id);
|
||||
StreamParams* param = GetStreamByIds(*current_streams, "", stream_it->id);
|
||||
// groupid is empty for StreamParams generated using
|
||||
// MediaSessionDescriptionFactory.
|
||||
if (!param) {
|
||||
@ -500,6 +499,10 @@ static bool AddStreamParams(MediaType media_type,
|
||||
// This is necessary so that we can use the CNAME for other media types.
|
||||
current_streams->push_back(stream_param);
|
||||
} else {
|
||||
// Use existing generated SSRCs/groups, but update the sync_label if
|
||||
// necessary. This may be needed if a MediaStreamTrack was moved from one
|
||||
// MediaStream to another.
|
||||
param->sync_label = stream_it->sync_label;
|
||||
content_description->AddStream(*param);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,6 +217,10 @@ class PeerConnectionWrapper : public webrtc::PeerConnectionObserver,
|
||||
return client;
|
||||
}
|
||||
|
||||
webrtc::PeerConnectionFactoryInterface* pc_factory() const {
|
||||
return peer_connection_factory_.get();
|
||||
}
|
||||
|
||||
webrtc::PeerConnectionInterface* pc() const { return peer_connection_.get(); }
|
||||
|
||||
// If a signaling message receiver is set (via ConnectFakeSignaling), this
|
||||
@ -2773,6 +2777,38 @@ TEST_F(PeerConnectionIntegrationTest, GetSources) {
|
||||
contributing_sources[0].source_id());
|
||||
}
|
||||
|
||||
// Test that if a track is removed and added again with a different stream ID,
|
||||
// the new stream ID is successfully communicated in SDP and media continues to
|
||||
// flow end-to-end.
|
||||
TEST_F(PeerConnectionIntegrationTest, RemoveAndAddTrackWithNewStreamId) {
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
|
||||
rtc::scoped_refptr<MediaStreamInterface> stream_1 =
|
||||
caller()->pc_factory()->CreateLocalMediaStream("stream_1");
|
||||
rtc::scoped_refptr<MediaStreamInterface> stream_2 =
|
||||
caller()->pc_factory()->CreateLocalMediaStream("stream_2");
|
||||
|
||||
// Add track using stream 1, do offer/answer.
|
||||
rtc::scoped_refptr<webrtc::AudioTrackInterface> track =
|
||||
caller()->CreateLocalAudioTrack();
|
||||
rtc::scoped_refptr<webrtc::RtpSenderInterface> sender =
|
||||
caller()->pc()->AddTrack(track, {stream_1.get()});
|
||||
caller()->CreateAndSetAndSignalOffer();
|
||||
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
||||
// Wait for one audio frame to be received by the callee.
|
||||
ExpectNewFramesReceivedWithWait(0, 0, 1, 0, kMaxWaitForFramesMs);
|
||||
|
||||
// Remove the sender, and create a new one with the new stream.
|
||||
caller()->pc()->RemoveTrack(sender);
|
||||
sender = caller()->pc()->AddTrack(track, {stream_2.get()});
|
||||
caller()->CreateAndSetAndSignalOffer();
|
||||
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
||||
// Wait for additional audio frames to be received by the callee.
|
||||
ExpectNewFramesReceivedWithWait(0, 0, kDefaultExpectedAudioFrameCount, 0,
|
||||
kMaxWaitForFramesMs);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // if !defined(THREAD_SANITIZER)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user