blob: b189e4bb562ae77872ce3380dfbb977d3bd4756a [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
172const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
173 uint8_t rtp_payload_type) const {
174 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
175 if (it == decoders_.end()) {
176 // Decoder not found.
177 return NULL;
178 }
179 return &(*it).second;
180}
181
182uint8_t DecoderDatabase::GetRtpPayloadType(
183 NetEqDecoder codec_type) const {
184 DecoderMap::const_iterator it;
185 for (it = decoders_.begin(); it != decoders_.end(); ++it) {
186 if ((*it).second.codec_type == codec_type) {
187 // Match found.
188 return (*it).first;
189 }
190 }
191 // No match.
192 return kRtpPayloadTypeError;
193}
194
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000195int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
196 bool* new_decoder) {
197 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700198 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
199 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000200 // Decoder not found.
201 return kDecoderNotFound;
202 }
ossu84bc9852016-08-26 05:41:23 -0700203 RTC_CHECK(!info->IsComfortNoise());
204 RTC_DCHECK(new_decoder);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000205 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700206 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000207 // This is the first active decoder.
208 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700209 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000210 // Moving from one active decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700211 const DecoderInfo *old_info = GetDecoderInfo(active_decoder_type_);
212 RTC_DCHECK(old_info);
213 old_info->DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000214 *new_decoder = true;
215 }
ossu97ba30e2016-04-25 07:55:58 -0700216 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000217 return kOK;
218}
219
ossu84bc9852016-08-26 05:41:23 -0700220AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700221 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000222 // No active decoder.
223 return NULL;
224 }
ossu97ba30e2016-04-25 07:55:58 -0700225 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000226}
227
228int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
229 // Check that |rtp_payload_type| exists in the database.
ossu84bc9852016-08-26 05:41:23 -0700230 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
231 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000232 // Decoder not found.
233 return kDecoderNotFound;
234 }
ossu97ba30e2016-04-25 07:55:58 -0700235 if (active_cng_decoder_type_ >= 0 &&
236 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000237 // Moving from one active CNG decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700238 RTC_DCHECK(active_cng_decoder_);
ossu97ba30e2016-04-25 07:55:58 -0700239 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000240 }
ossu97ba30e2016-04-25 07:55:58 -0700241 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000242 return kOK;
243}
244
ossu84bc9852016-08-26 05:41:23 -0700245ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700246 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000247 // No active CNG decoder.
248 return NULL;
249 }
ossu97ba30e2016-04-25 07:55:58 -0700250 if (!active_cng_decoder_) {
251 active_cng_decoder_.reset(new ComfortNoiseDecoder);
252 }
253 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000254}
255
ossu84bc9852016-08-26 05:41:23 -0700256AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
257 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
258 return info ? info->GetDecoder() : nullptr;
259}
260
261bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
262 NetEqDecoder codec_type) const {
263 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
264 return info && info->codec_type == codec_type;
265}
266
267bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
268 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
269 return info && info->IsComfortNoise();
270}
271
272bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
273 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
274 return info && info->IsDtmf();
275}
276
277bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
278 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
279 return info && info->IsRed();
280}
281
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000282int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
283 PacketList::const_iterator it;
284 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
ossu84bc9852016-08-26 05:41:23 -0700285 if (!GetDecoderInfo((*it)->header.payloadType)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000286 // Payload type is not found.
Henrik Lundind67a2192015-08-03 12:54:37 +0200287 LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
288 << static_cast<int>((*it)->header.payloadType);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000289 return kDecoderNotFound;
290 }
291 }
292 return kOK;
293}
294
295
296} // namespace webrtc