diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/acm2/acm_receiver.cc index 85cbd8a4ed..afd1ff44f6 100644 --- a/webrtc/modules/audio_coding/acm2/acm_receiver.cc +++ b/webrtc/modules/audio_coding/acm2/acm_receiver.cc @@ -180,9 +180,12 @@ int AcmReceiver::GetAudio(int desired_freq_hz, int32_t AcmReceiver::AddCodec(int acm_codec_id, uint8_t payload_type, size_t channels, - int sample_rate_hz, + int /*sample_rate_hz*/, AudioDecoder* audio_decoder, const std::string& name) { + // TODO(kwiberg): This function has been ignoring the |sample_rate_hz| + // argument for a long time. Arguably, it should simply be removed. + const auto neteq_decoder = [acm_codec_id, channels]() -> NetEqDecoder { if (acm_codec_id == -1) return NetEqDecoder::kDecoderArbitrary; // External decoder. @@ -194,29 +197,22 @@ int32_t AcmReceiver::AddCodec(int acm_codec_id, RTC_DCHECK(ned) << "Invalid codec ID: " << static_cast(*cid); return *ned; }(); + const rtc::Optional new_format = + RentACodec::NetEqDecoderToSdpAudioFormat(neteq_decoder); rtc::CritScope lock(&crit_sect_); - // The corresponding NetEq decoder ID. - // If this codec has been registered before. - auto it = decoders_.find(payload_type); - if (it != decoders_.end()) { - const Decoder& decoder = it->second; - if (acm_codec_id != -1 && decoder.acm_codec_id == acm_codec_id && - decoder.channels == channels && - decoder.sample_rate_hz == sample_rate_hz) { - // Re-registering the same codec. Do nothing and return. - return 0; - } + const SdpAudioFormat* const 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; + } - // Changing codec. First unregister the old codec, then register the new - // one. - if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK) { - LOG(LERROR) << "Cannot remove payload " << static_cast(payload_type); - return -1; - } - - decoders_.erase(it); + if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK && + neteq_->LastError() != NetEq::kDecoderNotFound) { + LOG(LERROR) << "Cannot remove payload " << static_cast(payload_type); + return -1; } int ret_val; @@ -232,13 +228,6 @@ int32_t AcmReceiver::AddCodec(int acm_codec_id, << " channels: " << channels; return -1; } - - Decoder decoder; - decoder.acm_codec_id = acm_codec_id; - decoder.payload_type = payload_type; - decoder.channels = channels; - decoder.sample_rate_hz = sample_rate_hz; - decoders_[payload_type] = decoder; return 0; } @@ -249,18 +238,14 @@ void AcmReceiver::FlushBuffers() { void AcmReceiver::RemoveAllCodecs() { rtc::CritScope lock(&crit_sect_); neteq_->RemoveAllPayloadTypes(); - decoders_.clear(); last_audio_decoder_ = rtc::Optional(); last_packet_sample_rate_hz_ = rtc::Optional(); } int AcmReceiver::RemoveCodec(uint8_t payload_type) { rtc::CritScope lock(&crit_sect_); - auto it = decoders_.find(payload_type); - if (it == decoders_.end()) { // Such a payload-type is not registered. - return 0; - } - if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK) { + if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK && + neteq_->LastError() != NetEq::kDecoderNotFound) { LOG(LERROR) << "AcmReceiver::RemoveCodec" << static_cast(payload_type); return -1; } @@ -268,7 +253,6 @@ int AcmReceiver::RemoveCodec(uint8_t payload_type) { last_audio_decoder_ = rtc::Optional(); last_packet_sample_rate_hz_ = rtc::Optional(); } - decoders_.erase(it); return 0; } diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.h b/webrtc/modules/audio_coding/acm2/acm_receiver.h index 53def2b164..94f15a25dc 100644 --- a/webrtc/modules/audio_coding/acm2/acm_receiver.h +++ b/webrtc/modules/audio_coding/acm2/acm_receiver.h @@ -274,8 +274,6 @@ class AcmReceiver { std::unique_ptr last_audio_buffer_ GUARDED_BY(crit_sect_); CallStatistics call_stats_ GUARDED_BY(crit_sect_); NetEq* neteq_; - // Decoders map is keyed by payload type - std::map decoders_ GUARDED_BY(crit_sect_); Clock* clock_; // TODO(henrik.lundin) Make const if possible. bool resampled_last_output_frame_ GUARDED_BY(crit_sect_); rtc::Optional last_packet_sample_rate_hz_ GUARDED_BY(crit_sect_); diff --git a/webrtc/modules/audio_coding/codecs/audio_format.cc b/webrtc/modules/audio_coding/codecs/audio_format.cc index 86d5d80042..ebd7cb030b 100644 --- a/webrtc/modules/audio_coding/codecs/audio_format.cc +++ b/webrtc/modules/audio_coding/codecs/audio_format.cc @@ -10,6 +10,8 @@ #include "webrtc/modules/audio_coding/codecs/audio_format.h" +#include "webrtc/common_types.h" + namespace webrtc { SdpAudioFormat::SdpAudioFormat(const SdpAudioFormat&) = default; @@ -33,6 +35,12 @@ SdpAudioFormat::~SdpAudioFormat() = default; SdpAudioFormat& SdpAudioFormat::operator=(const SdpAudioFormat&) = default; SdpAudioFormat& SdpAudioFormat::operator=(SdpAudioFormat&&) = default; +bool operator==(const SdpAudioFormat& a, const SdpAudioFormat& b) { + return STR_CASE_CMP(a.name.c_str(), b.name.c_str()) == 0 && + a.clockrate_hz == b.clockrate_hz && a.num_channels == b.num_channels && + a.parameters == b.parameters; +} + void swap(SdpAudioFormat& a, SdpAudioFormat& b) { using std::swap; swap(a.name, b.name); diff --git a/webrtc/modules/audio_coding/codecs/audio_format.h b/webrtc/modules/audio_coding/codecs/audio_format.h index 43f82dcf04..1199cc27cd 100644 --- a/webrtc/modules/audio_coding/codecs/audio_format.h +++ b/webrtc/modules/audio_coding/codecs/audio_format.h @@ -35,6 +35,11 @@ struct SdpAudioFormat { SdpAudioFormat& operator=(const SdpAudioFormat&); SdpAudioFormat& operator=(SdpAudioFormat&&); + friend bool operator==(const SdpAudioFormat& a, const SdpAudioFormat& b); + friend bool operator!=(const SdpAudioFormat& a, const SdpAudioFormat& b) { + return !(a == b); + } + std::string name; int clockrate_hz; int num_channels; diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.h b/webrtc/modules/audio_coding/neteq/decoder_database.h index 3728d1da90..296d059f73 100644 --- a/webrtc/modules/audio_coding/neteq/decoder_database.h +++ b/webrtc/modules/audio_coding/neteq/decoder_database.h @@ -64,9 +64,8 @@ class DecoderDatabase { return decoder ? decoder->SampleRateHz() : cng_decoder_->sample_rate_hz; } - const SdpAudioFormat& GetFormat() const { - RTC_DCHECK(audio_format_); - return *audio_format_; + const SdpAudioFormat* GetFormat() const { + return audio_format_ ? &*audio_format_ : nullptr; } // Returns true if |codec_type| is comfort noise. diff --git a/webrtc/modules/audio_coding/neteq/include/neteq.h b/webrtc/modules/audio_coding/neteq/include/neteq.h index 952ab238eb..98bb37cf1f 100644 --- a/webrtc/modules/audio_coding/neteq/include/neteq.h +++ b/webrtc/modules/audio_coding/neteq/include/neteq.h @@ -259,6 +259,11 @@ 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; + // Not implemented. virtual int SetTargetNumberOfChannels() = 0; diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc index 98588f49cb..221b07c969 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc @@ -457,6 +457,18 @@ rtc::Optional NetEqImpl::GetDecoder(int payload_type) const { return rtc::Optional(ci); } +const SdpAudioFormat* 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. + } + // This will return null if the payload type was registered without an + // SdpAudioFormat. + return di->GetFormat(); +} + int NetEqImpl::SetTargetNumberOfChannels() { return kNotImplemented; } diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.h b/webrtc/modules/audio_coding/neteq/neteq_impl.h index 7903ba665c..dd35301d7a 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.h +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.h @@ -173,6 +173,8 @@ class NetEqImpl : public webrtc::NetEq { rtc::Optional GetDecoder(int payload_type) const override; + const SdpAudioFormat* GetDecoderFormat(int payload_type) const override; + int SetTargetNumberOfChannels() override; int SetTargetSampleRate() override; diff --git a/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc b/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc index 1f28639e43..fc3a846f7e 100644 --- a/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc +++ b/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc @@ -50,7 +50,7 @@ uint32_t TimestampScaler::ToInternal(uint32_t external_timestamp, // support timestamp scaling of them. denominator_ = numerator_; } else { - denominator_ = info->GetFormat().clockrate_hz; + denominator_ = info->GetFormat()->clockrate_hz; } } if (numerator_ != denominator_) {