blob: 4fddf75ce26d1e5ede4040911cda02415a24e6eb [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(
23 std::unique_ptr<AudioDecoderFactory> decoder_factory)
24 : active_decoder_type_(-1),
25 active_cng_decoder_type_(-1),
26 decoder_factory_(std::move(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,
31 const std::string& nm,
32 int fs,
33 AudioDecoder* ext_dec)
34 : codec_type(ct),
35 name(nm),
36 fs_hz(fs),
kwiberg5178ee82016-05-03 01:39:01 -070037 external_decoder(ext_dec),
38 audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)) {}
kwiberg0fa0a972016-04-19 05:03:45 -070039
40DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
41DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
42
kwiberg5178ee82016-05-03 01:39:01 -070043AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder(
44 AudioDecoderFactory* factory) {
kwiberg0fa0a972016-04-19 05:03:45 -070045 if (external_decoder) {
46 RTC_DCHECK(!decoder_);
47 return external_decoder;
48 }
kwiberg5178ee82016-05-03 01:39:01 -070049 RTC_DCHECK(audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -070050 if (!decoder_) {
kwiberg5178ee82016-05-03 01:39:01 -070051 decoder_ = factory->MakeAudioDecoder(*audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -070052 }
kwiberg5178ee82016-05-03 01:39:01 -070053 RTC_DCHECK(decoder_) << "Failed to create: " << *audio_format_;
kwiberg0fa0a972016-04-19 05:03:45 -070054 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000055}
56
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000057bool DecoderDatabase::Empty() const { return decoders_.empty(); }
58
turaj@webrtc.org362a55e2013-09-20 16:25:28 +000059int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000060
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000061void DecoderDatabase::Reset() {
62 decoders_.clear();
ossu97ba30e2016-04-25 07:55:58 -070063 active_decoder_type_ = -1;
64 active_cng_decoder_type_ = -1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000065}
66
67int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -080068 NetEqDecoder codec_type,
69 const std::string& name) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +000070 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000071 return kInvalidRtpPayloadType;
72 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000073 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000074 return kCodecNotSupported;
75 }
henrik.lundin4cf61dd2015-12-09 06:20:58 -080076 const int fs_hz = CodecSampleRateHz(codec_type);
kwiberg0fa0a972016-04-19 05:03:45 -070077 DecoderInfo info(codec_type, name, fs_hz, nullptr);
78 auto ret =
79 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000080 if (ret.second == false) {
81 // Database already contains a decoder with type |rtp_payload_type|.
82 return kDecoderExists;
83 }
84 return kOK;
85}
86
87int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
88 NetEqDecoder codec_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -080089 const std::string& codec_name,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000090 int fs_hz,
91 AudioDecoder* decoder) {
92 if (rtp_payload_type > 0x7F) {
93 return kInvalidRtpPayloadType;
94 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +000095 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000096 return kCodecNotSupported;
97 }
98 if (fs_hz != 8000 && fs_hz != 16000 && fs_hz != 32000 && fs_hz != 48000) {
99 return kInvalidSampleRate;
100 }
101 if (!decoder) {
102 return kInvalidPointer;
103 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000104 std::pair<DecoderMap::iterator, bool> ret;
kwiberg0fa0a972016-04-19 05:03:45 -0700105 DecoderInfo info(codec_type, codec_name, fs_hz, decoder);
106 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000107 if (ret.second == false) {
108 // Database already contains a decoder with type |rtp_payload_type|.
109 return kDecoderExists;
110 }
111 return kOK;
112}
113
114int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
115 if (decoders_.erase(rtp_payload_type) == 0) {
116 // No decoder with that |rtp_payload_type|.
117 return kDecoderNotFound;
118 }
ossu97ba30e2016-04-25 07:55:58 -0700119 if (active_decoder_type_ == rtp_payload_type) {
120 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000121 }
ossu97ba30e2016-04-25 07:55:58 -0700122 if (active_cng_decoder_type_ == rtp_payload_type) {
123 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000124 }
125 return kOK;
126}
127
128const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
129 uint8_t rtp_payload_type) const {
130 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
131 if (it == decoders_.end()) {
132 // Decoder not found.
133 return NULL;
134 }
135 return &(*it).second;
136}
137
138uint8_t DecoderDatabase::GetRtpPayloadType(
139 NetEqDecoder codec_type) const {
140 DecoderMap::const_iterator it;
141 for (it = decoders_.begin(); it != decoders_.end(); ++it) {
142 if ((*it).second.codec_type == codec_type) {
143 // Match found.
144 return (*it).first;
145 }
146 }
147 // No match.
148 return kRtpPayloadTypeError;
149}
150
151AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) {
ossu97ba30e2016-04-25 07:55:58 -0700152 if (IsDtmf(rtp_payload_type) || IsRed(rtp_payload_type) ||
153 IsComfortNoise(rtp_payload_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000154 // These are not real decoders.
155 return NULL;
156 }
157 DecoderMap::iterator it = decoders_.find(rtp_payload_type);
158 if (it == decoders_.end()) {
159 // Decoder not found.
160 return NULL;
161 }
162 DecoderInfo* info = &(*it).second;
kwiberg5178ee82016-05-03 01:39:01 -0700163 return info->GetDecoder(decoder_factory_.get());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000164}
165
166bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
167 NetEqDecoder codec_type) const {
168 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
169 if (it == decoders_.end()) {
170 // Decoder not found.
171 return false;
172 }
173 return ((*it).second.codec_type == codec_type);
174}
175
176bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
ossu63537232016-04-27 07:43:38 -0700177 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
178 if (it == decoders_.end()) {
179 // Decoder not found.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000180 return false;
181 }
ossu63537232016-04-27 07:43:38 -0700182 const auto& type = it->second.codec_type;
183 return type == NetEqDecoder::kDecoderCNGnb
184 || type == NetEqDecoder::kDecoderCNGwb
185 || type == NetEqDecoder::kDecoderCNGswb32kHz
186 || type == NetEqDecoder::kDecoderCNGswb48kHz;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000187}
188
189bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700190 return IsType(rtp_payload_type, NetEqDecoder::kDecoderAVT);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000191}
192
193bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700194 return IsType(rtp_payload_type, NetEqDecoder::kDecoderRED);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000195}
196
197int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
198 bool* new_decoder) {
199 // Check that |rtp_payload_type| exists in the database.
200 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
201 if (it == decoders_.end()) {
202 // Decoder not found.
203 return kDecoderNotFound;
204 }
ossu97ba30e2016-04-25 07:55:58 -0700205 RTC_CHECK(!IsComfortNoise(rtp_payload_type));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000206 assert(new_decoder);
207 *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.
ossu97ba30e2016-04-25 07:55:58 -0700213 DecoderMap::iterator it = decoders_.find(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000214 if (it == decoders_.end()) {
215 // Decoder not found. This should not be possible.
216 assert(false);
217 return kDecoderNotFound;
218 }
kwiberg0fa0a972016-04-19 05:03:45 -0700219 it->second.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
226AudioDecoder* DecoderDatabase::GetActiveDecoder() {
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.
236 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
237 if (it == decoders_.end()) {
238 // 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.
ossu97ba30e2016-04-25 07:55:58 -0700244 DecoderMap::iterator it = decoders_.find(active_cng_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000245 if (it == decoders_.end()) {
246 // Decoder not found. This should not be possible.
247 assert(false);
248 return kDecoderNotFound;
249 }
ossu97ba30e2016-04-25 07:55:58 -0700250 // The CNG decoder should never be provided externally.
251 RTC_CHECK(!it->second.external_decoder);
252 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000253 }
ossu97ba30e2016-04-25 07:55:58 -0700254 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000255 return kOK;
256}
257
ossu97ba30e2016-04-25 07:55:58 -0700258ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() {
259 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000260 // No active CNG decoder.
261 return NULL;
262 }
ossu97ba30e2016-04-25 07:55:58 -0700263 if (!active_cng_decoder_) {
264 active_cng_decoder_.reset(new ComfortNoiseDecoder);
265 }
266 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000267}
268
269int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
270 PacketList::const_iterator it;
271 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
272 if (decoders_.find((*it)->header.payloadType) == decoders_.end()) {
273 // Payload type is not found.
Henrik Lundind67a2192015-08-03 12:54:37 +0200274 LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
275 << static_cast<int>((*it)->header.payloadType);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000276 return kDecoderNotFound;
277 }
278 }
279 return kOK;
280}
281
282
283} // namespace webrtc