blob: 27bc6d56970c9835300fc1cb398c387a6f03b220 [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),
ossuf1b08da2016-09-23 02:19:43 -070034 cng_decoder_(CngDecoder::Create(audio_format)) {}
kwibergc0f2dcf2016-05-31 06:28:03 -070035
36DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
ossuf1b08da2016-09-23 02:19:43 -070037 AudioDecoderFactory* factory)
38 : audio_format_(*acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)),
39 factory_(factory),
40 external_decoder_(nullptr),
41 cng_decoder_(CngDecoder::Create(audio_format_)) {}
42
43DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
kwiberg0fa0a972016-04-19 05:03:45 -070044 AudioDecoder* ext_dec)
ossuf1b08da2016-09-23 02:19:43 -070045 : audio_format_(audio_format),
46 factory_(nullptr),
kwiberg342f7402016-06-16 03:18:00 -070047 external_decoder_(ext_dec) {
kwibergc0f2dcf2016-05-31 06:28:03 -070048 RTC_CHECK(ext_dec);
49}
kwiberg0fa0a972016-04-19 05:03:45 -070050
51DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
52DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
53
ossu84bc9852016-08-26 05:41:23 -070054AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
ossuf1b08da2016-09-23 02:19:43 -070055 if (IsDtmf() || IsRed() || IsComfortNoise()) {
56 // These are handled internally, so they have no AudioDecoder objects.
57 return nullptr;
58 }
kwiberg342f7402016-06-16 03:18:00 -070059 if (external_decoder_) {
kwiberg0fa0a972016-04-19 05:03:45 -070060 RTC_DCHECK(!decoder_);
kwiberg342f7402016-06-16 03:18:00 -070061 RTC_DCHECK(!cng_decoder_);
62 return external_decoder_;
kwiberg0fa0a972016-04-19 05:03:45 -070063 }
64 if (!decoder_) {
ossuf1b08da2016-09-23 02:19:43 -070065 // TODO(ossu): Keep a check here for now, since a number of tests create
66 // DecoderInfos without factories.
ossu84bc9852016-08-26 05:41:23 -070067 RTC_DCHECK(factory_);
ossuf1b08da2016-09-23 02:19:43 -070068 decoder_ = factory_->MakeAudioDecoder(audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -070069 }
ossuf1b08da2016-09-23 02:19:43 -070070 RTC_DCHECK(decoder_) << "Failed to create: " << audio_format_;
kwiberg0fa0a972016-04-19 05:03:45 -070071 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000072}
73
ossu84bc9852016-08-26 05:41:23 -070074bool DecoderDatabase::DecoderInfo::IsComfortNoise() const {
ossuf1b08da2016-09-23 02:19:43 -070075 RTC_DCHECK_EQ(!!cng_decoder_, IsType("CN"));
76 return !!cng_decoder_;
ossu84bc9852016-08-26 05:41:23 -070077}
78
79bool DecoderDatabase::DecoderInfo::IsDtmf() const {
ossuf1b08da2016-09-23 02:19:43 -070080 return IsType("telephone-event");
ossu84bc9852016-08-26 05:41:23 -070081}
82
83bool DecoderDatabase::DecoderInfo::IsRed() const {
ossuf1b08da2016-09-23 02:19:43 -070084 return IsType("red");
85}
86
87bool DecoderDatabase::DecoderInfo::IsType(const char* name) const {
88 return STR_CASE_CMP(audio_format_.name.c_str(), name) == 0;
89}
90
91bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const {
92 return IsType(name.c_str());
ossu84bc9852016-08-26 05:41:23 -070093}
94
kwibergc0f2dcf2016-05-31 06:28:03 -070095rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>
ossuf1b08da2016-09-23 02:19:43 -070096DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
97 if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
98 return rtc::Optional<CngDecoder>({format.clockrate_hz});
99 } else {
100 return rtc::Optional<CngDecoder>();
kwibergc0f2dcf2016-05-31 06:28:03 -0700101 }
102}
103
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000104bool DecoderDatabase::Empty() const { return decoders_.empty(); }
105
turaj@webrtc.org362a55e2013-09-20 16:25:28 +0000106int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000107
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000108void DecoderDatabase::Reset() {
109 decoders_.clear();
ossu97ba30e2016-04-25 07:55:58 -0700110 active_decoder_type_ = -1;
111 active_cng_decoder_type_ = -1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000112}
113
114int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800115 NetEqDecoder codec_type,
116 const std::string& name) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000117 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000118 return kInvalidRtpPayloadType;
119 }
ossuf1b08da2016-09-23 02:19:43 -0700120 // kCodecArbitrary is only supported through InsertExternal.
121 if (codec_type == NetEqDecoder::kDecoderArbitrary ||
122 !CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000123 return kCodecNotSupported;
124 }
ossuf1b08da2016-09-23 02:19:43 -0700125 const auto opt_format =
126 acm2::RentACodec::NetEqDecoderToSdpAudioFormat(codec_type);
127 if (!opt_format) {
128 return kCodecNotSupported;
129 }
130 DecoderInfo info(*opt_format, decoder_factory_);
131 info.name = name;
kwiberg0fa0a972016-04-19 05:03:45 -0700132 auto ret =
133 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000134 if (ret.second == false) {
135 // Database already contains a decoder with type |rtp_payload_type|.
136 return kDecoderExists;
137 }
138 return kOK;
139}
140
141int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
142 NetEqDecoder codec_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800143 const std::string& codec_name,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000144 AudioDecoder* decoder) {
145 if (rtp_payload_type > 0x7F) {
146 return kInvalidRtpPayloadType;
147 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000148 if (!decoder) {
149 return kInvalidPointer;
150 }
ossuf1b08da2016-09-23 02:19:43 -0700151
152 const auto opt_db_format =
153 acm2::RentACodec::NetEqDecoderToSdpAudioFormat(codec_type);
154 const SdpAudioFormat format = opt_db_format.value_or({"arbitrary", 0, 0});
155
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000156 std::pair<DecoderMap::iterator, bool> ret;
ossuf1b08da2016-09-23 02:19:43 -0700157 DecoderInfo info(format, decoder);
158 info.name = codec_name;
kwiberg0fa0a972016-04-19 05:03:45 -0700159 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000160 if (ret.second == false) {
161 // Database already contains a decoder with type |rtp_payload_type|.
162 return kDecoderExists;
163 }
164 return kOK;
165}
166
167int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
168 if (decoders_.erase(rtp_payload_type) == 0) {
169 // No decoder with that |rtp_payload_type|.
170 return kDecoderNotFound;
171 }
ossu97ba30e2016-04-25 07:55:58 -0700172 if (active_decoder_type_ == rtp_payload_type) {
173 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000174 }
ossu97ba30e2016-04-25 07:55:58 -0700175 if (active_cng_decoder_type_ == rtp_payload_type) {
176 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000177 }
178 return kOK;
179}
180
kwiberg6b19b562016-09-20 04:02:25 -0700181void DecoderDatabase::RemoveAll() {
182 decoders_.clear();
183 active_decoder_type_ = -1; // No active decoder.
184 active_cng_decoder_type_ = -1; // No active CNG decoder.
185}
186
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000187const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
188 uint8_t rtp_payload_type) const {
189 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
190 if (it == decoders_.end()) {
191 // Decoder not found.
192 return NULL;
193 }
ossuf1b08da2016-09-23 02:19:43 -0700194 return &it->second;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000195}
196
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000197int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
198 bool* new_decoder) {
199 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700200 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
201 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000202 // Decoder not found.
203 return kDecoderNotFound;
204 }
ossu84bc9852016-08-26 05:41:23 -0700205 RTC_CHECK(!info->IsComfortNoise());
206 RTC_DCHECK(new_decoder);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000207 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700208 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000209 // This is the first active decoder.
210 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700211 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000212 // Moving from one active decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700213 const DecoderInfo *old_info = GetDecoderInfo(active_decoder_type_);
214 RTC_DCHECK(old_info);
215 old_info->DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000216 *new_decoder = true;
217 }
ossu97ba30e2016-04-25 07:55:58 -0700218 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000219 return kOK;
220}
221
ossu84bc9852016-08-26 05:41:23 -0700222AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700223 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000224 // No active decoder.
225 return NULL;
226 }
ossu97ba30e2016-04-25 07:55:58 -0700227 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000228}
229
230int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
231 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700232 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
233 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000234 // Decoder not found.
235 return kDecoderNotFound;
236 }
ossu97ba30e2016-04-25 07:55:58 -0700237 if (active_cng_decoder_type_ >= 0 &&
238 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000239 // Moving from one active CNG decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700240 RTC_DCHECK(active_cng_decoder_);
ossu97ba30e2016-04-25 07:55:58 -0700241 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000242 }
ossu97ba30e2016-04-25 07:55:58 -0700243 active_cng_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 -0700247ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700248 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000249 // No active CNG decoder.
250 return NULL;
251 }
ossu97ba30e2016-04-25 07:55:58 -0700252 if (!active_cng_decoder_) {
253 active_cng_decoder_.reset(new ComfortNoiseDecoder);
254 }
255 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000256}
257
ossu84bc9852016-08-26 05:41:23 -0700258AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
259 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
260 return info ? info->GetDecoder() : nullptr;
261}
262
ossuf1b08da2016-09-23 02:19:43 -0700263bool DecoderDatabase::IsType(uint8_t rtp_payload_type, const char* name) const {
264 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
265 return info && info->IsType(name);
266}
267
ossu84bc9852016-08-26 05:41:23 -0700268bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
ossuf1b08da2016-09-23 02:19:43 -0700269 const std::string& name) const {
270 return IsType(rtp_payload_type, name.c_str());
ossu84bc9852016-08-26 05:41:23 -0700271}
272
273bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
274 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
275 return info && info->IsComfortNoise();
276}
277
278bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
279 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
280 return info && info->IsDtmf();
281}
282
283bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
284 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
285 return info && info->IsRed();
286}
287
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000288int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
289 PacketList::const_iterator it;
290 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
ossu84bc9852016-08-26 05:41:23 -0700291 if (!GetDecoderInfo((*it)->header.payloadType)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000292 // Payload type is not found.
Henrik Lundind67a2192015-08-03 12:54:37 +0200293 LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
294 << static_cast<int>((*it)->header.payloadType);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000295 return kDecoderNotFound;
296 }
297 }
298 return kOK;
299}
300
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000301} // namespace webrtc