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