Reland "Allow AudioSendStream to reconfig AudioNetworkAdaptor"

BUG=b/63898232, b/64053465

Originally Reviewed-on: https://chromium-review.googlesource.com/584707

Reverted-on: https://chromium-review.googlesource.com/586268
Change-Id: I212b0c1e81a6ccd73b051e6728e601a8641463b8
Reviewed-on: https://chromium-review.googlesource.com/586328
Commit-Queue: Minyue Li <minyue@webrtc.org>
Reviewed-by: Michael T <tschumim@webrtc.org>
Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#19153}
diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc
index 376af81..f1395ab 100644
--- a/webrtc/audio/audio_send_stream.cc
+++ b/webrtc/audio/audio_send_stream.cc
@@ -487,7 +487,17 @@
 bool AudioSendStream::ReconfigureSendCodec(AudioSendStream* stream,
                                            const Config& new_config) {
   const auto& old_config = stream->config_;
-  if (new_config.send_codec_spec == old_config.send_codec_spec) {
+
+  if (!new_config.send_codec_spec) {
+    // We cannot de-configure a send codec. So we will do nothing.
+    // By design, the send codec should have not been configured.
+    RTC_DCHECK(!old_config.send_codec_spec);
+    return true;
+  }
+
+  if (new_config.send_codec_spec == old_config.send_codec_spec &&
+      new_config.audio_network_adaptor_config ==
+          old_config.audio_network_adaptor_config) {
     return true;
   }
 
@@ -501,9 +511,6 @@
     return SetupSendCodec(stream, new_config);
   }
 
-  // Should never move a stream from fully configured to unconfigured.
-  RTC_CHECK(new_config.send_codec_spec);
-
   const rtc::Optional<int>& new_target_bitrate_bps =
       new_config.send_codec_spec->target_bitrate_bps;
   // If a bitrate has been specified for the codec, use it over the
diff --git a/webrtc/audio/audio_send_stream_unittest.cc b/webrtc/audio/audio_send_stream_unittest.cc
index 12fad6f..bec696b 100644
--- a/webrtc/audio/audio_send_stream_unittest.cc
+++ b/webrtc/audio/audio_send_stream_unittest.cc
@@ -43,6 +43,7 @@
 using testing::Ne;
 using testing::Invoke;
 using testing::Return;
+using testing::StrEq;
 
 const int kChannelId = 1;
 const uint32_t kSsrc = 1234;
@@ -141,7 +142,8 @@
             &packet_router_)),
         fake_transport_(&packet_router_, send_side_cc_.get()),
         bitrate_allocator_(&limit_observer_),
-        worker_queue_("ConfigHelper_worker_queue") {
+        worker_queue_("ConfigHelper_worker_queue"),
+        audio_encoder_(nullptr) {
     using testing::Invoke;
 
     EXPECT_CALL(voice_engine_,
@@ -206,7 +208,6 @@
   }
 
   void SetupDefaultChannelProxy(bool audio_bwe_enabled) {
-    using testing::StrEq;
     channel_proxy_ = new testing::StrictMock<MockVoEChannelProxy>();
     EXPECT_CALL(*channel_proxy_, GetRtpRtcp(_, _))
         .WillRepeatedly(Invoke(
@@ -250,10 +251,25 @@
   void SetupMockForSetupSendCodec(bool expect_set_encoder_call) {
     if (expect_set_encoder_call) {
       EXPECT_CALL(*channel_proxy_, SetEncoderForMock(_, _))
-          .WillOnce(Return(true));
+          .WillOnce(Invoke(
+              [this](int payload_type, std::unique_ptr<AudioEncoder>* encoder) {
+                this->audio_encoder_ = std::move(*encoder);
+                return true;
+              }));
     }
   }
 
+  void SetupMockForModifyEncoder() {
+    // Let ModifyEncoder to invoke mock audio encoder.
+    EXPECT_CALL(*channel_proxy_, ModifyEncoder(_))
+        .WillRepeatedly(Invoke(
+            [this](rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)>
+                       modifier) {
+              if (this->audio_encoder_)
+                modifier(&this->audio_encoder_);
+            }));
+  }
+
   RtcpRttStats* rtcp_rtt_stats() { return &rtcp_rtt_stats_; }
 
   void SetupMockForSendTelephoneEvent() {
@@ -329,6 +345,7 @@
   // |worker_queue| is defined last to ensure all pending tasks are cancelled
   // and deleted before any other members.
   rtc::TaskQueue worker_queue_;
+  std::unique_ptr<AudioEncoder> audio_encoder_;
 };
 }  // namespace
 
@@ -458,19 +475,27 @@
   EXPECT_FALSE(send_stream.GetStats().typing_noise_detected);
 }
 
-TEST(AudioSendStreamTest, SendCodecAppliesNetworkAdaptor) {
+TEST(AudioSendStreamTest, SendCodecAppliesAudioNetworkAdaptor) {
   ConfigHelper helper(false, true);
   auto stream_config = helper.config();
   stream_config.send_codec_spec =
       rtc::Optional<AudioSendStream::Config::SendCodecSpec>({0, kOpusFormat});
+  const std::string kAnaConfigString = "abcde";
+  const std::string kAnaReconfigString = "12345";
+
   stream_config.audio_network_adaptor_config =
-      rtc::Optional<std::string>("abced");
+      rtc::Optional<std::string>(kAnaConfigString);
 
   EXPECT_CALL(helper.mock_encoder_factory(), MakeAudioEncoderMock(_, _, _))
-      .WillOnce(Invoke([](int payload_type, const SdpAudioFormat& format,
-                          std::unique_ptr<AudioEncoder>* return_value) {
+      .WillOnce(Invoke([&kAnaConfigString, &kAnaReconfigString](
+                           int payload_type, const SdpAudioFormat& format,
+                           std::unique_ptr<AudioEncoder>* return_value) {
         auto mock_encoder = SetupAudioEncoderMock(payload_type, format);
-        EXPECT_CALL(*mock_encoder.get(), EnableAudioNetworkAdaptor(_, _))
+        EXPECT_CALL(*mock_encoder,
+                    EnableAudioNetworkAdaptor(StrEq(kAnaConfigString), _))
+            .WillOnce(Return(true));
+        EXPECT_CALL(*mock_encoder,
+                    EnableAudioNetworkAdaptor(StrEq(kAnaReconfigString), _))
             .WillOnce(Return(true));
         *return_value = std::move(mock_encoder);
       }));
@@ -479,6 +504,12 @@
       stream_config, helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
       helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
+
+  stream_config.audio_network_adaptor_config =
+      rtc::Optional<std::string>(kAnaReconfigString);
+
+  helper.SetupMockForModifyEncoder();
+  send_stream.Reconfigure(stream_config);
 }
 
 // VAD is applied when codec is mono and the CNG frequency matches the codec