diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/acm2/acm_receiver.cc index afd1ff44f6..89eee00fc3 100644 --- a/webrtc/modules/audio_coding/acm2/acm_receiver.cc +++ b/webrtc/modules/audio_coding/acm2/acm_receiver.cc @@ -202,8 +202,7 @@ int32_t AcmReceiver::AddCodec(int acm_codec_id, rtc::CritScope lock(&crit_sect_); - const SdpAudioFormat* const old_format = - neteq_->GetDecoderFormat(payload_type); + const auto old_format = neteq_->GetDecoderFormat(payload_type); if (old_format && new_format && *old_format == *new_format) { // Re-registering the same codec. Do nothing and return. 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 e7aebcd14b..9468f0c921 100644 --- a/webrtc/modules/audio_coding/acm2/rent_a_codec.cc +++ b/webrtc/modules/audio_coding/acm2/rent_a_codec.cc @@ -94,7 +94,19 @@ rtc::Optional RentACodec::NetEqDecoderToSdpAudioFormat( return rtc::Optional( SdpAudioFormat("opus", 48000, 2, std::map{{"stereo", "1"}})); - + case NetEqDecoder::kDecoderRED: + return rtc::Optional(SdpAudioFormat("red", 8000, 1)); + case NetEqDecoder::kDecoderAVT: + return rtc::Optional( + SdpAudioFormat("telephone-event", 8000, 1)); + case NetEqDecoder::kDecoderCNGnb: + return rtc::Optional(SdpAudioFormat("cn", 8000, 1)); + case NetEqDecoder::kDecoderCNGwb: + return rtc::Optional(SdpAudioFormat("cn", 16000, 1)); + case NetEqDecoder::kDecoderCNGswb32kHz: + return rtc::Optional(SdpAudioFormat("cn", 32000, 1)); + case NetEqDecoder::kDecoderCNGswb48kHz: + return rtc::Optional(SdpAudioFormat("cn", 48000, 1)); default: return rtc::Optional(); } diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.cc b/webrtc/modules/audio_coding/neteq/decoder_database.cc index f5fbad3446..27bc6d5697 100644 --- a/webrtc/modules/audio_coding/neteq/decoder_database.cc +++ b/webrtc/modules/audio_coding/neteq/decoder_database.cc @@ -26,23 +26,24 @@ DecoderDatabase::DecoderDatabase( DecoderDatabase::~DecoderDatabase() = default; -DecoderDatabase::DecoderInfo::DecoderInfo( - NetEqDecoder ct, - const std::string& nm, - AudioDecoderFactory* factory) - : codec_type(ct), - name(nm), - audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)), +DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format, + AudioDecoderFactory* factory) + : audio_format_(audio_format), factory_(factory), external_decoder_(nullptr), - cng_decoder_(CngDecoder::Create(ct)) {} + cng_decoder_(CngDecoder::Create(audio_format)) {} DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct, - const std::string& nm, + AudioDecoderFactory* factory) + : audio_format_(*acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)), + factory_(factory), + external_decoder_(nullptr), + cng_decoder_(CngDecoder::Create(audio_format_)) {} + +DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format, AudioDecoder* ext_dec) - : codec_type(ct), - name(nm), - audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)), + : audio_format_(audio_format), + factory_(nullptr), external_decoder_(ext_dec) { RTC_CHECK(ext_dec); } @@ -51,55 +52,52 @@ DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default; DecoderDatabase::DecoderInfo::~DecoderInfo() = default; AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const { + if (IsDtmf() || IsRed() || IsComfortNoise()) { + // These are handled internally, so they have no AudioDecoder objects. + return nullptr; + } if (external_decoder_) { RTC_DCHECK(!decoder_); RTC_DCHECK(!cng_decoder_); return external_decoder_; } - if (IsRed() || IsComfortNoise() || IsDtmf()) - return nullptr; - RTC_DCHECK(audio_format_); if (!decoder_) { + // TODO(ossu): Keep a check here for now, since a number of tests create + // DecoderInfos without factories. RTC_DCHECK(factory_); - decoder_ = factory_->MakeAudioDecoder(*audio_format_); + decoder_ = factory_->MakeAudioDecoder(audio_format_); } - RTC_DCHECK(decoder_) << "Failed to create: " << *audio_format_; + RTC_DCHECK(decoder_) << "Failed to create: " << audio_format_; return decoder_.get(); } - bool DecoderDatabase::DecoderInfo::IsComfortNoise() const { - return codec_type == NetEqDecoder::kDecoderCNGnb - || codec_type == NetEqDecoder::kDecoderCNGwb - || codec_type == NetEqDecoder::kDecoderCNGswb32kHz - || codec_type == NetEqDecoder::kDecoderCNGswb48kHz; + RTC_DCHECK_EQ(!!cng_decoder_, IsType("CN")); + return !!cng_decoder_; } bool DecoderDatabase::DecoderInfo::IsDtmf() const { - return codec_type == NetEqDecoder::kDecoderAVT; + return IsType("telephone-event"); } bool DecoderDatabase::DecoderInfo::IsRed() const { - return codec_type == NetEqDecoder::kDecoderRED; + return IsType("red"); +} + +bool DecoderDatabase::DecoderInfo::IsType(const char* name) const { + return STR_CASE_CMP(audio_format_.name.c_str(), name) == 0; +} + +bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const { + return IsType(name.c_str()); } rtc::Optional -DecoderDatabase::DecoderInfo::CngDecoder::Create(NetEqDecoder ct) { - const auto cng = [](int sample_rate_hz) { - return rtc::Optional( - {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::Create(const SdpAudioFormat& format) { + if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) { + return rtc::Optional({format.clockrate_hz}); + } else { + return rtc::Optional(); } } @@ -119,10 +117,18 @@ int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type, if (rtp_payload_type > 0x7F) { return kInvalidRtpPayloadType; } - if (!CodecSupported(codec_type)) { + // kCodecArbitrary is only supported through InsertExternal. + if (codec_type == NetEqDecoder::kDecoderArbitrary || + !CodecSupported(codec_type)) { return kCodecNotSupported; } - DecoderInfo info(codec_type, name, decoder_factory_.get()); + const auto opt_format = + acm2::RentACodec::NetEqDecoderToSdpAudioFormat(codec_type); + if (!opt_format) { + return kCodecNotSupported; + } + DecoderInfo info(*opt_format, decoder_factory_); + info.name = name; auto ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info))); if (ret.second == false) { @@ -139,14 +145,17 @@ int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type, if (rtp_payload_type > 0x7F) { return kInvalidRtpPayloadType; } - if (!CodecSupported(codec_type)) { - return kCodecNotSupported; - } if (!decoder) { return kInvalidPointer; } + + const auto opt_db_format = + acm2::RentACodec::NetEqDecoderToSdpAudioFormat(codec_type); + const SdpAudioFormat format = opt_db_format.value_or({"arbitrary", 0, 0}); + std::pair ret; - DecoderInfo info(codec_type, codec_name, decoder); + DecoderInfo info(format, decoder); + info.name = codec_name; ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info))); if (ret.second == false) { // Database already contains a decoder with type |rtp_payload_type|. @@ -182,20 +191,7 @@ const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo( // Decoder not found. return NULL; } - return &(*it).second; -} - -uint8_t DecoderDatabase::GetRtpPayloadType( - NetEqDecoder codec_type) const { - DecoderMap::const_iterator it; - for (it = decoders_.begin(); it != decoders_.end(); ++it) { - if ((*it).second.codec_type == codec_type) { - // Match found. - return (*it).first; - } - } - // No match. - return kRtpPayloadTypeError; + return &it->second; } int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type, @@ -264,10 +260,14 @@ AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const { return info ? info->GetDecoder() : nullptr; } +bool DecoderDatabase::IsType(uint8_t rtp_payload_type, const char* name) const { + const DecoderInfo* info = GetDecoderInfo(rtp_payload_type); + return info && info->IsType(name); +} + bool DecoderDatabase::IsType(uint8_t rtp_payload_type, - NetEqDecoder codec_type) const { - const DecoderInfo *info = GetDecoderInfo(rtp_payload_type); - return info && info->codec_type == codec_type; + const std::string& name) const { + return IsType(rtp_payload_type, name.c_str()); } bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const { @@ -298,5 +298,4 @@ int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const { return kOK; } - } // namespace webrtc diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.h b/webrtc/modules/audio_coding/neteq/decoder_database.h index 296d059f73..36248562bc 100644 --- a/webrtc/modules/audio_coding/neteq/decoder_database.h +++ b/webrtc/modules/audio_coding/neteq/decoder_database.h @@ -41,13 +41,11 @@ class DecoderDatabase { // Class that stores decoder info in the database. class DecoderInfo { public: - DecoderInfo( - NetEqDecoder ct, - const std::string& nm, - AudioDecoderFactory* factory = nullptr); - DecoderInfo(NetEqDecoder ct, - const std::string& nm, - AudioDecoder* ext_dec); + explicit DecoderInfo(const SdpAudioFormat& audio_format, + AudioDecoderFactory* factory = nullptr); + explicit DecoderInfo(NetEqDecoder ct, + AudioDecoderFactory* factory = nullptr); + DecoderInfo(const SdpAudioFormat& audio_format, AudioDecoder* ext_dec); DecoderInfo(DecoderInfo&&); ~DecoderInfo(); @@ -64,25 +62,30 @@ class DecoderDatabase { return decoder ? decoder->SampleRateHz() : cng_decoder_->sample_rate_hz; } - const SdpAudioFormat* GetFormat() const { - return audio_format_ ? &*audio_format_ : nullptr; - } + const SdpAudioFormat& GetFormat() const { return audio_format_; } - // Returns true if |codec_type| is comfort noise. + // Returns true if the decoder's format is comfort noise. bool IsComfortNoise() const; - // Returns true if |codec_type| is DTMF. + // Returns true if the decoder's format is DTMF. bool IsDtmf() const; - // Returns true if |codec_type| is RED. + // Returns true if the decoder's format is RED. bool IsRed() const; - const NetEqDecoder codec_type; - const std::string name; + // Returns true if the decoder's format is named |name|. + bool IsType(const char* name) const; + // Returns true if the decoder's format is named |name|. + bool IsType(const std::string& name) const; + + // TODO(ossu): |name| is kept here while we retain the old external decoder + // interface. Remove this once using an AudioDecoderFactory has + // supplanted the old functionality. + std::string name; private: - const rtc::Optional audio_format_; - AudioDecoderFactory* factory_; + const SdpAudioFormat audio_format_; + AudioDecoderFactory* const factory_; mutable std::unique_ptr decoder_; // Set iff this is an external decoder. @@ -90,7 +93,7 @@ class DecoderDatabase { // Set iff this is a comfort noise decoder. struct CngDecoder { - static rtc::Optional Create(NetEqDecoder ct); + static rtc::Optional Create(const SdpAudioFormat& format); int sample_rate_hz; }; const rtc::Optional cng_decoder_; @@ -142,12 +145,6 @@ class DecoderDatabase { // no decoder is registered with that |rtp_payload_type|, NULL is returned. virtual const DecoderInfo* GetDecoderInfo(uint8_t rtp_payload_type) const; - // Returns one RTP payload type associated with |codec_type|, or - // kDecoderNotFound if no entry exists for that value. Note that one - // |codec_type| may be registered with several RTP payload types, and the - // method may return any of them. - virtual uint8_t GetRtpPayloadType(NetEqDecoder codec_type) const; - // Sets the active decoder to be |rtp_payload_type|. If this call results in a // change of active decoder, |new_decoder| is set to true. The previous active // decoder's AudioDecoder object is deleted. @@ -174,8 +171,11 @@ class DecoderDatabase { // object does not exist for that decoder, the object is created. AudioDecoder* GetDecoder(uint8_t rtp_payload_type) const; - // Returns true if |rtp_payload_type| is registered as a |codec_type|. - bool IsType(uint8_t rtp_payload_type, NetEqDecoder codec_type) const; + // Returns if |rtp_payload_type| is registered with a format named |name|. + bool IsType(uint8_t rtp_payload_type, const char* name) const; + + // Returns if |rtp_payload_type| is registered with a format named |name|. + bool IsType(uint8_t rtp_payload_type, const std::string& name) const; // Returns true if |rtp_payload_type| is registered as comfort noise. bool IsComfortNoise(uint8_t rtp_payload_type) const; diff --git a/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc b/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc index 39c000c05e..6ddad14f12 100644 --- a/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc @@ -81,27 +81,13 @@ TEST(DecoderDatabase, GetDecoderInfo) { const DecoderDatabase::DecoderInfo* info; info = db.GetDecoderInfo(kPayloadType); ASSERT_TRUE(info != NULL); - EXPECT_EQ(NetEqDecoder::kDecoderPCMu, info->codec_type); + EXPECT_TRUE(info->IsType("pcmu")); 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. } -TEST(DecoderDatabase, GetRtpPayloadType) { - DecoderDatabase db(new rtc::RefCountedObject); - const uint8_t kPayloadType = 0; - const std::string kCodecName = "Robert\'); DROP TABLE Students;"; - EXPECT_EQ( - DecoderDatabase::kOK, - db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu, kCodecName)); - EXPECT_EQ(kPayloadType, db.GetRtpPayloadType(NetEqDecoder::kDecoderPCMu)); - const uint8_t expected_value = DecoderDatabase::kRtpPayloadTypeError; - EXPECT_EQ(expected_value, - db.GetRtpPayloadType( - NetEqDecoder::kDecoderISAC)); // iSAC is not registered. -} - TEST(DecoderDatabase, GetDecoder) { DecoderDatabase db(CreateBuiltinAudioDecoderFactory()); const uint8_t kPayloadType = 0; @@ -141,8 +127,8 @@ TEST(DecoderDatabase, TypeTests) { EXPECT_FALSE(db.IsComfortNoise(kPayloadTypePcmU)); EXPECT_FALSE(db.IsDtmf(kPayloadTypePcmU)); EXPECT_FALSE(db.IsRed(kPayloadTypePcmU)); - EXPECT_FALSE(db.IsType(kPayloadTypePcmU, NetEqDecoder::kDecoderISAC)); - EXPECT_TRUE(db.IsType(kPayloadTypePcmU, NetEqDecoder::kDecoderPCMu)); + EXPECT_FALSE(db.IsType(kPayloadTypePcmU, "isac")); + EXPECT_TRUE(db.IsType(kPayloadTypePcmU, "pcmu")); EXPECT_TRUE(db.IsComfortNoise(kPayloadTypeCng)); EXPECT_TRUE(db.IsDtmf(kPayloadTypeDtmf)); EXPECT_TRUE(db.IsRed(kPayloadTypeRed)); @@ -164,7 +150,8 @@ TEST(DecoderDatabase, ExternalDecoder) { const DecoderDatabase::DecoderInfo* info; info = db.GetDecoderInfo(kPayloadType); ASSERT_TRUE(info != NULL); - EXPECT_EQ(NetEqDecoder::kDecoderPCMu, info->codec_type); + EXPECT_TRUE(info->IsType("pcmu")); + EXPECT_EQ(info->name, kCodecName); EXPECT_EQ(kCodecName, info->name); // Expect not to delete the decoder when removing it from the database, since // it was declared externally. @@ -182,9 +169,8 @@ TEST(DecoderDatabase, CheckPayloadTypes) { // matter for the test). const int kNumPayloads = 10; for (uint8_t payload_type = 0; payload_type < kNumPayloads; ++payload_type) { - EXPECT_EQ( - DecoderDatabase::kOK, - db.RegisterPayload(payload_type, NetEqDecoder::kDecoderArbitrary, "")); + EXPECT_EQ(DecoderDatabase::kOK, + db.RegisterPayload(payload_type, NetEqDecoder::kDecoderPCMu, "")); } PacketList packet_list; for (int i = 0; i < kNumPayloads + 1; ++i) { diff --git a/webrtc/modules/audio_coding/neteq/delay_manager.cc b/webrtc/modules/audio_coding/neteq/delay_manager.cc index 5ccb81c3f1..a6efdab8dc 100644 --- a/webrtc/modules/audio_coding/neteq/delay_manager.cc +++ b/webrtc/modules/audio_coding/neteq/delay_manager.cc @@ -371,12 +371,8 @@ int DelayManager::TargetLevel() const { return target_level_; } -void DelayManager::LastDecoderType(NetEqDecoder decoder_type) { - if (decoder_type == NetEqDecoder::kDecoderAVT || - decoder_type == NetEqDecoder::kDecoderCNGnb || - decoder_type == NetEqDecoder::kDecoderCNGwb || - decoder_type == NetEqDecoder::kDecoderCNGswb32kHz || - decoder_type == NetEqDecoder::kDecoderCNGswb48kHz) { +void DelayManager::LastDecodedWasCngOrDtmf(bool it_was) { + if (it_was) { last_pack_cng_or_dtmf_ = 1; } else if (last_pack_cng_or_dtmf_ != 0) { last_pack_cng_or_dtmf_ = -1; diff --git a/webrtc/modules/audio_coding/neteq/delay_manager.h b/webrtc/modules/audio_coding/neteq/delay_manager.h index 6f3c14aea9..2f928f175b 100644 --- a/webrtc/modules/audio_coding/neteq/delay_manager.h +++ b/webrtc/modules/audio_coding/neteq/delay_manager.h @@ -91,7 +91,9 @@ class DelayManager { // includes any extra delay set through the set_extra_delay_ms() method. virtual int TargetLevel() const; - virtual void LastDecoderType(NetEqDecoder decoder_type); + // Informs the delay manager whether or not the last decoded packet contained + // speech. + virtual void LastDecodedWasCngOrDtmf(bool it_was); // Accessors and mutators. // Assuming |delay| is in valid range. diff --git a/webrtc/modules/audio_coding/neteq/include/neteq.h b/webrtc/modules/audio_coding/neteq/include/neteq.h index c07143c062..8520905b10 100644 --- a/webrtc/modules/audio_coding/neteq/include/neteq.h +++ b/webrtc/modules/audio_coding/neteq/include/neteq.h @@ -258,10 +258,10 @@ class NetEq { // value if we have no decoder for that payload type. virtual rtc::Optional GetDecoder(int payload_type) const = 0; - // Returns the decoder format for the given payload type. Returns null if no - // such payload type was registered, or if it was registered without - // providing an SdpAudioFormat. - virtual const SdpAudioFormat* GetDecoderFormat(int payload_type) const = 0; + // Returns the decoder format for the given payload type. Returns empty if no + // such payload type was registered. + virtual rtc::Optional GetDecoderFormat( + int payload_type) const = 0; // Not implemented. virtual int SetTargetNumberOfChannels() = 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 6152799b82..64be080b96 100644 --- a/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h +++ b/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h @@ -33,8 +33,6 @@ class MockAudioDecoder : public AudioDecoder { 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)); }; } // namespace webrtc diff --git a/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h b/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h index 7347959e8c..d3ee0af765 100644 --- a/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h +++ b/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h @@ -45,8 +45,6 @@ class MockDecoderDatabase : public DecoderDatabase { MOCK_METHOD0(RemoveAll, void()); MOCK_CONST_METHOD1(GetDecoderInfo, const DecoderInfo*(uint8_t rtp_payload_type)); - MOCK_CONST_METHOD1(GetRtpPayloadType, - uint8_t(NetEqDecoder codec_type)); MOCK_METHOD2(SetActiveDecoder, int(uint8_t rtp_payload_type, bool* new_decoder)); MOCK_CONST_METHOD0(GetActiveDecoder, diff --git a/webrtc/modules/audio_coding/neteq/mock/mock_delay_manager.h b/webrtc/modules/audio_coding/neteq/mock/mock_delay_manager.h index 7ceea70621..1e20dca03b 100644 --- a/webrtc/modules/audio_coding/neteq/mock/mock_delay_manager.h +++ b/webrtc/modules/audio_coding/neteq/mock/mock_delay_manager.h @@ -47,8 +47,6 @@ class MockDelayManager : public DelayManager { void(int* lower_limit, int* higher_limit)); MOCK_CONST_METHOD0(TargetLevel, int()); - MOCK_METHOD1(LastDecoderType, - void(NetEqDecoder decoder_type)); MOCK_METHOD1(set_extra_delay_ms, void(int16_t delay)); MOCK_CONST_METHOD0(base_target_level, diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc index 6b2fa4c9ec..e21294aa38 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc @@ -457,16 +457,15 @@ rtc::Optional NetEqImpl::GetDecoder(int payload_type) const { return rtc::Optional(ci); } -const SdpAudioFormat* NetEqImpl::GetDecoderFormat(int payload_type) const { +rtc::Optional NetEqImpl::GetDecoderFormat( + int payload_type) const { rtc::CritScope lock(&crit_sect_); const DecoderDatabase::DecoderInfo* const di = decoder_database_->GetDecoderInfo(payload_type); if (!di) { - return nullptr; // Payload type not registered. + return rtc::Optional(); // Payload type not registered. } - // This will return null if the payload type was registered without an - // SdpAudioFormat. - return di->GetFormat(); + return rtc::Optional(di->GetFormat()); } int NetEqImpl::SetTargetNumberOfChannels() { @@ -781,7 +780,8 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, const DecoderDatabase::DecoderInfo* dec_info = decoder_database_->GetDecoderInfo(main_header.payloadType); assert(dec_info); // Already checked that the payload type is known. - delay_manager_->LastDecoderType(dec_info->codec_type); + delay_manager_->LastDecodedWasCngOrDtmf(dec_info->IsComfortNoise() || + dec_info->IsDtmf()); if (delay_manager_->last_pack_cng_or_dtmf() == 0) { // Calculate the total speech length carried in each packet. const size_t buffer_length_after_insert = diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.h b/webrtc/modules/audio_coding/neteq/neteq_impl.h index dda3d64494..e143a2a43f 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.h +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.h @@ -173,7 +173,8 @@ class NetEqImpl : public webrtc::NetEq { rtc::Optional GetDecoder(int payload_type) const override; - const SdpAudioFormat* GetDecoderFormat(int payload_type) const override; + rtc::Optional GetDecoderFormat( + int payload_type) const override; int SetTargetNumberOfChannels() override; diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc index e3029dba8d..24a0780609 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc @@ -275,7 +275,7 @@ TEST_F(NetEqImplTest, InsertPacket) { *dec = std::move(mock_decoder); })); - DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, "", + DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, mock_decoder_factory); // Expectations for decoder database. @@ -313,9 +313,6 @@ TEST_F(NetEqImplTest, InsertPacket) { // All expectations within this block must be called in this specific order. InSequence sequence; // Dummy variable. // Expectations when the first packet is inserted. - EXPECT_CALL(*mock_delay_manager_, - LastDecoderType(NetEqDecoder::kDecoderPCMu)) - .Times(1); EXPECT_CALL(*mock_delay_manager_, last_pack_cng_or_dtmf()) .Times(2) .WillRepeatedly(Return(-1)); @@ -323,9 +320,6 @@ TEST_F(NetEqImplTest, InsertPacket) { .Times(1); EXPECT_CALL(*mock_delay_manager_, ResetPacketIatCount()).Times(1); // Expectations when the second packet is inserted. Slightly different. - EXPECT_CALL(*mock_delay_manager_, - LastDecoderType(NetEqDecoder::kDecoderPCMu)) - .Times(1); EXPECT_CALL(*mock_delay_manager_, last_pack_cng_or_dtmf()) .WillOnce(Return(0)); EXPECT_CALL(*mock_delay_manager_, SetPacketAudioLength(30)) diff --git a/webrtc/modules/audio_coding/neteq/packet_buffer_unittest.cc b/webrtc/modules/audio_coding/neteq/packet_buffer_unittest.cc index b39169f909..b1ac5ec17d 100644 --- a/webrtc/modules/audio_coding/neteq/packet_buffer_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/packet_buffer_unittest.cc @@ -174,8 +174,7 @@ TEST(PacketBuffer, InsertPacketList) { MockDecoderDatabase decoder_database; auto factory = CreateBuiltinAudioDecoderFactory(); - const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, "", - factory); + const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, factory); EXPECT_CALL(decoder_database, GetDecoderInfo(0)) .WillRepeatedly(Return(&info)); rtc::Optional current_pt; @@ -218,12 +217,10 @@ TEST(PacketBuffer, InsertPacketListChangePayloadType) { MockDecoderDatabase decoder_database; auto factory = CreateBuiltinAudioDecoderFactory(); - const DecoderDatabase::DecoderInfo info0(NetEqDecoder::kDecoderPCMu, "", - factory); + const DecoderDatabase::DecoderInfo info0(NetEqDecoder::kDecoderPCMu, factory); EXPECT_CALL(decoder_database, GetDecoderInfo(0)) .WillRepeatedly(Return(&info0)); - const DecoderDatabase::DecoderInfo info1(NetEqDecoder::kDecoderPCMa, "", - factory); + const DecoderDatabase::DecoderInfo info1(NetEqDecoder::kDecoderPCMa, factory); EXPECT_CALL(decoder_database, GetDecoderInfo(1)) .WillRepeatedly(Return(&info1)); rtc::Optional current_pt; @@ -356,8 +353,7 @@ TEST(PacketBuffer, Reordering) { MockDecoderDatabase decoder_database; auto factory = CreateBuiltinAudioDecoderFactory(); - const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, "", - factory); + const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, factory); EXPECT_CALL(decoder_database, GetDecoderInfo(0)) .WillRepeatedly(Return(&info)); rtc::Optional current_pt; @@ -396,12 +392,12 @@ TEST(PacketBuffer, CngFirstThenSpeechWithNewSampleRate) { MockDecoderDatabase decoder_database; auto factory = CreateBuiltinAudioDecoderFactory(); - const DecoderDatabase::DecoderInfo info_cng(NetEqDecoder::kDecoderCNGnb, "", + const DecoderDatabase::DecoderInfo info_cng(NetEqDecoder::kDecoderCNGnb, factory); EXPECT_CALL(decoder_database, GetDecoderInfo(kCngPt)) .WillRepeatedly(Return(&info_cng)); const DecoderDatabase::DecoderInfo info_speech(NetEqDecoder::kDecoderPCM16Bwb, - "", factory); + factory); EXPECT_CALL(decoder_database, GetDecoderInfo(kSpeechPt)) .WillRepeatedly(Return(&info_speech)); @@ -490,8 +486,7 @@ TEST(PacketBuffer, Failures) { list.push_back(gen.NextPacket(payload_len)); // Valid packet. MockDecoderDatabase decoder_database; auto factory = CreateBuiltinAudioDecoderFactory(); - const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, "", - factory); + const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, factory); EXPECT_CALL(decoder_database, GetDecoderInfo(0)) .WillRepeatedly(Return(&info)); rtc::Optional current_pt; diff --git a/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc b/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc index fc3a846f7e..b7eeb4be3a 100644 --- a/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc +++ b/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc @@ -45,12 +45,12 @@ uint32_t TimestampScaler::ToInternal(uint32_t external_timestamp, if (!(info->IsComfortNoise() || info->IsDtmf())) { // Do not change the timestamp scaling settings for DTMF or CNG. numerator_ = info->SampleRateHz(); - if (info->codec_type == NetEqDecoder::kDecoderArbitrary) { - // We have no format mapping for "arbitrary" external codecs, so we cannot - // support timestamp scaling of them. + if (info->GetFormat().clockrate_hz == 0) { + // If the clockrate is invalid (i.e. with an old-style external codec) + // we cannot do any timestamp scaling. denominator_ = numerator_; } else { - denominator_ = info->GetFormat()->clockrate_hz; + denominator_ = info->GetFormat().clockrate_hz; } } if (numerator_ != denominator_) { diff --git a/webrtc/modules/audio_coding/neteq/timestamp_scaler_unittest.cc b/webrtc/modules/audio_coding/neteq/timestamp_scaler_unittest.cc index 1b8910ef64..96cf2e45db 100644 --- a/webrtc/modules/audio_coding/neteq/timestamp_scaler_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/timestamp_scaler_unittest.cc @@ -26,8 +26,7 @@ TEST(TimestampScaler, TestNoScaling) { MockDecoderDatabase db; auto factory = CreateBuiltinAudioDecoderFactory(); // Use PCMu, because it doesn't use scaled timestamps. - const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, "", - factory); + const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, factory); static const uint8_t kRtpPayloadType = 0; EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) .WillRepeatedly(Return(&info)); @@ -48,8 +47,7 @@ TEST(TimestampScaler, TestNoScalingLargeStep) { MockDecoderDatabase db; auto factory = CreateBuiltinAudioDecoderFactory(); // Use PCMu, because it doesn't use scaled timestamps. - const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, "", - factory); + const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, factory); static const uint8_t kRtpPayloadType = 0; EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) .WillRepeatedly(Return(&info)); @@ -75,8 +73,7 @@ TEST(TimestampScaler, TestG722) { MockDecoderDatabase db; auto factory = CreateBuiltinAudioDecoderFactory(); // Use G722, which has a factor 2 scaling. - const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "", - factory); + const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, factory); static const uint8_t kRtpPayloadType = 17; EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) .WillRepeatedly(Return(&info)); @@ -101,8 +98,7 @@ TEST(TimestampScaler, TestG722LargeStep) { MockDecoderDatabase db; auto factory = CreateBuiltinAudioDecoderFactory(); // Use G722, which has a factor 2 scaling. - const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "", - factory); + const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, factory); static const uint8_t kRtpPayloadType = 17; EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) .WillRepeatedly(Return(&info)); @@ -131,9 +127,9 @@ TEST(TimestampScaler, TestG722WithCng) { MockDecoderDatabase db; auto factory = CreateBuiltinAudioDecoderFactory(); // Use G722, which has a factor 2 scaling. - const DecoderDatabase::DecoderInfo info_g722(NetEqDecoder::kDecoderG722, "", + const DecoderDatabase::DecoderInfo info_g722(NetEqDecoder::kDecoderG722, factory); - const DecoderDatabase::DecoderInfo info_cng(NetEqDecoder::kDecoderCNGwb, "", + const DecoderDatabase::DecoderInfo info_cng(NetEqDecoder::kDecoderCNGwb, factory); static const uint8_t kRtpPayloadTypeG722 = 17; static const uint8_t kRtpPayloadTypeCng = 13; @@ -175,8 +171,7 @@ TEST(TimestampScaler, TestG722Packet) { MockDecoderDatabase db; auto factory = CreateBuiltinAudioDecoderFactory(); // Use G722, which has a factor 2 scaling. - const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "", - factory); + const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, factory); static const uint8_t kRtpPayloadType = 17; EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) .WillRepeatedly(Return(&info)); @@ -205,8 +200,7 @@ TEST(TimestampScaler, TestG722PacketList) { MockDecoderDatabase db; auto factory = CreateBuiltinAudioDecoderFactory(); // Use G722, which has a factor 2 scaling. - const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "", - factory); + const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, factory); static const uint8_t kRtpPayloadType = 17; EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) .WillRepeatedly(Return(&info)); @@ -236,8 +230,7 @@ TEST(TimestampScaler, TestG722Reset) { MockDecoderDatabase db; auto factory = CreateBuiltinAudioDecoderFactory(); // Use G722, which has a factor 2 scaling. - const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, "", - factory); + const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722, factory); static const uint8_t kRtpPayloadType = 17; EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) .WillRepeatedly(Return(&info)); @@ -277,8 +270,7 @@ TEST(TimestampScaler, TestG722Reset) { TEST(TimestampScaler, TestOpusLargeStep) { MockDecoderDatabase db; auto factory = CreateBuiltinAudioDecoderFactory(); - const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderOpus, "", - factory); + const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderOpus, factory); static const uint8_t kRtpPayloadType = 17; EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) .WillRepeatedly(Return(&info));