NetEq decoder database: Don't keep track of sample rate for builtin decoders

This allows us to get rid of the function that computes it, which gets
us one step closer to getting rid of the NetEqDecoder type.

BUG=webrtc:5801

Review-Url: https://codereview.webrtc.org/2021063002
Cr-Commit-Position: refs/heads/master@{#12974}
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
index 762c385..b3f307f 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
@@ -82,59 +82,4 @@
   }
 }
 
-int CodecSampleRateHz(NetEqDecoder codec_type) {
-  switch (codec_type) {
-    case NetEqDecoder::kDecoderPCMu:
-    case NetEqDecoder::kDecoderPCMa:
-    case NetEqDecoder::kDecoderPCMu_2ch:
-    case NetEqDecoder::kDecoderPCMa_2ch:
-#ifdef WEBRTC_CODEC_ILBC
-    case NetEqDecoder::kDecoderILBC:
-#endif
-    case NetEqDecoder::kDecoderPCM16B:
-    case NetEqDecoder::kDecoderPCM16B_2ch:
-    case NetEqDecoder::kDecoderPCM16B_5ch:
-    case NetEqDecoder::kDecoderCNGnb: {
-      return 8000;
-    }
-#if defined(WEBRTC_CODEC_ISACFX) || defined(WEBRTC_CODEC_ISAC)
-    case NetEqDecoder::kDecoderISAC:
-#endif
-    case NetEqDecoder::kDecoderPCM16Bwb:
-    case NetEqDecoder::kDecoderPCM16Bwb_2ch:
-#ifdef WEBRTC_CODEC_G722
-    case NetEqDecoder::kDecoderG722:
-    case NetEqDecoder::kDecoderG722_2ch:
-#endif
-    case NetEqDecoder::kDecoderCNGwb: {
-      return 16000;
-    }
-#ifdef WEBRTC_CODEC_ISAC
-    case NetEqDecoder::kDecoderISACswb:
-#endif
-    case NetEqDecoder::kDecoderPCM16Bswb32kHz:
-    case NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch:
-    case NetEqDecoder::kDecoderCNGswb32kHz: {
-      return 32000;
-    }
-    case NetEqDecoder::kDecoderPCM16Bswb48kHz:
-    case NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch: {
-      return 48000;
-    }
-#ifdef WEBRTC_CODEC_OPUS
-    case NetEqDecoder::kDecoderOpus:
-    case NetEqDecoder::kDecoderOpus_2ch: {
-      return 48000;
-    }
-#endif
-    case NetEqDecoder::kDecoderCNGswb48kHz: {
-      // TODO(tlegrand): Remove limitation once ACM has full 48 kHz support.
-      return 32000;
-    }
-    default: {
-      return -1;  // Undefined sample rate.
-    }
-  }
-}
-
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
index 579ccb3..8636922 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
@@ -29,8 +29,5 @@
 // Returns true if |codec_type| is supported.
 bool CodecSupported(NetEqDecoder codec_type);
 
-// Returns the sample rate for |codec_type|.
-int CodecSampleRateHz(NetEqDecoder codec_type);
-
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_AUDIO_CODING_NETEQ_AUDIO_DECODER_IMPL_H_
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
index f83afcc..cddc3eb 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
@@ -674,46 +674,6 @@
 #endif
 }  // namespace
 
