decoder_database.cc (9556B)
1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/audio_coding/neteq/decoder_database.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <list> 16 #include <map> 17 #include <optional> 18 #include <utility> 19 #include <vector> 20 21 #include "absl/strings/match.h" 22 #include "absl/strings/str_cat.h" 23 #include "absl/strings/string_view.h" 24 #include "api/audio_codecs/audio_codec_pair_id.h" 25 #include "api/audio_codecs/audio_decoder.h" 26 #include "api/audio_codecs/audio_decoder_factory.h" 27 #include "api/audio_codecs/audio_format.h" 28 #include "api/environment/environment.h" 29 #include "api/scoped_refptr.h" 30 #include "modules/audio_coding/codecs/cng/webrtc_cng.h" 31 #include "modules/audio_coding/neteq/packet.h" 32 #include "rtc_base/checks.h" 33 #include "rtc_base/logging.h" 34 35 namespace webrtc { 36 37 DecoderDatabase::DecoderDatabase( 38 const Environment& env, 39 scoped_refptr<AudioDecoderFactory> decoder_factory, 40 std::optional<AudioCodecPairId> codec_pair_id) 41 : env_(env), 42 active_decoder_type_(-1), 43 active_cng_decoder_type_(-1), 44 decoder_factory_(std::move(decoder_factory)), 45 codec_pair_id_(codec_pair_id) {} 46 47 DecoderDatabase::~DecoderDatabase() = default; 48 49 DecoderDatabase::DecoderInfo::DecoderInfo( 50 const Environment& env, 51 const SdpAudioFormat& audio_format, 52 std::optional<AudioCodecPairId> codec_pair_id, 53 AudioDecoderFactory* factory) 54 : env_(env), 55 audio_format_(audio_format), 56 codec_pair_id_(codec_pair_id), 57 factory_(factory), 58 cng_decoder_(CngDecoder::Create(audio_format)), 59 subtype_(SubtypeFromFormat(audio_format)) {} 60 61 DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default; 62 DecoderDatabase::DecoderInfo::~DecoderInfo() = default; 63 64 AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const { 65 if (subtype_ != Subtype::kNormal) { 66 // These are handled internally, so they have no AudioDecoder objects. 67 return nullptr; 68 } 69 if (!decoder_) { 70 // TODO(ossu): Keep a check here for now, since a number of tests create 71 // DecoderInfos without factories. 72 RTC_DCHECK(factory_); 73 decoder_ = factory_->Create(env_, audio_format_, codec_pair_id_); 74 } 75 RTC_DCHECK(decoder_) << "Failed to create: " << absl::StrCat(audio_format_); 76 return decoder_.get(); 77 } 78 79 bool DecoderDatabase::DecoderInfo::IsType(absl::string_view name) const { 80 return absl::EqualsIgnoreCase(audio_format_.name, name); 81 } 82 83 std::optional<DecoderDatabase::DecoderInfo::CngDecoder> 84 DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) { 85 if (absl::EqualsIgnoreCase(format.name, "CN")) { 86 // CN has a 1:1 RTP clock rate to sample rate ratio. 87 const int sample_rate_hz = format.clockrate_hz; 88 RTC_DCHECK(sample_rate_hz == 8000 || sample_rate_hz == 16000 || 89 sample_rate_hz == 32000 || sample_rate_hz == 48000); 90 return DecoderDatabase::DecoderInfo::CngDecoder{sample_rate_hz}; 91 } else { 92 return std::nullopt; 93 } 94 } 95 96 DecoderDatabase::DecoderInfo::Subtype 97 DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) { 98 if (absl::EqualsIgnoreCase(format.name, "CN")) { 99 return Subtype::kComfortNoise; 100 } else if (absl::EqualsIgnoreCase(format.name, "telephone-event")) { 101 return Subtype::kDtmf; 102 } else if (absl::EqualsIgnoreCase(format.name, "red")) { 103 return Subtype::kRed; 104 } 105 106 return Subtype::kNormal; 107 } 108 109 bool DecoderDatabase::Empty() const { 110 return decoders_.empty(); 111 } 112 113 int DecoderDatabase::Size() const { 114 return static_cast<int>(decoders_.size()); 115 } 116 117 std::vector<int> DecoderDatabase::SetCodecs( 118 const std::map<int, SdpAudioFormat>& codecs) { 119 // First collect all payload types that we'll remove or reassign, then remove 120 // them from the database. 121 std::vector<int> changed_payload_types; 122 for (const std::pair<uint8_t, const DecoderInfo&> kv : decoders_) { 123 auto i = codecs.find(kv.first); 124 if (i == codecs.end() || i->second != kv.second.GetFormat()) { 125 changed_payload_types.push_back(kv.first); 126 } 127 } 128 for (int pl_type : changed_payload_types) { 129 Remove(pl_type); 130 } 131 132 // Enter the new and changed payload type mappings into the database. 133 for (const auto& kv : codecs) { 134 const int& rtp_payload_type = kv.first; 135 const SdpAudioFormat& audio_format = kv.second; 136 RTC_DCHECK_GE(rtp_payload_type, 0); 137 RTC_DCHECK_LE(rtp_payload_type, 0x7f); 138 if (decoders_.count(rtp_payload_type) == 0) { 139 decoders_.insert(std::make_pair( 140 rtp_payload_type, DecoderInfo(env_, audio_format, codec_pair_id_, 141 decoder_factory_.get()))); 142 } else { 143 // The mapping for this payload type hasn't changed. 144 } 145 } 146 147 return changed_payload_types; 148 } 149 150 int DecoderDatabase::RegisterPayload(int rtp_payload_type, 151 const SdpAudioFormat& audio_format) { 152 if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) { 153 return kInvalidRtpPayloadType; 154 } 155 const auto ret = decoders_.insert(std::make_pair( 156 rtp_payload_type, 157 DecoderInfo(env_, audio_format, codec_pair_id_, decoder_factory_.get()))); 158 if (ret.second == false) { 159 // Database already contains a decoder with type `rtp_payload_type`. 160 return kDecoderExists; 161 } 162 return kOK; 163 } 164 165 int DecoderDatabase::Remove(uint8_t rtp_payload_type) { 166 if (decoders_.erase(rtp_payload_type) == 0) { 167 // No decoder with that `rtp_payload_type`. 168 return kDecoderNotFound; 169 } 170 if (active_decoder_type_ == rtp_payload_type) { 171 active_decoder_type_ = -1; // No active decoder. 172 } 173 if (active_cng_decoder_type_ == rtp_payload_type) { 174 active_cng_decoder_type_ = -1; // No active CNG decoder. 175 } 176 return kOK; 177 } 178 179 void DecoderDatabase::RemoveAll() { 180 decoders_.clear(); 181 active_decoder_type_ = -1; // No active decoder. 182 active_cng_decoder_type_ = -1; // No active CNG decoder. 183 } 184 185 const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo( 186 uint8_t rtp_payload_type) const { 187 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type); 188 if (it == decoders_.end()) { 189 // Decoder not found. 190 return nullptr; 191 } 192 return &it->second; 193 } 194 195 int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type, 196 bool* new_decoder) { 197 // Check that `rtp_payload_type` exists in the database. 198 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type); 199 if (!info) { 200 // Decoder not found. 201 return kDecoderNotFound; 202 } 203 RTC_CHECK(!info->IsComfortNoise()); 204 RTC_DCHECK(new_decoder); 205 *new_decoder = false; 206 if (active_decoder_type_ < 0) { 207 // This is the first active decoder. 208 *new_decoder = true; 209 } else if (active_decoder_type_ != rtp_payload_type) { 210 // Moving from one active decoder to another. Delete the first one. 211 const DecoderInfo* old_info = GetDecoderInfo(active_decoder_type_); 212 RTC_DCHECK(old_info); 213 old_info->DropDecoder(); 214 *new_decoder = true; 215 } 216 active_decoder_type_ = rtp_payload_type; 217 return kOK; 218 } 219 220 AudioDecoder* DecoderDatabase::GetActiveDecoder() const { 221 if (active_decoder_type_ < 0) { 222 // No active decoder. 223 return nullptr; 224 } 225 return GetDecoder(active_decoder_type_); 226 } 227 228 int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) { 229 // Check that `rtp_payload_type` exists in the database. 230 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type); 231 if (!info) { 232 // Decoder not found. 233 return kDecoderNotFound; 234 } 235 if (active_cng_decoder_type_ >= 0 && 236 active_cng_decoder_type_ != rtp_payload_type) { 237 // Moving from one active CNG decoder to another. Delete the first one. 238 RTC_DCHECK(active_cng_decoder_); 239 active_cng_decoder_.reset(); 240 } 241 active_cng_decoder_type_ = rtp_payload_type; 242 return kOK; 243 } 244 245 ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const { 246 if (active_cng_decoder_type_ < 0) { 247 // No active CNG decoder. 248 return nullptr; 249 } 250 if (!active_cng_decoder_) { 251 active_cng_decoder_.reset(new ComfortNoiseDecoder); 252 } 253 return active_cng_decoder_.get(); 254 } 255 256 AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const { 257 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type); 258 return info ? info->GetDecoder() : nullptr; 259 } 260 261 bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const { 262 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type); 263 return info && info->IsComfortNoise(); 264 } 265 266 bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const { 267 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type); 268 return info && info->IsDtmf(); 269 } 270 271 bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const { 272 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type); 273 return info && info->IsRed(); 274 } 275 276 int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const { 277 PacketList::const_iterator it; 278 for (it = packet_list.begin(); it != packet_list.end(); ++it) { 279 if (!GetDecoderInfo(it->payload_type)) { 280 // Payload type is not found. 281 RTC_LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type " 282 << static_cast<int>(it->payload_type); 283 return kDecoderNotFound; 284 } 285 } 286 return kOK; 287 } 288 289 } // namespace webrtc