Pass ownership of external encoders to the ACM

We want this because otherwise the ACM uses its mutex to protect an
encoder that's owned by someone else. That someone else may easily
slip up and delete or otherwise touch the encoder before making sure
that the ACM has stopped using it, bypassing the lock.

BUG=webrtc:5028

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

Cr-Commit-Position: refs/heads/master@{#11909}
diff --git a/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.cc b/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.cc
index 2b62022..37a0a8c 100644
--- a/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.cc
+++ b/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.cc
@@ -31,6 +31,12 @@
 
 namespace acm2 {
 
+struct EncoderFactory {
+  AudioEncoder* external_speech_encoder = nullptr;
+  CodecManager codec_manager;
+  RentACodec rent_a_codec;
+};
+
 namespace {
 
 // TODO(turajs): the same functionality is used in NetEq. If both classes
@@ -90,6 +96,79 @@
     frag->fragmentationPlType[i] = info.redundant[i].payload_type;
   }
 }
+
+// Wraps a raw AudioEncoder pointer. The idea is that you can put one of these
+// in a unique_ptr, to protect the contained raw pointer from being deleted
+// when the unique_ptr expires. (This is of course a bad idea in general, but
+// backwards compatibility.)
+class RawAudioEncoderWrapper final : public AudioEncoder {
+ public:
+  RawAudioEncoderWrapper(AudioEncoder* enc) : enc_(enc) {}
+  size_t MaxEncodedBytes() const override { return enc_->MaxEncodedBytes(); }
+  int SampleRateHz() const override { return enc_->SampleRateHz(); }
+  size_t NumChannels() const override { return enc_->NumChannels(); }
+  int RtpTimestampRateHz() const override { return enc_->RtpTimestampRateHz(); }
+  size_t Num10MsFramesInNextPacket() const override {
+    return enc_->Num10MsFramesInNextPacket();
+  }
+  size_t Max10MsFramesInAPacket() const override {
+    return enc_->Max10MsFramesInAPacket();
+  }
+  int GetTargetBitrate() const override { return enc_->GetTargetBitrate(); }
+  EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
+                         rtc::ArrayView<const int16_t> audio,
+                         rtc::Buffer* encoded) override {
+    return enc_->Encode(rtp_timestamp, audio, encoded);
+  }
+  EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
+                             rtc::ArrayView<const int16_t> audio,
+                             size_t max_encoded_bytes,
+                             uint8_t* encoded) override {
+    return enc_->EncodeInternal(rtp_timestamp, audio, max_encoded_bytes,
+                                encoded);
+  }
+  void Reset() override { return enc_->Reset(); }
+  bool SetFec(bool enable) override { return enc_->SetFec(enable); }
+  bool SetDtx(bool enable) override { return enc_->SetDtx(enable); }
+  bool SetApplication(Application application) override {
+    return enc_->SetApplication(application);
+  }
+  void SetMaxPlaybackRate(int frequency_hz) override {
+    return enc_->SetMaxPlaybackRate(frequency_hz);
+  }
+  void SetProjectedPacketLossRate(double fraction) override {
+    return enc_->SetProjectedPacketLossRate(fraction);
+  }
+  void SetTargetBitrate(int target_bps) override {
+    return enc_->SetTargetBitrate(target_bps);
+  }
+
+ private:
+  AudioEncoder* enc_;
+};
+
+// Return false on error.
+bool CreateSpeechEncoderIfNecessary(EncoderFactory* ef) {
+  auto* sp = ef->codec_manager.GetStackParams();
+  if (sp->speech_encoder) {
+    // Do nothing; we already have a speech encoder.
+  } else if (ef->codec_manager.GetCodecInst()) {
+    RTC_DCHECK(!ef->external_speech_encoder);
+    // We have no speech encoder, but we have a specification for making one.
+    std::unique_ptr<AudioEncoder> enc =
+        ef->rent_a_codec.RentEncoder(*ef->codec_manager.GetCodecInst());
+    if (!enc)
+      return false;  // Encoder spec was bad.
+    sp->speech_encoder = std::move(enc);
+  } else if (ef->external_speech_encoder) {
+    RTC_DCHECK(!ef->codec_manager.GetCodecInst());
+    // We have an external speech encoder.
+    sp->speech_encoder = std::unique_ptr<AudioEncoder>(
+        new RawAudioEncoderWrapper(ef->external_speech_encoder));
+  }
+  return true;
+}
+
 }  // namespace
 
 void AudioCodingModuleImpl::ChangeLogger::MaybeLog(int value) {
@@ -200,15 +279,13 @@
   if (!encoder_factory_->codec_manager.RegisterEncoder(send_codec)) {
     return -1;
   }
-  auto* sp = encoder_factory_->codec_manager.GetStackParams();
-  if (!sp->speech_encoder && encoder_factory_->codec_manager.GetCodecInst()) {
-    // We have no speech encoder, but we have a specification for making one.
-    AudioEncoder* enc = encoder_factory_->rent_a_codec.RentEncoder(
-        *encoder_factory_->codec_manager.GetCodecInst());
-    if (!enc)
-      return -1;
-    sp->speech_encoder = enc;
+  if (encoder_factory_->codec_manager.GetCodecInst()) {
+    encoder_factory_->external_speech_encoder = nullptr;
   }
+  if (!CreateSpeechEncoderIfNecessary(encoder_factory_.get())) {
+    return -1;
+  }
+  auto* sp = encoder_factory_->codec_manager.GetStackParams();
   if (sp->speech_encoder)
     encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp);
   return 0;
@@ -217,8 +294,11 @@
 void AudioCodingModuleImpl::RegisterExternalSendCodec(
     AudioEncoder* external_speech_encoder) {
   rtc::CritScope lock(&acm_crit_sect_);
+  encoder_factory_->codec_manager.UnsetCodecInst();
+  encoder_factory_->external_speech_encoder = external_speech_encoder;
+  RTC_CHECK(CreateSpeechEncoderIfNecessary(encoder_factory_.get()));
   auto* sp = encoder_factory_->codec_manager.GetStackParams();
-  sp->speech_encoder = external_speech_encoder;
+  RTC_CHECK(sp->speech_encoder);
   encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp);
 }
 