-TEST(AudioDecoder, CodecSampleRateHz) {
-  EXPECT_EQ(8000, CodecSampleRateHz(NetEqDecoder::kDecoderPCMu));
-  EXPECT_EQ(8000, CodecSampleRateHz(NetEqDecoder::kDecoderPCMa));
-  EXPECT_EQ(8000, CodecSampleRateHz(NetEqDecoder::kDecoderPCMu_2ch));
-  EXPECT_EQ(8000, CodecSampleRateHz(NetEqDecoder::kDecoderPCMa_2ch));
-  EXPECT_EQ(has_ilbc ? 8000 : -1,
-            CodecSampleRateHz(NetEqDecoder::kDecoderILBC));
-  EXPECT_EQ(has_isac ? 16000 : -1,
-            CodecSampleRateHz(NetEqDecoder::kDecoderISAC));
-  EXPECT_EQ(has_isac_swb ? 32000 : -1,
-            CodecSampleRateHz(NetEqDecoder::kDecoderISACswb));
-  EXPECT_EQ(8000, CodecSampleRateHz(NetEqDecoder::kDecoderPCM16B));
-  EXPECT_EQ(16000, CodecSampleRateHz(NetEqDecoder::kDecoderPCM16Bwb));
-  EXPECT_EQ(32000, CodecSampleRateHz(NetEqDecoder::kDecoderPCM16Bswb32kHz));
-  EXPECT_EQ(48000, CodecSampleRateHz(NetEqDecoder::kDecoderPCM16Bswb48kHz));
-  EXPECT_EQ(8000, CodecSampleRateHz(NetEqDecoder::kDecoderPCM16B_2ch));
-  EXPECT_EQ(16000, CodecSampleRateHz(NetEqDecoder::kDecoderPCM16Bwb_2ch));
-  EXPECT_EQ(32000, CodecSampleRateHz(NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch));
-  EXPECT_EQ(48000, CodecSampleRateHz(NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch));
-  EXPECT_EQ(8000, CodecSampleRateHz(NetEqDecoder::kDecoderPCM16B_5ch));
-  EXPECT_EQ(has_g722 ? 16000 : -1,
-            CodecSampleRateHz(NetEqDecoder::kDecoderG722));
-  EXPECT_EQ(has_g722 ? 16000 : -1,
-            CodecSampleRateHz(NetEqDecoder::kDecoderG722_2ch));
-  EXPECT_EQ(-1, CodecSampleRateHz(NetEqDecoder::kDecoderRED));
-  EXPECT_EQ(-1, CodecSampleRateHz(NetEqDecoder::kDecoderAVT));
-  EXPECT_EQ(8000, CodecSampleRateHz(NetEqDecoder::kDecoderCNGnb));
-  EXPECT_EQ(16000, CodecSampleRateHz(NetEqDecoder::kDecoderCNGwb));
-  EXPECT_EQ(32000, CodecSampleRateHz(NetEqDecoder::kDecoderCNGswb32kHz));
-  EXPECT_EQ(has_opus ? 48000 : -1,
-            CodecSampleRateHz(NetEqDecoder::kDecoderOpus));
-  EXPECT_EQ(has_opus ? 48000 : -1,
-            CodecSampleRateHz(NetEqDecoder::kDecoderOpus_2ch));
-  EXPECT_EQ(48000, CodecSampleRateHz(NetEqDecoder::kDecoderOpus));
-  EXPECT_EQ(48000, CodecSampleRateHz(NetEqDecoder::kDecoderOpus_2ch));
-  // TODO(tlegrand): Change 32000 to 48000 below once ACM has 48 kHz support.
-  EXPECT_EQ(32000, CodecSampleRateHz(NetEqDecoder::kDecoderCNGswb48kHz));
-  EXPECT_EQ(-1, CodecSampleRateHz(NetEqDecoder::kDecoderArbitrary));
-}
-
 TEST(AudioDecoder, CodecSupported) {
   EXPECT_TRUE(CodecSupported(NetEqDecoder::kDecoderPCMu));
   EXPECT_TRUE(CodecSupported(NetEqDecoder::kDecoderPCMa));
diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.cc b/webrtc/modules/audio_coding/neteq/decoder_database.cc
index e5f4462..ce402a7 100644
--- a/webrtc/modules/audio_coding/neteq/decoder_database.cc
+++ b/webrtc/modules/audio_coding/neteq/decoder_database.cc
@@ -28,14 +28,22 @@
 DecoderDatabase::~DecoderDatabase() = default;
 
 DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
+                                          const std::string& nm)
+    : codec_type(ct),
+      name(nm),
+      audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)),
+      cng_decoder_(CngDecoder::Create(ct)) {}
+
+DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
                                           const std::string& nm,
-                                          int fs,
+                                          int sample_rate_hz,
                                           AudioDecoder* ext_dec)
     : codec_type(ct),
       name(nm),
-      fs_hz(fs),
-      external_decoder(ext_dec),
-      audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)) {}
+      audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)),
+      external_decoder({sample_rate_hz, ext_dec}) {
+  RTC_CHECK(ext_dec);
+}
 
 DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
 DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
