blob: f5fbad34460d7dcaf48c69897659af05791884cc [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
ossu84bc9852016-08-26 05:41:23 -070029DecoderDatabase::DecoderInfo::DecoderInfo(
30 NetEqDecoder ct,
31 const std::string& nm,
32 AudioDecoderFactory* factory)
kwibergc0f2dcf2016-05-31 06:28:03 -070033 : codec_type(ct),
34 name(nm),
35 audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)),
ossu84bc9852016-08-26 05:41:23 -070036 factory_(factory),
kwiberg342f7402016-06-16 03:18:00 -070037 external_decoder_(nullptr),
kwibergc0f2dcf2016-05-31 06:28:03 -070038 cng_decoder_(CngDecoder::Create(ct)) {}
39
40DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
kwiberg0fa0a972016-04-19 05:03:45 -070041 const std::string& nm,
kwiberg0fa0a972016-04-19 05:03:45 -070042 AudioDecoder* ext_dec)
43 : codec_type(ct),
44 name(nm),
kwibergc0f2dcf2016-05-31 06:28:03 -070045 audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)),
kwiberg342f7402016-06-16 03:18:00 -070046 external_decoder_(ext_dec) {
kwibergc0f2dcf2016-05-31 06:28:03 -070047 RTC_CHECK(ext_dec);
48}
kwiberg0fa0a972016-04-19 05:03:45 -070049
50DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
51DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
52
ossu84bc9852016-08-26 05:41:23 -070053AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
kwiberg342f7402016-06-16 03:18:00 -070054 if (external_decoder_) {
kwiberg0fa0a972016-04-19 05:03:45 -070055 RTC_DCHECK(!decoder_);
kwiberg342f7402016-06-16 03:18:00 -070056 RTC_DCHECK(!cng_decoder_);
57 return external_decoder_;
kwiberg0fa0a972016-04-19 05:03:45 -070058 }
ossu84bc9852016-08-26 05:41:23 -070059 if (IsRed() || IsComfortNoise() || IsDtmf())
60 return nullptr;
kwiberg5178ee82016-05-03 01:39:01 -070061 RTC_DCHECK(audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -070062 if (!decoder_) {
ossu84bc9852016-08-26 05:41:23 -070063 RTC_DCHECK(factory_);
64 decoder_ = factory_->MakeAudioDecoder(*audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -070065 }
kwiberg5178ee82016-05-03 01:39:01 -070066 RTC_DCHECK(decoder_) << "Failed to create: " << *audio_format_;
kwiberg0fa0a972016-04-19 05:03:45 -070067 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000068}
69
ossu84bc9852016-08-26 05:41:23 -070070
71bool DecoderDatabase::DecoderInfo::IsComfortNoise() const {
72 return codec_type == NetEqDecoder::kDecoderCNGnb
73 || codec_type == NetEqDecoder::kDecoderCNGwb
74 || codec_type == NetEqDecoder::kDecoderCNGswb32kHz
75 || codec_type == NetEqDecoder::kDecoderCNGswb48kHz;
76}
77
78bool DecoderDatabase::DecoderInfo::IsDtmf() const {
79 return codec_type == NetEqDecoder::kDecoderAVT;
80}
81
82bool DecoderDatabase::DecoderInfo::IsRed() const {
83 return codec_type == NetEqDecoder::kDecoderRED;
84}
85
kwibergc0f2dcf2016-05-31 06:28:03 -070086rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>
87DecoderDatabase::DecoderInfo::CngDecoder::Create(NetEqDecoder ct) {
88 const auto cng = [](int sample_rate_hz) {
89 return rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>(
90 {sample_rate_hz});
91 };
92 switch (ct) {
93 case NetEqDecoder::kDecoderCNGnb:
94 return cng(8000);
95 case NetEqDecoder::kDecoderCNGwb:
96 return cng(16000);
97 case NetEqDecoder::kDecoderCNGswb32kHz:
98 return cng(32000);
99 case NetEqDecoder::kDecoderCNGswb48kHz:
100 return cng(48000);
101 default:
102 return rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>();
103 }
104}
105
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000106bool DecoderDatabase::Empty() const { return decoders_.empty(); }
107
turaj@webrtc.org362a55e2013-09-20 16:25:28 +0000108int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000109
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000110void DecoderDatabase::Reset() {
111 decoders_.clear();
ossu97ba30e2016-04-25 07:55:58 -0700112 active_decoder_type_ = -1;
113 active_cng_decoder_type_ = -1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000114}
115
116int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800117 NetEqDecoder codec_type,
118 const std::string& name) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000119 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000120 return kInvalidRtpPayloadType;
121 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +0000122 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000123 return kCodecNotSupported;
124 }
ossu84bc9852016-08-26 05:41:23 -0700125 DecoderInfo info(codec_type, name, decoder_factory_.get());
kwiberg0fa0a972016-04-19 05:03:45 -0700126 auto ret =
127 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000128 if (ret.second == false) {
129 // Database already contains a decoder with type |rtp_payload_type|.
130 return kDecoderExists;
131 }
132 return kOK;
133}
134
135int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
136 NetEqDecoder codec_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800137 const std::string& codec_name,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000138 AudioDecoder* decoder) {
139 if (rtp_payload_type > 0x7F) {
140 return kInvalidRtpPayloadType;
141 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +0000142 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000143 return kCodecNotSupported;
144 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000145 if (!decoder) {
146 return kInvalidPointer;
147 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000148 std::pair<DecoderMap::iterator, bool> ret;
kwiberg342f7402016-06-16 03:18:00 -0700149 DecoderInfo info(codec_type, codec_name, decoder);
kwiberg0fa0a972016-04-19 05:03:45 -0700150 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000151 if (ret.second == false) {
152 // Database already contains a decoder with type |rtp_payload_type|.
153 return kDecoderExists;
154 }
155 return kOK;
156}
157
158int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
159 if (decoders_.erase(rtp_payload_type) == 0) {
160 // No decoder with that |rtp_payload_type|.
161 return kDecoderNotFound;
162 }
ossu97ba30e2016-04-25 07:55:58 -0700163 if (active_decoder_type_ == rtp_payload_type) {
164 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000165 }
ossu97ba30e2016-04-25 07:55:58 -0700166 if (active_cng_decoder_type_ == rtp_payload_type) {
167 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000168 }
169 return kOK;
170}
171
kwiberg6b19b562016-09-20 04:02:25 -0700172void DecoderDatabase::RemoveAll() {
173 decoders_.clear();
174 active_decoder_type_ = -1; // No active decoder.
175 active_cng_decoder_type_ = -1; // No active CNG decoder.
176}
177
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000178const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
179 uint8_t rtp_payload_type) const {
180 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
181 if (it == decoders_.end()) {
182 // Decoder not found.
183 return NULL;
184 }
185 return &(*it).second;
186}
187
188uint8_t DecoderDatabase::GetRtpPayloadType(
189 NetEqDecoder codec_type) const {
190 DecoderMap::const_iterator it;
191 for (it = decoders_.begin(); it != decoders_.end(); ++it) {
192 if ((*it).second.codec_type == codec_type) {
193 // Match found.
194 return (*it).first;
195 }
196 }
197 // No match.
198 return kRtpPayloadTypeError;
199}
200
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000201int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
202 bool* new_decoder) {
203 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700204 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
205 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000206 // Decoder not found.
207 return kDecoderNotFound;
208 }
ossu84bc9852016-08-26 05:41:23 -0700209 RTC_CHECK(!info->IsComfortNoise());
210 RTC_DCHECK(new_decoder);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000211 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700212 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000213 // This is the first active decoder.
214 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700215 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000216 // Moving from one active decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700217 const DecoderInfo *old_info = GetDecoderInfo(active_decoder_type_);
218 RTC_DCHECK(old_info);
219 old_info->DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000220 *new_decoder = true;
221 }
ossu97ba30e2016-04-25 07:55:58 -0700222 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000223 return kOK;
224}
225
ossu84bc9852016-08-26 05:41:23 -0700226AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700227 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000228 // No active decoder.
229 return NULL;
230 }
ossu97ba30e2016-04-25 07:55:58 -0700231 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000232}
233
234int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
235 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700236 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
237 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000238 // Decoder not found.
239 return kDecoderNotFound;
240 }
ossu97ba30e2016-04-25 07:55:58 -0700241 if (active_cng_decoder_type_ >= 0 &&
242 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000243 // Moving from one active CNG decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700244 RTC_DCHECK(active_cng_decoder_);
ossu97ba30e2016-04-25 07:55:58 -0700245 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000246 }
ossu97ba30e2016-04-25 07:55:58 -0700247 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000248 return kOK;
249}
250
ossu84bc9852016-08-26 05:41:23 -0700251ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700252 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000253 // No active CNG decoder.
254 return NULL;
255 }
ossu97ba30e2016-04-25 07:55:58 -0700256 if (!active_cng_decoder_) {
257 active_cng_decoder_.reset(new ComfortNoiseDecoder);
258 }
259 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000260}
261
ossu84bc9852016-08-26 05:41:23 -0700262AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
263 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
264 return info ? info->GetDecoder() : nullptr;
265}
266
267bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
268 NetEqDecoder codec_type) const {
269 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
270 return info && info->codec_type == codec_type;
271}
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
301
302} // namespace webrtc