blob: 165522f0dffb0851ad117e62654e2b60d5185f66 [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
13#include <assert.h>
14#include <utility> // pair
15
henrik.lundin4cf61dd2015-12-09 06:20:58 -080016#include "webrtc/base/checks.h"
Henrik Lundind67a2192015-08-03 12:54:37 +020017#include "webrtc/base/logging.h"
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000018#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000019
20namespace webrtc {
21
kwiberg5178ee82016-05-03 01:39:01 -070022DecoderDatabase::DecoderDatabase(
ossue725f7c2016-05-19 10:48:04 -070023 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory)
kwiberg5178ee82016-05-03 01:39:01 -070024 : active_decoder_type_(-1),
25 active_cng_decoder_type_(-1),
ossue725f7c2016-05-19 10:48:04 -070026 decoder_factory_(decoder_factory) {}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000027
ossu97ba30e2016-04-25 07:55:58 -070028DecoderDatabase::~DecoderDatabase() = default;
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000029
kwiberg0fa0a972016-04-19 05:03:45 -070030DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
kwibergc0f2dcf2016-05-31 06:28:03 -070031 const std::string& nm)
32 : codec_type(ct),
33 name(nm),
34 audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)),
kwiberg342f7402016-06-16 03:18:00 -070035 external_decoder_(nullptr),
kwibergc0f2dcf2016-05-31 06:28:03 -070036 cng_decoder_(CngDecoder::Create(ct)) {}
37
38DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
kwiberg0fa0a972016-04-19 05:03:45 -070039 const std::string& nm,
kwiberg0fa0a972016-04-19 05:03:45 -070040 AudioDecoder* ext_dec)
41 : codec_type(ct),
42 name(nm),
kwibergc0f2dcf2016-05-31 06:28:03 -070043 audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)),
kwiberg342f7402016-06-16 03:18:00 -070044 external_decoder_(ext_dec) {
kwibergc0f2dcf2016-05-31 06:28:03 -070045 RTC_CHECK(ext_dec);
46}
kwiberg0fa0a972016-04-19 05:03:45 -070047
48DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
49DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
50
kwiberg5178ee82016-05-03 01:39:01 -070051AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder(
52 AudioDecoderFactory* factory) {
kwiberg342f7402016-06-16 03:18:00 -070053 if (external_decoder_) {
kwiberg0fa0a972016-04-19 05:03:45 -070054 RTC_DCHECK(!decoder_);
kwiberg342f7402016-06-16 03:18:00 -070055 RTC_DCHECK(!cng_decoder_);
56 return external_decoder_;
kwiberg0fa0a972016-04-19 05:03:45 -070057 }
kwiberg5178ee82016-05-03 01:39:01 -070058 RTC_DCHECK(audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -070059 if (!decoder_) {
kwiberg5178ee82016-05-03 01:39:01 -070060 decoder_ = factory->MakeAudioDecoder(*audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -070061 }
kwiberg5178ee82016-05-03 01:39:01 -070062 RTC_DCHECK(decoder_) << "Failed to create: " << *audio_format_;
kwiberg0fa0a972016-04-19 05:03:45 -070063 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000064}
65
kwibergc0f2dcf2016-05-31 06:28:03 -070066rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>
67DecoderDatabase::DecoderInfo::CngDecoder::Create(NetEqDecoder ct) {
68 const auto cng = [](int sample_rate_hz) {
69 return rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>(
70 {sample_rate_hz});
71 };
72 switch (ct) {
73 case NetEqDecoder::kDecoderCNGnb:
74 return cng(8000);
75 case NetEqDecoder::kDecoderCNGwb:
76 return cng(16000);
77 case NetEqDecoder::kDecoderCNGswb32kHz:
78 return cng(32000);
79 case NetEqDecoder::kDecoderCNGswb48kHz:
80 return cng(48000);
81 default:
82 return rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>();
83 }
84}
85
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000086bool DecoderDatabase::Empty() const { return decoders_.empty(); }
87
turaj@webrtc.org362a55e2013-09-20 16:25:28 +000088int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000089
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000090void DecoderDatabase::Reset() {
91 decoders_.clear();
ossu97ba30e2016-04-25 07:55:58 -070092 active_decoder_type_ = -1;
93 active_cng_decoder_type_ = -1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000094}
95
96int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -080097 NetEqDecoder codec_type,
98 const std::string& name) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +000099 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000100 return kInvalidRtpPayloadType;
101 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +0000102 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000103 return kCodecNotSupported;
104 }
kwibergc0f2dcf2016-05-31 06:28:03 -0700105 DecoderInfo info(codec_type, name);
kwiberg0fa0a972016-04-19 05:03:45 -0700106 auto ret =
107 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000108 if (ret.second == false) {
109 // Database already contains a decoder with type |rtp_payload_type|.
110 return kDecoderExists;
111 }
112 return kOK;
113}
114
115int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
116 NetEqDecoder codec_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800117 const std::string& codec_name,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000118 AudioDecoder* decoder) {
119 if (rtp_payload_type > 0x7F) {
120 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 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000125 if (!decoder) {
126 return kInvalidPointer;
127 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000128 std::pair<DecoderMap::iterator, bool> ret;
kwiberg342f7402016-06-16 03:18:00 -0700129 DecoderInfo info(codec_type, codec_name, decoder);
kwiberg0fa0a972016-04-19 05:03:45 -0700130 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000131 if (ret.second == false) {
132 // Database already contains a decoder with type |rtp_payload_type|.
133 return kDecoderExists;
134 }
135 return kOK;
136}
137
138int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
139 if (decoders_.erase(rtp_payload_type) == 0) {
140 // No decoder with that |rtp_payload_type|.
141 return kDecoderNotFound;
142 }
ossu97ba30e2016-04-25 07:55:58 -0700143 if (active_decoder_type_ == rtp_payload_type) {
144 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000145 }
ossu97ba30e2016-04-25 07:55:58 -0700146 if (active_cng_decoder_type_ == rtp_payload_type) {
147 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000148 }
149 return kOK;
150}
151
152const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
153 uint8_t rtp_payload_type) const {
154 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
155 if (it == decoders_.end()) {
156 // Decoder not found.
157 return NULL;
158 }
159 return &(*it).second;
160}
161
162uint8_t DecoderDatabase::GetRtpPayloadType(
163 NetEqDecoder codec_type) const {
164 DecoderMap::const_iterator it;
165 for (it = decoders_.begin(); it != decoders_.end(); ++it) {
166 if ((*it).second.codec_type == codec_type) {
167 // Match found.
168 return (*it).first;
169 }
170 }
171 // No match.
172 return kRtpPayloadTypeError;
173}
174
175AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) {
ossu97ba30e2016-04-25 07:55:58 -0700176 if (IsDtmf(rtp_payload_type) || IsRed(rtp_payload_type) ||
177 IsComfortNoise(rtp_payload_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000178 // These are not real decoders.
179 return NULL;
180 }
181 DecoderMap::iterator it = decoders_.find(rtp_payload_type);
182 if (it == decoders_.end()) {
183 // Decoder not found.
184 return NULL;
185 }
186 DecoderInfo* info = &(*it).second;
kwiberg5178ee82016-05-03 01:39:01 -0700187 return info->GetDecoder(decoder_factory_.get());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000188}
189
190bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
191 NetEqDecoder codec_type) const {
192 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
193 if (it == decoders_.end()) {
194 // Decoder not found.
195 return false;
196 }
197 return ((*it).second.codec_type == codec_type);
198}
199
200bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
ossu63537232016-04-27 07:43:38 -0700201 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
202 if (it == decoders_.end()) {
203 // Decoder not found.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000204 return false;
205 }
ossu63537232016-04-27 07:43:38 -0700206 const auto& type = it->second.codec_type;
207 return type == NetEqDecoder::kDecoderCNGnb
208 || type == NetEqDecoder::kDecoderCNGwb
209 || type == NetEqDecoder::kDecoderCNGswb32kHz
210 || type == NetEqDecoder::kDecoderCNGswb48kHz;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000211}
212
213bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700214 return IsType(rtp_payload_type, NetEqDecoder::kDecoderAVT);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000215}
216
217bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700218 return IsType(rtp_payload_type, NetEqDecoder::kDecoderRED);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000219}
220
221int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
222 bool* new_decoder) {
223 // Check that |rtp_payload_type| exists in the database.
224 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
225 if (it == decoders_.end()) {
226 // Decoder not found.
227 return kDecoderNotFound;
228 }
ossu97ba30e2016-04-25 07:55:58 -0700229 RTC_CHECK(!IsComfortNoise(rtp_payload_type));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000230 assert(new_decoder);
231 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700232 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000233 // This is the first active decoder.
234 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700235 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000236 // Moving from one active decoder to another. Delete the first one.
ossu97ba30e2016-04-25 07:55:58 -0700237 DecoderMap::iterator it = decoders_.find(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000238 if (it == decoders_.end()) {
239 // Decoder not found. This should not be possible.
240 assert(false);
241 return kDecoderNotFound;
242 }
kwiberg0fa0a972016-04-19 05:03:45 -0700243 it->second.DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000244 *new_decoder = true;
245 }
ossu97ba30e2016-04-25 07:55:58 -0700246 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000247 return kOK;
248}
249
250AudioDecoder* DecoderDatabase::GetActiveDecoder() {
ossu97ba30e2016-04-25 07:55:58 -0700251 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000252 // No active decoder.
253 return NULL;
254 }
ossu97ba30e2016-04-25 07:55:58 -0700255 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000256}
257
258int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
259 // Check that |rtp_payload_type| exists in the database.
260 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
261 if (it == decoders_.end()) {
262 // Decoder not found.
263 return kDecoderNotFound;
264 }
ossu97ba30e2016-04-25 07:55:58 -0700265 if (active_cng_decoder_type_ >= 0 &&
266 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000267 // Moving from one active CNG decoder to another. Delete the first one.
ossu97ba30e2016-04-25 07:55:58 -0700268 DecoderMap::iterator it = decoders_.find(active_cng_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000269 if (it == decoders_.end()) {
270 // Decoder not found. This should not be possible.
271 assert(false);
272 return kDecoderNotFound;
273 }
ossu97ba30e2016-04-25 07:55:58 -0700274 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000275 }
ossu97ba30e2016-04-25 07:55:58 -0700276 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000277 return kOK;
278}
279
ossu97ba30e2016-04-25 07:55:58 -0700280ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() {
281 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000282 // No active CNG decoder.
283 return NULL;
284 }
ossu97ba30e2016-04-25 07:55:58 -0700285 if (!active_cng_decoder_) {
286 active_cng_decoder_.reset(new ComfortNoiseDecoder);
287 }
288 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000289}
290
291int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
292 PacketList::const_iterator it;
293 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
294 if (decoders_.find((*it)->header.payloadType) == decoders_.end()) {
295 // 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
304
305} // namespace webrtc