diff --git a/media/webrtc/signaling/gtest/jsep_session_unittest.cpp b/media/webrtc/signaling/gtest/jsep_session_unittest.cpp index e3d85d1efb40..b1d00f3124c1 100644 --- a/media/webrtc/signaling/gtest/jsep_session_unittest.cpp +++ b/media/webrtc/signaling/gtest/jsep_session_unittest.cpp @@ -101,12 +101,12 @@ class JsepSessionTest : public JsepSessionTestBase, } void CheckTransceiverInvariants( - const std::vector>& oldTransceivers, - const std::vector>& newTransceivers) { + const std::map>& oldTransceivers, + const std::map>& newTransceivers) { ASSERT_LE(oldTransceivers.size(), newTransceivers.size()); std::set levels; - for (const RefPtr& newTransceiver : newTransceivers) { + for (const auto& [id, newTransceiver] : newTransceivers) { if (newTransceiver->HasLevel()) { ASSERT_FALSE(levels.count(newTransceiver->GetLevel())) << "Two new transceivers are mapped to level " @@ -124,7 +124,7 @@ class JsepSessionTest : public JsepSessionTestBase, "transceivers."; } - for (const RefPtr& oldTransceiver : oldTransceivers) { + for (const auto& [id, oldTransceiver] : oldTransceivers) { if (oldTransceiver->HasLevel()) { ASSERT_TRUE(levels.count(oldTransceiver->GetLevel())) << "Level " << oldTransceiver->GetLevel() @@ -136,18 +136,17 @@ class JsepSessionTest : public JsepSessionTestBase, } } - std::vector> DeepCopy( - const std::vector>& transceivers) { - std::vector> copy; - copy.reserve(transceivers.size()); - for (const RefPtr& transceiver : transceivers) { - copy.push_back(new JsepTransceiver(*transceiver)); + std::map> DeepCopy( + const std::map>& transceivers) { + std::map> copy; + for (const auto& [id, transceiver] : transceivers) { + copy[id] = new JsepTransceiver(*transceiver); } return copy; } std::string CreateOffer(const Maybe& options = Nothing()) { - std::vector> transceiversBefore = + std::map> transceiversBefore = DeepCopy(mSessionOff->GetTransceivers()); JsepOfferOptions defaultOptions; const JsepOfferOptions& optionsRef = options ? *options : defaultOptions; @@ -302,35 +301,36 @@ class JsepSessionTest : public JsepSessionTestBase, for (auto type : mediatypes) { ASSERT_TRUE(uuid_gen.Generate(&track_id)); - std::vector>& transceivers( - side.GetTransceivers()); - size_t i = transceivers.size(); + RefPtr suitableTransceiver; + size_t i; if (magic == ADDTRACK_MAGIC) { - for (i = 0; i < transceivers.size(); ++i) { - if (transceivers[i]->mSendTrack.GetMediaType() != type) { + for (auto& [id, transceiver] : side.GetTransceivers()) { + if (transceiver->mSendTrack.GetMediaType() != type) { continue; } - if (IsNull(transceivers[i]->mSendTrack) || - transceivers[i]->GetMediaType() == - SdpMediaSection::kApplication) { + if (IsNull(transceiver->mSendTrack) || + transceiver->GetMediaType() == SdpMediaSection::kApplication) { + suitableTransceiver = transceiver; + i = id; break; } } } - if (i == transceivers.size()) { - side.AddTransceiver(new JsepTransceiver(type)); - MOZ_ASSERT(i < transceivers.size()); + if (!suitableTransceiver) { + suitableTransceiver = new JsepTransceiver(type); + side.AddTransceiver(suitableTransceiver); + i = side.GetTransceivers().rbegin()->first; } std::cerr << "Updating send track for transceiver " << i << std::endl; if (magic == ADDTRACK_MAGIC) { - transceivers[i]->SetAddTrackMagic(); + suitableTransceiver->SetAddTrackMagic(); } - transceivers[i]->mJsDirection |= + suitableTransceiver->mJsDirection |= SdpDirectionAttribute::Direction::kSendonly; - transceivers[i]->mSendTrack.UpdateStreamIds( + suitableTransceiver->mSendTrack.UpdateStreamIds( std::vector(1, stream_id)); } } @@ -351,7 +351,7 @@ class JsepSessionTest : public JsepSessionTestBase, std::vector GetLocalTracks(const JsepSession& session) const { std::vector result; - for (const auto& transceiver : session.GetTransceivers()) { + for (const auto& [id, transceiver] : session.GetTransceivers()) { if (!IsNull(transceiver->mSendTrack)) { result.push_back(transceiver->mSendTrack); } @@ -361,7 +361,7 @@ class JsepSessionTest : public JsepSessionTestBase, std::vector GetRemoteTracks(const JsepSession& session) const { std::vector result; - for (const auto& transceiver : session.GetTransceivers()) { + for (const auto& [id, transceiver] : session.GetTransceivers()) { if (!IsNull(transceiver->mRecvTrack)) { result.push_back(transceiver->mRecvTrack); } @@ -370,7 +370,7 @@ class JsepSessionTest : public JsepSessionTestBase, } JsepTransceiver* GetDatachannelTransceiver(JsepSession& side) { - for (const auto& transceiver : side.GetTransceivers()) { + for (const auto& [id, transceiver] : side.GetTransceivers()) { if (transceiver->mSendTrack.GetMediaType() == SdpMediaSection::MediaType::kApplication) { return transceiver.get(); @@ -381,7 +381,7 @@ class JsepSessionTest : public JsepSessionTestBase, } JsepTransceiver* GetNegotiatedTransceiver(JsepSession& side, size_t index) { - for (RefPtr& transceiver : side.GetTransceivers()) { + for (const auto& [id, transceiver] : side.GetTransceivers()) { if (transceiver->mSendTrack.GetNegotiatedDetails() || transceiver->mRecvTrack.GetNegotiatedDetails()) { if (index) { @@ -397,8 +397,9 @@ class JsepSessionTest : public JsepSessionTestBase, } JsepTransceiver* GetTransceiverByLevel( - const std::vector>& transceivers, size_t level) { - for (auto& transceiver : transceivers) { + const std::map>& transceivers, + size_t level) { + for (const auto& [id, transceiver] : transceivers) { if (transceiver->HasLevel() && transceiver->GetLevel() == level) { return transceiver.get(); } @@ -454,7 +455,7 @@ class JsepSessionTest : public JsepSessionTestBase, JsepTrack GetTrack(JsepSessionImpl& side, SdpMediaSection::MediaType type, size_t index) const { - for (const auto& transceiver : side.GetTransceivers()) { + for (const auto& [id, transceiver] : side.GetTransceivers()) { if (IsNull(transceiver->mSendTrack) || transceiver->mSendTrack.GetMediaType() != type) { continue; @@ -647,16 +648,19 @@ class JsepSessionTest : public JsepSessionTestBase, return true; } - bool Equals(const std::vector>& t1, - const std::vector>& t2) const { + bool Equals(const std::map>& t1, + const std::map>& t2) const { if (t1.size() != t2.size()) { std::cerr << "Size differs: t1.size = " << t1.size() << ", t2.size = " << t2.size() << std::endl; return false; } - for (size_t i = 0; i < t1.size(); ++i) { - if (!Equals(*t1[i], *t2[i])) { + for (const auto& [id, transceiver] : t1) { + if (!t2.count(id)) { + return false; + } + if (!Equals(*transceiver, *t2.at(id))) { return false; } } @@ -732,7 +736,7 @@ class JsepSessionTest : public JsepSessionTestBase, } std::string CreateAnswer() { - std::vector> transceiversBefore = + std::map> transceiversBefore = DeepCopy(mSessionAns->GetTransceivers()); JsepAnswerOptions options; @@ -768,7 +772,7 @@ class JsepSessionTest : public JsepSessionTestBase, void SetLocalOffer(const std::string& offer, uint32_t checkFlags = ALL_CHECKS) { - std::vector> transceiversBefore = + std::map> transceiversBefore = DeepCopy(mSessionOff->GetTransceivers()); JsepSession::Result result = @@ -784,7 +788,7 @@ class JsepSessionTest : public JsepSessionTestBase, if (checkFlags & CHECK_TRACKS) { // This assumes no recvonly or inactive transceivers. ASSERT_EQ(types.size(), mSessionOff->GetTransceivers().size()); - for (const auto& transceiver : mSessionOff->GetTransceivers()) { + for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) { if (!transceiver->HasLevel()) { continue; } @@ -808,7 +812,7 @@ class JsepSessionTest : public JsepSessionTestBase, void SetRemoteOffer(const std::string& offer, uint32_t checkFlags = ALL_CHECKS) { - std::vector> transceiversBefore = + std::map> transceiversBefore = DeepCopy(mSessionAns->GetTransceivers()); JsepSession::Result result = @@ -824,7 +828,7 @@ class JsepSessionTest : public JsepSessionTestBase, if (checkFlags & CHECK_TRACKS) { // This assumes no recvonly or inactive transceivers. ASSERT_EQ(types.size(), mSessionAns->GetTransceivers().size()); - for (const auto& transceiver : mSessionAns->GetTransceivers()) { + for (const auto& [id, transceiver] : mSessionAns->GetTransceivers()) { if (!transceiver->HasLevel()) { continue; } @@ -845,7 +849,7 @@ class JsepSessionTest : public JsepSessionTestBase, void SetLocalAnswer(const std::string& answer, uint32_t checkFlags = ALL_CHECKS) { - std::vector> transceiversBefore = + std::map> transceiversBefore = DeepCopy(mSessionAns->GetTransceivers()); JsepSession::Result result = @@ -860,7 +864,7 @@ class JsepSessionTest : public JsepSessionTestBase, if (checkFlags & CHECK_TRACKS) { // Verify that the right stuff is in the tracks. ASSERT_EQ(types.size(), mSessionAns->GetTransceivers().size()); - for (const auto& transceiver : mSessionAns->GetTransceivers()) { + for (const auto& [id, transceiver] : mSessionAns->GetTransceivers()) { if (!transceiver->HasLevel()) { continue; } @@ -892,7 +896,7 @@ class JsepSessionTest : public JsepSessionTestBase, void SetRemoteAnswer(const std::string& answer, uint32_t checkFlags = ALL_CHECKS) { - std::vector> transceiversBefore = + std::map> transceiversBefore = DeepCopy(mSessionOff->GetTransceivers()); JsepSession::Result result = @@ -907,7 +911,7 @@ class JsepSessionTest : public JsepSessionTestBase, if (checkFlags & CHECK_TRACKS) { // Verify that the right stuff is in the tracks. ASSERT_EQ(types.size(), mSessionOff->GetTransceivers().size()); - for (const auto& transceiver : mSessionOff->GetTransceivers()) { + for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) { if (!transceiver->HasLevel()) { continue; } @@ -935,7 +939,7 @@ class JsepSessionTest : public JsepSessionTestBase, } std::string GetTransportId(const JsepSession& session, size_t level) { - for (const auto& transceiver : session.GetTransceivers()) { + for (const auto& [id, transceiver] : session.GetTransceivers()) { if (transceiver->HasLevel() && transceiver->GetLevel() == level) { return transceiver->mTransport.mTransportId; } @@ -950,7 +954,7 @@ class JsepSessionTest : public JsepSessionTestBase, CandidateSet() {} void Gather(JsepSession& session, ComponentType maxComponent = RTCP) { - for (const auto& transceiver : session.GetTransceivers()) { + for (const auto& [id, transceiver] : session.GetTransceivers()) { if (transceiver->HasOwnTransport()) { Gather(session, transceiver->mTransport.mTransportId, RTP); if (transceiver->mTransport.mComponents > 1) { @@ -1182,7 +1186,7 @@ class JsepSessionTest : public JsepSessionTestBase, void CheckTransceiversAreBundled(const JsepSession& session, const std::string& context) { - for (const auto& transceiver : session.GetTransceivers()) { + for (const auto& [id, transceiver] : session.GetTransceivers()) { ASSERT_TRUE(transceiver->HasBundleLevel()) << context; ASSERT_EQ(0U, transceiver->BundleLevel()) << context; @@ -1330,7 +1334,7 @@ class JsepSessionTest : public JsepSessionTestBase, } void DumpTransceivers(const JsepSessionImpl& session) { - for (const auto& transceiver : session.GetTransceivers()) { + for (const auto& [id, transceiver] : session.GetTransceivers()) { std::cerr << "Transceiver "; if (transceiver->HasLevel()) { std::cerr << transceiver->GetLevel() << std::endl; @@ -1567,9 +1571,9 @@ TEST_P(JsepSessionTest, RenegotiationNoChange) { ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass); ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); std::string reoffer = CreateOffer(); @@ -1628,6 +1632,14 @@ TEST_P(JsepSessionTest, DISABLED_RenegotiationSwappedRolesNoChange) { ASSERT_TRUE(Equals(answererTransceivers, newOffererTransceivers)); } +static void RemoveLastN( + std::map>& aTransceivers, size_t aNum) { + while (aNum--) { + // erase doesn't take reverse_iterator :( + aTransceivers.erase(--aTransceivers.end()); + } +} + TEST_P(JsepSessionTest, RenegotiationOffererAddsTrack) { AddTracks(*mSessionOff); AddTracks(*mSessionAns); @@ -1637,9 +1649,9 @@ TEST_P(JsepSessionTest, RenegotiationOffererAddsTrack) { ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass); ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); std::vector extraTypes; @@ -1657,11 +1669,11 @@ TEST_P(JsepSessionTest, RenegotiationOffererAddsTrack) { auto newAnswererTransceivers = mSessionAns->GetTransceivers(); ASSERT_LE(2U, newOffererTransceivers.size()); - newOffererTransceivers.resize(newOffererTransceivers.size() - 2); + RemoveLastN(newOffererTransceivers, 2); ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers)); ASSERT_LE(2U, newAnswererTransceivers.size()); - newAnswererTransceivers.resize(newAnswererTransceivers.size() - 2); + RemoveLastN(newAnswererTransceivers, 2); ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers)); } @@ -1674,9 +1686,9 @@ TEST_P(JsepSessionTest, RenegotiationAnswererAddsTrack) { ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass); ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); std::vector extraTypes; @@ -1706,11 +1718,11 @@ TEST_P(JsepSessionTest, RenegotiationAnswererAddsTrack) { auto newAnswererTransceivers = mSessionAns->GetTransceivers(); ASSERT_LE(2U, newOffererTransceivers.size()); - newOffererTransceivers.resize(newOffererTransceivers.size() - 2); + RemoveLastN(newOffererTransceivers, 2); ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers)); ASSERT_LE(2U, newAnswererTransceivers.size()); - newAnswererTransceivers.resize(newAnswererTransceivers.size() - 2); + RemoveLastN(newAnswererTransceivers, 2); ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers)); } @@ -1723,9 +1735,9 @@ TEST_P(JsepSessionTest, RenegotiationBothAddTrack) { ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass); ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); std::vector extraTypes; @@ -1744,11 +1756,11 @@ TEST_P(JsepSessionTest, RenegotiationBothAddTrack) { auto newAnswererTransceivers = mSessionAns->GetTransceivers(); ASSERT_LE(2U, newOffererTransceivers.size()); - newOffererTransceivers.resize(newOffererTransceivers.size() - 2); + RemoveLastN(newOffererTransceivers, 2); ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers)); ASSERT_LE(2U, newAnswererTransceivers.size()); - newAnswererTransceivers.resize(newAnswererTransceivers.size() - 2); + RemoveLastN(newAnswererTransceivers, 2); ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers)); } @@ -1886,14 +1898,15 @@ TEST_P(JsepSessionTest, RenegotiationOffererStopsTransceiver) { OfferAnswer(); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); + auto lastTransceiver = mSessionOff->GetTransceivers().rbegin()->second; // Avoid bundle transport side effects; don't stop the BUNDLE-tag! - mSessionOff->GetTransceivers().back()->Stop(); - JsepTrack removedTrack(mSessionOff->GetTransceivers().back()->mSendTrack); + lastTransceiver->Stop(); + JsepTrack removedTrack(lastTransceiver->mSendTrack); OfferAnswer(CHECK_SUCCESS); @@ -1915,17 +1928,15 @@ TEST_P(JsepSessionTest, RenegotiationOffererStopsTransceiver) { ASSERT_EQ(origOffererTransceivers.size(), newOffererTransceivers.size()); - ASSERT_FALSE(origOffererTransceivers.back()->IsStopped()); - ASSERT_TRUE(newOffererTransceivers.back()->IsStopped()); + ASSERT_FALSE(origOffererTransceivers.rbegin()->second->IsStopped()); + ASSERT_TRUE(newOffererTransceivers.rbegin()->second->IsStopped()); - ASSERT_FALSE(origOffererTransceivers.back()->IsStopped()); - ASSERT_TRUE(newOffererTransceivers.back()->IsStopped()); - ASSERT_FALSE(origAnswererTransceivers.back()->IsStopped()); - ASSERT_TRUE(newAnswererTransceivers.back()->IsStopped()); - origOffererTransceivers.pop_back(); // Ignore this one - newOffererTransceivers.pop_back(); // Ignore this one - origAnswererTransceivers.pop_back(); // Ignore this one - newAnswererTransceivers.pop_back(); // Ignore this one + ASSERT_FALSE(origAnswererTransceivers.rbegin()->second->IsStopped()); + ASSERT_TRUE(newAnswererTransceivers.rbegin()->second->IsStopped()); + RemoveLastN(origOffererTransceivers, 1); // Ignore this one + RemoveLastN(newOffererTransceivers, 1); // Ignore this one + RemoveLastN(origAnswererTransceivers, 1); // Ignore this one + RemoveLastN(newAnswererTransceivers, 1); // Ignore this one ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers)); ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers)); @@ -1940,14 +1951,15 @@ TEST_P(JsepSessionTest, RenegotiationAnswererStopsTransceiver) { OfferAnswer(); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); // Avoid bundle transport side effects; don't stop the BUNDLE-tag! - mSessionAns->GetTransceivers().back()->Stop(); - JsepTrack removedTrack(mSessionAns->GetTransceivers().back()->mSendTrack); + mSessionAns->GetTransceivers().rbegin()->second->Stop(); + JsepTrack removedTrack( + mSessionAns->GetTransceivers().rbegin()->second->mSendTrack); OfferAnswer(CHECK_SUCCESS); @@ -1970,14 +1982,14 @@ TEST_P(JsepSessionTest, RenegotiationAnswererStopsTransceiver) { ASSERT_EQ(origOffererTransceivers.size(), newOffererTransceivers.size()); - ASSERT_FALSE(origOffererTransceivers.back()->IsStopped()); - ASSERT_TRUE(newOffererTransceivers.back()->IsStopped()); - ASSERT_FALSE(origAnswererTransceivers.back()->IsStopped()); - ASSERT_TRUE(newAnswererTransceivers.back()->IsStopped()); - origOffererTransceivers.pop_back(); // Ignore this one - newOffererTransceivers.pop_back(); // Ignore this one - origAnswererTransceivers.pop_back(); // Ignore this one - newAnswererTransceivers.pop_back(); // Ignore this one + ASSERT_FALSE(origOffererTransceivers.rbegin()->second->IsStopped()); + ASSERT_TRUE(newOffererTransceivers.rbegin()->second->IsStopped()); + ASSERT_FALSE(origAnswererTransceivers.rbegin()->second->IsStopped()); + ASSERT_TRUE(newAnswererTransceivers.rbegin()->second->IsStopped()); + RemoveLastN(origOffererTransceivers, 1); // Ignore this one + RemoveLastN(newOffererTransceivers, 1); // Ignore this one + RemoveLastN(origAnswererTransceivers, 1); // Ignore this one + RemoveLastN(newAnswererTransceivers, 1); // Ignore this one ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers)); ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers)); @@ -1992,18 +2004,18 @@ TEST_P(JsepSessionTest, RenegotiationBothStopSameTransceiver) { OfferAnswer(); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); // Avoid bundle transport side effects; don't stop the BUNDLE-tag! - mSessionOff->GetTransceivers().back()->Stop(); + mSessionOff->GetTransceivers().rbegin()->second->Stop(); JsepTrack removedTrackOffer( - mSessionOff->GetTransceivers().back()->mSendTrack); - mSessionAns->GetTransceivers().back()->Stop(); + mSessionOff->GetTransceivers().rbegin()->second->mSendTrack); + mSessionAns->GetTransceivers().rbegin()->second->Stop(); JsepTrack removedTrackAnswer( - mSessionAns->GetTransceivers().back()->mSendTrack); + mSessionAns->GetTransceivers().rbegin()->second->mSendTrack); OfferAnswer(CHECK_SUCCESS); @@ -2025,14 +2037,14 @@ TEST_P(JsepSessionTest, RenegotiationBothStopSameTransceiver) { ASSERT_EQ(origOffererTransceivers.size(), newOffererTransceivers.size()); - ASSERT_FALSE(origOffererTransceivers.back()->IsStopped()); - ASSERT_TRUE(newOffererTransceivers.back()->IsStopped()); - ASSERT_FALSE(origAnswererTransceivers.back()->IsStopped()); - ASSERT_TRUE(newAnswererTransceivers.back()->IsStopped()); - origOffererTransceivers.pop_back(); // Ignore this one - newOffererTransceivers.pop_back(); // Ignore this one - origAnswererTransceivers.pop_back(); // Ignore this one - newAnswererTransceivers.pop_back(); // Ignore this one + ASSERT_FALSE(origOffererTransceivers.rbegin()->second->IsStopped()); + ASSERT_TRUE(newOffererTransceivers.rbegin()->second->IsStopped()); + ASSERT_FALSE(origAnswererTransceivers.rbegin()->second->IsStopped()); + ASSERT_TRUE(newAnswererTransceivers.rbegin()->second->IsStopped()); + RemoveLastN(origOffererTransceivers, 1); // Ignore this one + RemoveLastN(newOffererTransceivers, 1); // Ignore this one + RemoveLastN(origAnswererTransceivers, 1); // Ignore this one + RemoveLastN(newAnswererTransceivers, 1); // Ignore this one ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers)); ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers)); @@ -2050,18 +2062,18 @@ TEST_P(JsepSessionTest, RenegotiationBothStopTransceiverThenAddTrack) { OfferAnswer(); // Avoid bundle transport side effects; don't stop the BUNDLE-tag! - mSessionOff->GetTransceivers().back()->Stop(); + mSessionOff->GetTransceivers().rbegin()->second->Stop(); JsepTrack removedTrackOffer( - mSessionOff->GetTransceivers().back()->mSendTrack); - mSessionOff->GetTransceivers().back()->Stop(); + mSessionOff->GetTransceivers().rbegin()->second->mSendTrack); + mSessionOff->GetTransceivers().rbegin()->second->Stop(); JsepTrack removedTrackAnswer( - mSessionOff->GetTransceivers().back()->mSendTrack); + mSessionOff->GetTransceivers().rbegin()->second->mSendTrack); OfferAnswer(CHECK_SUCCESS); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); std::vector extraTypes; @@ -2080,11 +2092,11 @@ TEST_P(JsepSessionTest, RenegotiationBothStopTransceiverThenAddTrack) { newAnswererTransceivers.size()); // Ensure that the m-section was re-used; no gaps - ASSERT_EQ(origOffererTransceivers.back()->GetLevel(), - newOffererTransceivers.back()->GetLevel()); + ASSERT_EQ(origOffererTransceivers.rbegin()->second->GetLevel(), + newOffererTransceivers.rbegin()->second->GetLevel()); - ASSERT_EQ(origAnswererTransceivers.back()->GetLevel(), - newAnswererTransceivers.back()->GetLevel()); + ASSERT_EQ(origAnswererTransceivers.rbegin()->second->GetLevel(), + newAnswererTransceivers.rbegin()->second->GetLevel()); } TEST_P(JsepSessionTest, RenegotiationBothStopTransceiverDifferentMsection) { @@ -2167,9 +2179,9 @@ TEST_P(JsepSessionTest, RenegotiationAutoAssignedMsidIsStable) { SetRemoteAnswer(answer, CHECK_SUCCESS); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); ASSERT_EQ(origOffererTransceivers.size(), origAnswererTransceivers.size()); @@ -2204,7 +2216,7 @@ TEST_P(JsepSessionTest, RenegotiationOffererDisablesTelephoneEvent) { // check all the audio tracks to make sure they have 2 codecs (109 and 101), // and dtmf is enabled on all audio tracks std::vector tracks; - for (const auto& transceiver : mSessionOff->GetTransceivers()) { + for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) { tracks.push_back(transceiver->mSendTrack); tracks.push_back(transceiver->mRecvTrack); } @@ -2243,7 +2255,7 @@ TEST_P(JsepSessionTest, RenegotiationOffererDisablesTelephoneEvent) { // check all the audio tracks to make sure they have 1 codec (109), // and dtmf is disabled on all audio tracks tracks.clear(); - for (const auto& transceiver : mSessionOff->GetTransceivers()) { + for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) { tracks.push_back(transceiver->mSendTrack); tracks.push_back(transceiver->mRecvTrack); } @@ -2281,9 +2293,9 @@ TEST_P(JsepSessionTest, RenegotiationAnswererEnablesMsid) { SetRemoteAnswer(answer, CHECK_SUCCESS); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); offer = CreateOffer(); @@ -2327,9 +2339,9 @@ TEST_P(JsepSessionTest, RenegotiationAnswererDisablesMsid) { SetLocalAnswer(answer); SetRemoteAnswer(answer, CHECK_SUCCESS); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); offer = CreateOffer(); @@ -2387,9 +2399,9 @@ TEST_P(JsepSessionTest, RenegotiationOffererEnablesBundle) { SetLocalAnswer(answer); SetRemoteAnswer(answer); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); OfferAnswer(); @@ -2434,9 +2446,9 @@ TEST_P(JsepSessionTest, RenegotiationOffererDisablesBundleTransport) { GetTransceiverByLevel(*mSessionOff, 0)->Stop(); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); OfferAnswer(CHECK_SUCCESS); @@ -2485,9 +2497,9 @@ TEST_P(JsepSessionTest, RenegotiationAnswererDisablesBundleTransport) { OfferAnswer(); - std::vector> origOffererTransceivers = + std::map> origOffererTransceivers = DeepCopy(mSessionOff->GetTransceivers()); - std::vector> origAnswererTransceivers = + std::map> origAnswererTransceivers = DeepCopy(mSessionAns->GetTransceivers()); GetTransceiverByLevel(*mSessionAns, 0)->Stop(); @@ -3038,10 +3050,10 @@ TEST_F(JsepSessionTest, OfferAnswerRecvOnlyLines) { SetLocalAnswer(answer, CHECK_SUCCESS); SetRemoteAnswer(answer, CHECK_SUCCESS); - std::vector> transceivers( + std::map> transceivers( mSessionOff->GetTransceivers()); ASSERT_EQ(3U, transceivers.size()); - for (const auto& transceiver : transceivers) { + for (const auto& [id, transceiver] : transceivers) { auto ssrcs = parsedOffer->GetMediaSection(transceiver->GetLevel()) .GetAttributeList() .GetSsrc() @@ -4799,7 +4811,7 @@ TEST_P(JsepSessionTest, TestRejectOfferRollback) { ASSERT_FALSE( mSessionAns->SetRemoteDescription(kJsepSdpRollback, "").mError.isSome()); ASSERT_EQ(kJsepStateStable, mSessionAns->GetState()); - for (const auto& transceiver : mSessionAns->GetTransceivers()) { + for (const auto& [id, transceiver] : mSessionAns->GetTransceivers()) { ASSERT_EQ(0U, transceiver->mRecvTrack.GetStreamIds().size()); } @@ -4852,7 +4864,7 @@ TEST_P(JsepSessionTest, TestInvalidRollback) { size_t GetActiveTransportCount(const JsepSession& session) { size_t activeTransportCount = 0; - for (const auto& transceiver : session.GetTransceivers()) { + for (const auto& [id, transceiver] : session.GetTransceivers()) { if (!transceiver->HasBundleLevel() || (transceiver->BundleLevel() == transceiver->GetLevel())) { activeTransportCount += transceiver->mTransport.mComponents; @@ -6529,12 +6541,12 @@ TEST_F(JsepSessionTest, ComplicatedRemoteRollback) { // Third audio transceiver should also be gone. // Fourth audio transceiver, created after SetRemote - ASSERT_FALSE(mSessionAns->GetTransceivers()[3]->HasLevel()); - ASSERT_FALSE(mSessionAns->GetTransceivers()[3]->IsStopped()); - ASSERT_FALSE(mSessionAns->GetTransceivers()[3]->IsAssociated()); - ASSERT_FALSE(mSessionAns->GetTransceivers()[3]->HasAddTrackMagic()); + ASSERT_FALSE(mSessionAns->GetTransceivers()[5]->HasLevel()); + ASSERT_FALSE(mSessionAns->GetTransceivers()[5]->IsStopped()); + ASSERT_FALSE(mSessionAns->GetTransceivers()[5]->IsAssociated()); + ASSERT_FALSE(mSessionAns->GetTransceivers()[5]->HasAddTrackMagic()); ASSERT_TRUE( - mSessionAns->GetTransceivers()[3]->mSendTrack.GetStreamIds().empty()); + mSessionAns->GetTransceivers()[5]->mSendTrack.GetStreamIds().empty()); } TEST_F(JsepSessionTest, LocalRollback) { diff --git a/media/webrtc/signaling/src/jsep/JsepSession.h b/media/webrtc/signaling/src/jsep/JsepSession.h index 93c94059a0d2..869be00fa3dc 100644 --- a/media/webrtc/signaling/src/jsep/JsepSession.h +++ b/media/webrtc/signaling/src/jsep/JsepSession.h @@ -5,6 +5,7 @@ #ifndef _JSEPSESSION_H_ #define _JSEPSESSION_H_ +#include #include #include #include "mozilla/Attributes.h" @@ -106,7 +107,7 @@ class JsepSession { template void ForEachCodec(UnaryFunction& function) { std::for_each(Codecs().begin(), Codecs().end(), function); - for (auto& transceiver : GetTransceivers()) { + for (auto& [id, transceiver] : GetTransceivers()) { transceiver->mSendTrack.ForEachCodec(function); transceiver->mRecvTrack.ForEachCodec(function); } @@ -115,15 +116,15 @@ class JsepSession { template void SortCodecs(BinaryPredicate& sorter) { std::stable_sort(Codecs().begin(), Codecs().end(), sorter); - for (auto& transceiver : GetTransceivers()) { + for (auto& [id, transceiver] : GetTransceivers()) { transceiver->mSendTrack.SortCodecs(sorter); transceiver->mRecvTrack.SortCodecs(sorter); } } - virtual const std::vector>& GetTransceivers() + virtual const std::map>& GetTransceivers() const = 0; - virtual std::vector>& GetTransceivers() = 0; + virtual std::map>& GetTransceivers() = 0; virtual nsresult AddTransceiver(RefPtr transceiver) = 0; class Result { @@ -190,7 +191,7 @@ class JsepSession { memset(receiving, 0, sizeof(receiving)); memset(sending, 0, sizeof(sending)); - for (const auto& transceiver : GetTransceivers()) { + for (const auto& [id, transceiver] : GetTransceivers()) { if (transceiver->mRecvTrack.GetActive() || transceiver->GetMediaType() == SdpMediaSection::kApplication) { receiving[transceiver->mRecvTrack.GetMediaType()]++; diff --git a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp index b193f1faa14e..a2b5a5079a61 100644 --- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp +++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp @@ -113,7 +113,7 @@ nsresult JsepSessionImpl::AddTransceiver(RefPtr transceiver) { // of asserting. transceiver->mJsDirection = SdpDirectionAttribute::kSendrecv; #ifdef DEBUG - for (auto& transceiver : mTransceivers) { + for (const auto& [id, transceiver] : mTransceivers) { MOZ_ASSERT(transceiver->GetMediaType() != SdpMediaSection::kApplication); } #endif @@ -123,7 +123,7 @@ nsresult JsepSessionImpl::AddTransceiver(RefPtr transceiver) { transceiver->mRecvTrack.PopulateCodecs(mSupportedCodecs); // We do not set mLevel yet, we do that either on createOffer, or setRemote - mTransceivers.push_back(transceiver); + mTransceivers[mTransceiverIdCounter++] = transceiver; return NS_OK; } @@ -690,8 +690,8 @@ JsepSession::Result JsepSessionImpl::SetLocalDescription( if (type == kJsepSdpOffer) { // Save in case we need to rollback mOldTransceivers.clear(); - for (const auto& transceiver : mTransceivers) { - mOldTransceivers.push_back(new JsepTransceiver(*transceiver)); + for (const auto& [id, transceiver] : mTransceivers) { + mOldTransceivers[id] = new JsepTransceiver(*transceiver); } } @@ -862,8 +862,8 @@ JsepSession::Result JsepSessionImpl::SetRemoteDescription( // Save in case we need to rollback. if (type == kJsepSdpOffer) { mOldTransceivers.clear(); - for (const auto& transceiver : mTransceivers) { - mOldTransceivers.push_back(new JsepTransceiver(*transceiver)); + for (const auto& [id, transceiver] : mTransceivers) { + mOldTransceivers[id] = new JsepTransceiver(*transceiver); if (!transceiver->IsNegotiated()) { // We chose a level for this transceiver, but never negotiated it. // Discard this state. @@ -958,7 +958,7 @@ nsresult JsepSessionImpl::HandleNegotiatedSession( } std::vector remoteTracks; - for (const RefPtr& transceiver : mTransceivers) { + for (const auto& [id, transceiver] : mTransceivers) { remoteTracks.push_back(&transceiver->mRecvTrack); } JsepTrack::SetUniquePayloadTypes(remoteTracks); @@ -1331,7 +1331,7 @@ nsresult JsepSessionImpl::SetRemoteDescriptionAnswer(JsepSdpType type, } JsepTransceiver* JsepSessionImpl::GetTransceiverForLevel(size_t level) { - for (RefPtr& transceiver : mTransceivers) { + for (auto& [id, transceiver] : mTransceivers) { if (transceiver->HasLevel() && (transceiver->GetLevel() == level)) { return transceiver.get(); } @@ -1341,7 +1341,7 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForLevel(size_t level) { } JsepTransceiver* JsepSessionImpl::GetTransceiverForMid(const std::string& mid) { - for (RefPtr& transceiver : mTransceivers) { + for (auto& [id, transceiver] : mTransceivers) { if (transceiver->IsAssociated() && (transceiver->GetMid() == mid)) { return transceiver.get(); } @@ -1371,7 +1371,7 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForLocal(size_t level) { // There is no transceiver for |level| right now. // Look for an RTP transceiver - for (RefPtr& transceiver : mTransceivers) { + for (auto& [id, transceiver] : mTransceivers) { if (transceiver->GetMediaType() != SdpMediaSection::kApplication && !transceiver->IsStopped() && !transceiver->HasLevel()) { transceiver->SetLevel(level); @@ -1380,7 +1380,7 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForLocal(size_t level) { } // Ok, look for a datachannel - for (RefPtr& transceiver : mTransceivers) { + for (auto& [id, transceiver] : mTransceivers) { if (!transceiver->IsStopped() && !transceiver->HasLevel()) { transceiver->SetLevel(level); return transceiver.get(); @@ -1417,12 +1417,12 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForRemote( newTransceiver->SetCreatedBySetRemote(); nsresult rv = AddTransceiver(newTransceiver); NS_ENSURE_SUCCESS(rv, nullptr); - return mTransceivers.back().get(); + return newTransceiver.get(); } JsepTransceiver* JsepSessionImpl::GetTransceiverWithTransport( const std::string& transportId) { - for (const auto& transceiver : mTransceivers) { + for (const auto& [id, transceiver] : mTransceivers) { if (transceiver->HasOwnTransport() && (transceiver->mTransport.mTransportId == transportId)) { MOZ_ASSERT(transceiver->HasLevel(), @@ -1485,7 +1485,7 @@ nsresult JsepSessionImpl::UpdateTransceiversFromRemoteDescription( JsepTransceiver* JsepSessionImpl::FindUnassociatedTransceiver( SdpMediaSection::MediaType type, bool magic) { // Look through transceivers that are not mapped to an m-section - for (RefPtr& transceiver : mTransceivers) { + for (auto& [id, transceiver] : mTransceivers) { if (type == SdpMediaSection::kApplication && type == transceiver->GetMediaType()) { transceiver->RestartDatachannelTransceiver(); @@ -1502,10 +1502,10 @@ JsepTransceiver* JsepSessionImpl::FindUnassociatedTransceiver( } void JsepSessionImpl::RollbackLocalOffer() { - for (size_t i = 0; i < mTransceivers.size(); ++i) { - RefPtr& transceiver(mTransceivers[i]); - if (i < mOldTransceivers.size()) { - transceiver->Rollback(*mOldTransceivers[i], false); + for (auto& [id, transceiver] : mTransceivers) { + if (mOldTransceivers.count(id)) { + transceiver->Rollback(*mOldTransceivers[id], false); + mOldTransceivers[id] = transceiver; continue; } @@ -1514,16 +1514,18 @@ void JsepSessionImpl::RollbackLocalOffer() { temp->mSendTrack.PopulateCodecs(mSupportedCodecs); temp->mRecvTrack.PopulateCodecs(mSupportedCodecs); transceiver->Rollback(*temp, false); + mOldTransceivers[id] = transceiver; } - mOldTransceivers.clear(); + mTransceivers = std::move(mOldTransceivers); } void JsepSessionImpl::RollbackRemoteOffer() { - for (size_t i = 0; i < mTransceivers.size(); ++i) { - RefPtr& transceiver(mTransceivers[i]); - if (i < mOldTransceivers.size()) { - transceiver->Rollback(*mOldTransceivers[i], true); + for (auto& [id, transceiver] : mTransceivers) { + if (mOldTransceivers.count(id)) { + // Some stuff cannot be rolled back. Save this information. + transceiver->Rollback(*mOldTransceivers[id], true); + mOldTransceivers[id] = transceiver; continue; } @@ -1542,12 +1544,12 @@ void JsepSessionImpl::RollbackRemoteOffer() { if (shouldRemove) { transceiver->Stop(); transceiver->SetRemoved(); - mTransceivers.erase(mTransceivers.begin() + i); - --i; + } else { + mOldTransceivers[id] = transceiver; } } - mOldTransceivers.clear(); + mTransceivers = std::move(mOldTransceivers); } nsresult JsepSessionImpl::ValidateLocalDescription(const Sdp& description, @@ -2133,7 +2135,7 @@ nsresult JsepSessionImpl::UpdateDefaultCandidate( return NS_ERROR_UNEXPECTED; } - for (const auto& transceiver : mTransceivers) { + for (const auto& [id, transceiver] : mTransceivers) { // We set the default address for bundled m-sections, but not candidate // attributes. Ugh. if (transceiver->mTransport.mTransportId == transportId) { @@ -2236,7 +2238,7 @@ const std::string JsepSessionImpl::GetLastError() const { return mLastError; } bool JsepSessionImpl::CheckNegotiationNeeded() const { MOZ_ASSERT(mState == kJsepStateStable); - for (const auto& transceiver : mTransceivers) { + for (const auto& [id, transceiver] : mTransceivers) { if (transceiver->IsStopped()) { if (transceiver->IsAssociated()) { MOZ_MTLOG(ML_DEBUG, "[" << mName diff --git a/media/webrtc/signaling/src/jsep/JsepSessionImpl.h b/media/webrtc/signaling/src/jsep/JsepSessionImpl.h index a20853c785da..723e76ade86d 100644 --- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.h +++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.h @@ -5,6 +5,7 @@ #ifndef _JSEPSESSIONIMPL_H_ #define _JSEPSESSIONIMPL_H_ +#include #include #include #include @@ -131,12 +132,13 @@ class JsepSessionImpl : public JsepSession { return !mOldIceUfrag.empty(); } - virtual const std::vector>& GetTransceivers() + virtual const std::map>& GetTransceivers() const override { return mTransceivers; } - virtual std::vector>& GetTransceivers() override { + virtual std::map>& GetTransceivers() + override { return mTransceivers; } @@ -225,11 +227,12 @@ class JsepSessionImpl : public JsepSession { const Sdp* GetAnswer() const; void SetIceRestarting(bool restarting); - // !!!NOT INDEXED BY LEVEL!!! These are in the order they were created in. The - // level mapping is done with JsepTransceiver::mLevel. - std::vector> mTransceivers; + // !!!NOT INDEXED BY LEVEL!!! The level mapping is done with + // JsepTransceiver::mLevel. The keys are opaque, stable identifiers that are + // unique within the JsepSession. + std::map> mTransceivers; // So we can rollback. Not as simple as just going back to the old, though... - std::vector> mOldTransceivers; + std::map> mOldTransceivers; Maybe mIsPendingOfferer; Maybe mIsCurrentOfferer; @@ -247,6 +250,7 @@ class JsepSessionImpl : public JsepSession { size_t mMidCounter; std::set mUsedMids; size_t mTransportIdCounter; + size_t mTransceiverIdCounter = 0; std::vector mRtpExtensions; UniquePtr mUuidGen; std::string mDefaultRemoteStreamId; diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp index 8bd01c439763..ab5a0fd9f994 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp @@ -878,7 +878,7 @@ nsresult PeerConnectionImpl::GetDatachannelParameters( transportId->clear(); RefPtr datachannelTransceiver; - for (const auto& transceiver : mJsepSession->GetTransceivers()) { + for (const auto& [id, transceiver] : mJsepSession->GetTransceivers()) { if ((transceiver->GetMediaType() == SdpMediaSection::kApplication) && transceiver->mSendTrack.GetNegotiatedDetails()) { datachannelTransceiver = transceiver; @@ -895,7 +895,7 @@ nsresult PeerConnectionImpl::GetDatachannelParameters( transportTransceiver = datachannelTransceiver; } else if (datachannelTransceiver->HasBundleLevel()) { // Find the actual transport. - for (const auto& transceiver : mJsepSession->GetTransceivers()) { + for (const auto& [id, transceiver] : mJsepSession->GetTransceivers()) { if (transceiver->HasLevel() && transceiver->GetLevel() == datachannelTransceiver->BundleLevel() && transceiver->HasOwnTransport()) { @@ -1118,7 +1118,7 @@ PeerConnectionImpl::CreateDataChannel( CSFLogDebug(LOGTAG, "%s: making DOMDataChannel", __FUNCTION__); RefPtr dcTransceiver; - for (auto& transceiver : mJsepSession->GetTransceivers()) { + for (auto& [id, transceiver] : mJsepSession->GetTransceivers()) { if (transceiver->GetMediaType() == SdpMediaSection::kApplication) { dcTransceiver = transceiver; break; @@ -1403,7 +1403,7 @@ PeerConnectionImpl::SetRemoteDescription(int32_t action, const char* aSDP) { return NS_ERROR_FAILURE; } - size_t originalTransceiverCount = mJsepSession->GetTransceivers().size(); + auto originalTransceivers = mJsepSession->GetTransceivers(); JsepSession::Result result = mJsepSession->SetRemoteDescription(sdpType, mRemoteRequestedSDP); if (result.mError.isSome()) { @@ -1413,18 +1413,17 @@ PeerConnectionImpl::SetRemoteDescription(int32_t action, const char* aSDP) { mPCObserver->OnSetDescriptionError(*buildJSErrorData(result, errorString), jrv); } else { - // Iterate over the JSEP transceivers that were just created - for (size_t i = originalTransceiverCount; - i < mJsepSession->GetTransceivers().size(); ++i) { - RefPtr jsepTransceiver = - mJsepSession->GetTransceivers()[i]; - + for (const auto& [id, jsepTransceiver] : mJsepSession->GetTransceivers()) { if (jsepTransceiver->GetMediaType() == SdpMediaSection::MediaType::kApplication) { continue; } - // Audio or video transceiver, need to tell JS about it. + if (originalTransceivers.count(id)) { + continue; + } + + // New audio or video transceiver, need to tell JS about it. RefPtr transceiverImpl = CreateTransceiverImpl(jsepTransceiver, nullptr, jrv); if (jrv.Failed()) { diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp index 49ceebce1e5b..1fedebd6a528 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp @@ -165,7 +165,7 @@ nsresult PeerConnectionMedia::Init() { } void PeerConnectionMedia::EnsureTransports(const JsepSession& aSession) { - for (const auto& transceiver : aSession.GetTransceivers()) { + for (const auto& [id, transceiver] : aSession.GetTransceivers()) { if (transceiver->HasOwnTransport()) { mTransportHandler->EnsureProvisionalTransport( transceiver->mTransport.mTransportId, @@ -181,7 +181,7 @@ void PeerConnectionMedia::EnsureTransports(const JsepSession& aSession) { nsresult PeerConnectionMedia::UpdateTransports(const JsepSession& aSession, const bool forceIceTcp) { std::set finalTransports; - for (const auto& transceiver : aSession.GetTransceivers()) { + for (const auto& [id, transceiver] : aSession.GetTransceivers()) { if (transceiver->HasOwnTransport()) { finalTransports.insert(transceiver->mTransport.mTransportId); UpdateTransport(*transceiver, forceIceTcp);