[Merge-111] Preserve mid of sections added with AddTrack after a rollback

Since AddTrack now has an implicit init_encodings value, it will also
have a StableState saved when associating a transceiver.
That state may not have a saved mid and mline_index, and so on a
rollback, it could blindly reset the mid and mline_index of an
associated transceiver.

This is wrong, the mid and mline_index of associated transceivers
should only be updated when the StableState objects actually
have one saved.

# Try bots not possible due to
# https://webrtc-review.googlesource.com/c/src/+/292820
NOTRY=True

(cherry picked from commit b3d424cd484dd7a109547ca7be7f1575a29df7e7)

Bug: chromium:1424238
Change-Id: I8e80a04cd072d90200ca7643de892c0ef29b1f1a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/297920
Commit-Queue: Florent Castelli <orphis@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Original-Commit-Position: refs/heads/main@{#39577}
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/297984
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/branch-heads/5563@{#5}
Cr-Branched-From: 6c032cb8356b0d3f717c4fcf50796241f2bba6c2-refs/heads/main@{#39207}
diff --git a/pc/sdp_offer_answer.cc b/pc/sdp_offer_answer.cc
index ade3be7..6332d51 100644
--- a/pc/sdp_offer_answer.cc
+++ b/pc/sdp_offer_answer.cc
@@ -3079,8 +3079,10 @@
     }
     transceiver->internal()->sender_internal()->set_transport(nullptr);
     transceiver->internal()->receiver_internal()->set_transport(nullptr);
-    transceiver->internal()->set_mid(state.mid());
-    transceiver->internal()->set_mline_index(state.mline_index());
+    if (state.has_m_section()) {
+      transceiver->internal()->set_mid(state.mid());
+      transceiver->internal()->set_mline_index(state.mline_index());
+    }
   }
   RTCError e = transport_controller_s()->RollbackTransports();
   if (!e.ok()) {
diff --git a/pc/sdp_offer_answer_unittest.cc b/pc/sdp_offer_answer_unittest.cc
index bdd3301..e16cd6a 100644
--- a/pc/sdp_offer_answer_unittest.cc
+++ b/pc/sdp_offer_answer_unittest.cc
@@ -388,4 +388,67 @@
   EXPECT_EQ(error.type(), RTCErrorType::INVALID_PARAMETER);
 }
 
+TEST_F(SdpOfferAnswerTest, RollbackPreservesAddTrackMid) {
+  std::string sdp =
+      "v=0\r\n"
+      "o=- 4131505339648218884 3 IN IP4 **-----**\r\n"
+      "s=-\r\n"
+      "t=0 0\r\n"
+      "a=ice-lite\r\n"
+      "a=msid-semantic: WMS 100030878598094:4Qs1PjbLM32RK5u3\r\n"
+      "a=ice-ufrag:zGWFZ+fVXDeN6UoI/136\r\n"
+      "a=ice-pwd:9AUNgUqRNI5LSIrC1qFD2iTR\r\n"
+      "a=fingerprint:sha-256 "
+      "AD:52:52:E0:B1:37:34:21:0E:15:8E:B7:56:56:7B:B4:39:0E:6D:1C:F5:84:A7:EE:"
+      "B5:27:3E:30:B1:7D:69:42\r\n"
+      "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n"
+      "a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\n"
+      "a=group:BUNDLE 0 1\r\n"
+      "m=audio 40005 UDP/TLS/RTP/SAVPF 111\r\n"
+      "a=rtpmap:111 opus/48000/2\r\n"
+      "a=fmtp:111 "
+      "maxaveragebitrate=20000;maxplaybackrate=16000;minptime=10;usedtx=1;"
+      "useinbandfec=1;stereo=0\r\n"
+      "a=rtcp-fb:111 nack\r\n"
+      "a=setup:passive\r\n"
+      "a=mid:0\r\n"
+      "a=msid:- 75156ebd-e705-4da1-920e-2dac39794dfd\r\n"
+      "a=ptime:60\r\n"
+      "a=recvonly\r\n"
+      "a=rtcp-mux\r\n"
+      "m=audio 40005 UDP/TLS/RTP/SAVPF 111\r\n"
+      "a=rtpmap:111 opus/48000/2\r\n"
+      "a=fmtp:111 "
+      "maxaveragebitrate=20000;maxplaybackrate=16000;minptime=10;usedtx=1;"
+      "useinbandfec=1;stereo=0\r\n"
+      "a=rtcp-fb:111 nack\r\n"
+      "a=setup:passive\r\n"
+      "a=mid:1\r\n"
+      "a=msid:100030878598094:4Qs1PjbLM32RK5u3 9695447562408476674\r\n"
+      "a=ptime:60\r\n"
+      "a=sendonly\r\n"
+      "a=ssrc:2565730539 cname:100030878598094:4Qs1PjbLM32RK5u3\r\n"
+      "a=rtcp-mux\r\n";
+  auto pc = CreatePeerConnection();
+  auto audio_track = pc->AddAudioTrack("audio_track", {});
+  auto first_transceiver = pc->pc()->GetTransceivers()[0];
+  EXPECT_FALSE(first_transceiver->mid().has_value());
+  auto desc = CreateSessionDescription(SdpType::kOffer, sdp);
+  ASSERT_NE(desc, nullptr);
+  RTCError error;
+  ASSERT_TRUE(pc->SetRemoteDescription(std::move(desc)));
+  pc->CreateAnswerAndSetAsLocal();
+  auto saved_mid = first_transceiver->mid();
+  EXPECT_TRUE(saved_mid.has_value());
+  auto offer_before_rollback = pc->CreateOfferAndSetAsLocal();
+  EXPECT_EQ(saved_mid, first_transceiver->mid());
+  auto rollback = pc->CreateRollback();
+  ASSERT_NE(rollback, nullptr);
+  ASSERT_TRUE(pc->SetLocalDescription(std::move(rollback)));
+  EXPECT_EQ(saved_mid, first_transceiver->mid());
+  auto offer2 = pc->CreateOfferAndSetAsLocal();
+  ASSERT_NE(offer2, nullptr);
+  EXPECT_EQ(saved_mid, first_transceiver->mid());
+}
+
 }  // namespace webrtc