Add rollback for send encodings

Bug: chromium:1188398
Change-Id: I9491426cd4a3983c7065f18af3c843d498eeafe1
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/214121
Commit-Queue: Eldar Rello <elrello@microsoft.com>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33630}
diff --git a/pc/peer_connection_jsep_unittest.cc b/pc/peer_connection_jsep_unittest.cc
index 00e202c..f0accf4 100644
--- a/pc/peer_connection_jsep_unittest.cc
+++ b/pc/peer_connection_jsep_unittest.cc
@@ -1915,6 +1915,68 @@
   EXPECT_TRUE(callee->SetLocalDescription(std::move(offer)));
 }
 
+TEST_F(PeerConnectionJsepTest, RollbackRestoresInitSendEncodings) {
+  auto caller = CreatePeerConnection();
+  RtpTransceiverInit init;
+  init.direction = RtpTransceiverDirection::kSendRecv;
+  RtpEncodingParameters encoding;
+  encoding.rid = "hi";
+  init.send_encodings.push_back(encoding);
+  encoding.rid = "mid";
+  init.send_encodings.push_back(encoding);
+  encoding.rid = "lo";
+  init.send_encodings.push_back(encoding);
+  caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
+  auto encodings =
+      caller->pc()->GetTransceivers()[0]->sender()->init_send_encodings();
+  EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
+  EXPECT_NE(caller->pc()->GetTransceivers()[0]->sender()->init_send_encodings(),
+            encodings);
+  EXPECT_TRUE(caller->SetLocalDescription(caller->CreateRollback()));
+  EXPECT_EQ(caller->pc()->GetTransceivers()[0]->sender()->init_send_encodings(),
+            encodings);
+}
+
+TEST_F(PeerConnectionJsepTest, RollbackDoesNotAffectSendEncodings) {
+  auto caller = CreatePeerConnection();
+  auto callee = CreatePeerConnection();
+  RtpTransceiverInit init;
+  init.direction = RtpTransceiverDirection::kSendOnly;
+  RtpEncodingParameters encoding;
+  encoding.rid = "hi";
+  init.send_encodings.push_back(encoding);
+  encoding.rid = "mid";
+  init.send_encodings.push_back(encoding);
+  encoding.rid = "lo";
+  init.send_encodings.push_back(encoding);
+  caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
+  callee->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
+  callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal());
+  caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal());
+  auto params = caller->pc()->GetTransceivers()[0]->sender()->GetParameters();
+  EXPECT_TRUE(params.encodings[0].active);
+  params.encodings[0].active = false;
+  caller->pc()->GetTransceivers()[0]->sender()->SetParameters(params);
+  auto offer = caller->CreateOffer();
+  std::string offer_string;
+  EXPECT_TRUE(offer.get()->ToString(&offer_string));
+  std::string simulcast_line =
+      offer_string.substr(offer_string.find("a=simulcast"));
+  EXPECT_FALSE(simulcast_line.empty());
+  EXPECT_TRUE(caller->SetLocalDescription(std::move(offer)));
+  EXPECT_TRUE(caller->SetLocalDescription(caller->CreateRollback()));
+  EXPECT_FALSE(caller->pc()
+                   ->GetTransceivers()[0]
+                   ->sender()
+                   ->GetParameters()
+                   .encodings[0]
+                   .active);
+  offer = caller->CreateOffer();
+  EXPECT_TRUE(offer.get()->ToString(&offer_string));
+  EXPECT_EQ(offer_string.substr(offer_string.find("a=simulcast")),
+            simulcast_line);
+}
+
 TEST_F(PeerConnectionJsepTest, RollbackRestoresMidAndRemovesTransceiver) {
   auto callee = CreatePeerConnection();
   callee->AddVideoTrack("a");
diff --git a/pc/sdp_offer_answer.cc b/pc/sdp_offer_answer.cc
index 293c5cb..1381bf9 100644
--- a/pc/sdp_offer_answer.cc
+++ b/pc/sdp_offer_answer.cc
@@ -1423,8 +1423,15 @@
         const std::vector<StreamParams>& streams = channel->local_streams();
         transceiver->internal()->sender_internal()->set_stream_ids(
             streams[0].stream_ids());
+        auto encodings =
+            transceiver->internal()->sender_internal()->init_send_encodings();
         transceiver->internal()->sender_internal()->SetSsrc(
             streams[0].first_ssrc());
+        if (!encodings.empty()) {
+          transceivers()
+              ->StableState(transceiver)
+              ->SetInitSendEncodings(encodings);
+        }
       }
     }
   } else {
@@ -2722,6 +2729,10 @@
         transceivers()->Remove(transceiver);
       }
     }
+    if (state.init_send_encodings()) {
+      transceiver->internal()->sender_internal()->set_init_send_encodings(
+          state.init_send_encodings().value());
+    }
     transceiver->internal()->sender_internal()->set_transport(nullptr);
     transceiver->internal()->receiver_internal()->set_transport(nullptr);
     transceiver->internal()->set_mid(state.mid());
diff --git a/pc/transceiver_list.cc b/pc/transceiver_list.cc
index aeb89d6..63d3e67 100644
--- a/pc/transceiver_list.cc
+++ b/pc/transceiver_list.cc
@@ -36,6 +36,11 @@
   }
 }
 
+void TransceiverStableState::SetInitSendEncodings(
+    const std::vector<RtpEncodingParameters>& encodings) {
+  init_send_encodings_ = encodings;
+}
+
 RtpTransceiverProxyRefPtr TransceiverList::FindBySender(
     rtc::scoped_refptr<RtpSenderInterface> sender) const {
   for (auto transceiver : transceivers_) {
diff --git a/pc/transceiver_list.h b/pc/transceiver_list.h
index 4364c3c..2eb4313 100644
--- a/pc/transceiver_list.h
+++ b/pc/transceiver_list.h
@@ -39,11 +39,17 @@
   void SetMSectionIfUnset(absl::optional<std::string> mid,
                           absl::optional<size_t> mline_index);
   void SetRemoteStreamIdsIfUnset(const std::vector<std::string>& ids);
+  void SetInitSendEncodings(
+      const std::vector<RtpEncodingParameters>& encodings);
   absl::optional<std::string> mid() const { return mid_; }
   absl::optional<size_t> mline_index() const { return mline_index_; }
   absl::optional<std::vector<std::string>> remote_stream_ids() const {
     return remote_stream_ids_;
   }
+  absl::optional<std::vector<RtpEncodingParameters>> init_send_encodings()
+      const {
+    return init_send_encodings_;
+  }
   bool has_m_section() const { return has_m_section_; }
   bool newly_created() const { return newly_created_; }
 
@@ -51,6 +57,7 @@
   absl::optional<std::string> mid_;
   absl::optional<size_t> mline_index_;
   absl::optional<std::vector<std::string>> remote_stream_ids_;
+  absl::optional<std::vector<RtpEncodingParameters>> init_send_encodings_;
   // Indicates that mid value from stable state has been captured and
   // that rollback has to restore the transceiver. Also protects against
   // subsequent overwrites.