@@ -44,7 +52,8 @@
     AudioDecoderFactory* factory) {
   if (external_decoder) {
     RTC_DCHECK(!decoder_);
-    return external_decoder;
+    RTC_DCHECK(external_decoder->decoder);
+    return external_decoder->decoder;
   }
   RTC_DCHECK(audio_format_);
   if (!decoder_) {
@@ -54,6 +63,26 @@
   return decoder_.get();
 }
 
+rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>
+DecoderDatabase::DecoderInfo::CngDecoder::Create(NetEqDecoder ct) {
+  const auto cng = [](int sample_rate_hz) {
+    return rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>(
+        {sample_rate_hz});
+  };
+  switch (ct) {
+    case NetEqDecoder::kDecoderCNGnb:
+      return cng(8000);
+    case NetEqDecoder::kDecoderCNGwb:
+      return cng(16000);
+    case NetEqDecoder::kDecoderCNGswb32kHz:
+      return cng(32000);
+    case NetEqDecoder::kDecoderCNGswb48kHz:
+      return cng(48000);
+    default:
+      return rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>();
+  }
+}
+
 bool DecoderDatabase::Empty() const { return decoders_.empty(); }
 
 int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
@@ -73,8 +102,7 @@
   if (!CodecSupported(codec_type)) {
     return kCodecNotSupported;
   }
-  const int fs_hz = CodecSampleRateHz(codec_type);
-  DecoderInfo info(codec_type, name, fs_hz, nullptr);
+  DecoderInfo info(codec_type, name);
   auto ret =
       decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
   if (ret.second == false) {
@@ -247,8 +275,6 @@
       assert(false);
       return kDecoderNotFound;
     }
-    // The CNG decoder should never be provided externally.
-    RTC_CHECK(!it->second.external_decoder);
     active_cng_decoder_.reset();
   }
   active_cng_decoder_type_ = rtp_payload_type;
diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.h b/webrtc/modules/audio_coding/neteq/decoder_database.h
index 72b43df..4169dc2 100644
--- a/webrtc/modules/audio_coding/neteq/decoder_database.h
+++ b/webrtc/modules/audio_coding/neteq/decoder_database.h
@@ -41,9 +41,10 @@
   // Class that stores decoder info in the database.
   class DecoderInfo {
    public:
+    DecoderInfo(NetEqDecoder ct, const std::string& nm);
     DecoderInfo(NetEqDecoder ct,
                 const std::string& nm,
-                int fs,
+                int sample_rate_hz,
                 AudioDecoder* ext_dec);
     DecoderInfo(DecoderInfo&&);
     ~DecoderInfo();
@@ -55,14 +56,35 @@
     // always recreate it later if we need it.)
     void DropDecoder() { decoder_.reset(); }
 
+    int SampleRateHz() const {
+      RTC_DCHECK_EQ(1, !!decoder_ + !!external_decoder + !!cng_decoder_);
+      return decoder_ ? decoder_->SampleRateHz()
+                      : external_decoder ? external_decoder->sample_rate_hz
+                                         : cng_decoder_->sample_rate_hz;
+    }
+
     const NetEqDecoder codec_type;
     const std::string name;
-    const int fs_hz;
-    AudioDecoder* const external_decoder;
 
    private:
     const rtc::Optional<SdpAudioFormat> audio_format_;
     std::unique_ptr<AudioDecoder> decoder_;
+
+    // Set iff this is an external decoder.
+    struct ExternalDecoder {
+      // TODO(kwiberg): Remove sample_rate_hz once we can trust all decoders to
+      // implement SampleRateHz().
+      int sample_rate_hz;
+      AudioDecoder* decoder;
+    };
+    const rtc::Optional<ExternalDecoder> external_decoder;
+
+    // Set iff this is a comfort noise decoder.
+    struct CngDecoder {
+      static rtc::Optional<CngDecoder> Create(NetEqDecoder ct);
+      int sample_rate_hz;
+    };
+    const rtc::Optional<CngDecoder> cng_decoder_;
   };
 
   // Maximum value for 8 bits, and an invalid RTP payload type (since it is
diff --git a/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc b/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc
index 9efc2fc..1aade2c 100644
--- a/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc
@@ -22,6 +22,9 @@
 #include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h"
 #include "webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h"
 
