blob: 845b2adaef7071ae040978d2d9efa76904c252a1 [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
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000022DecoderDatabase::DecoderDatabase()
ossu97ba30e2016-04-25 07:55:58 -070023 : active_decoder_type_(-1), active_cng_decoder_type_(-1) {
24}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000025
ossu97ba30e2016-04-25 07:55:58 -070026DecoderDatabase::~DecoderDatabase() = default;
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000027
kwiberg0fa0a972016-04-19 05:03:45 -070028DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
29 const std::string& nm,
30 int fs,
31 AudioDecoder* ext_dec)
32 : codec_type(ct),
33 name(nm),
34 fs_hz(fs),
kwiberg0fa0a972016-04-19 05:03:45 -070035 external_decoder(ext_dec) {}
36
37DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
38DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
39
40AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() {
41 if (external_decoder) {
42 RTC_DCHECK(!decoder_);
43 return external_decoder;
44 }
45 if (!decoder_) {
46 decoder_.reset(CreateAudioDecoder(codec_type));
47 }
48 RTC_DCHECK(decoder_);
49 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000050}
51
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000052bool DecoderDatabase::Empty() const { return decoders_.empty(); }
53
turaj@webrtc.org362a55e2013-09-20 16:25:28 +000054int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000055
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000056void DecoderDatabase::Reset() {
57 decoders_.clear();
ossu97ba30e2016-04-25 07:55:58 -070058 active_decoder_type_ = -1;
59 active_cng_decoder_type_ = -1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000060}
61
62int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -080063 NetEqDecoder codec_type,
64 const std::string& name) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +000065 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000066 return kInvalidRtpPayloadType;
67 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000068 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000069 return kCodecNotSupported;
70 }
henrik.lundin4cf61dd2015-12-09 06:20:58 -080071 const int fs_hz = CodecSampleRateHz(codec_type);
kwiberg0fa0a972016-04-19 05:03:45 -070072 DecoderInfo info(codec_type, name, fs_hz, nullptr);
73 auto ret =
74 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000075 if (ret.second == false) {
76 // Database already contains a decoder with type |rtp_payload_type|.
77 return kDecoderExists;
78 }
79 return kOK;
80}
81
82int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
83 NetEqDecoder codec_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -080084 const std::string& codec_name,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000085 int fs_hz,
86 AudioDecoder* decoder) {
87 if (rtp_payload_type > 0x7F) {
88 return kInvalidRtpPayloadType;
89 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000090 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000091 return kCodecNotSupported;
92 }
93 if (fs_hz != 8000 && fs_hz != 16000 && fs_hz != 32000 && fs_hz != 48000) {
94 return kInvalidSampleRate;
95 }
96 if (!decoder) {
97 return kInvalidPointer;
98 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000099 std::pair<DecoderMap::iterator, bool> ret;
kwiberg0fa0a972016-04-19 05:03:45 -0700100 DecoderInfo info(codec_type, codec_name, fs_hz, decoder);
101 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000102 if (ret.second == false) {
103 // Database already contains a decoder with type |rtp_payload_type|.
104 return kDecoderExists;
105 }
106 return kOK;
107}
108
109int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
110 if (decoders_.erase(rtp_payload_type) == 0) {
111 // No decoder with that |rtp_payload_type|.
112 return kDecoderNotFound;
113 }
ossu97ba30e2016-04-25 07:55:58 -0700114 if (active_decoder_type_ == rtp_payload_type) {
115 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000116 }
ossu97ba30e2016-04-25 07:55:58 -0700117 if (active_cng_decoder_type_ == rtp_payload_type) {
118 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000119 }
120 return kOK;
121}
122
123const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
124 uint8_t rtp_payload_type) const {
125 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
126 if (it == decoders_.end()) {
127 // Decoder not found.
128 return NULL;
129 }
130 return &(*it).second;
131}
132
133uint8_t DecoderDatabase::GetRtpPayloadType(
134 NetEqDecoder codec_type) const {
135 DecoderMap::const_iterator it;
136 for (it = decoders_.begin(); it != decoders_.end(); ++it) {
137 if ((*it).second.codec_type == codec_type) {
138 // Match found.
139 return (*it).first;
140 }
141 }
142 // No match.
143 return kRtpPayloadTypeError;
144}
145
146AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) {
ossu97ba30e2016-04-25 07:55:58 -0700147 if (IsDtmf(rtp_payload_type) || IsRed(rtp_payload_type) ||
148 IsComfortNoise(rtp_payload_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000149 // These are not real decoders.
150 return NULL;
151 }
152 DecoderMap::iterator it = decoders_.find(rtp_payload_type);
153 if (it == decoders_.end()) {
154 // Decoder not found.
155 return NULL;
156 }
157 DecoderInfo* info = &(*it).second;
kwiberg0fa0a972016-04-19 05:03:45 -0700158 return info->GetDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000159}
160
161bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
162 NetEqDecoder codec_type) const {
163 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
164 if (it == decoders_.end()) {
165 // Decoder not found.
166 return false;
167 }
168 return ((*it).second.codec_type == codec_type);
169}
170
171bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
ossu63537232016-04-27 07:43:38 -0700172 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
173 if (it == decoders_.end()) {
174 // Decoder not found.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000175 return false;
176 }
ossu63537232016-04-27 07:43:38 -0700177 const auto& type = it->second.codec_type;
178 return type == NetEqDecoder::kDecoderCNGnb
179 || type == NetEqDecoder::kDecoderCNGwb
180 || type == NetEqDecoder::kDecoderCNGswb32kHz
181 || type == NetEqDecoder::kDecoderCNGswb48kHz;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000182}
183
184bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700185 return IsType(rtp_payload_type, NetEqDecoder::kDecoderAVT);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000186}
187
188bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700189 return IsType(rtp_payload_type, NetEqDecoder::kDecoderRED);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000190}
191
192int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
193 bool* new_decoder) {
194 // Check that |rtp_payload_type| exists in the database.
195 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
196 if (it == decoders_.end()) {
197 // Decoder not found.
198 return kDecoderNotFound;
199 }
ossu97ba30e2016-04-25 07:55:58 -0700200 RTC_CHECK(!IsComfortNoise(rtp_payload_type));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000201 assert(new_decoder);
202 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700203 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000204 // This is the first active decoder.
205 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700206 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000207 // Moving from one active decoder to another. Delete the first one.
ossu97ba30e2016-04-25 07:55:58 -0700208 DecoderMap::iterator it = decoders_.find(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000209 if (it == decoders_.end()) {
210 // Decoder not found. This should not be possible.
211 assert(false);
212 return kDecoderNotFound;
213 }
kwiberg0fa0a972016-04-19 05:03:45 -0700214 it->second.DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000215 *new_decoder = true;
216 }
ossu97ba30e2016-04-25 07:55:58 -0700217 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000218 return kOK;
219}
220
221AudioDecoder* DecoderDatabase::GetActiveDecoder() {
ossu97ba30e2016-04-25 07:55:58 -0700222 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000223 // No active decoder.
224 return NULL;
225 }
ossu97ba30e2016-04-25 07:55:58 -0700226 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000227}
228
229int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
230 // Check that |rtp_payload_type| exists in the database.
231 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
232 if (it == decoders_.end()) {
233 // Decoder not found.
234 return kDecoderNotFound;
235 }
ossu97ba30e2016-04-25 07:55:58 -0700236 if (active_cng_decoder_type_ >= 0 &&
237 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000238 // Moving from one active CNG decoder to another. Delete the first one.
ossu97ba30e2016-04-25 07:55:58 -0700239 DecoderMap::iterator it = decoders_.find(active_cng_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000240 if (it == decoders_.end()) {
241 // Decoder not found. This should not be possible.
242 assert(false);
243 return kDecoderNotFound;
244 }
ossu97ba30e2016-04-25 07:55:58 -0700245 // The CNG decoder should never be provided externally.
246 RTC_CHECK(!it->second.external_decoder);
247 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000248 }
ossu97ba30e2016-04-25 07:55:58 -0700249 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000250 return kOK;
251}
252
ossu97ba30e2016-04-25 07:55:58 -0700253ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() {
254 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000255 // No active CNG decoder.
256 return NULL;
257 }
ossu97ba30e2016-04-25 07:55:58 -0700258 if (!active_cng_decoder_) {
259 active_cng_decoder_.reset(new ComfortNoiseDecoder);
260 }
261 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000262}
263
264int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
265 PacketList::const_iterator it;
266 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
267 if (decoders_.find((*it)->header.payloadType) == decoders_.end()) {
268 // Payload type is not found.
Henrik Lundind67a2192015-08-03 12:54:37 +0200269 LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
270 << static_cast<int>((*it)->header.payloadType);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000271 return kDecoderNotFound;
272 }
273 }
274 return kOK;
275}
276
277
278} // namespace webrtc