blob: 7244c8dab7ba134b25e6045f321ddc393403f3b8 [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/neteq/decoder_database.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000012
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000013#include <utility> // pair
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "api/audio_codecs/audio_decoder.h"
16#include "rtc_base/checks.h"
17#include "rtc_base/logging.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000018
19namespace webrtc {
20
kwiberg5178ee82016-05-03 01:39:01 -070021DecoderDatabase::DecoderDatabase(
Karl Wiberg08126342018-03-20 19:18:55 +010022 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory,
23 rtc::Optional<AudioCodecPairId> codec_pair_id)
kwiberg5178ee82016-05-03 01:39:01 -070024 : active_decoder_type_(-1),
25 active_cng_decoder_type_(-1),
Karl Wiberg08126342018-03-20 19:18:55 +010026 decoder_factory_(decoder_factory),
27 codec_pair_id_(codec_pair_id) {}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000028
ossu97ba30e2016-04-25 07:55:58 -070029DecoderDatabase::~DecoderDatabase() = default;
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000030
Karl Wiberg08126342018-03-20 19:18:55 +010031DecoderDatabase::DecoderInfo::DecoderInfo(
32 const SdpAudioFormat& audio_format,
33 rtc::Optional<AudioCodecPairId> codec_pair_id,
34 AudioDecoderFactory* factory,
35 const std::string& codec_name)
kwiberge9413062016-11-03 05:29:05 -070036 : name_(codec_name),
37 audio_format_(audio_format),
Karl Wiberg08126342018-03-20 19:18:55 +010038 codec_pair_id_(codec_pair_id),
ossu84bc9852016-08-26 05:41:23 -070039 factory_(factory),
kwiberg342f7402016-06-16 03:18:00 -070040 external_decoder_(nullptr),
ossu9f38c212016-10-04 05:23:32 -070041 cng_decoder_(CngDecoder::Create(audio_format)),
42 subtype_(SubtypeFromFormat(audio_format)) {}
kwibergc0f2dcf2016-05-31 06:28:03 -070043
Karl Wiberg08126342018-03-20 19:18:55 +010044DecoderDatabase::DecoderInfo::DecoderInfo(
45 const SdpAudioFormat& audio_format,
46 rtc::Optional<AudioCodecPairId> codec_pair_id,
47 AudioDecoderFactory* factory)
48 : DecoderInfo(audio_format, codec_pair_id, factory, audio_format.name) {}
kwiberge9413062016-11-03 05:29:05 -070049
Karl Wiberg08126342018-03-20 19:18:55 +010050DecoderDatabase::DecoderInfo::DecoderInfo(
51 NetEqDecoder ct,
52 rtc::Optional<AudioCodecPairId> codec_pair_id,
53 AudioDecoderFactory* factory)
54 : DecoderInfo(*NetEqDecoderToSdpAudioFormat(ct), codec_pair_id, factory) {}
ossuf1b08da2016-09-23 02:19:43 -070055
56DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
kwiberge9413062016-11-03 05:29:05 -070057 AudioDecoder* ext_dec,
58 const std::string& codec_name)
59 : name_(codec_name),
60 audio_format_(audio_format),
Karl Wiberg08126342018-03-20 19:18:55 +010061 codec_pair_id_(rtc::nullopt),
ossuf1b08da2016-09-23 02:19:43 -070062 factory_(nullptr),
ossu9f38c212016-10-04 05:23:32 -070063 external_decoder_(ext_dec),
64 subtype_(Subtype::kNormal) {
kwibergc0f2dcf2016-05-31 06:28:03 -070065 RTC_CHECK(ext_dec);
66}
kwiberg0fa0a972016-04-19 05:03:45 -070067
68DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
69DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
70
Karl Wiberg31fbb542017-10-16 12:42:38 +020071bool DecoderDatabase::DecoderInfo::CanGetDecoder() const {
72 if (subtype_ == Subtype::kNormal && !external_decoder_ && !decoder_) {
73 // TODO(ossu): Keep a check here for now, since a number of tests create
74 // DecoderInfos without factories.
75 RTC_DCHECK(factory_);
76 return factory_->IsSupportedDecoder(audio_format_);
77 } else {
78 return true;
79 }
80}
81
ossu84bc9852016-08-26 05:41:23 -070082AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
ossu9f38c212016-10-04 05:23:32 -070083 if (subtype_ != Subtype::kNormal) {
ossuf1b08da2016-09-23 02:19:43 -070084 // These are handled internally, so they have no AudioDecoder objects.
85 return nullptr;
86 }
kwiberg342f7402016-06-16 03:18:00 -070087 if (external_decoder_) {
kwiberg0fa0a972016-04-19 05:03:45 -070088 RTC_DCHECK(!decoder_);
kwiberg342f7402016-06-16 03:18:00 -070089 RTC_DCHECK(!cng_decoder_);
90 return external_decoder_;
kwiberg0fa0a972016-04-19 05:03:45 -070091 }
92 if (!decoder_) {
ossuf1b08da2016-09-23 02:19:43 -070093 // TODO(ossu): Keep a check here for now, since a number of tests create
94 // DecoderInfos without factories.
ossu84bc9852016-08-26 05:41:23 -070095 RTC_DCHECK(factory_);
Karl Wiberg08126342018-03-20 19:18:55 +010096 decoder_ = factory_->MakeAudioDecoder(audio_format_, codec_pair_id_);
kwiberg0fa0a972016-04-19 05:03:45 -070097 }
ossuf1b08da2016-09-23 02:19:43 -070098 RTC_DCHECK(decoder_) << "Failed to create: " << audio_format_;
kwiberg0fa0a972016-04-19 05:03:45 -070099 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000100}
101
ossuf1b08da2016-09-23 02:19:43 -0700102bool DecoderDatabase::DecoderInfo::IsType(const char* name) const {
103 return STR_CASE_CMP(audio_format_.name.c_str(), name) == 0;
104}
105
106bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const {
107 return IsType(name.c_str());
ossu84bc9852016-08-26 05:41:23 -0700108}
109
kwibergc0f2dcf2016-05-31 06:28:03 -0700110rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>
ossuf1b08da2016-09-23 02:19:43 -0700111DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
112 if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
kwiberg5adaf732016-10-04 09:33:27 -0700113 // CN has a 1:1 RTP clock rate to sample rate ratio.
114 const int sample_rate_hz = format.clockrate_hz;
115 RTC_DCHECK(sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
116 sample_rate_hz == 32000 || sample_rate_hz == 48000);
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100117 return DecoderDatabase::DecoderInfo::CngDecoder{sample_rate_hz};
ossuf1b08da2016-09-23 02:19:43 -0700118 } else {
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100119 return rtc::nullopt;
kwibergc0f2dcf2016-05-31 06:28:03 -0700120 }
121}
122
ossu9f38c212016-10-04 05:23:32 -0700123DecoderDatabase::DecoderInfo::Subtype
124DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
125 if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
126 return Subtype::kComfortNoise;
127 } else if (STR_CASE_CMP(format.name.c_str(), "telephone-event") == 0) {
128 return Subtype::kDtmf;
129 } else if (STR_CASE_CMP(format.name.c_str(), "red") == 0) {
130 return Subtype::kRed;
131 }
132
133 return Subtype::kNormal;
134}
135
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000136bool DecoderDatabase::Empty() const { return decoders_.empty(); }
137
turaj@webrtc.org362a55e2013-09-20 16:25:28 +0000138int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000139
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000140void DecoderDatabase::Reset() {
141 decoders_.clear();
ossu97ba30e2016-04-25 07:55:58 -0700142 active_decoder_type_ = -1;
143 active_cng_decoder_type_ = -1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000144}
145
kwiberg1c07c702017-03-27 07:15:49 -0700146std::vector<int> DecoderDatabase::SetCodecs(
147 const std::map<int, SdpAudioFormat>& codecs) {
148 // First collect all payload types that we'll remove or reassign, then remove
149 // them from the database.
150 std::vector<int> changed_payload_types;
151 for (const std::pair<uint8_t, const DecoderInfo&> kv : decoders_) {
152 auto i = codecs.find(kv.first);
153 if (i == codecs.end() || i->second != kv.second.GetFormat()) {
154 changed_payload_types.push_back(kv.first);
155 }
156 }
157 for (int pl_type : changed_payload_types) {
158 Remove(pl_type);
159 }
160
161 // Enter the new and changed payload type mappings into the database.
162 for (const auto& kv : codecs) {
163 const int& rtp_payload_type = kv.first;
164 const SdpAudioFormat& audio_format = kv.second;
165 RTC_DCHECK_GE(rtp_payload_type, 0);
166 RTC_DCHECK_LE(rtp_payload_type, 0x7f);
167 if (decoders_.count(rtp_payload_type) == 0) {
168 decoders_.insert(std::make_pair(
Karl Wiberg08126342018-03-20 19:18:55 +0100169 rtp_payload_type,
170 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
kwiberg1c07c702017-03-27 07:15:49 -0700171 } else {
172 // The mapping for this payload type hasn't changed.
173 }
174 }
175
176 return changed_payload_types;
177}
178
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000179int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800180 NetEqDecoder codec_type,
181 const std::string& name) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000182 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000183 return kInvalidRtpPayloadType;
184 }
Karl Wiberg31fbb542017-10-16 12:42:38 +0200185 if (codec_type == NetEqDecoder::kDecoderArbitrary) {
186 return kCodecNotSupported; // Only supported through InsertExternal.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000187 }
kwiberg65cb70d2017-03-03 06:16:28 -0800188 const auto opt_format = NetEqDecoderToSdpAudioFormat(codec_type);
ossuf1b08da2016-09-23 02:19:43 -0700189 if (!opt_format) {
190 return kCodecNotSupported;
191 }
Karl Wiberg08126342018-03-20 19:18:55 +0100192 DecoderInfo info(*opt_format, codec_pair_id_, decoder_factory_, name);
Karl Wiberg31fbb542017-10-16 12:42:38 +0200193 if (!info.CanGetDecoder()) {
194 return kCodecNotSupported;
195 }
kwiberg0fa0a972016-04-19 05:03:45 -0700196 auto ret =
197 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000198 if (ret.second == false) {
199 // Database already contains a decoder with type |rtp_payload_type|.
200 return kDecoderExists;
201 }
202 return kOK;
203}
204
kwiberg5adaf732016-10-04 09:33:27 -0700205int DecoderDatabase::RegisterPayload(int rtp_payload_type,
206 const SdpAudioFormat& audio_format) {
207 if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) {
208 return kInvalidRtpPayloadType;
209 }
210 const auto ret = decoders_.insert(std::make_pair(
Karl Wiberg08126342018-03-20 19:18:55 +0100211 rtp_payload_type,
212 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
kwiberg5adaf732016-10-04 09:33:27 -0700213 if (ret.second == false) {
214 // Database already contains a decoder with type |rtp_payload_type|.
215 return kDecoderExists;
216 }
217 return kOK;
218}
219
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000220int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
221 NetEqDecoder codec_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800222 const std::string& codec_name,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000223 AudioDecoder* decoder) {
224 if (rtp_payload_type > 0x7F) {
225 return kInvalidRtpPayloadType;
226 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000227 if (!decoder) {
228 return kInvalidPointer;
229 }
ossuf1b08da2016-09-23 02:19:43 -0700230
kwiberg65cb70d2017-03-03 06:16:28 -0800231 const auto opt_db_format = NetEqDecoderToSdpAudioFormat(codec_type);
ossuf1b08da2016-09-23 02:19:43 -0700232 const SdpAudioFormat format = opt_db_format.value_or({"arbitrary", 0, 0});
233
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000234 std::pair<DecoderMap::iterator, bool> ret;
kwiberge9413062016-11-03 05:29:05 -0700235 DecoderInfo info(format, decoder, codec_name);
kwiberg0fa0a972016-04-19 05:03:45 -0700236 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000237 if (ret.second == false) {
238 // Database already contains a decoder with type |rtp_payload_type|.
239 return kDecoderExists;
240 }
241 return kOK;
242}
243
244int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
245 if (decoders_.erase(rtp_payload_type) == 0) {
246 // No decoder with that |rtp_payload_type|.
247 return kDecoderNotFound;
248 }
ossu97ba30e2016-04-25 07:55:58 -0700249 if (active_decoder_type_ == rtp_payload_type) {
250 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000251 }
ossu97ba30e2016-04-25 07:55:58 -0700252 if (active_cng_decoder_type_ == rtp_payload_type) {
253 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000254 }
255 return kOK;
256}
257
kwiberg6b19b562016-09-20 04:02:25 -0700258void DecoderDatabase::RemoveAll() {
259 decoders_.clear();
260 active_decoder_type_ = -1; // No active decoder.
261 active_cng_decoder_type_ = -1; // No active CNG decoder.
262}
263
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000264const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
265 uint8_t rtp_payload_type) const {
266 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
267 if (it == decoders_.end()) {
268 // Decoder not found.
269 return NULL;
270 }
ossuf1b08da2016-09-23 02:19:43 -0700271 return &it->second;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000272}
273
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000274int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
275 bool* new_decoder) {
276 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700277 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
278 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000279 // Decoder not found.
280 return kDecoderNotFound;
281 }
ossu84bc9852016-08-26 05:41:23 -0700282 RTC_CHECK(!info->IsComfortNoise());
283 RTC_DCHECK(new_decoder);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000284 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700285 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000286 // This is the first active decoder.
287 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700288 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000289 // Moving from one active decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700290 const DecoderInfo *old_info = GetDecoderInfo(active_decoder_type_);
291 RTC_DCHECK(old_info);
292 old_info->DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000293 *new_decoder = true;
294 }
ossu97ba30e2016-04-25 07:55:58 -0700295 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000296 return kOK;
297}
298
ossu84bc9852016-08-26 05:41:23 -0700299AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700300 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000301 // No active decoder.
302 return NULL;
303 }
ossu97ba30e2016-04-25 07:55:58 -0700304 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000305}
306
307int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
308 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700309 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
310 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000311 // Decoder not found.
312 return kDecoderNotFound;
313 }
ossu97ba30e2016-04-25 07:55:58 -0700314 if (active_cng_decoder_type_ >= 0 &&
315 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000316 // Moving from one active CNG decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700317 RTC_DCHECK(active_cng_decoder_);
ossu97ba30e2016-04-25 07:55:58 -0700318 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000319 }
ossu97ba30e2016-04-25 07:55:58 -0700320 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000321 return kOK;
322}
323
ossu84bc9852016-08-26 05:41:23 -0700324ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700325 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000326 // No active CNG decoder.
327 return NULL;
328 }
ossu97ba30e2016-04-25 07:55:58 -0700329 if (!active_cng_decoder_) {
330 active_cng_decoder_.reset(new ComfortNoiseDecoder);
331 }
332 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000333}
334
ossu84bc9852016-08-26 05:41:23 -0700335AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
336 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
337 return info ? info->GetDecoder() : nullptr;
338}
339
ossuf1b08da2016-09-23 02:19:43 -0700340bool DecoderDatabase::IsType(uint8_t rtp_payload_type, const char* name) const {
341 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
342 return info && info->IsType(name);
343}
344
ossu84bc9852016-08-26 05:41:23 -0700345bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
ossuf1b08da2016-09-23 02:19:43 -0700346 const std::string& name) const {
347 return IsType(rtp_payload_type, name.c_str());
ossu84bc9852016-08-26 05:41:23 -0700348}
349
350bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
351 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
352 return info && info->IsComfortNoise();
353}
354
355bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
356 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
357 return info && info->IsDtmf();
358}
359
360bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
361 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
362 return info && info->IsRed();
363}
364
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000365int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
366 PacketList::const_iterator it;
367 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
ossua73f6c92016-10-24 08:25:28 -0700368 if (!GetDecoderInfo(it->payload_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000369 // Payload type is not found.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100370 RTC_LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
371 << static_cast<int>(it->payload_type);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000372 return kDecoderNotFound;
373 }
374 }
375 return kOK;
376}
377
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000378} // namespace webrtc