+using testing::_;
+using testing::Invoke;
+
 namespace webrtc {
 
 TEST(DecoderDatabase, CreateAndDestroy) {
@@ -45,7 +48,16 @@
 }
 
 TEST(DecoderDatabase, GetDecoderInfo) {
-  DecoderDatabase db(new rtc::RefCountedObject<MockAudioDecoderFactory>);
+  rtc::scoped_refptr<MockAudioDecoderFactory> factory(
+      new rtc::RefCountedObject<MockAudioDecoderFactory>);
+  auto* decoder = new MockAudioDecoder;
+  EXPECT_CALL(*factory, MakeAudioDecoderMock(_, _))
+      .WillOnce(Invoke([decoder](const SdpAudioFormat& format,
+                                 std::unique_ptr<AudioDecoder>* dec) {
+        EXPECT_EQ("pcmu", format.name);
+        dec->reset(decoder);
+      }));
+  DecoderDatabase db(factory);
   const uint8_t kPayloadType = 0;
   const std::string kCodecName = "Robert\'); DROP TABLE Students;";
   EXPECT_EQ(
@@ -55,9 +67,8 @@
   info = db.GetDecoderInfo(kPayloadType);
   ASSERT_TRUE(info != NULL);
   EXPECT_EQ(NetEqDecoder::kDecoderPCMu, info->codec_type);
-  EXPECT_EQ(nullptr, info->external_decoder);
-  EXPECT_EQ(8000, info->fs_hz);
   EXPECT_EQ(kCodecName, info->name);
+  EXPECT_EQ(decoder, db.GetDecoder(kPayloadType));
   info = db.GetDecoderInfo(kPayloadType + 1);  // Other payload type.
   EXPECT_TRUE(info == NULL);  // Should not be found.
 }
@@ -140,8 +151,6 @@
   ASSERT_TRUE(info != NULL);
   EXPECT_EQ(NetEqDecoder::kDecoderPCMu, info->codec_type);
   EXPECT_EQ(kCodecName, info->name);
-  EXPECT_EQ(&decoder, info->external_decoder);
-  EXPECT_EQ(8000, info->fs_hz);
   // Expect not to delete the decoder when removing it from the database, since
   // it was declared externally.
   EXPECT_CALL(decoder, Die()).Times(0);
diff --git a/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h b/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h
index c1cc09c..6152799 100644
--- a/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h
+++ b/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h
@@ -32,6 +32,7 @@
   MOCK_METHOD0(ErrorCode, int());
   MOCK_CONST_METHOD2(PacketDuration, int(const uint8_t*, size_t));
   MOCK_CONST_METHOD0(Channels, size_t());
+  MOCK_CONST_METHOD0(SampleRateHz, int());
   MOCK_CONST_METHOD0(codec_type, NetEqDecoder());
   MOCK_METHOD1(CodecSupported, bool(NetEqDecoder));
 };
diff --git a/webrtc/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc
index f92e36c..f4f65ae 100644
--- a/webrtc/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc
@@ -31,10 +31,11 @@
   static const int kFrameSizeMs = 10;  // Frame size of Pcm16B.
 
   NetEqExternalDecoderUnitTest(NetEqDecoder codec,
+                               int sample_rate_hz,
                                MockExternalPcm16B* decoder)
-      : NetEqExternalDecoderTest(codec, decoder),
+      : NetEqExternalDecoderTest(codec, sample_rate_hz, decoder),
         external_decoder_(decoder),
-        samples_per_ms_(CodecSampleRateHz(codec) / 1000),
+        samples_per_ms_(sample_rate_hz / 1000),
         frame_size_samples_(kFrameSizeMs * samples_per_ms_),
         rtp_generator_(new test::RtpGenerator(samples_per_ms_)),
         input_(new int16_t[frame_size_samples_]),
@@ -173,12 +174,11 @@
 
   NetEqExternalVsInternalDecoderTest()
       : NetEqExternalDecoderUnitTest(NetEqDecoder::kDecoderPCM16Bswb32kHz,
+                                     32000,
                                      new MockExternalPcm16B),
-        sample_rate_hz_(
-            CodecSampleRateHz(NetEqDecoder::kDecoderPCM16Bswb32kHz)) {
+        sample_rate_hz_(32000) {
     NetEq::Config config;
-    config.sample_rate_hz =
-        CodecSampleRateHz(NetEqDecoder::kDecoderPCM16Bswb32kHz);
+    config.sample_rate_hz = sample_rate_hz_;
     neteq_internal_.reset(
         NetEq::Create(config, CreateBuiltinAudioDecoderFactory()));
   }
@@ -247,6 +247,7 @@
 
   LargeTimestampJumpTest()
       : NetEqExternalDecoderUnitTest(NetEqDecoder::kDecoderPCM16B,
+                                     8000,
                                      new MockExternalPcm16B),
         test_state_(kInitialPhase) {
     EXPECT_CALL(*external_decoder(), HasDecodePlc())
diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
index 87d12f5..b8e8c71 100644
--- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc
+++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
@@ -761,9 +761,10 @@
     const DecoderDatabase::DecoderInfo* decoder_info =
         decoder_database_->GetDecoderInfo(payload_type);
     assert(decoder_info);
-    if (decoder_info->fs_hz != fs_hz_ ||
+    if (decoder_info->SampleRateHz() != fs_hz_ ||
         channels != algorithm_buffer_->Channels()) {
-      SetSampleRateAndChannels(decoder_info->fs_hz, channels);
+      SetSampleRateAndChannels(decoder_info->SampleRateHz(),
+                               channels);
     }
     if (nack_enabled_) {
       RTC_DCHECK(nack_);
@@ -1347,10 +1348,11 @@
         }
         // If sampling rate or number of channels has changed, we need to make
         // a reset.
-        if (decoder_info->fs_hz != fs_hz_ ||
+        if (decoder_info->SampleRateHz() != fs_hz_ ||
             decoder->Channels() != algorithm_buffer_->Channels()) {
           // TODO(tlegrand): Add unittest to cover this event.
-          SetSampleRateAndChannels(decoder_info->fs_hz, decoder->Channels());
+          SetSampleRateAndChannels(decoder_info->SampleRateHz(),
+                                   decoder->Channels());
         }
         sync_buffer_->set_end_timestamp(timestamp_);
         playout_timestamp_ = timestamp_;
diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc
index 6e6226a..34e36dc 100644
--- a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc
@@ -17,6 +17,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webrtc/base/safe_conversions.h"
 #include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h"
+#include "webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h"
 #include "webrtc/modules/audio_coding/neteq/accelerate.h"
 #include "webrtc/modules/audio_coding/neteq/expand.h"
 #include "webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h"
@@ -244,22 +245,31 @@
   rtp_header.header.timestamp = kFirstTimestamp;
   rtp_header.header.ssrc = kSsrc;
 
-  // Create a mock decoder object.
-  MockAudioDecoder mock_decoder;
-  EXPECT_CALL(mock_decoder, Channels()).WillRepeatedly(Return(1));
-  // BWE update function called with first packet.
-  EXPECT_CALL(mock_decoder, IncomingPacket(_,
-                                           kPayloadLength,
-                                           kFirstSequenceNumber,
-                                           kFirstTimestamp,
-                                           kFirstReceiveTime));
-  // BWE update function called with second packet.
-  EXPECT_CALL(mock_decoder, IncomingPacket(_,
-                                           kPayloadLength,
-                                           kFirstSequenceNumber + 1,
-                                           kFirstTimestamp + 160,
-                                           kFirstReceiveTime + 155));
-  EXPECT_CALL(mock_decoder, Die()).Times(1);  // Called when deleted.
+  rtc::scoped_refptr<MockAudioDecoderFactory> mock_decoder_factory(
+      new rtc::RefCountedObject<MockAudioDecoderFactory>);
+  EXPECT_CALL(*mock_decoder_factory, MakeAudioDecoderMock(_, _))
+      .WillOnce(Invoke([kPayloadLength, kFirstSequenceNumber, kFirstTimestamp,
+                        kFirstReceiveTime](const SdpAudioFormat& format,
+                                           std::unique_ptr<AudioDecoder>* dec) {
+        EXPECT_EQ("pcmu", format.name);
+
+        std::unique_ptr<MockAudioDecoder> mock_decoder(new MockAudioDecoder);
+        EXPECT_CALL(*mock_decoder, Channels()).WillRepeatedly(Return(1));
+        EXPECT_CALL(*mock_decoder, SampleRateHz()).WillRepeatedly(Return(8000));
+        // BWE update function called with first packet.
+        EXPECT_CALL(*mock_decoder,
+                    IncomingPacket(_, kPayloadLength, kFirstSequenceNumber,
+                                   kFirstTimestamp, kFirstReceiveTime));
+        // BWE update function called with second packet.
+        EXPECT_CALL(
+            *mock_decoder,
+            IncomingPacket(_, kPayloadLength, kFirstSequenceNumber + 1,
+                           kFirstTimestamp + 160, kFirstReceiveTime + 155));
+        EXPECT_CALL(*mock_decoder, Die()).Times(1);  // Called when deleted.
+
+        *dec = std::move(mock_decoder);
+      }));
+  DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, "");
 
   // Expectations for decoder database.
   EXPECT_CALL(*mock_decoder_database_, IsRed(kPayloadType))
@@ -271,11 +281,12 @@
       .WillRepeatedly(Return(false));  // This is not DTMF.
   EXPECT_CALL(*mock_decoder_database_, GetDecoder(kPayloadType))
       .Times(3)
-      .WillRepeatedly(Return(&mock_decoder));
+      .WillRepeatedly(
+          Invoke([&info, mock_decoder_factory](uint8_t payload_type) {
+            return info.GetDecoder(mock_decoder_factory);
+          }));
   EXPECT_CALL(*mock_decoder_database_, IsComfortNoise(kPayloadType))
       .WillRepeatedly(Return(false));  // This is not CNG.
-  DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, "", 8000,
-                                    nullptr);
   EXPECT_CALL(*mock_decoder_database_, GetDecoderInfo(kPayloadType))
       .WillRepeatedly(Return(&info));
 
diff --git a/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
index 1a77abc..cf413a4 100644
--- a/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
@@ -113,16 +113,17 @@
   NetEqNetworkStatistics stats_ref;
 };
 
-  NetEqNetworkStatsTest(NetEqDecoder codec,
-                        MockAudioDecoder* decoder)
-      : NetEqExternalDecoderTest(codec, decoder),
-        external_decoder_(decoder),
-        samples_per_ms_(CodecSampleRateHz(codec) / 1000),
-        frame_size_samples_(kFrameSizeMs * samples_per_ms_),
-        rtp_generator_(new test::RtpGenerator(samples_per_ms_)),
-        last_lost_time_(0),
-        packet_loss_interval_(0xffffffff) {
-    Init();
+NetEqNetworkStatsTest(NetEqDecoder codec,
+                      int sample_rate_hz,
+                      MockAudioDecoder* decoder)
+    : NetEqExternalDecoderTest(codec, sample_rate_hz, decoder),
+      external_decoder_(decoder),
+      samples_per_ms_(sample_rate_hz / 1000),
+      frame_size_samples_(kFrameSizeMs * samples_per_ms_),
+      rtp_generator_(new test::RtpGenerator(samples_per_ms_)),
+      last_lost_time_(0),
+      packet_loss_interval_(0xffffffff) {
+  Init();
   }
 
   bool Lost(uint32_t send_time) {
@@ -278,21 +279,21 @@
 
 TEST(NetEqNetworkStatsTest, DecodeFec) {
   MockAudioDecoder decoder(1);
-  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, &decoder);
+  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, 48000, &decoder);
   test.DecodeFecTest();
   EXPECT_CALL(decoder, Die()).Times(1);
 }
 
 TEST(NetEqNetworkStatsTest, StereoDecodeFec) {
   MockAudioDecoder decoder(2);
-  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, &decoder);
+  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, 48000, &decoder);
   test.DecodeFecTest();
   EXPECT_CALL(decoder, Die()).Times(1);
 }
 
 TEST(NetEqNetworkStatsTest, NoiseExpansionTest) {
   MockAudioDecoder decoder(1);
-  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, &decoder);
+  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, 48000, &decoder);
   test.NoiseExpansionTest();
   EXPECT_CALL(decoder, Die()).Times(1);
 }