@@ -229,9 +309,11 @@
   if (ci) {
     return rtc::Optional<CodecInst>(*ci);
   }
-  auto* enc = encoder_factory_->codec_manager.GetStackParams()->speech_encoder;
+  CreateSpeechEncoderIfNecessary(encoder_factory_.get());
+  const std::unique_ptr<AudioEncoder>& enc =
+      encoder_factory_->codec_manager.GetStackParams()->speech_encoder;
   if (enc) {
-    return rtc::Optional<CodecInst>(CodecManager::ForgeCodecInst(enc));
+    return rtc::Optional<CodecInst>(CodecManager::ForgeCodecInst(enc.get()));
   }
   return rtc::Optional<CodecInst>();
 }
@@ -451,6 +533,7 @@
 int AudioCodingModuleImpl::SetREDStatus(bool enable_red) {
 #ifdef WEBRTC_CODEC_RED
   rtc::CritScope lock(&acm_crit_sect_);
+  CreateSpeechEncoderIfNecessary(encoder_factory_.get());
   if (!encoder_factory_->codec_manager.SetCopyRed(enable_red)) {
     return -1;
   }
@@ -476,6 +559,7 @@
 
 int AudioCodingModuleImpl::SetCodecFEC(bool enable_codec_fec) {
   rtc::CritScope lock(&acm_crit_sect_);
+  CreateSpeechEncoderIfNecessary(encoder_factory_.get());
   if (!encoder_factory_->codec_manager.SetCodecFEC(enable_codec_fec)) {
     return -1;
   }
@@ -507,6 +591,7 @@
   // Note: |enable_vad| is not used; VAD is enabled based on the DTX setting.
   RTC_DCHECK_EQ(enable_dtx, enable_vad);
   rtc::CritScope lock(&acm_crit_sect_);
+  CreateSpeechEncoderIfNecessary(encoder_factory_.get());
   if (!encoder_factory_->codec_manager.SetVAD(enable_dtx, mode)) {
     return -1;
   }
diff --git a/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.h b/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.h
index cdf4944..195ec28 100644
--- a/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.h
+++ b/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.h
@@ -30,6 +30,8 @@
 
 namespace acm2 {
 
+struct EncoderFactory;
+
 class AudioCodingModuleImpl final : public AudioCodingModule {
  public:
   friend webrtc::AudioCodingImpl;
@@ -249,16 +251,12 @@
   AcmReceiver receiver_;  // AcmReceiver has it's own internal lock.
   ChangeLogger bitrate_logger_ GUARDED_BY(acm_crit_sect_);
 
-  struct EncoderFactory {
-    CodecManager codec_manager;
-    RentACodec rent_a_codec;
-  };
   std::unique_ptr<EncoderFactory> encoder_factory_ GUARDED_BY(acm_crit_sect_);
 
   // Current encoder stack, either obtained from
   // encoder_factory_->rent_a_codec.RentEncoderStack or provided by a call to
   // RegisterEncoder.
-  AudioEncoder* encoder_stack_ GUARDED_BY(acm_crit_sect_);
+  std::unique_ptr<AudioEncoder> encoder_stack_ GUARDED_BY(acm_crit_sect_);
 
   // This is to keep track of CN instances where we can send DTMFs.
   uint8_t previous_pltype_ GUARDED_BY(acm_crit_sect_);
diff --git a/webrtc/modules/audio_coding/acm2/audio_coding_module_unittest_oldapi.cc b/webrtc/modules/audio_coding/acm2/audio_coding_module_unittest_oldapi.cc
index 463ff7b..6e004f9 100644
--- a/webrtc/modules/audio_coding/acm2/audio_coding_module_unittest_oldapi.cc
+++ b/webrtc/modules/audio_coding/acm2/audio_coding_module_unittest_oldapi.cc
@@ -1632,6 +1632,7 @@
   MockAudioEncoder mock_encoder;
   // Set expectations on the mock encoder and also delegate the calls to the
   // real encoder.
+  EXPECT_CALL(mock_encoder, Die());
   EXPECT_CALL(mock_encoder, SampleRateHz())
       .Times(AtLeast(1))
       .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::SampleRateHz));
diff --git a/webrtc/modules/audio_coding/acm2/codec_manager.cc b/webrtc/modules/audio_coding/acm2/codec_manager.cc
index ad67377..81adf81 100644
--- a/webrtc/modules/audio_coding/acm2/codec_manager.cc
+++ b/webrtc/modules/audio_coding/acm2/codec_manager.cc
@@ -113,7 +113,7 @@
   }
 
   send_codec_inst_ = rtc::Optional<CodecInst>(send_codec);
-  codec_stack_params_.speech_encoder = nullptr;  // Caller must recreate it.
+  codec_stack_params_.speech_encoder.reset();  // Caller must recreate it.
   return true;
 }
 
