blob: fa120d235386f1007744a0d22ff617cc8186feec [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
henrik.lundin@webrtc.org9c55f0f2014-06-09 08:10:28 +000011#include "webrtc/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
henrik.lundin4cf61dd2015-12-09 06:20:58 -080015#include "webrtc/base/checks.h"
Henrik Lundind67a2192015-08-03 12:54:37 +020016#include "webrtc/base/logging.h"
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000017#include "webrtc/modules/audio_coding/codecs/audio_decoder.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)
kwiberge9413062016-11-03 05:29:05 -070045 : DecoderInfo(*acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct),
46 factory) {}
ossuf1b08da2016-09-23 02:19:43 -070047
48DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
kwiberge9413062016-11-03 05:29:05 -070049 AudioDecoder* ext_dec,
50 const std::string& codec_name)
51 : name_(codec_name),
52 audio_format_(audio_format),
ossuf1b08da2016-09-23 02:19:43 -070053 factory_(nullptr),
ossu9f38c212016-10-04 05:23:32 -070054 external_decoder_(ext_dec),
55 subtype_(Subtype::kNormal) {
kwibergc0f2dcf2016-05-31 06:28:03 -070056 RTC_CHECK(ext_dec);
57}
kwiberg0fa0a972016-04-19 05:03:45 -070058
59DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
60DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
61
ossu84bc9852016-08-26 05:41:23 -070062AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
ossu9f38c212016-10-04 05:23:32 -070063 if (subtype_ != Subtype::kNormal) {
ossuf1b08da2016-09-23 02:19:43 -070064 // These are handled internally, so they have no AudioDecoder objects.
65 return nullptr;
66 }
kwiberg342f7402016-06-16 03:18:00 -070067 if (external_decoder_) {
kwiberg0fa0a972016-04-19 05:03:45 -070068 RTC_DCHECK(!decoder_);
kwiberg342f7402016-06-16 03:18:00 -070069 RTC_DCHECK(!cng_decoder_);
70 return external_decoder_;
kwiberg0fa0a972016-04-19 05:03:45 -070071 }
72 if (!decoder_) {
ossuf1b08da2016-09-23 02:19:43 -070073 // TODO(ossu): Keep a check here for now, since a number of tests create
74 // DecoderInfos without factories.
ossu84bc9852016-08-26 05:41:23 -070075 RTC_DCHECK(factory_);
ossuf1b08da2016-09-23 02:19:43 -070076 decoder_ = factory_->MakeAudioDecoder(audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -070077 }
ossuf1b08da2016-09-23 02:19:43 -070078 RTC_DCHECK(decoder_) << "Failed to create: " << audio_format_;
kwiberg0fa0a972016-04-19 05:03:45 -070079 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000080}
81
ossuf1b08da2016-09-23 02:19:43 -070082bool DecoderDatabase::DecoderInfo::IsType(const char* name) const {
83 return STR_CASE_CMP(audio_format_.name.c_str(), name) == 0;
84}
85
86bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const {
87 return IsType(name.c_str());
ossu84bc9852016-08-26 05:41:23 -070088}
89
kwibergc0f2dcf2016-05-31 06:28:03 -070090rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>
ossuf1b08da2016-09-23 02:19:43 -070091DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
92 if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
kwiberg5adaf732016-10-04 09:33:27 -070093 // CN has a 1:1 RTP clock rate to sample rate ratio.
94 const int sample_rate_hz = format.clockrate_hz;
95 RTC_DCHECK(sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
96 sample_rate_hz == 32000 || sample_rate_hz == 48000);
97 return rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>(
98 {sample_rate_hz});
ossuf1b08da2016-09-23 02:19:43 -070099 } else {
100 return rtc::Optional<CngDecoder>();
kwibergc0f2dcf2016-05-31 06:28:03 -0700101 }
102}
103
ossu9f38c212016-10-04 05:23:32 -0700104DecoderDatabase::DecoderInfo::Subtype
105DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
106 if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
107 return Subtype::kComfortNoise;
108 } else if (STR_CASE_CMP(format.name.c_str(), "telephone-event") == 0) {
109 return Subtype::kDtmf;
110 } else if (STR_CASE_CMP(format.name.c_str(), "red") == 0) {
111 return Subtype::kRed;
112 }
113
114 return Subtype::kNormal;
115}
116
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000117bool DecoderDatabase::Empty() const { return decoders_.empty(); }
118
turaj@webrtc.org362a55e2013-09-20 16:25:28 +0000119int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000120
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000121void DecoderDatabase::Reset() {
122 decoders_.clear();
ossu97ba30e2016-04-25 07:55:58 -0700123 active_decoder_type_ = -1;
124 active_cng_decoder_type_ = -1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000125}
126
127int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800128 NetEqDecoder codec_type,
129 const std::string& name) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000130 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000131 return kInvalidRtpPayloadType;
132 }
ossuf1b08da2016-09-23 02:19:43 -0700133 // kCodecArbitrary is only supported through InsertExternal.
134 if (codec_type == NetEqDecoder::kDecoderArbitrary ||
135 !CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000136 return kCodecNotSupported;
137 }
ossuf1b08da2016-09-23 02:19:43 -0700138 const auto opt_format =
139 acm2::RentACodec::NetEqDecoderToSdpAudioFormat(codec_type);
140 if (!opt_format) {
141 return kCodecNotSupported;
142 }
kwiberge9413062016-11-03 05:29:05 -0700143 DecoderInfo info(*opt_format, decoder_factory_, name);
kwiberg0fa0a972016-04-19 05:03:45 -0700144 auto ret =
145 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000146 if (ret.second == false) {
147 // Database already contains a decoder with type |rtp_payload_type|.
148 return kDecoderExists;
149 }
150 return kOK;
151}
152
kwiberg5adaf732016-10-04 09:33:27 -0700153int DecoderDatabase::RegisterPayload(int rtp_payload_type,
154 const SdpAudioFormat& audio_format) {
155 if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) {
156 return kInvalidRtpPayloadType;
157 }
158 const auto ret = decoders_.insert(std::make_pair(
159 rtp_payload_type, DecoderInfo(audio_format, decoder_factory_.get())));
160 if (ret.second == false) {
161 // Database already contains a decoder with type |rtp_payload_type|.
162 return kDecoderExists;
163 }
164 return kOK;
165}
166
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000167int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
168 NetEqDecoder codec_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800169 const std::string& codec_name,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000170 AudioDecoder* decoder) {
171 if (rtp_payload_type > 0x7F) {
172 return kInvalidRtpPayloadType;
173 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000174 if (!decoder) {
175 return kInvalidPointer;
176 }
ossuf1b08da2016-09-23 02:19:43 -0700177
178 const auto opt_db_format =
179 acm2::RentACodec::NetEqDecoderToSdpAudioFormat(codec_type);
180 const SdpAudioFormat format = opt_db_format.value_or({"arbitrary", 0, 0});
181
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000182 std::pair<DecoderMap::iterator, bool> ret;
kwiberge9413062016-11-03 05:29:05 -0700183 DecoderInfo info(format, decoder, codec_name);
kwiberg0fa0a972016-04-19 05:03:45 -0700184 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000185 if (ret.second == false) {
186 // Database already contains a decoder with type |rtp_payload_type|.
187 return kDecoderExists;
188 }
189 return kOK;
190}
191
192int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
193 if (decoders_.erase(rtp_payload_type) == 0) {
194 // No decoder with that |rtp_payload_type|.
195 return kDecoderNotFound;
196 }
ossu97ba30e2016-04-25 07:55:58 -0700197 if (active_decoder_type_ == rtp_payload_type) {
198 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000199 }
ossu97ba30e2016-04-25 07:55:58 -0700200 if (active_cng_decoder_type_ == rtp_payload_type) {
201 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000202 }
203 return kOK;
204}
205
kwiberg6b19b562016-09-20 04:02:25 -0700206void DecoderDatabase::RemoveAll() {
207 decoders_.clear();
208 active_decoder_type_ = -1; // No active decoder.
209 active_cng_decoder_type_ = -1; // No active CNG decoder.
210}
211
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000212const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
213 uint8_t rtp_payload_type) const {
214 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
215 if (it == decoders_.end()) {
216 // Decoder not found.
217 return NULL;
218 }
ossuf1b08da2016-09-23 02:19:43 -0700219 return &it->second;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000220}
221
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000222int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
223 bool* new_decoder) {
224 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700225 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
226 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000227 // Decoder not found.
228 return kDecoderNotFound;
229 }
ossu84bc9852016-08-26 05:41:23 -0700230 RTC_CHECK(!info->IsComfortNoise());
231 RTC_DCHECK(new_decoder);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000232 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700233 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000234 // This is the first active decoder.
235 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700236 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000237 // Moving from one active decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700238 const DecoderInfo *old_info = GetDecoderInfo(active_decoder_type_);
239 RTC_DCHECK(old_info);
240 old_info->DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000241 *new_decoder = true;
242 }
ossu97ba30e2016-04-25 07:55:58 -0700243 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000244 return kOK;
245}
246
ossu84bc9852016-08-26 05:41:23 -0700247AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700248 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000249 // No active decoder.
250 return NULL;
251 }
ossu97ba30e2016-04-25 07:55:58 -0700252 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000253}
254
255int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
256 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700257 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
258 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000259 // Decoder not found.
260 return kDecoderNotFound;
261 }
ossu97ba30e2016-04-25 07:55:58 -0700262 if (active_cng_decoder_type_ >= 0 &&
263 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000264 // Moving from one active CNG decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700265 RTC_DCHECK(active_cng_decoder_);
ossu97ba30e2016-04-25 07:55:58 -0700266 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000267 }
ossu97ba30e2016-04-25 07:55:58 -0700268 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000269 return kOK;
270}
271
ossu84bc9852016-08-26 05:41:23 -0700272ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700273 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000274 // No active CNG decoder.
275 return NULL;
276 }
ossu97ba30e2016-04-25 07:55:58 -0700277 if (!active_cng_decoder_) {
278 active_cng_decoder_.reset(new ComfortNoiseDecoder);
279 }
280 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000281}
282
ossu84bc9852016-08-26 05:41:23 -0700283AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
284 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
285 return info ? info->GetDecoder() : nullptr;
286}
287
ossuf1b08da2016-09-23 02:19:43 -0700288bool DecoderDatabase::IsType(uint8_t rtp_payload_type, const char* name) const {
289 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
290 return info && info->IsType(name);
291}
292
ossu84bc9852016-08-26 05:41:23 -0700293bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
ossuf1b08da2016-09-23 02:19:43 -0700294 const std::string& name) const {
295 return IsType(rtp_payload_type, name.c_str());
ossu84bc9852016-08-26 05:41:23 -0700296}
297
298bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
299 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
300 return info && info->IsComfortNoise();
301}
302
303bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
304 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
305 return info && info->IsDtmf();
306}
307
308bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
309 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
310 return info && info->IsRed();
311}
312
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000313int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
314 PacketList::const_iterator it;
315 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
ossua73f6c92016-10-24 08:25:28 -0700316 if (!GetDecoderInfo(it->payload_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000317 // Payload type is not found.
Henrik Lundind67a2192015-08-03 12:54:37 +0200318 LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
ossua73f6c92016-10-24 08:25:28 -0700319 << static_cast<int>(it->payload_type);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000320 return kDecoderNotFound;
321 }
322 }
323 return kOK;
324}
325
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000326} // namespace webrtc