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 <utility>  // pair
14 
15 #include "api/audio_codecs/audio_decoder.h"
16 #include "rtc_base/checks.h"
17 #include "rtc_base/logging.h"
18 
19 namespace webrtc {
20 
DecoderDatabase(const rtc::scoped_refptr<AudioDecoderFactory> & decoder_factory)21 DecoderDatabase::DecoderDatabase(
22     const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory)
23     : active_decoder_type_(-1),
24       active_cng_decoder_type_(-1),
25       decoder_factory_(decoder_factory) {}
26 
27 DecoderDatabase::~DecoderDatabase() = default;
28 
DecoderInfo(const SdpAudioFormat & audio_format,AudioDecoderFactory * factory,const std::string & codec_name)29 DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
30                                           AudioDecoderFactory* factory,
31                                           const std::string& codec_name)
32     : name_(codec_name),
33       audio_format_(audio_format),
34       factory_(factory),
35       external_decoder_(nullptr),
36       cng_decoder_(CngDecoder::Create(audio_format)),
37       subtype_(SubtypeFromFormat(audio_format)) {}
38 
DecoderInfo(const SdpAudioFormat & audio_format,AudioDecoderFactory * factory)39 DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
40                                           AudioDecoderFactory* factory)
41     : DecoderInfo(audio_format, factory, audio_format.name) {}
42 
DecoderInfo(NetEqDecoder ct,AudioDecoderFactory * factory)43 DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
44                                           AudioDecoderFactory* factory)
45     : DecoderInfo(*NetEqDecoderToSdpAudioFormat(ct), factory) {}
46 
DecoderInfo(const SdpAudioFormat & audio_format,AudioDecoder * ext_dec,const std::string & codec_name)47 DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
48                                           AudioDecoder* ext_dec,
49                                           const std::string& codec_name)
50     : name_(codec_name),
51       audio_format_(audio_format),
52       factory_(nullptr),
53       external_decoder_(ext_dec),
54       subtype_(Subtype::kNormal) {
55   RTC_CHECK(ext_dec);
56 }
57 
58 DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
59 DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
60 
CanGetDecoder() const61 bool DecoderDatabase::DecoderInfo::CanGetDecoder() const {
62   if (subtype_ == Subtype::kNormal && !external_decoder_ && !decoder_) {
63     // TODO(ossu): Keep a check here for now, since a number of tests create
64     // DecoderInfos without factories.
65     RTC_DCHECK(factory_);
66     return factory_->IsSupportedDecoder(audio_format_);
67   } else {
68     return true;
69   }
70 }
71 
GetDecoder() const72 AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
73   if (subtype_ != Subtype::kNormal) {
74     // These are handled internally, so they have no AudioDecoder objects.
75     return nullptr;
76   }
77   if (external_decoder_) {
78     RTC_DCHECK(!decoder_);
79     RTC_DCHECK(!cng_decoder_);
80     return external_decoder_;
81   }
82   if (!decoder_) {
83     // TODO(ossu): Keep a check here for now, since a number of tests create
84     // DecoderInfos without factories.
85     RTC_DCHECK(factory_);
86     decoder_ = factory_->MakeAudioDecoder(audio_format_);
87   }
88   RTC_DCHECK(decoder_) << "Failed to create: " << audio_format_;
89   return decoder_.get();
90 }
91 
IsType(const char * name) const92 bool DecoderDatabase::DecoderInfo::IsType(const char* name) const {
93   return STR_CASE_CMP(audio_format_.name.c_str(), name) == 0;
94 }
95 
IsType(const std::string & name) const96 bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const {
97   return IsType(name.c_str());
98 }
99 
100 rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>
Create(const SdpAudioFormat & format)101 DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
102   if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
103     // CN has a 1:1 RTP clock rate to sample rate ratio.
104     const int sample_rate_hz = format.clockrate_hz;
105     RTC_DCHECK(sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
106                sample_rate_hz == 32000 || sample_rate_hz == 48000);
107     return DecoderDatabase::DecoderInfo::CngDecoder{sample_rate_hz};
108   } else {
109     return rtc::nullopt;
110   }
111 }
112 
113 DecoderDatabase::DecoderInfo::Subtype
SubtypeFromFormat(const SdpAudioFormat & format)114 DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
115   if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
116     return Subtype::kComfortNoise;
117   } else if (STR_CASE_CMP(format.name.c_str(), "telephone-event") == 0) {
118     return Subtype::kDtmf;
119   } else if (STR_CASE_CMP(format.name.c_str(), "red") == 0) {
120     return Subtype::kRed;
121   }
122 
123   return Subtype::kNormal;
124 }
125 
Empty() const126 bool DecoderDatabase::Empty() const { return decoders_.empty(); }
127 
Size() const128 int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
129 
Reset()130 void DecoderDatabase::Reset() {
131   decoders_.clear();
132   active_decoder_type_ = -1;
133   active_cng_decoder_type_ = -1;
134 }
135 
SetCodecs(const std::map<int,SdpAudioFormat> & codecs)136 std::vector<int> DecoderDatabase::SetCodecs(
137     const std::map<int, SdpAudioFormat>& codecs) {
138   // First collect all payload types that we'll remove or reassign, then remove
139   // them from the database.
140   std::vector<int> changed_payload_types;
141   for (const std::pair<uint8_t, const DecoderInfo&> kv : decoders_) {
142     auto i = codecs.find(kv.first);
143     if (i == codecs.end() || i->second != kv.second.GetFormat()) {
144       changed_payload_types.push_back(kv.first);
145     }
146   }
147   for (int pl_type : changed_payload_types) {
148     Remove(pl_type);
149   }
150 
151   // Enter the new and changed payload type mappings into the database.
152   for (const auto& kv : codecs) {
153     const int& rtp_payload_type = kv.first;
154     const SdpAudioFormat& audio_format = kv.second;
155     RTC_DCHECK_GE(rtp_payload_type, 0);
156     RTC_DCHECK_LE(rtp_payload_type, 0x7f);
157     if (decoders_.count(rtp_payload_type) == 0) {
158       decoders_.insert(std::make_pair(
159           rtp_payload_type, DecoderInfo(audio_format, decoder_factory_.get())));
160     } else {
161       // The mapping for this payload type hasn't changed.
162     }
163   }
164 
165   return changed_payload_types;
166 }
167 
RegisterPayload(uint8_t rtp_payload_type,NetEqDecoder codec_type,const std::string & name)168 int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
169                                      NetEqDecoder codec_type,
170                                      const std::string& name) {
171   if (rtp_payload_type > 0x7F) {
172     return kInvalidRtpPayloadType;
173   }
174   if (codec_type == NetEqDecoder::kDecoderArbitrary) {
175     return kCodecNotSupported;  // Only supported through InsertExternal.
176   }
177   const auto opt_format = NetEqDecoderToSdpAudioFormat(codec_type);
178   if (!opt_format) {
179     return kCodecNotSupported;
180   }
181   DecoderInfo info(*opt_format, decoder_factory_, name);
182   if (!info.CanGetDecoder()) {
183     return kCodecNotSupported;
184   }
185   auto ret =
186       decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
187   if (ret.second == false) {
188     // Database already contains a decoder with type |rtp_payload_type|.
189     return kDecoderExists;
190   }
191   return kOK;
192 }
193 
RegisterPayload(int rtp_payload_type,const SdpAudioFormat & audio_format)194 int DecoderDatabase::RegisterPayload(int rtp_payload_type,
195                                      const SdpAudioFormat& audio_format) {
196   if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) {
197     return kInvalidRtpPayloadType;
198   }
199   const auto ret = decoders_.insert(std::make_pair(
200       rtp_payload_type, DecoderInfo(audio_format, decoder_factory_.get())));
201   if (ret.second == false) {
202     // Database already contains a decoder with type |rtp_payload_type|.
203     return kDecoderExists;
204   }
205   return kOK;
206 }
207 
InsertExternal(uint8_t rtp_payload_type,NetEqDecoder codec_type,const std::string & codec_name,AudioDecoder * decoder)208 int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
209                                     NetEqDecoder codec_type,
210                                     const std::string& codec_name,
211                                     AudioDecoder* decoder) {
212   if (rtp_payload_type > 0x7F) {
213     return kInvalidRtpPayloadType;
214   }
215   if (!decoder) {
216     return kInvalidPointer;
217   }
218 
219   const auto opt_db_format = NetEqDecoderToSdpAudioFormat(codec_type);
220   const SdpAudioFormat format = opt_db_format.value_or({"arbitrary", 0, 0});
221 
222   std::pair<DecoderMap::iterator, bool> ret;
223   DecoderInfo info(format, decoder, codec_name);
224   ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
225   if (ret.second == false) {
226     // Database already contains a decoder with type |rtp_payload_type|.
227     return kDecoderExists;
228   }
229   return kOK;
230 }
231 
Remove(uint8_t rtp_payload_type)232 int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
233   if (decoders_.erase(rtp_payload_type) == 0) {
234     // No decoder with that |rtp_payload_type|.
235     return kDecoderNotFound;
236   }
237   if (active_decoder_type_ == rtp_payload_type) {
238     active_decoder_type_ = -1;  // No active decoder.
239   }
240   if (active_cng_decoder_type_ == rtp_payload_type) {
241     active_cng_decoder_type_ = -1;  // No active CNG decoder.
242   }
243   return kOK;
244 }
245 
RemoveAll()246 void DecoderDatabase::RemoveAll() {
247   decoders_.clear();
248   active_decoder_type_ = -1;      // No active decoder.
249   active_cng_decoder_type_ = -1;  // No active CNG decoder.
250 }
251 
GetDecoderInfo(uint8_t rtp_payload_type) const252 const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
253     uint8_t rtp_payload_type) const {
254   DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
255   if (it == decoders_.end()) {
256     // Decoder not found.
257     return NULL;
258   }
259   return &it->second;
260 }
261 
SetActiveDecoder(uint8_t rtp_payload_type,bool * new_decoder)262 int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
263                                       bool* new_decoder) {
264   // Check that |rtp_payload_type| exists in the database.
265   const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
266   if (!info) {
267     // Decoder not found.
268     return kDecoderNotFound;
269   }
270   RTC_CHECK(!info->IsComfortNoise());
271   RTC_DCHECK(new_decoder);
272   *new_decoder = false;
273   if (active_decoder_type_ < 0) {
274     // This is the first active decoder.
275     *new_decoder = true;
276   } else if (active_decoder_type_ != rtp_payload_type) {
277     // Moving from one active decoder to another. Delete the first one.
278     const DecoderInfo *old_info = GetDecoderInfo(active_decoder_type_);
279     RTC_DCHECK(old_info);
280     old_info->DropDecoder();
281     *new_decoder = true;
282   }
283   active_decoder_type_ = rtp_payload_type;
284   return kOK;
285 }
286 
GetActiveDecoder() const287 AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
288   if (active_decoder_type_ < 0) {
289     // No active decoder.
290     return NULL;
291   }
292   return GetDecoder(active_decoder_type_);
293 }
294 
SetActiveCngDecoder(uint8_t rtp_payload_type)295 int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
296   // Check that |rtp_payload_type| exists in the database.
297   const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
298   if (!info) {
299     // Decoder not found.
300     return kDecoderNotFound;
301   }
302   if (active_cng_decoder_type_ >= 0 &&
303       active_cng_decoder_type_ != rtp_payload_type) {
304     // Moving from one active CNG decoder to another. Delete the first one.
305     RTC_DCHECK(active_cng_decoder_);
306     active_cng_decoder_.reset();
307   }
308   active_cng_decoder_type_ = rtp_payload_type;
309   return kOK;
310 }
311 
GetActiveCngDecoder() const312 ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
313   if (active_cng_decoder_type_ < 0) {
314     // No active CNG decoder.
315     return NULL;
316   }
317   if (!active_cng_decoder_) {
318     active_cng_decoder_.reset(new ComfortNoiseDecoder);
319   }
320   return active_cng_decoder_.get();
321 }
322 
GetDecoder(uint8_t rtp_payload_type) const323 AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
324   const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
325   return info ? info->GetDecoder() : nullptr;
326 }
327 
IsType(uint8_t rtp_payload_type,const char * name) const328 bool DecoderDatabase::IsType(uint8_t rtp_payload_type, const char* name) const {
329   const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
330   return info && info->IsType(name);
331 }
332 
IsType(uint8_t rtp_payload_type,const std::string & name) const333 bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
334                              const std::string& name) const {
335   return IsType(rtp_payload_type, name.c_str());
336 }
337 
IsComfortNoise(uint8_t rtp_payload_type) const338 bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
339   const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
340   return info && info->IsComfortNoise();
341 }
342 
IsDtmf(uint8_t rtp_payload_type) const343 bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
344   const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
345   return info && info->IsDtmf();
346 }
347 
IsRed(uint8_t rtp_payload_type) const348 bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
349   const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
350   return info && info->IsRed();
351 }
352 
CheckPayloadTypes(const PacketList & packet_list) const353 int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
354   PacketList::const_iterator it;
355   for (it = packet_list.begin(); it != packet_list.end(); ++it) {
356     if (!GetDecoderInfo(it->payload_type)) {
357       // Payload type is not found.
358       RTC_LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
359                           << static_cast<int>(it->payload_type);
360       return kDecoderNotFound;
361     }
362   }
363   return kOK;
364 }
365 
366 }  // namespace webrtc
367