diff --git a/webrtc/modules/audio_coding/acm2/codec_manager.h b/webrtc/modules/audio_coding/acm2/codec_manager.h
index 660a9c0..fbd3a18 100644
--- a/webrtc/modules/audio_coding/acm2/codec_manager.h
+++ b/webrtc/modules/audio_coding/acm2/codec_manager.h
@@ -41,6 +41,9 @@
   const CodecInst* GetCodecInst() const {
     return send_codec_inst_ ? &*send_codec_inst_ : nullptr;
   }
+
+  void UnsetCodecInst() { send_codec_inst_ = rtc::Optional<CodecInst>(); }
+
   const RentACodec::StackParameters* GetStackParams() const {
     return &codec_stack_params_;
   }
diff --git a/webrtc/modules/audio_coding/acm2/codec_manager_unittest.cc b/webrtc/modules/audio_coding/acm2/codec_manager_unittest.cc
index 8320614..e8fe144 100644
--- a/webrtc/modules/audio_coding/acm2/codec_manager_unittest.cc
+++ b/webrtc/modules/audio_coding/acm2/codec_manager_unittest.cc
@@ -37,36 +37,32 @@
 TEST(CodecManagerTest, ExternalEncoderFec) {
   auto enc0 = CreateMockEncoder();
   auto enc1 = CreateMockEncoder();
+  auto enc2 = CreateMockEncoder();
   {
     ::testing::InSequence s;
     EXPECT_CALL(*enc0, SetFec(false)).WillOnce(Return(true));
-    EXPECT_CALL(*enc0, Mark("A"));
-    EXPECT_CALL(*enc0, SetFec(true)).WillOnce(Return(true));
     EXPECT_CALL(*enc1, SetFec(true)).WillOnce(Return(true));
-    EXPECT_CALL(*enc1, SetFec(false)).WillOnce(Return(true));
-    EXPECT_CALL(*enc0, Mark("B"));
-    EXPECT_CALL(*enc0, SetFec(false)).WillOnce(Return(true));
+    EXPECT_CALL(*enc2, SetFec(true)).WillOnce(Return(false));
   }
 
   CodecManager cm;
   RentACodec rac;
+
+  // use_codec_fec starts out false.
   EXPECT_FALSE(cm.GetStackParams()->use_codec_fec);
-  cm.GetStackParams()->speech_encoder = enc0.get();
+  cm.GetStackParams()->speech_encoder = std::move(enc0);
   EXPECT_TRUE(rac.RentEncoderStack(cm.GetStackParams()));
   EXPECT_FALSE(cm.GetStackParams()->use_codec_fec);
-  enc0->Mark("A");
+
+  // Set it to true.
   EXPECT_EQ(true, cm.SetCodecFEC(true));
-  EXPECT_TRUE(rac.RentEncoderStack(cm.GetStackParams()));
   EXPECT_TRUE(cm.GetStackParams()->use_codec_fec);
-  cm.GetStackParams()->speech_encoder = enc1.get();
+  cm.GetStackParams()->speech_encoder = std::move(enc1);
   EXPECT_TRUE(rac.RentEncoderStack(cm.GetStackParams()));
   EXPECT_TRUE(cm.GetStackParams()->use_codec_fec);
 
-  EXPECT_EQ(true, cm.SetCodecFEC(false));
-  EXPECT_TRUE(rac.RentEncoderStack(cm.GetStackParams()));
-  enc0->Mark("B");
-  EXPECT_FALSE(cm.GetStackParams()->use_codec_fec);
-  cm.GetStackParams()->speech_encoder = enc0.get();
+  // Switch to a codec that doesn't support it.
+  cm.GetStackParams()->speech_encoder = std::move(enc2);
   EXPECT_TRUE(rac.RentEncoderStack(cm.GetStackParams()));
   EXPECT_FALSE(cm.GetStackParams()->use_codec_fec);
 }