diff --git a/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc b/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc
index 128bdcc..f0b16d0 100644
--- a/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc
@@ -375,33 +375,27 @@
   // codec types.
   // Use scoped pointers to avoid having to delete them later.
   std::unique_ptr<DecoderDatabase::DecoderInfo> info0(
-      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderISAC, "", 16000,
-                                       nullptr));
+      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderISAC, ""));
   EXPECT_CALL(decoder_database, GetDecoderInfo(0))
       .WillRepeatedly(Return(info0.get()));
   std::unique_ptr<DecoderDatabase::DecoderInfo> info1(
-      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderISACswb, "", 32000,
-                                       nullptr));
+      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderISACswb, ""));
   EXPECT_CALL(decoder_database, GetDecoderInfo(1))
       .WillRepeatedly(Return(info1.get()));
   std::unique_ptr<DecoderDatabase::DecoderInfo> info2(
-      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderRED, "", 8000,
-                                       nullptr));
+      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderRED, ""));
   EXPECT_CALL(decoder_database, GetDecoderInfo(2))
       .WillRepeatedly(Return(info2.get()));
   std::unique_ptr<DecoderDatabase::DecoderInfo> info3(
-      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderAVT, "", 8000,
-                                       nullptr));
+      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderAVT, ""));
   EXPECT_CALL(decoder_database, GetDecoderInfo(3))
       .WillRepeatedly(Return(info3.get()));
   std::unique_ptr<DecoderDatabase::DecoderInfo> info4(
-      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderCNGnb, "", 8000,
-                                       nullptr));
+      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderCNGnb, ""));
   EXPECT_CALL(decoder_database, GetDecoderInfo(4))
       .WillRepeatedly(Return(info4.get()));
   std::unique_ptr<DecoderDatabase::DecoderInfo> info5(
-      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderArbitrary, "",
-                                       8000, nullptr));
+      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderArbitrary, ""));
   EXPECT_CALL(decoder_database, GetDecoderInfo(5))
       .WillRepeatedly(Return(info5.get()));
 
