AcmReceiver: Look up last decoder in NetEq's table of decoders
AcmReceiver::decoders_ is now one step closer to being unused.
(This is a re-land of https://codereview.webrtc.org/2339953002.)
BUG=webrtc:5801
Review-Url: https://codereview.webrtc.org/2354453003
Cr-Commit-Position: refs/heads/master@{#14303}
diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/acm2/acm_receiver.cc
index 417a346..641818d 100644
--- a/webrtc/modules/audio_coding/acm2/acm_receiver.cc
+++ b/webrtc/modules/audio_coding/acm2/acm_receiver.cc
@@ -32,23 +32,8 @@
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 @@
{
rtc::CritScope lock(&crit_sect_);
- const Decoder* decoder = RtpHeaderToDecoder(*header, incoming_payload[0]);
- if (!decoder) {
+ const rtc::Optional<CodecInst> ci =
+ RtpHeaderToDecoder(*header, incoming_payload[0]);
+ if (!ci) {
LOG_F(LS_ERROR) << "Payload-type "
<< static_cast<int>(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<int>(decoder->sample_rate_hz);
+ }
+ } else {
+ last_audio_decoder_ = ci;
+ last_packet_sample_rate_hz_ = rtc::Optional<int>(ci->plfreq);
}
} // |crit_sect_| is released.
@@ -283,7 +264,7 @@
}
// No codec is registered, invalidate last audio decoder.
- last_audio_decoder_ = nullptr;
+ last_audio_decoder_ = rtc::Optional<CodecInst>();
last_packet_sample_rate_hz_ = rtc::Optional<int>();
return ret_val;
}
@@ -298,8 +279,8 @@
LOG(LERROR) << "AcmReceiver::RemoveCodec" << static_cast<int>(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<CodecInst>();
last_packet_sample_rate_hz_ = rtc::Optional<int>();
}
decoders_.erase(it);
@@ -319,11 +300,7 @@
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;
}
@@ -387,20 +364,17 @@
// TODO(turajs): Should NetEq Buffer be flushed?
}
-const AcmReceiver::Decoder* AcmReceiver::RtpHeaderToDecoder(
+const rtc::Optional<CodecInst> 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);
+ uint8_t first_payload_byte) const {
+ const rtc::Optional<CodecInst> 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(first_payload_byte & 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 e62e714..d39581e 100644
--- a/webrtc/modules/audio_coding/acm2/acm_receiver.h
+++ b/webrtc/modules/audio_coding/acm2/acm_receiver.h
@@ -39,15 +39,6 @@
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 @@
void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const;
private:
- const Decoder* RtpHeaderToDecoder(const RTPHeader& rtp_header,
- uint8_t payload_type) const
- EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+ 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<CodecInst> RtpHeaderToDecoder(
+ const RTPHeader& rtp_header,
+ uint8_t first_payload_byte) 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<CodecInst> last_audio_decoder_ GUARDED_BY(crit_sect_);
ACMResampler resampler_ GUARDED_BY(crit_sect_);
std::unique_ptr<int16_t[]> 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 81a57da..5622fc1 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 @@
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 cae56b3..22d994e3 100644
--- a/webrtc/modules/audio_coding/neteq/include/neteq.h
+++ b/webrtc/modules/audio_coding/neteq/include/neteq.h
@@ -252,6 +252,10 @@
// (Config::sample_rate_hz) is returned.
virtual int last_output_sample_rate_hz() const = 0;
+ // Returns info about the decoder for the given payload type, or an empty
+ // value if we have no decoder for that payload type.
+ virtual rtc::Optional<CodecInst> 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 d62d44f..27d47c1 100644
--- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc
+++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
@@ -431,6 +431,27 @@
return last_output_sample_rate_hz_;
}
+rtc::Optional<CodecInst> 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<CodecInst>();
+ }
+
+ // 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<CodecInst>(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 e74f090..8795ef5 100644
--- a/webrtc/modules/audio_coding/neteq/neteq_impl.h
+++ b/webrtc/modules/audio_coding/neteq/neteq_impl.h
@@ -169,6 +169,8 @@
int last_output_sample_rate_hz() const override;
+ rtc::Optional<CodecInst> GetDecoder(int payload_type) const override;
+
int SetTargetNumberOfChannels() override;
int SetTargetSampleRate() override;