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