blob: ce402a76ac06418a49c0cb69f60a3a43f5f71058 [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)),
35 cng_decoder_(CngDecoder::Create(ct)) {}
36
37DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
kwiberg0fa0a972016-04-19 05:03:45 -070038 const std::string& nm,
kwibergc0f2dcf2016-05-31 06:28:03 -070039 int sample_rate_hz,
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)),
44 external_decoder({sample_rate_hz, ext_dec}) {
45 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) {
kwiberg0fa0a972016-04-19 05:03:45 -070053 if (external_decoder) {
54 RTC_DCHECK(!decoder_);
kwibergc0f2dcf2016-05-31 06:28:03 -070055 RTC_DCHECK(external_decoder->decoder);
56 return external_decoder->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 int fs_hz,
119 AudioDecoder* decoder) {
120 if (rtp_payload_type > 0x7F) {
121 return kInvalidRtpPayloadType;
122 }
kwiberg@webrtc.orge04a93b2014-12-09 10:12:53 +0000123 if (!CodecSupported(codec_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000124 return kCodecNotSupported;
125 }
126 if (fs_hz != 8000 && fs_hz != 16000 && fs_hz != 32000 && fs_hz != 48000) {
127 return kInvalidSampleRate;
128 }
129 if (!decoder) {
130 return kInvalidPointer;
131 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000132 std::pair<DecoderMap::iterator, bool> ret;
kwiberg0fa0a972016-04-19 05:03:45 -0700133 DecoderInfo info(codec_type, codec_name, fs_hz, decoder);
134 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000135 if (ret.second == false) {
136 // Database already contains a decoder with type |rtp_payload_type|.
137 return kDecoderExists;
138 }
139 return kOK;
140}
141
142int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
143 if (decoders_.erase(rtp_payload_type) == 0) {
144 // No decoder with that |rtp_payload_type|.
145 return kDecoderNotFound;
146 }
ossu97ba30e2016-04-25 07:55:58 -0700147 if (active_decoder_type_ == rtp_payload_type) {
148 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000149 }
ossu97ba30e2016-04-25 07:55:58 -0700150 if (active_cng_decoder_type_ == rtp_payload_type) {
151 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000152 }
153 return kOK;
154}
155
156const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
157 uint8_t rtp_payload_type) const {
158 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
159 if (it == decoders_.end()) {
160 // Decoder not found.
161 return NULL;
162 }
163 return &(*it).second;
164}
165
166uint8_t DecoderDatabase::GetRtpPayloadType(
167 NetEqDecoder codec_type) const {
168 DecoderMap::const_iterator it;
169 for (it = decoders_.begin(); it != decoders_.end(); ++it) {
170 if ((*it).second.codec_type == codec_type) {
171 // Match found.
172 return (*it).first;
173 }
174 }
175 // No match.
176 return kRtpPayloadTypeError;
177}
178
179AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) {
ossu97ba30e2016-04-25 07:55:58 -0700180 if (IsDtmf(rtp_payload_type) || IsRed(rtp_payload_type) ||
181 IsComfortNoise(rtp_payload_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000182 // These are not real decoders.
183 return NULL;
184 }
185 DecoderMap::iterator it = decoders_.find(rtp_payload_type);
186 if (it == decoders_.end()) {
187 // Decoder not found.
188 return NULL;
189 }
190 DecoderInfo* info = &(*it).second;
kwiberg5178ee82016-05-03 01:39:01 -0700191 return info->GetDecoder(decoder_factory_.get());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000192}
193
194bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
195 NetEqDecoder codec_type) const {
196 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
197 if (it == decoders_.end()) {
198 // Decoder not found.
199 return false;
200 }
201 return ((*it).second.codec_type == codec_type);
202}
203
204bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
ossu63537232016-04-27 07:43:38 -0700205 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
206 if (it == decoders_.end()) {
207 // Decoder not found.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000208 return false;
209 }
ossu63537232016-04-27 07:43:38 -0700210 const auto& type = it->second.codec_type;
211 return type == NetEqDecoder::kDecoderCNGnb
212 || type == NetEqDecoder::kDecoderCNGwb
213 || type == NetEqDecoder::kDecoderCNGswb32kHz
214 || type == NetEqDecoder::kDecoderCNGswb48kHz;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000215}
216
217bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700218 return IsType(rtp_payload_type, NetEqDecoder::kDecoderAVT);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000219}
220
221bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
kwibergee1879c2015-10-29 06:20:28 -0700222 return IsType(rtp_payload_type, NetEqDecoder::kDecoderRED);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000223}
224
225int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
226 bool* new_decoder) {
227 // Check that |rtp_payload_type| exists in the database.
228 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
229 if (it == decoders_.end()) {
230 // Decoder not found.
231 return kDecoderNotFound;
232 }
ossu97ba30e2016-04-25 07:55:58 -0700233 RTC_CHECK(!IsComfortNoise(rtp_payload_type));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000234 assert(new_decoder);
235 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700236 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000237 // This is the first active decoder.
238 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700239 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000240 // Moving from one active decoder to another. Delete the first one.
ossu97ba30e2016-04-25 07:55:58 -0700241 DecoderMap::iterator it = decoders_.find(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000242 if (it == decoders_.end()) {
243 // Decoder not found. This should not be possible.
244 assert(false);
245 return kDecoderNotFound;
246 }
kwiberg0fa0a972016-04-19 05:03:45 -0700247 it->second.DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000248 *new_decoder = true;
249 }
ossu97ba30e2016-04-25 07:55:58 -0700250 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000251 return kOK;
252}
253
254AudioDecoder* DecoderDatabase::GetActiveDecoder() {
ossu97ba30e2016-04-25 07:55:58 -0700255 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000256 // No active decoder.
257 return NULL;
258 }
ossu97ba30e2016-04-25 07:55:58 -0700259 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000260}
261
262int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
263 // Check that |rtp_payload_type| exists in the database.
264 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
265 if (it == decoders_.end()) {
266 // Decoder not found.
267 return kDecoderNotFound;
268 }
ossu97ba30e2016-04-25 07:55:58 -0700269 if (active_cng_decoder_type_ >= 0 &&
270 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000271 // Moving from one active CNG decoder to another. Delete the first one.
ossu97ba30e2016-04-25 07:55:58 -0700272 DecoderMap::iterator it = decoders_.find(active_cng_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000273 if (it == decoders_.end()) {
274 // Decoder not found. This should not be possible.
275 assert(false);
276 return kDecoderNotFound;
277 }
ossu97ba30e2016-04-25 07:55:58 -0700278 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000279 }
ossu97ba30e2016-04-25 07:55:58 -0700280 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000281 return kOK;
282}
283
ossu97ba30e2016-04-25 07:55:58 -0700284ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() {
285 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000286 // No active CNG decoder.
287 return NULL;
288 }
ossu97ba30e2016-04-25 07:55:58 -0700289 if (!active_cng_decoder_) {
290 active_cng_decoder_.reset(new ComfortNoiseDecoder);
291 }
292 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000293}
294
295int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
296 PacketList::const_iterator it;
297 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
298 if (decoders_.find((*it)->header.payloadType) == decoders_.end()) {
299 // Payload type is not found.
Henrik Lundind67a2192015-08-03 12:54:37 +0200300 LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
301 << static_cast<int>((*it)->header.payloadType);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000302 return kDecoderNotFound;
303 }
304 }
305 return kOK;
306}
307
308
309} // namespace webrtc