@@ -539,7 +533,7 @@
   // Use scoped pointers to avoid having to delete them later.
   // (Sample rate is set to 8000 Hz, but does not matter.)
   std::unique_ptr<DecoderDatabase::DecoderInfo> info(
-      new DecoderDatabase::DecoderInfo(decoder_type_, "", 8000, nullptr));
+      new DecoderDatabase::DecoderInfo(decoder_type_, ""));
   EXPECT_CALL(decoder_database, GetDecoderInfo(kPayloadType))
       .WillRepeatedly(Return(info.get()));
 
@@ -626,8 +620,7 @@
   // codec types.
   // Use scoped pointers to avoid having to delete them later.
   std::unique_ptr<DecoderDatabase::DecoderInfo> info(
-      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderILBC, "", 8000,
-                                       nullptr));
+      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderILBC, ""));
   EXPECT_CALL(decoder_database, GetDecoderInfo(kPayloadType))
       .WillRepeatedly(Return(info.get()));
 
@@ -690,8 +683,7 @@
 
   MockDecoderDatabase decoder_database;
   std::unique_ptr<DecoderDatabase::DecoderInfo> info(
-      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderILBC, "", 8000,
-                                       nullptr));
+      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderILBC, ""));
   EXPECT_CALL(decoder_database, GetDecoderInfo(kPayloadType))
       .WillRepeatedly(Return(info.get()));
 
