Add speech encoder to the encoder stack specification struct

BUG=webrtc:5028

Review URL: https://codereview.webrtc.org/1527933002

Cr-Commit-Position: refs/heads/master@{#11037}
diff --git a/webrtc/modules/audio_coding/acm2/codec_manager.cc b/webrtc/modules/audio_coding/acm2/codec_manager.cc
index 561d744..19a79c2 100644
--- a/webrtc/modules/audio_coding/acm2/codec_manager.cc
+++ b/webrtc/modules/audio_coding/acm2/codec_manager.cc
@@ -165,7 +165,8 @@
     AudioEncoder* enc = rent_a_codec_.RentEncoder(send_codec);
     if (!enc)
       return -1;
-    rent_a_codec_.RentEncoderStack(enc, &codec_stack_params_);
+    codec_stack_params_.speech_encoder = enc;
+    rent_a_codec_.RentEncoderStack(&codec_stack_params_);
     RTC_DCHECK(CurrentEncoder());
   }
 
@@ -187,7 +188,8 @@
   static const char kName[] = "external";
   memcpy(send_codec_inst_.plname, kName, sizeof(kName));
 
-  rent_a_codec_.RentEncoderStack(external_speech_encoder, &codec_stack_params_);
+  codec_stack_params_.speech_encoder = external_speech_encoder;
+  rent_a_codec_.RentEncoderStack(&codec_stack_params_);
 }
 
 rtc::Optional<CodecInst> CodecManager::GetCodecInst() const {
@@ -219,8 +221,7 @@
   if (codec_stack_params_.use_red != enable) {
     codec_stack_params_.use_red = enable;
     if (CurrentEncoder())
-      rent_a_codec_.RentEncoderStack(rent_a_codec_.GetEncoder(),
-                                     &codec_stack_params_);
+      rent_a_codec_.RentEncoderStack(&codec_stack_params_);
   }
   return true;
 }
@@ -232,8 +233,10 @@
 
   // Check that the send codec is mono. We don't support VAD/DTX for stereo
   // sending.
-  auto* enc = rent_a_codec_.GetEncoder();
-  const bool stereo_send = enc ? (enc->NumChannels() != 1) : false;
+  const bool stereo_send =
+      codec_stack_params_.speech_encoder
+          ? (codec_stack_params_.speech_encoder->NumChannels() != 1)
+          : false;
   if (enable && stereo_send) {
     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
                  "VAD/DTX not supported for stereo sending");
@@ -252,8 +255,8 @@
       codec_stack_params_.vad_mode != mode) {
     codec_stack_params_.use_cng = enable;
     codec_stack_params_.vad_mode = mode;
-    if (enc)
-      rent_a_codec_.RentEncoderStack(enc, &codec_stack_params_);
+    if (codec_stack_params_.speech_encoder)
+      rent_a_codec_.RentEncoderStack(&codec_stack_params_);
   }
   return 0;
 }
diff --git a/webrtc/modules/audio_coding/acm2/rent_a_codec.cc b/webrtc/modules/audio_coding/acm2/rent_a_codec.cc
index 4800249..e0d1b6f 100644
--- a/webrtc/modules/audio_coding/acm2/rent_a_codec.cc
+++ b/webrtc/modules/audio_coding/acm2/rent_a_codec.cc
@@ -249,37 +249,36 @@
 
 RentACodec::StackParameters::~StackParameters() = default;
 
