diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/acm2/acm_receiver.cc index 9a882aac37..2ae75485e0 100644 --- a/webrtc/modules/audio_coding/acm2/acm_receiver.cc +++ b/webrtc/modules/audio_coding/acm2/acm_receiver.cc @@ -32,23 +32,8 @@ namespace webrtc { namespace acm2 { -namespace { - -// Is the given codec a CNG codec? -// TODO(kwiberg): Move to RentACodec. -bool IsCng(int codec_id) { - auto i = RentACodec::CodecIdFromIndex(codec_id); - return (i && (*i == RentACodec::CodecId::kCNNB || - *i == RentACodec::CodecId::kCNWB || - *i == RentACodec::CodecId::kCNSWB || - *i == RentACodec::CodecId::kCNFB)); -} - -} // namespace - AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config) - : last_audio_decoder_(nullptr), - last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), + : last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), neteq_(NetEq::Create(config.neteq_config, config.decoder_factory)), clock_(config.clock), resampled_last_output_frame_(true) { @@ -95,29 +80,25 @@ int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header, { rtc::CritScope lock(&crit_sect_); - const Decoder* decoder = RtpHeaderToDecoder(*header, incoming_payload[0]); - if (!decoder) { + const rtc::Optional ci = + RtpHeaderToDecoder(*header, incoming_payload[0]); + if (!ci) { LOG_F(LS_ERROR) << "Payload-type " << static_cast(header->payloadType) << " is not registered."; return -1; } - const int sample_rate_hz = [&decoder] { - const auto ci = RentACodec::CodecIdFromIndex(decoder->acm_codec_id); - return ci ? RentACodec::CodecInstById(*ci)->plfreq : -1; - }(); - receive_timestamp = NowInTimestamp(sample_rate_hz); + receive_timestamp = NowInTimestamp(ci->plfreq); - // If this is a CNG while the audio codec is not mono, skip pushing in - // packets into NetEq. - if (IsCng(decoder->acm_codec_id) && last_audio_decoder_ && - last_audio_decoder_->channels > 1) + if (STR_CASE_CMP(ci->plname, "cn") == 0) { + if (last_audio_decoder_ && last_audio_decoder_->channels > 1) { + // This is a CNG and the audio codec is not mono, so skip pushing in + // packets into NetEq. return 0; - if (!IsCng(decoder->acm_codec_id) && - decoder->acm_codec_id != - *RentACodec::CodecIndexFromId(RentACodec::CodecId::kAVT)) { - last_audio_decoder_ = decoder; - last_packet_sample_rate_hz_ = rtc::Optional(decoder->sample_rate_hz); + } + } else { + last_audio_decoder_ = ci; + last_packet_sample_rate_hz_ = rtc::Optional(ci->plfreq); } } // |crit_sect_| is released. @@ -282,7 +263,7 @@ int AcmReceiver::RemoveAllCodecs() { } // No codec is registered, invalidate last audio decoder. - last_audio_decoder_ = nullptr; + last_audio_decoder_ = rtc::Optional(); last_packet_sample_rate_hz_ = rtc::Optional(); return ret_val; } @@ -297,8 +278,8 @@ int AcmReceiver::RemoveCodec(uint8_t payload_type) { LOG(LERROR) << "AcmReceiver::RemoveCodec" << static_cast(payload_type); return -1; } - if (last_audio_decoder_ == &it->second) { - last_audio_decoder_ = nullptr; + if (last_audio_decoder_ && payload_type == last_audio_decoder_->pltype) { + last_audio_decoder_ = rtc::Optional(); last_packet_sample_rate_hz_ = rtc::Optional(); } decoders_.erase(it); @@ -318,11 +299,7 @@ int AcmReceiver::LastAudioCodec(CodecInst* codec) const { if (!last_audio_decoder_) { return -1; } - *codec = *RentACodec::CodecInstById( - *RentACodec::CodecIdFromIndex(last_audio_decoder_->acm_codec_id)); - codec->pltype = last_audio_decoder_->payload_type; - codec->channels = last_audio_decoder_->channels; - codec->plfreq = last_audio_decoder_->sample_rate_hz; + *codec = *last_audio_decoder_; return 0; } @@ -386,20 +363,17 @@ void AcmReceiver::ResetInitialDelay() { // TODO(turajs): Should NetEq Buffer be flushed? } -const AcmReceiver::Decoder* AcmReceiver::RtpHeaderToDecoder( +const rtc::Optional AcmReceiver::RtpHeaderToDecoder( const RTPHeader& rtp_header, uint8_t payload_type) const { - auto it = decoders_.find(rtp_header.payloadType); - const auto red_index = - RentACodec::CodecIndexFromId(RentACodec::CodecId::kRED); - if (red_index && // This ensures that RED is defined in WebRTC. - it != decoders_.end() && it->second.acm_codec_id == *red_index) { - // This is a RED packet, get the payload of the audio codec. - it = decoders_.find(payload_type & 0x7F); + const rtc::Optional ci = + neteq_->GetDecoder(rtp_header.payloadType); + if (ci && STR_CASE_CMP(ci->plname, "red") == 0) { + // This is a RED packet. Get the payload of the audio codec. + return neteq_->GetDecoder(payload_type & 0x7f); + } else { + return ci; } - - // Check if the payload is registered. - return it != decoders_.end() ? &it->second : nullptr; } uint32_t AcmReceiver::NowInTimestamp(int decoder_sampling_rate) const { diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.h b/webrtc/modules/audio_coding/acm2/acm_receiver.h index e62e7144d6..5b864c2b70 100644 --- a/webrtc/modules/audio_coding/acm2/acm_receiver.h +++ b/webrtc/modules/audio_coding/acm2/acm_receiver.h @@ -39,15 +39,6 @@ namespace acm2 { class AcmReceiver { public: - struct Decoder { - int acm_codec_id; - uint8_t payload_type; - // This field is meaningful for codecs where both mono and - // stereo versions are registered under the same ID. - size_t channels; - int sample_rate_hz; - }; - // Constructor of the class explicit AcmReceiver(const AudioCodingModule::Config& config); @@ -262,14 +253,23 @@ class AcmReceiver { void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const; private: - const Decoder* RtpHeaderToDecoder(const RTPHeader& rtp_header, - uint8_t payload_type) const + struct Decoder { + int acm_codec_id; + uint8_t payload_type; + // This field is meaningful for codecs where both mono and + // stereo versions are registered under the same ID. + size_t channels; + int sample_rate_hz; + }; + + const rtc::Optional RtpHeaderToDecoder(const RTPHeader& rtp_header, + uint8_t payload_type) const EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); uint32_t NowInTimestamp(int decoder_sampling_rate) const; rtc::CriticalSection crit_sect_; - const Decoder* last_audio_decoder_ GUARDED_BY(crit_sect_); + rtc::Optional last_audio_decoder_ GUARDED_BY(crit_sect_); ACMResampler resampler_ GUARDED_BY(crit_sect_); std::unique_ptr last_audio_buffer_ GUARDED_BY(crit_sect_); CallStatistics call_stats_ GUARDED_BY(crit_sect_); diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver_unittest_oldapi.cc b/webrtc/modules/audio_coding/acm2/acm_receiver_unittest_oldapi.cc index 81a57da3fa..5622fc1073 100644 --- a/webrtc/modules/audio_coding/acm2/acm_receiver_unittest_oldapi.cc +++ b/webrtc/modules/audio_coding/acm2/acm_receiver_unittest_oldapi.cc @@ -119,9 +119,9 @@ class AcmReceiverTestOldApi : public AudioPacketizationCallback, for (auto id : ids) { const auto i = RentACodec::CodecIndexFromId(id); ASSERT_TRUE(i); - ASSERT_EQ( - 0, receiver_->AddCodec(*i, codecs_[*i].pltype, codecs_[*i].channels, - codecs_[*i].plfreq, nullptr, "")); + ASSERT_EQ(0, receiver_->AddCodec(*i, codecs_[*i].pltype, + codecs_[*i].channels, codecs_[*i].plfreq, + nullptr, codecs_[*i].plname)); } } diff --git a/webrtc/modules/audio_coding/neteq/include/neteq.h b/webrtc/modules/audio_coding/neteq/include/neteq.h index cae56b3862..1f6205f1e4 100644 --- a/webrtc/modules/audio_coding/neteq/include/neteq.h +++ b/webrtc/modules/audio_coding/neteq/include/neteq.h @@ -252,6 +252,8 @@ class NetEq { // (Config::sample_rate_hz) is returned. virtual int last_output_sample_rate_hz() const = 0; + virtual rtc::Optional GetDecoder(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 9c4f580906..71eea2114c 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc @@ -431,6 +431,27 @@ int NetEqImpl::last_output_sample_rate_hz() const { return last_output_sample_rate_hz_; } +rtc::Optional NetEqImpl::GetDecoder(int payload_type) const { + rtc::CritScope lock(&crit_sect_); + const DecoderDatabase::DecoderInfo* di = + decoder_database_->GetDecoderInfo(payload_type); + if (!di) { + return rtc::Optional(); + } + + // Create a CodecInst with some fields set. The remaining fields are zeroed, + // but we tell MSan to consider them uninitialized. + CodecInst ci = {0}; + rtc::MsanMarkUninitialized(rtc::MakeArrayView(&ci, 1)); + ci.pltype = payload_type; + std::strncpy(ci.plname, di->name.c_str(), sizeof(ci.plname)); + ci.plname[sizeof(ci.plname) - 1] = '\0'; + ci.plfreq = di->IsRed() || di->IsDtmf() ? 8000 : di->SampleRateHz(); + AudioDecoder* const decoder = di->GetDecoder(); + ci.channels = decoder ? decoder->Channels() : 1; + return rtc::Optional(ci); +} + 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 e74f090ac6..8795ef5210 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.h +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.h @@ -169,6 +169,8 @@ class NetEqImpl : public webrtc::NetEq { int last_output_sample_rate_hz() const override; + rtc::Optional GetDecoder(int payload_type) const override; + int SetTargetNumberOfChannels() override; int SetTargetSampleRate() override;