@@ -722,8 +714,7 @@
 
   MockDecoderDatabase decoder_database;
   std::unique_ptr<DecoderDatabase::DecoderInfo> info(
-      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderILBC, "", 8000,
-                                       nullptr));
+      new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderILBC, ""));
   EXPECT_CALL(decoder_database, GetDecoderInfo(kPayloadType))
       .WillRepeatedly(Return(info.get()));
 
diff --git a/webrtc/modules/audio_coding/neteq/timestamp_scaler_unittest.cc b/webrtc/modules/audio_coding/neteq/timestamp_scaler_unittest.cc
index adaf162..91e1342 100644
--- a/webrtc/modules/audio_coding/neteq/timestamp_scaler_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/timestamp_scaler_unittest.cc
@@ -24,8 +24,7 @@
 TEST(TimestampScaler, TestNoScaling) {
   MockDecoderDatabase db;
   // Use PCMu, because it doesn't use scaled timestamps.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, "", 8000,
-                                          nullptr);
+  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, "");
   static const uint8_t kRtpPayloadType = 0;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
       .WillRepeatedly(Return(&info));
@@ -45,8 +44,7 @@
 TEST(TimestampScaler, TestNoScalingLargeStep) {
   MockDecoderDatabase db;
   // Use PCMu, because it doesn't use scaled timestamps.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, "", 8000,
-                                          nullptr);
+  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, "");
   static const uint8_t kRtpPayloadType = 0;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
       .WillRepeatedly(Return(&info));