diff --git a/webrtc/modules/audio_coding/acm2/rent_a_codec.cc b/webrtc/modules/audio_coding/acm2/rent_a_codec.cc
index 91c5e4d..f37b12c 100644
--- a/webrtc/modules/audio_coding/acm2/rent_a_codec.cc
+++ b/webrtc/modules/audio_coding/acm2/rent_a_codec.cc
@@ -179,25 +179,28 @@
   return std::unique_ptr<AudioEncoder>();
 }
 
-std::unique_ptr<AudioEncoder> CreateRedEncoder(AudioEncoder* encoder,
-                                               int red_payload_type) {
+std::unique_ptr<AudioEncoder> CreateRedEncoder(
+    std::unique_ptr<AudioEncoder> encoder,
+    int red_payload_type) {
 #ifdef WEBRTC_CODEC_RED
   AudioEncoderCopyRed::Config config;
   config.payload_type = red_payload_type;
-  config.speech_encoder = encoder;
-  return std::unique_ptr<AudioEncoder>(new AudioEncoderCopyRed(config));
+  config.speech_encoder = std::move(encoder);
+  return std::unique_ptr<AudioEncoder>(
+      new AudioEncoderCopyRed(std::move(config)));
 #else
   return std::unique_ptr<AudioEncoder>();
 #endif
 }
 
-std::unique_ptr<AudioEncoder> CreateCngEncoder(AudioEncoder* encoder,
-                                               int payload_type,
-                                               ACMVADMode vad_mode) {
+std::unique_ptr<AudioEncoder> CreateCngEncoder(
+    std::unique_ptr<AudioEncoder> encoder,
+    int payload_type,
+    ACMVADMode vad_mode) {
   AudioEncoderCng::Config config;
   config.num_channels = encoder->NumChannels();
   config.payload_type = payload_type;
-  config.speech_encoder = encoder;
+  config.speech_encoder = std::move(encoder);
   switch (vad_mode) {
     case VADNormal:
       config.vad_mode = Vad::kVadNormal;
@@ -214,7 +217,7 @@
     default:
       FATAL();
   }
-  return std::unique_ptr<AudioEncoder>(new AudioEncoderCng(config));
+  return std::unique_ptr<AudioEncoder>(new AudioEncoderCng(std::move(config)));
 }
 
 std::unique_ptr<AudioDecoder> CreateIsacDecoder(
@@ -234,13 +237,9 @@
 RentACodec::RentACodec() = default;
 RentACodec::~RentACodec() = default;
 
-AudioEncoder* RentACodec::RentEncoder(const CodecInst& codec_inst) {
-  std::unique_ptr<AudioEncoder> enc =
-      CreateEncoder(codec_inst, &isac_bandwidth_info_);
-  if (!enc)
-    return nullptr;
-  speech_encoder_ = std::move(enc);
-  return speech_encoder_.get();
+std::unique_ptr<AudioEncoder> RentACodec::RentEncoder(
+    const CodecInst& codec_inst) {
+  return CreateEncoder(codec_inst, &isac_bandwidth_info_);
 }
 
 RentACodec::StackParameters::StackParameters() {
@@ -253,7 +252,8 @@
 
 RentACodec::StackParameters::~StackParameters() = default;
 
-AudioEncoder* RentACodec::RentEncoderStack(StackParameters* param) {
+std::unique_ptr<AudioEncoder> RentACodec::RentEncoderStack(
+    StackParameters* param) {
   RTC_DCHECK(param->speech_encoder);
 
   if (param->use_codec_fec) {
@@ -282,19 +282,14 @@
     // reset the latter to ensure its buffer is empty.
     param->speech_encoder->Reset();
   }
-  AudioEncoder* encoder_stack = param->speech_encoder;
+  std::unique_ptr<AudioEncoder> encoder_stack =
+      std::move(param->speech_encoder);
   if (param->use_red) {
-    red_encoder_ = CreateRedEncoder(encoder_stack, *red_pt);
-    if (red_encoder_)
-      encoder_stack = red_encoder_.get();
-  } else {
-    red_encoder_.reset();
+    encoder_stack = CreateRedEncoder(std::move(encoder_stack), *red_pt);
   }
   if (param->use_cng) {
-    cng_encoder_ = CreateCngEncoder(encoder_stack, *cng_pt, param->vad_mode);
-    encoder_stack = cng_encoder_.get();
-  } else {
-    cng_encoder_.reset();
+    encoder_stack =
+        CreateCngEncoder(std::move(encoder_stack), *cng_pt, param->vad_mode);
   }
   return encoder_stack;
 }
diff --git a/webrtc/modules/audio_coding/acm2/rent_a_codec.h b/webrtc/modules/audio_coding/acm2/rent_a_codec.h
index dd2dece..d6f159a 100644
--- a/webrtc/modules/audio_coding/acm2/rent_a_codec.h
+++ b/webrtc/modules/audio_coding/acm2/rent_a_codec.h
@@ -197,15 +197,15 @@
   ~RentACodec();
 
   // Creates and returns an audio encoder built to the given specification.
-  // Returns null in case of error. The returned encoder is live until the next
-  // successful call to this function, or until the Rent-A-Codec is destroyed.
-  AudioEncoder* RentEncoder(const CodecInst& codec_inst);
+  // Returns null in case of error.
+  std::unique_ptr<AudioEncoder> RentEncoder(const CodecInst& codec_inst);
 
   struct StackParameters {
     StackParameters();
     ~StackParameters();
 
-    AudioEncoder* speech_encoder = nullptr;
+    std::unique_ptr<AudioEncoder> speech_encoder;
+
     bool use_codec_fec = false;
     bool use_red = false;
     bool use_cng = false;
@@ -218,10 +218,9 @@
 
   // Creates and returns an audio encoder stack constructed to the given
   // specification. If the specification isn't compatible with the encoder, it
-  // 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(StackParameters* param);
+  // will be changed to match (things will be switched off). The speech encoder
+  // will be stolen.
+  std::unique_ptr<AudioEncoder> RentEncoderStack(StackParameters* param);
 
   // Creates and returns an iSAC decoder, which will remain live until the
   // Rent-A-Codec is destroyed. Subsequent calls will simply return the same
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 8cc59d6..cbdd5e9 100644
--- a/webrtc/modules/audio_coding/acm2/rent_a_codec_unittest.cc
+++ b/webrtc/modules/audio_coding/acm2/rent_a_codec_unittest.cc
@@ -19,22 +19,29 @@
 using ::testing::Return;
 
 namespace {
+
 const int kDataLengthSamples = 80;
 const int kPacketSizeSamples = 2 * kDataLengthSamples;
 const int16_t kZeroData[kDataLengthSamples] = {0};
 const CodecInst kDefaultCodecInst = {0, "pcmu", 8000, kPacketSizeSamples,
                                      1, 64000};
 const int kCngPt = 13;
+
+class Marker final {
+ public:
+  MOCK_METHOD1(Mark, void(std::string desc));
+};
+
 }  // namespace
 
 class RentACodecTestF : public ::testing::Test {
  protected:
   void CreateCodec() {
-    speech_encoder_ = rent_a_codec_.RentEncoder(kDefaultCodecInst);
-    ASSERT_TRUE(speech_encoder_);
+    auto speech_encoder = rent_a_codec_.RentEncoder(kDefaultCodecInst);
+    ASSERT_TRUE(speech_encoder);
     RentACodec::StackParameters param;
     param.use_cng = true;
-    param.speech_encoder = speech_encoder_;
+    param.speech_encoder = std::move(speech_encoder);
     encoder_ = rent_a_codec_.RentEncoderStack(&param);
   }
 
@@ -58,8 +65,7 @@
   }
 
   RentACodec rent_a_codec_;
-  AudioEncoder* speech_encoder_ = nullptr;
-  AudioEncoder* encoder_ = nullptr;
+  std::unique_ptr<AudioEncoder> encoder_;
   uint32_t timestamp_ = 0;
 };
 
@@ -103,87 +109,91 @@
 
 TEST(RentACodecTest, ExternalEncoder) {
   const int kSampleRateHz = 8000;
-  MockAudioEncoder external_encoder;
-  EXPECT_CALL(external_encoder, SampleRateHz())
+  auto* external_encoder = new MockAudioEncoder;
+  EXPECT_CALL(*external_encoder, SampleRateHz())
       .WillRepeatedly(Return(kSampleRateHz));
-  EXPECT_CALL(external_encoder, NumChannels()).WillRepeatedly(Return(1));
-  EXPECT_CALL(external_encoder, SetFec(false)).WillRepeatedly(Return(true));
+  EXPECT_CALL(*external_encoder, NumChannels()).WillRepeatedly(Return(1));
+  EXPECT_CALL(*external_encoder, SetFec(false)).WillRepeatedly(Return(true));
 
   RentACodec rac;
   RentACodec::StackParameters param;
-  param.speech_encoder = &external_encoder;
-  EXPECT_EQ(&external_encoder, rac.RentEncoderStack(&param));
+  param.speech_encoder = std::unique_ptr<AudioEncoder>(external_encoder);
+  std::unique_ptr<AudioEncoder> encoder_stack = rac.RentEncoderStack(&param);
+  EXPECT_EQ(external_encoder, encoder_stack.get());
   const int kPacketSizeSamples = kSampleRateHz / 100;
   int16_t audio[kPacketSizeSamples] = {0};
   rtc::Buffer encoded;
   AudioEncoder::EncodedInfo info;
 
+  Marker marker;
   {
     ::testing::InSequence s;
     info.encoded_timestamp = 0;
-    EXPECT_CALL(external_encoder,
-                EncodeImpl(0, rtc::ArrayView<const int16_t>(audio),
-                               &encoded))
+    EXPECT_CALL(
+        *external_encoder,
+        EncodeImpl(0, rtc::ArrayView<const int16_t>(audio), &encoded))
         .WillOnce(Return(info));
-    EXPECT_CALL(external_encoder, Mark("A"));
-    EXPECT_CALL(external_encoder, Mark("B"));
-    info.encoded_timestamp = 2;
-    EXPECT_CALL(external_encoder,
-                EncodeImpl(2, rtc::ArrayView<const int16_t>(audio),
-                               &encoded))
-        .WillOnce(Return(info));
-    EXPECT_CALL(external_encoder, Die());
+    EXPECT_CALL(marker, Mark("A"));
+    EXPECT_CALL(marker, Mark("B"));
+    EXPECT_CALL(*external_encoder, Die());
+    EXPECT_CALL(marker, Mark("C"));
   }
 
-  info = external_encoder.Encode(0, audio, &encoded);
+  info = encoder_stack->Encode(0, audio, &encoded);
   EXPECT_EQ(0u, info.encoded_timestamp);
-  external_encoder.Mark("A");
+  marker.Mark("A");
 
   // Change to internal encoder.
   CodecInst codec_inst = kDefaultCodecInst;
   codec_inst.pacsize = kPacketSizeSamples;
   param.speech_encoder = rac.RentEncoder(codec_inst);
   ASSERT_TRUE(param.speech_encoder);
-  EXPECT_EQ(param.speech_encoder, rac.RentEncoderStack(&param));
+  AudioEncoder* enc = param.speech_encoder.get();
+  std::unique_ptr<AudioEncoder> stack = rac.RentEncoderStack(&param);
+  EXPECT_EQ(enc, stack.get());
 
   // Don't expect any more calls to the external encoder.
-  info = param.speech_encoder->Encode(1, audio, &encoded);
-  external_encoder.Mark("B");
-
-  // Change back to external encoder again.
-  param.speech_encoder = &external_encoder;
-  EXPECT_EQ(&external_encoder, rac.RentEncoderStack(&param));
-  info = external_encoder.Encode(2, audio, &encoded);
-  EXPECT_EQ(2u, info.encoded_timestamp);
+  info = stack->Encode(1, audio, &encoded);
+  marker.Mark("B");
+  encoder_stack.reset();
+  marker.Mark("C");
 }
 
 // Verify that the speech encoder's Reset method is called when CNG or RED
 // (or both) are switched on, but not when they're switched off.
 void TestCngAndRedResetSpeechEncoder(bool use_cng, bool use_red) {
-  MockAudioEncoder speech_encoder;
-  EXPECT_CALL(speech_encoder, NumChannels()).WillRepeatedly(Return(1));
-  EXPECT_CALL(speech_encoder, Max10MsFramesInAPacket())
-      .WillRepeatedly(Return(2));
-  EXPECT_CALL(speech_encoder, SampleRateHz()).WillRepeatedly(Return(8000));
-  EXPECT_CALL(speech_encoder, SetFec(false)).WillRepeatedly(Return(true));
+  auto make_enc = [] {
+    auto speech_encoder =
+        std::unique_ptr<MockAudioEncoder>(new MockAudioEncoder);
+    EXPECT_CALL(*speech_encoder, NumChannels()).WillRepeatedly(Return(1));
+    EXPECT_CALL(*speech_encoder, Max10MsFramesInAPacket())
+        .WillRepeatedly(Return(2));
+    EXPECT_CALL(*speech_encoder, SampleRateHz()).WillRepeatedly(Return(8000));
+    EXPECT_CALL(*speech_encoder, SetFec(false)).WillRepeatedly(Return(true));
+    return speech_encoder;
+  };
+  auto speech_encoder1 = make_enc();
+  auto speech_encoder2 = make_enc();
+  Marker marker;
   {
     ::testing::InSequence s;
-    EXPECT_CALL(speech_encoder, Mark("disabled"));
-    EXPECT_CALL(speech_encoder, Mark("enabled"));
+    EXPECT_CALL(marker, Mark("disabled"));
+    EXPECT_CALL(*speech_encoder1, Die());
+    EXPECT_CALL(marker, Mark("enabled"));
     if (use_cng || use_red)
-      EXPECT_CALL(speech_encoder, Reset());
-    EXPECT_CALL(speech_encoder, Die());
+      EXPECT_CALL(*speech_encoder2, Reset());
+    EXPECT_CALL(*speech_encoder2, Die());
   }
 
   RentACodec::StackParameters param1, param2;
-  param1.speech_encoder = &speech_encoder;
-  param2.speech_encoder = &speech_encoder;
+  param1.speech_encoder = std::move(speech_encoder1);
+  param2.speech_encoder = std::move(speech_encoder2);
   param2.use_cng = use_cng;
   param2.use_red = use_red;
-  speech_encoder.Mark("disabled");
+  marker.Mark("disabled");
   RentACodec rac;
   rac.RentEncoderStack(&param1);
-  speech_encoder.Mark("enabled");
+  marker.Mark("enabled");
   rac.RentEncoderStack(&param2);
 }