blob: 743ca8775e152c8c96d2ad3af9102b7cec331420 [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(
ossue725f7c2016-05-19 10:48:04 -070022 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory)
kwiberg5178ee82016-05-03 01:39:01 -070023 : active_decoder_type_(-1),
24 active_cng_decoder_type_(-1),
ossue725f7c2016-05-19 10:48:04 -070025 decoder_factory_(decoder_factory) {}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000026
ossu97ba30e2016-04-25 07:55:58 -070027DecoderDatabase::~DecoderDatabase() = default;
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000028
ossuf1b08da2016-09-23 02:19:43 -070029DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
kwiberge9413062016-11-03 05:29:05 -070030 AudioDecoderFactory* factory,
31 const std::string& codec_name)
32 : name_(codec_name),
33 audio_format_(audio_format),
ossu84bc9852016-08-26 05:41:23 -070034 factory_(factory),
kwiberg342f7402016-06-16 03:18:00 -070035 external_decoder_(nullptr),
ossu9f38c212016-10-04 05:23:32 -070036 cng_decoder_(CngDecoder::Create(audio_format)),
37 subtype_(SubtypeFromFormat(audio_format)) {}
kwibergc0f2dcf2016-05-31 06:28:03 -070038
kwiberge9413062016-11-03 05:29:05 -070039DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
40 AudioDecoderFactory* factory)
41 : DecoderInfo(audio_format, factory, audio_format.name) {}
42
kwibergc0f2dcf2016-05-31 06:28:03 -070043DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
ossuf1b08da2016-09-23 02:19:43 -070044 AudioDecoderFactory* factory)
kwiberg65cb70d2017-03-03 06:16:28 -080045 : DecoderInfo(*NetEqDecoderToSdpAudioFormat(ct), factory) {}
ossuf1b08da2016-09-23 02:19:43 -070046
47DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
kwiberge9413062016-11-03 05:29:05 -070048 AudioDecoder* ext_dec,
49 const std::string& codec_name)
50 : name_(codec_name),
51 audio_format_(audio_format),
ossuf1b08da2016-09-23 02:19:43 -070052 factory_(nullptr),
ossu9f38c212016-10-04 05:23:32 -070053 external_decoder_(ext_dec),
54 subtype_(Subtype::kNormal) {
kwibergc0f2dcf2016-05-31 06:28:03 -070055 RTC_CHECK(ext_dec);
56}
kwiberg0fa0a972016-04-19 05:03:45 -070057
58DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
59DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
60
Karl Wiberg31fbb542017-10-16 12:42:38 +020061bool 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
ossu84bc9852016-08-26 05:41:23 -070072AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
ossu9f38c212016-10-04 05:23:32 -070073 if (subtype_ != Subtype::kNormal) {
ossuf1b08da2016-09-23 02:19:43 -070074 // These are handled internally, so they have no AudioDecoder objects.
75 return nullptr;
76 }
kwiberg342f7402016-06-16 03:18:00 -070077 if (external_decoder_) {
kwiberg0fa0a972016-04-19 05:03:45 -070078 RTC_DCHECK(!decoder_);
kwiberg342f7402016-06-16 03:18:00 -070079 RTC_DCHECK(!cng_decoder_);
80 return external_decoder_;
kwiberg0fa0a972016-04-19 05:03:45 -070081 }
82 if (!decoder_) {
ossuf1b08da2016-09-23 02:19:43 -070083 // TODO(ossu): Keep a check here for now, since a number of tests create
84 // DecoderInfos without factories.
ossu84bc9852016-08-26 05:41:23 -070085 RTC_DCHECK(factory_);
ossuf1b08da2016-09-23 02:19:43 -070086 decoder_ = factory_->MakeAudioDecoder(audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -070087 }
ossuf1b08da2016-09-23 02:19:43 -070088 RTC_DCHECK(decoder_) << "Failed to create: " << audio_format_;
kwiberg0fa0a972016-04-19 05:03:45 -070089 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000090}
91
ossuf1b08da2016-09-23 02:19:43 -070092bool DecoderDatabase::DecoderInfo::IsType(const char* name) const {
93 return STR_CASE_CMP(audio_format_.name.c_str(), name) == 0;
94}
95
96bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const {
97 return IsType(name.c_str());
ossu84bc9852016-08-26 05:41:23 -070098}
99
kwibergc0f2dcf2016-05-31 06:28:03 -0700100rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>
ossuf1b08da2016-09-23 02:19:43 -0700101DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
102 if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
kwiberg5adaf732016-10-04 09:33:27 -0700103 // 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 rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>(
108 {sample_rate_hz});
ossuf1b08da2016-09-23 02:19:43 -0700109 } else {
110 return rtc::Optional<CngDecoder>();
kwibergc0f2dcf2016-05-31 06:28:03 -0700111 }
112}
113
ossu9f38c212016-10-04 05:23:32 -0700114DecoderDatabase::DecoderInfo::Subtype
115DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
116 if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
117 return Subtype::kComfortNoise;
118 } else if (STR_CASE_CMP(format.name.c_str(), "telephone-event") == 0) {
119 return Subtype::kDtmf;
120 } else if (STR_CASE_CMP(format.name.c_str(), "red") == 0) {
121 return Subtype::kRed;
122 }
123
124 return Subtype::kNormal;
125}
126
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000127bool DecoderDatabase::Empty() const { return decoders_.empty(); }
128
turaj@webrtc.org362a55e2013-09-20 16:25:28 +0000129int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000130
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000131void DecoderDatabase::Reset() {
132 decoders_.clear();
ossu97ba30e2016-04-25 07:55:58 -0700133 active_decoder_type_ = -1;
134 active_cng_decoder_type_ = -1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000135}
136
kwiberg1c07c702017-03-27 07:15:49 -0700137std::vector<int> DecoderDatabase::SetCodecs(
138 const std::map<int, SdpAudioFormat>& codecs) {
139 // First collect all payload types that we'll remove or reassign, then remove
140 // them from the database.
141 std::vector<int> changed_payload_types;
142 for (const std::pair<uint8_t, const DecoderInfo&> kv : decoders_) {
143 auto i = codecs.find(kv.first);
144 if (i == codecs.end() || i->second != kv.second.GetFormat()) {
145 changed_payload_types.push_back(kv.first);
146 }
147 }
148 for (int pl_type : changed_payload_types) {
149 Remove(pl_type);
150 }
151
152 // Enter the new and changed payload type mappings into the database.
153 for (const auto& kv : codecs) {
154 const int& rtp_payload_type = kv.first;
155 const SdpAudioFormat& audio_format = kv.second;
156 RTC_DCHECK_GE(rtp_payload_type, 0);
157 RTC_DCHECK_LE(rtp_payload_type, 0x7f);
158 if (decoders_.count(rtp_payload_type) == 0) {
159 decoders_.insert(std::make_pair(
160 rtp_payload_type, DecoderInfo(audio_format, decoder_factory_.get())));
161 } else {
162 // The mapping for this payload type hasn't changed.
163 }
164 }
165
166 return changed_payload_types;
167}
168
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000169int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800170 NetEqDecoder codec_type,
171 const std::string& name) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000172 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000173 return kInvalidRtpPayloadType;
174 }
Karl Wiberg31fbb542017-10-16 12:42:38 +0200175 if (codec_type == NetEqDecoder::kDecoderArbitrary) {
176 return kCodecNotSupported; // Only supported through InsertExternal.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000177 }
kwiberg65cb70d2017-03-03 06:16:28 -0800178 const auto opt_format = NetEqDecoderToSdpAudioFormat(codec_type);
ossuf1b08da2016-09-23 02:19:43 -0700179 if (!opt_format) {
180 return kCodecNotSupported;
181 }
kwiberge9413062016-11-03 05:29:05 -0700182 DecoderInfo info(*opt_format, decoder_factory_, name);
Karl Wiberg31fbb542017-10-16 12:42:38 +0200183 if (!info.CanGetDecoder()) {
184 return kCodecNotSupported;
185 }
kwiberg0fa0a972016-04-19 05:03:45 -0700186 auto ret =
187 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000188 if (ret.second == false) {
189 // Database already contains a decoder with type |rtp_payload_type|.
190 return kDecoderExists;
191 }
192 return kOK;
193}
194
kwiberg5adaf732016-10-04 09:33:27 -0700195int DecoderDatabase::RegisterPayload(int rtp_payload_type,
196 const SdpAudioFormat& audio_format) {
197 if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) {
198 return kInvalidRtpPayloadType;
199 }
200 const auto ret = decoders_.insert(std::make_pair(
201 rtp_payload_type, DecoderInfo(audio_format, decoder_factory_.get())));
202 if (ret.second == false) {
203 // Database already contains a decoder with type |rtp_payload_type|.
204 return kDecoderExists;
205 }
206 return kOK;
207}
208
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000209int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
210 NetEqDecoder codec_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800211 const std::string& codec_name,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000212 AudioDecoder* decoder) {
213 if (rtp_payload_type > 0x7F) {
214 return kInvalidRtpPayloadType;
215 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000216 if (!decoder) {
217 return kInvalidPointer;
218 }
ossuf1b08da2016-09-23 02:19:43 -0700219
kwiberg65cb70d2017-03-03 06:16:28 -0800220 const auto opt_db_format = NetEqDecoderToSdpAudioFormat(codec_type);
ossuf1b08da2016-09-23 02:19:43 -0700221 const SdpAudioFormat format = opt_db_format.value_or({"arbitrary", 0, 0});
222
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000223 std::pair<DecoderMap::iterator, bool> ret;
kwiberge9413062016-11-03 05:29:05 -0700224 DecoderInfo info(format, decoder, codec_name);
kwiberg0fa0a972016-04-19 05:03:45 -0700225 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000226 if (ret.second == false) {
227 // Database already contains a decoder with type |rtp_payload_type|.
228 return kDecoderExists;
229 }
230 return kOK;
231}
232
233int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
234 if (decoders_.erase(rtp_payload_type) == 0) {
235 // No decoder with that |rtp_payload_type|.
236 return kDecoderNotFound;
237 }
ossu97ba30e2016-04-25 07:55:58 -0700238 if (active_decoder_type_ == rtp_payload_type) {
239 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000240 }
ossu97ba30e2016-04-25 07:55:58 -0700241 if (active_cng_decoder_type_ == rtp_payload_type) {
242 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000243 }
244 return kOK;
245}
246
kwiberg6b19b562016-09-20 04:02:25 -0700247void DecoderDatabase::RemoveAll() {
248 decoders_.clear();
249 active_decoder_type_ = -1; // No active decoder.
250 active_cng_decoder_type_ = -1; // No active CNG decoder.
251}
252
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000253const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
254 uint8_t rtp_payload_type) const {
255 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
256 if (it == decoders_.end()) {
257 // Decoder not found.
258 return NULL;
259 }
ossuf1b08da2016-09-23 02:19:43 -0700260 return &it->second;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000261}
262
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000263int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
264 bool* new_decoder) {
265 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700266 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
267 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000268 // Decoder not found.
269 return kDecoderNotFound;
270 }
ossu84bc9852016-08-26 05:41:23 -0700271 RTC_CHECK(!info->IsComfortNoise());
272 RTC_DCHECK(new_decoder);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000273 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700274 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000275 // This is the first active decoder.
276 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700277 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000278 // Moving from one active decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700279 const DecoderInfo *old_info = GetDecoderInfo(active_decoder_type_);
280 RTC_DCHECK(old_info);
281 old_info->DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000282 *new_decoder = true;
283 }
ossu97ba30e2016-04-25 07:55:58 -0700284 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000285 return kOK;
286}
287
ossu84bc9852016-08-26 05:41:23 -0700288AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700289 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000290 // No active decoder.
291 return NULL;
292 }
ossu97ba30e2016-04-25 07:55:58 -0700293 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000294}
295
296int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
297 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700298 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
299 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000300 // Decoder not found.
301 return kDecoderNotFound;
302 }
ossu97ba30e2016-04-25 07:55:58 -0700303 if (active_cng_decoder_type_ >= 0 &&
304 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000305 // Moving from one active CNG decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700306 RTC_DCHECK(active_cng_decoder_);
ossu97ba30e2016-04-25 07:55:58 -0700307 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000308 }
ossu97ba30e2016-04-25 07:55:58 -0700309 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000310 return kOK;
311}
312
ossu84bc9852016-08-26 05:41:23 -0700313ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700314 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000315 // No active CNG decoder.
316 return NULL;
317 }
ossu97ba30e2016-04-25 07:55:58 -0700318 if (!active_cng_decoder_) {
319 active_cng_decoder_.reset(new ComfortNoiseDecoder);
320 }
321 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000322}
323
ossu84bc9852016-08-26 05:41:23 -0700324AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
325 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
326 return info ? info->GetDecoder() : nullptr;
327}
328
ossuf1b08da2016-09-23 02:19:43 -0700329bool DecoderDatabase::IsType(uint8_t rtp_payload_type, const char* name) const {
330 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
331 return info && info->IsType(name);
332}
333
ossu84bc9852016-08-26 05:41:23 -0700334bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
ossuf1b08da2016-09-23 02:19:43 -0700335 const std::string& name) const {
336 return IsType(rtp_payload_type, name.c_str());
ossu84bc9852016-08-26 05:41:23 -0700337}
338
339bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
340 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
341 return info && info->IsComfortNoise();
342}
343
344bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
345 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
346 return info && info->IsDtmf();
347}
348
349bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
350 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
351 return info && info->IsRed();
352}
353
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000354int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
355 PacketList::const_iterator it;
356 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
ossua73f6c92016-10-24 08:25:28 -0700357 if (!GetDecoderInfo(it->payload_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000358 // Payload type is not found.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100359 RTC_LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
360 << static_cast<int>(it->payload_type);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000361 return kDecoderNotFound;
362 }
363 }
364 return kOK;
365}
366
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000367} // namespace webrtc