@@ -71,8 +69,7 @@
 TEST(TimestampScaler, TestG722) {
   MockDecoderDatabase db;
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "", 16000,
-                                          nullptr);
+  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "");
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
       .WillRepeatedly(Return(&info));
@@ -96,8 +93,7 @@
 TEST(TimestampScaler, TestG722LargeStep) {
   MockDecoderDatabase db;
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "", 16000,
-                                          nullptr);
+  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "");
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
       .WillRepeatedly(Return(&info));
@@ -125,10 +121,8 @@
 TEST(TimestampScaler, TestG722WithCng) {
   MockDecoderDatabase db;
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info_g722(NetEqDecoder::kDecoderG722, "",
-                                               16000, nullptr);
-  const DecoderDatabase::DecoderInfo info_cng(NetEqDecoder::kDecoderCNGwb, "",
-                                              16000, nullptr);
+  const DecoderDatabase::DecoderInfo info_g722(NetEqDecoder::kDecoderG722, "");
+  const DecoderDatabase::DecoderInfo info_cng(NetEqDecoder::kDecoderCNGwb, "");
   static const uint8_t kRtpPayloadTypeG722 = 17;
   static const uint8_t kRtpPayloadTypeCng = 13;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadTypeG722))
@@ -168,8 +162,7 @@
 TEST(TimestampScaler, TestG722Packet) {
   MockDecoderDatabase db;
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "", 16000,
-                                          nullptr);
+  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "");
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
       .WillRepeatedly(Return(&info));
@@ -197,8 +190,7 @@
 TEST(TimestampScaler, TestG722PacketList) {
   MockDecoderDatabase db;
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "", 16000,
-                                          nullptr);
+  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "");
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
       .WillRepeatedly(Return(&info));
@@ -227,8 +219,7 @@
 TEST(TimestampScaler, TestG722Reset) {
   MockDecoderDatabase db;
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "", 16000,
-                                          nullptr);
+  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "");
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
       .WillRepeatedly(Return(&info));
@@ -267,8 +258,7 @@
 // timestamp scaler.
 TEST(TimestampScaler, TestOpusLargeStep) {
   MockDecoderDatabase db;
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderOpus, "", 48000,
-                                          nullptr);
+  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderOpus, "");
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
       .WillRepeatedly(Return(&info));
diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc
index 206e0ab..cbbfd27 100644
--- a/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc
+++ b/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc
@@ -19,10 +19,11 @@
 namespace test {
 
 NetEqExternalDecoderTest::NetEqExternalDecoderTest(NetEqDecoder codec,
+                                                   int sample_rate_hz,
                                                    AudioDecoder* decoder)
     : codec_(codec),
       decoder_(decoder),
-      sample_rate_hz_(CodecSampleRateHz(codec_)),
+      sample_rate_hz_(sample_rate_hz),
       channels_(decoder_->Channels()) {
   NetEq::Config config;
   config.sample_rate_hz = sample_rate_hz_;
diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h b/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h
index 8999d02..fb1c5b2 100644
--- a/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h
+++ b/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h
@@ -27,7 +27,9 @@
   static const int kOutputLengthMs = 10;
 
   // The external decoder |decoder| is suppose to be of type |codec|.
-  NetEqExternalDecoderTest(NetEqDecoder codec, AudioDecoder* decoder);
+  NetEqExternalDecoderTest(NetEqDecoder codec,
+                           int sample_rate_hz,
+                           AudioDecoder* decoder);
 
   virtual ~NetEqExternalDecoderTest() { }