blob: e755e7bb3ce298235c79a50a720fc928274c3e38 [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:211/*
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
Mirko Bonadei92ea95e2017-09-15 04:47:3111#include "modules/audio_coding/neteq/decoder_database.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2112
Yves Gerey988cc082018-10-23 10:03:0113#include <stddef.h>
Jonas Olssona4d87372019-07-05 17:08:3314
Yves Gerey988cc082018-10-23 10:03:0115#include <cstdint>
16#include <list>
17#include <type_traits>
18#include <utility>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2119
Niels Möller2edab4c2018-10-22 07:48:0820#include "absl/strings/match.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3121#include "api/audio_codecs/audio_decoder.h"
22#include "rtc_base/checks.h"
23#include "rtc_base/logging.h"
Jonas Olssonabbe8412018-04-03 11:40:0524#include "rtc_base/strings/audio_format_to_string.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2125
26namespace webrtc {
27
kwiberg5178ee82016-05-03 08:39:0128DecoderDatabase::DecoderDatabase(
Karl Wiberg08126342018-03-20 18:18:5529 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory,
Danil Chapovalovb6021232018-06-19 11:26:3630 absl::optional<AudioCodecPairId> codec_pair_id)
kwiberg5178ee82016-05-03 08:39:0131 : active_decoder_type_(-1),
32 active_cng_decoder_type_(-1),
Karl Wiberg08126342018-03-20 18:18:5533 decoder_factory_(decoder_factory),
34 codec_pair_id_(codec_pair_id) {}
pbos@webrtc.org2d1a55c2013-07-31 15:54:0035
ossu97ba30e2016-04-25 14:55:5836DecoderDatabase::~DecoderDatabase() = default;
pbos@webrtc.org2d1a55c2013-07-31 15:54:0037
Karl Wiberg08126342018-03-20 18:18:5538DecoderDatabase::DecoderInfo::DecoderInfo(
39 const SdpAudioFormat& audio_format,
Danil Chapovalovb6021232018-06-19 11:26:3640 absl::optional<AudioCodecPairId> codec_pair_id,
Karl Wiberg08126342018-03-20 18:18:5541 AudioDecoderFactory* factory,
42 const std::string& codec_name)
kwiberge9413062016-11-03 12:29:0543 : name_(codec_name),
44 audio_format_(audio_format),
Karl Wiberg08126342018-03-20 18:18:5545 codec_pair_id_(codec_pair_id),
ossu84bc9852016-08-26 12:41:2346 factory_(factory),
ossu9f38c212016-10-04 12:23:3247 cng_decoder_(CngDecoder::Create(audio_format)),
48 subtype_(SubtypeFromFormat(audio_format)) {}
kwibergc0f2dcf2016-05-31 13:28:0349
Karl Wiberg08126342018-03-20 18:18:5550DecoderDatabase::DecoderInfo::DecoderInfo(
51 const SdpAudioFormat& audio_format,
Danil Chapovalovb6021232018-06-19 11:26:3652 absl::optional<AudioCodecPairId> codec_pair_id,
Karl Wiberg08126342018-03-20 18:18:5553 AudioDecoderFactory* factory)
54 : DecoderInfo(audio_format, codec_pair_id, factory, audio_format.name) {}
kwiberge9413062016-11-03 12:29:0555
kwiberg0fa0a972016-04-19 12:03:4556DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
57DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
58
ossu84bc9852016-08-26 12:41:2359AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
ossu9f38c212016-10-04 12:23:3260 if (subtype_ != Subtype::kNormal) {
ossuf1b08da2016-09-23 09:19:4361 // These are handled internally, so they have no AudioDecoder objects.
62 return nullptr;
63 }
kwiberg0fa0a972016-04-19 12:03:4564 if (!decoder_) {
ossuf1b08da2016-09-23 09:19:4365 // TODO(ossu): Keep a check here for now, since a number of tests create
66 // DecoderInfos without factories.
ossu84bc9852016-08-26 12:41:2367 RTC_DCHECK(factory_);
Karl Wiberg08126342018-03-20 18:18:5568 decoder_ = factory_->MakeAudioDecoder(audio_format_, codec_pair_id_);
kwiberg0fa0a972016-04-19 12:03:4569 }
Jonas Olssonabbe8412018-04-03 11:40:0570 RTC_DCHECK(decoder_) << "Failed to create: " << rtc::ToString(audio_format_);
kwiberg0fa0a972016-04-19 12:03:4571 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2172}
73
ossuf1b08da2016-09-23 09:19:4374bool DecoderDatabase::DecoderInfo::IsType(const char* name) const {
Niels Möller2edab4c2018-10-22 07:48:0875 return absl::EqualsIgnoreCase(audio_format_.name, name);
ossuf1b08da2016-09-23 09:19:4376}
77
78bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const {
79 return IsType(name.c_str());
ossu84bc9852016-08-26 12:41:2380}
81
Danil Chapovalovb6021232018-06-19 11:26:3682absl::optional<DecoderDatabase::DecoderInfo::CngDecoder>
ossuf1b08da2016-09-23 09:19:4383DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
Niels Möller2edab4c2018-10-22 07:48:0884 if (absl::EqualsIgnoreCase(format.name, "CN")) {
kwiberg5adaf732016-10-04 16:33:2785 // CN has a 1:1 RTP clock rate to sample rate ratio.
86 const int sample_rate_hz = format.clockrate_hz;
87 RTC_DCHECK(sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
88 sample_rate_hz == 32000 || sample_rate_hz == 48000);
Oskar Sundbom12ab00b2017-11-16 14:31:3889 return DecoderDatabase::DecoderInfo::CngDecoder{sample_rate_hz};
ossuf1b08da2016-09-23 09:19:4390 } else {
Danil Chapovalovb6021232018-06-19 11:26:3691 return absl::nullopt;
kwibergc0f2dcf2016-05-31 13:28:0392 }
93}
94
ossu9f38c212016-10-04 12:23:3295DecoderDatabase::DecoderInfo::Subtype
96DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
Niels Möller2edab4c2018-10-22 07:48:0897 if (absl::EqualsIgnoreCase(format.name, "CN")) {
ossu9f38c212016-10-04 12:23:3298 return Subtype::kComfortNoise;
Niels Möller2edab4c2018-10-22 07:48:0899 } else if (absl::EqualsIgnoreCase(format.name, "telephone-event")) {
ossu9f38c212016-10-04 12:23:32100 return Subtype::kDtmf;
Niels Möller2edab4c2018-10-22 07:48:08101 } else if (absl::EqualsIgnoreCase(format.name, "red")) {
ossu9f38c212016-10-04 12:23:32102 return Subtype::kRed;
103 }
104
105 return Subtype::kNormal;
106}
107
Yves Gerey665174f2018-06-19 13:03:05108bool DecoderDatabase::Empty() const {
109 return decoders_.empty();
110}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00111
Yves Gerey665174f2018-06-19 13:03:05112int DecoderDatabase::Size() const {
113 return static_cast<int>(decoders_.size());
114}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00115
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21116void DecoderDatabase::Reset() {
117 decoders_.clear();
ossu97ba30e2016-04-25 14:55:58118 active_decoder_type_ = -1;
119 active_cng_decoder_type_ = -1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21120}
121
kwiberg1c07c702017-03-27 14:15:49122std::vector<int> DecoderDatabase::SetCodecs(
123 const std::map<int, SdpAudioFormat>& codecs) {
124 // First collect all payload types that we'll remove or reassign, then remove
125 // them from the database.
126 std::vector<int> changed_payload_types;
127 for (const std::pair<uint8_t, const DecoderInfo&> kv : decoders_) {
128 auto i = codecs.find(kv.first);
129 if (i == codecs.end() || i->second != kv.second.GetFormat()) {
130 changed_payload_types.push_back(kv.first);
131 }
132 }
133 for (int pl_type : changed_payload_types) {
134 Remove(pl_type);
135 }
136
137 // Enter the new and changed payload type mappings into the database.
138 for (const auto& kv : codecs) {
139 const int& rtp_payload_type = kv.first;
140 const SdpAudioFormat& audio_format = kv.second;
141 RTC_DCHECK_GE(rtp_payload_type, 0);
142 RTC_DCHECK_LE(rtp_payload_type, 0x7f);
143 if (decoders_.count(rtp_payload_type) == 0) {
144 decoders_.insert(std::make_pair(
Karl Wiberg08126342018-03-20 18:18:55145 rtp_payload_type,
146 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
kwiberg1c07c702017-03-27 14:15:49147 } else {
148 // The mapping for this payload type hasn't changed.
149 }
150 }
151
152 return changed_payload_types;
153}
154
kwiberg5adaf732016-10-04 16:33:27155int DecoderDatabase::RegisterPayload(int rtp_payload_type,
156 const SdpAudioFormat& audio_format) {
157 if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) {
158 return kInvalidRtpPayloadType;
159 }
160 const auto ret = decoders_.insert(std::make_pair(
Karl Wiberg08126342018-03-20 18:18:55161 rtp_payload_type,
162 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
kwiberg5adaf732016-10-04 16:33:27163 if (ret.second == false) {
164 // Database already contains a decoder with type |rtp_payload_type|.
165 return kDecoderExists;
166 }
167 return kOK;
168}
169
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21170int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
171 if (decoders_.erase(rtp_payload_type) == 0) {
172 // No decoder with that |rtp_payload_type|.
173 return kDecoderNotFound;
174 }
ossu97ba30e2016-04-25 14:55:58175 if (active_decoder_type_ == rtp_payload_type) {
176 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21177 }
ossu97ba30e2016-04-25 14:55:58178 if (active_cng_decoder_type_ == rtp_payload_type) {
179 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21180 }
181 return kOK;
182}
183
kwiberg6b19b562016-09-20 11:02:25184void DecoderDatabase::RemoveAll() {
185 decoders_.clear();
186 active_decoder_type_ = -1; // No active decoder.
187 active_cng_decoder_type_ = -1; // No active CNG decoder.
188}
189
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21190const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
191 uint8_t rtp_payload_type) const {
192 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
193 if (it == decoders_.end()) {
194 // Decoder not found.
195 return NULL;
196 }
ossuf1b08da2016-09-23 09:19:43197 return &it->second;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21198}
199
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21200int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
201 bool* new_decoder) {
202 // Check that |rtp_payload_type| exists in the database.
Yves Gerey665174f2018-06-19 13:03:05203 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 12:41:23204 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21205 // Decoder not found.
206 return kDecoderNotFound;
207 }
ossu84bc9852016-08-26 12:41:23208 RTC_CHECK(!info->IsComfortNoise());
209 RTC_DCHECK(new_decoder);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21210 *new_decoder = false;
ossu97ba30e2016-04-25 14:55:58211 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21212 // This is the first active decoder.
213 *new_decoder = true;
ossu97ba30e2016-04-25 14:55:58214 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21215 // Moving from one active decoder to another. Delete the first one.
Yves Gerey665174f2018-06-19 13:03:05216 const DecoderInfo* old_info = GetDecoderInfo(active_decoder_type_);
ossu84bc9852016-08-26 12:41:23217 RTC_DCHECK(old_info);
218 old_info->DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21219 *new_decoder = true;
220 }
ossu97ba30e2016-04-25 14:55:58221 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21222 return kOK;
223}
224
ossu84bc9852016-08-26 12:41:23225AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
ossu97ba30e2016-04-25 14:55:58226 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21227 // No active decoder.
228 return NULL;
229 }
ossu97ba30e2016-04-25 14:55:58230 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21231}
232
233int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
234 // Check that |rtp_payload_type| exists in the database.
Yves Gerey665174f2018-06-19 13:03:05235 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 12:41:23236 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21237 // Decoder not found.
238 return kDecoderNotFound;
239 }
ossu97ba30e2016-04-25 14:55:58240 if (active_cng_decoder_type_ >= 0 &&
241 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21242 // Moving from one active CNG decoder to another. Delete the first one.
ossu84bc9852016-08-26 12:41:23243 RTC_DCHECK(active_cng_decoder_);
ossu97ba30e2016-04-25 14:55:58244 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21245 }
ossu97ba30e2016-04-25 14:55:58246 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21247 return kOK;
248}
249
ossu84bc9852016-08-26 12:41:23250ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
ossu97ba30e2016-04-25 14:55:58251 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21252 // No active CNG decoder.
253 return NULL;
254 }
ossu97ba30e2016-04-25 14:55:58255 if (!active_cng_decoder_) {
256 active_cng_decoder_.reset(new ComfortNoiseDecoder);
257 }
258 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21259}
260
ossu84bc9852016-08-26 12:41:23261AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 13:03:05262 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 12:41:23263 return info ? info->GetDecoder() : nullptr;
264}
265
ossuf1b08da2016-09-23 09:19:43266bool DecoderDatabase::IsType(uint8_t rtp_payload_type, const char* name) const {
267 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
268 return info && info->IsType(name);
269}
270
ossu84bc9852016-08-26 12:41:23271bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
ossuf1b08da2016-09-23 09:19:43272 const std::string& name) const {
273 return IsType(rtp_payload_type, name.c_str());
ossu84bc9852016-08-26 12:41:23274}
275
276bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 13:03:05277 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 12:41:23278 return info && info->IsComfortNoise();
279}
280
281bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 13:03:05282 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 12:41:23283 return info && info->IsDtmf();
284}
285
286bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 13:03:05287 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 12:41:23288 return info && info->IsRed();
289}
290
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21291int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
292 PacketList::const_iterator it;
293 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
ossua73f6c92016-10-24 15:25:28294 if (!GetDecoderInfo(it->payload_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21295 // Payload type is not found.
Mirko Bonadei675513b2017-11-09 10:09:25296 RTC_LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
297 << static_cast<int>(it->payload_type);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21298 return kDecoderNotFound;
299 }
300 }
301 return kOK;
302}
303
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21304} // namespace webrtc