blob: ebea7e89a8dba495eb983c1f92cc0c153d07a724 [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,
30 AudioDecoderFactory* factory)
31 : audio_format_(audio_format),
ossu84bc9852016-08-26 05:41:23 -070032 factory_(factory),
kwiberg342f7402016-06-16 03:18:00 -070033 external_decoder_(nullptr),
ossu9f38c212016-10-04 05:23:32 -070034 cng_decoder_(CngDecoder::Create(audio_format)),
35 subtype_(SubtypeFromFormat(audio_format)) {}
kwibergc0f2dcf2016-05-31 06:28:03 -070036
37DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
ossuf1b08da2016-09-23 02:19:43 -070038 AudioDecoderFactory* factory)
39 : audio_format_(*acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)),
40 factory_(factory),
41 external_decoder_(nullptr),
ossu9f38c212016-10-04 05:23:32 -070042 cng_decoder_(CngDecoder::Create(audio_format_)),
43 subtype_(SubtypeFromFormat(audio_format_)) {}
ossuf1b08da2016-09-23 02:19:43 -070044
45DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
kwiberg0fa0a972016-04-19 05:03:45 -070046 AudioDecoder* ext_dec)
ossuf1b08da2016-09-23 02:19:43 -070047 : audio_format_(audio_format),
48 factory_(nullptr),
ossu9f38c212016-10-04 05:23:32 -070049 external_decoder_(ext_dec),
50 subtype_(Subtype::kNormal) {
kwibergc0f2dcf2016-05-31 06:28:03 -070051 RTC_CHECK(ext_dec);
52}
kwiberg0fa0a972016-04-19 05:03:45 -070053
54DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
55DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
56
ossu84bc9852016-08-26 05:41:23 -070057AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
ossu9f38c212016-10-04 05:23:32 -070058 if (subtype_ != Subtype::kNormal) {
ossuf1b08da2016-09-23 02:19:43 -070059 // These are handled internally, so they have no AudioDecoder objects.
60 return nullptr;
61 }
kwiberg342f7402016-06-16 03:18:00 -070062 if (external_decoder_) {
kwiberg0fa0a972016-04-19 05:03:45 -070063 RTC_DCHECK(!decoder_);
kwiberg342f7402016-06-16 03:18:00 -070064 RTC_DCHECK(!cng_decoder_);
65 return external_decoder_;
kwiberg0fa0a972016-04-19 05:03:45 -070066 }
67 if (!decoder_) {
ossuf1b08da2016-09-23 02:19:43 -070068 // TODO(ossu): Keep a check here for now, since a number of tests create
69 // DecoderInfos without factories.
ossu84bc9852016-08-26 05:41:23 -070070 RTC_DCHECK(factory_);
ossuf1b08da2016-09-23 02:19:43 -070071 decoder_ = factory_->MakeAudioDecoder(audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -070072 }
ossuf1b08da2016-09-23 02:19:43 -070073 RTC_DCHECK(decoder_) << "Failed to create: " << audio_format_;
kwiberg0fa0a972016-04-19 05:03:45 -070074 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000075}
76
ossuf1b08da2016-09-23 02:19:43 -070077bool DecoderDatabase::DecoderInfo::IsType(const char* name) const {
78 return STR_CASE_CMP(audio_format_.name.c_str(), name) == 0;
79}
80
81bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const {
82 return IsType(name.c_str());
ossu84bc9852016-08-26 05:41:23 -070083}
84
kwibergc0f2dcf2016-05-31 06:28:03 -070085rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>
ossuf1b08da2016-09-23 02:19:43 -070086DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
87 if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
88 return rtc::Optional<CngDecoder>({format.clockrate_hz});
89 } else {
90 return rtc::Optional<CngDecoder>();
kwibergc0f2dcf2016-05-31 06:28:03 -070091 }
92}
93
ossu9f38c212016-10-04 05:23:32 -070094DecoderDatabase::DecoderInfo::Subtype
95DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
96 if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
97 return Subtype::kComfortNoise;
98 } else if (STR_CASE_CMP(format.name.c_str(), "telephone-event") == 0) {
99 return Subtype::kDtmf;
100 } else if (STR_CASE_CMP(format.name.c_str(), "red") == 0) {
101 return Subtype::kRed;
102 }
103
104 return Subtype::kNormal;
105}
106
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000107bool DecoderDatabase::Empty() const { return decoders_.empty(); }
108
turaj@webrtc.org362a55e2013-09-20 16:25:28 +0000109int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000110
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000111void DecoderDatabase::Reset() {
112 decoders_.clear();
ossu97ba30e2016-04-25 07:55:58 -0700113 active_decoder_type_ = -1;
114 active_cng_decoder_type_ = -1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000115}
116
117int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800118 NetEqDecoder codec_type,
119 const std::string& name) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000120 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000121 return kInvalidRtpPayloadType;
122 }
ossuf1b08da2016-09-23 02:19:43 -0700123 // kCodecArbitrary is only supported through InsertExternal.
124 if (codec_type == NetEqDecoder::kDecoderArbitrary ||
125 !CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000126 return kCodecNotSupported;
127 }
ossuf1b08da2016-09-23 02:19:43 -0700128 const auto opt_format =
129 acm2::RentACodec::NetEqDecoderToSdpAudioFormat(codec_type);
130 if (!opt_format) {
131 return kCodecNotSupported;
132 }
133 DecoderInfo info(*opt_format, decoder_factory_);
134 info.name = name;
kwiberg0fa0a972016-04-19 05:03:45 -0700135 auto ret =
136 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000137 if (ret.second == false) {
138 // Database already contains a decoder with type |rtp_payload_type|.
139 return kDecoderExists;
140 }
141 return kOK;
142}
143
144int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
145 NetEqDecoder codec_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800146 const std::string& codec_name,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000147 AudioDecoder* decoder) {
148 if (rtp_payload_type > 0x7F) {
149 return kInvalidRtpPayloadType;
150 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000151 if (!decoder) {
152 return kInvalidPointer;
153 }
ossuf1b08da2016-09-23 02:19:43 -0700154
155 const auto opt_db_format =
156 acm2::RentACodec::NetEqDecoderToSdpAudioFormat(codec_type);
157 const SdpAudioFormat format = opt_db_format.value_or({"arbitrary", 0, 0});
158
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000159 std::pair<DecoderMap::iterator, bool> ret;
ossuf1b08da2016-09-23 02:19:43 -0700160 DecoderInfo info(format, decoder);
161 info.name = codec_name;
kwiberg0fa0a972016-04-19 05:03:45 -0700162 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000163 if (ret.second == false) {
164 // Database already contains a decoder with type |rtp_payload_type|.
165 return kDecoderExists;
166 }
167 return kOK;
168}
169
170int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
171 if (decoders_.erase(rtp_payload_type) == 0) {
172 // No decoder with that |rtp_payload_type|.
173 return kDecoderNotFound;
174 }
ossu97ba30e2016-04-25 07:55:58 -0700175 if (active_decoder_type_ == rtp_payload_type) {
176 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000177 }
ossu97ba30e2016-04-25 07:55:58 -0700178 if (active_cng_decoder_type_ == rtp_payload_type) {
179 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000180 }
181 return kOK;
182}
183
kwiberg6b19b562016-09-20 04:02:25 -0700184void DecoderDatabase::RemoveAll() {
185 decoders_.clear();
186 active_decoder_type_ = -1; // No active decoder.
187 active_cng_decoder_type_ = -1; // No active CNG decoder.
188}
189
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000190const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
191 uint8_t rtp_payload_type) const {
192 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
193 if (it == decoders_.end()) {
194 // Decoder not found.
195 return NULL;
196 }
ossuf1b08da2016-09-23 02:19:43 -0700197 return &it->second;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000198}
199
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000200int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
201 bool* new_decoder) {
202 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700203 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
204 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000205 // Decoder not found.
206 return kDecoderNotFound;
207 }
ossu84bc9852016-08-26 05:41:23 -0700208 RTC_CHECK(!info->IsComfortNoise());
209 RTC_DCHECK(new_decoder);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000210 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700211 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000212 // This is the first active decoder.
213 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700214 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000215 // Moving from one active decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700216 const DecoderInfo *old_info = GetDecoderInfo(active_decoder_type_);
217 RTC_DCHECK(old_info);
218 old_info->DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000219 *new_decoder = true;
220 }
ossu97ba30e2016-04-25 07:55:58 -0700221 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000222 return kOK;
223}
224
ossu84bc9852016-08-26 05:41:23 -0700225AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700226 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000227 // No active decoder.
228 return NULL;
229 }
ossu97ba30e2016-04-25 07:55:58 -0700230 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000231}
232
233int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
234 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700235 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
236 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000237 // Decoder not found.
238 return kDecoderNotFound;
239 }
ossu97ba30e2016-04-25 07:55:58 -0700240 if (active_cng_decoder_type_ >= 0 &&
241 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000242 // Moving from one active CNG decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700243 RTC_DCHECK(active_cng_decoder_);
ossu97ba30e2016-04-25 07:55:58 -0700244 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000245 }
ossu97ba30e2016-04-25 07:55:58 -0700246 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000247 return kOK;
248}
249
ossu84bc9852016-08-26 05:41:23 -0700250ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700251 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000252 // No active CNG decoder.
253 return NULL;
254 }
ossu97ba30e2016-04-25 07:55:58 -0700255 if (!active_cng_decoder_) {
256 active_cng_decoder_.reset(new ComfortNoiseDecoder);
257 }
258 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000259}
260
ossu84bc9852016-08-26 05:41:23 -0700261AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
262 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
263 return info ? info->GetDecoder() : nullptr;
264}
265
ossuf1b08da2016-09-23 02:19:43 -0700266bool DecoderDatabase::IsType(uint8_t rtp_payload_type, const char* name) const {
267 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
268 return info && info->IsType(name);
269}
270
ossu84bc9852016-08-26 05:41:23 -0700271bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
ossuf1b08da2016-09-23 02:19:43 -0700272 const std::string& name) const {
273 return IsType(rtp_payload_type, name.c_str());
ossu84bc9852016-08-26 05:41:23 -0700274}
275
276bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
277 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
278 return info && info->IsComfortNoise();
279}
280
281bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
282 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
283 return info && info->IsDtmf();
284}
285
286bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
287 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
288 return info && info->IsRed();
289}
290
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000291int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
292 PacketList::const_iterator it;
293 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
ossu84bc9852016-08-26 05:41:23 -0700294 if (!GetDecoderInfo((*it)->header.payloadType)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000295 // Payload type is not found.
Henrik Lundind67a2192015-08-03 12:54:37 +0200296 LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
297 << static_cast<int>((*it)->header.payloadType);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000298 return kDecoderNotFound;
299 }
300 }
301 return kOK;
302}
303
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000304} // namespace webrtc