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