-AudioEncoder* RentACodec::RentEncoderStack(AudioEncoder* speech_encoder,
-                                           StackParameters* param) {
-  RTC_DCHECK(speech_encoder);
+AudioEncoder* RentACodec::RentEncoderStack(StackParameters* param) {
+  RTC_DCHECK(param->speech_encoder);
 
   if (param->use_codec_fec) {
     // Switch FEC on. On failure, remember that FEC is off.
-    if (!speech_encoder->SetFec(true))
+    if (!param->speech_encoder->SetFec(true))
       param->use_codec_fec = false;
   } else {
     // Switch FEC off. This shouldn't fail.
-    const bool success = speech_encoder->SetFec(false);
+    const bool success = param->speech_encoder->SetFec(false);
     RTC_DCHECK(success);
   }
 
-  auto pt = [&speech_encoder](const std::map<int, int>& m) {
-    auto it = m.find(speech_encoder->SampleRateHz());
+  auto pt = [&param](const std::map<int, int>& m) {
+    auto it = m.find(param->speech_encoder->SampleRateHz());
     return it == m.end() ? rtc::Optional<int>()
                          : rtc::Optional<int>(it->second);
   };
   auto cng_pt = pt(param->cng_payload_types);
   param->use_cng =
-      param->use_cng && cng_pt && speech_encoder->NumChannels() == 1;
+      param->use_cng && cng_pt && param->speech_encoder->NumChannels() == 1;
   auto red_pt = pt(param->red_payload_types);
   param->use_red = param->use_red && red_pt;
 
   if (param->use_cng || param->use_red) {
     // The RED and CNG encoders need to be in sync with the speech encoder, so
     // reset the latter to ensure its buffer is empty.
-    speech_encoder->Reset();
+    param->speech_encoder->Reset();
   }
-  encoder_stack_ = speech_encoder;
+  encoder_stack_ = param->speech_encoder;
   if (param->use_red) {
     red_encoder_ = CreateRedEncoder(encoder_stack_, *red_pt);
     if (red_encoder_)
diff --git a/webrtc/modules/audio_coding/acm2/rent_a_codec.h b/webrtc/modules/audio_coding/acm2/rent_a_codec.h
index 7035104..cf6891a 100644
--- a/webrtc/modules/audio_coding/acm2/rent_a_codec.h
+++ b/webrtc/modules/audio_coding/acm2/rent_a_codec.h
@@ -204,6 +204,7 @@
     StackParameters();
     ~StackParameters();
 
+    AudioEncoder* speech_encoder = nullptr;
     bool use_codec_fec = false;
     bool use_red = false;
     bool use_cng = false;
@@ -219,12 +220,10 @@
   // will be changed to match (things will be switched off). The returned
   // encoder is live until the next successful call to this function, or until
   // the Rent-A-Codec is destroyed.
-  AudioEncoder* RentEncoderStack(AudioEncoder* speech_encoder,
-                                 StackParameters* param);
+  AudioEncoder* RentEncoderStack(StackParameters* param);
 
-  // Get the last return values of RentEncoder and RentEncoderStack, or null if
-  // they haven't been called.
-  AudioEncoder* GetEncoder() const { return speech_encoder_.get(); }
+  // The last return value of RentEncoderStack, or null if it hasn't been
+  // called.
   AudioEncoder* GetEncoderStack() const { return encoder_stack_; }
 
   // Creates and returns an iSAC decoder, which will remain live until the
diff --git a/webrtc/modules/audio_coding/acm2/rent_a_codec_unittest.cc b/webrtc/modules/audio_coding/acm2/rent_a_codec_unittest.cc
index 11c4bcb..e838488 100644
--- a/webrtc/modules/audio_coding/acm2/rent_a_codec_unittest.cc
+++ b/webrtc/modules/audio_coding/acm2/rent_a_codec_unittest.cc
@@ -34,7 +34,8 @@
     ASSERT_TRUE(speech_encoder_);
     RentACodec::StackParameters param;
     param.use_cng = true;
-    encoder_ = rent_a_codec_.RentEncoderStack(speech_encoder_, &param);
+    param.speech_encoder = speech_encoder_;
+    encoder_ = rent_a_codec_.RentEncoderStack(&param);
   }
 
   void EncodeAndVerify(size_t expected_out_length,
@@ -110,7 +111,8 @@
 
   RentACodec rac;
   RentACodec::StackParameters param;
-  EXPECT_EQ(&external_encoder, rac.RentEncoderStack(&external_encoder, &param));
+  param.speech_encoder = &external_encoder;
+  EXPECT_EQ(&external_encoder, rac.RentEncoderStack(&param));
   const int kPacketSizeSamples = kSampleRateHz / 100;
   int16_t audio[kPacketSizeSamples] = {0};
   uint8_t encoded[kPacketSizeSamples];
@@ -140,16 +142,17 @@
   // Change to internal encoder.
   CodecInst codec_inst = kDefaultCodecInst;
   codec_inst.pacsize = kPacketSizeSamples;
-  AudioEncoder* enc = rac.RentEncoder(codec_inst);
-  ASSERT_TRUE(enc);
-  EXPECT_EQ(enc, rac.RentEncoderStack(enc, &param));
+  param.speech_encoder = rac.RentEncoder(codec_inst);
+  ASSERT_TRUE(param.speech_encoder);
+  EXPECT_EQ(param.speech_encoder, rac.RentEncoderStack(&param));
 
   // Don't expect any more calls to the external encoder.
   info = rac.GetEncoderStack()->Encode(1, audio, arraysize(encoded), encoded);
   external_encoder.Mark("B");
 
   // Change back to external encoder again.
-  EXPECT_EQ(&external_encoder, rac.RentEncoderStack(&external_encoder, &param));
+  param.speech_encoder = &external_encoder;
+  EXPECT_EQ(&external_encoder, rac.RentEncoderStack(&param));
   info = rac.GetEncoderStack()->Encode(2, audio, arraysize(encoded), encoded);
   EXPECT_EQ(2u, info.encoded_timestamp);
 }
@@ -173,13 +176,15 @@
   }
 
   RentACodec::StackParameters param1, param2;
+  param1.speech_encoder = &speech_encoder;
+  param2.speech_encoder = &speech_encoder;
   param2.use_cng = use_cng;
   param2.use_red = use_red;
   speech_encoder.Mark("disabled");
   RentACodec rac;
-  rac.RentEncoderStack(&speech_encoder, &param1);
+  rac.RentEncoderStack(&param1);
   speech_encoder.Mark("enabled");
-  rac.RentEncoderStack(&speech_encoder, &param2);
+  rac.RentEncoderStack(&param2);
 }
 
 TEST(RentACodecTest, CngResetsSpeechEncoder) {
@@ -205,5 +210,13 @@
   EXPECT_FALSE(rent_a_codec.RentEncoder(codec_inst));
 }
 
+#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+TEST(RentACodecTest, RentEncoderStackWithoutSpeechEncoder) {
+  RentACodec::StackParameters sp;
+  EXPECT_EQ(nullptr, sp.speech_encoder);
+  EXPECT_DEATH(RentACodec().RentEncoderStack(&sp), "");
+}
+#endif
+
 }  // namespace acm2
 }  // namespace webrtc