blob: 2049569c50f6396ef34d97169cdcce21ba1a600d [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/neteq/decoder_database.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000012
Yves Gerey988cc082018-10-23 12:03:01 +020013#include <stddef.h>
14#include <cstdint>
15#include <list>
16#include <type_traits>
17#include <utility>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000018
Niels Möller2edab4c2018-10-22 09:48:08 +020019#include "absl/strings/match.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "api/audio_codecs/audio_decoder.h"
21#include "rtc_base/checks.h"
22#include "rtc_base/logging.h"
Jonas Olssonabbe8412018-04-03 13:40:05 +020023#include "rtc_base/strings/audio_format_to_string.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000024
25namespace webrtc {
26
kwiberg5178ee82016-05-03 01:39:01 -070027DecoderDatabase::DecoderDatabase(
Karl Wiberg08126342018-03-20 19:18:55 +010028 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory,
Danil Chapovalovb6021232018-06-19 13:26:36 +020029 absl::optional<AudioCodecPairId> codec_pair_id)
kwiberg5178ee82016-05-03 01:39:01 -070030 : active_decoder_type_(-1),
31 active_cng_decoder_type_(-1),
Karl Wiberg08126342018-03-20 19:18:55 +010032 decoder_factory_(decoder_factory),
33 codec_pair_id_(codec_pair_id) {}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000034
ossu97ba30e2016-04-25 07:55:58 -070035DecoderDatabase::~DecoderDatabase() = default;
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000036
Karl Wiberg08126342018-03-20 19:18:55 +010037DecoderDatabase::DecoderInfo::DecoderInfo(
38 const SdpAudioFormat& audio_format,
Danil Chapovalovb6021232018-06-19 13:26:36 +020039 absl::optional<AudioCodecPairId> codec_pair_id,
Karl Wiberg08126342018-03-20 19:18:55 +010040 AudioDecoderFactory* factory,
41 const std::string& codec_name)
kwiberge9413062016-11-03 05:29:05 -070042 : name_(codec_name),
43 audio_format_(audio_format),
Karl Wiberg08126342018-03-20 19:18:55 +010044 codec_pair_id_(codec_pair_id),
ossu84bc9852016-08-26 05:41:23 -070045 factory_(factory),
ossu9f38c212016-10-04 05:23:32 -070046 cng_decoder_(CngDecoder::Create(audio_format)),
47 subtype_(SubtypeFromFormat(audio_format)) {}
kwibergc0f2dcf2016-05-31 06:28:03 -070048
Karl Wiberg08126342018-03-20 19:18:55 +010049DecoderDatabase::DecoderInfo::DecoderInfo(
50 const SdpAudioFormat& audio_format,
Danil Chapovalovb6021232018-06-19 13:26:36 +020051 absl::optional<AudioCodecPairId> codec_pair_id,
Karl Wiberg08126342018-03-20 19:18:55 +010052 AudioDecoderFactory* factory)
53 : DecoderInfo(audio_format, codec_pair_id, factory, audio_format.name) {}
kwiberge9413062016-11-03 05:29:05 -070054
kwiberg0fa0a972016-04-19 05:03:45 -070055DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
56DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
57
ossu84bc9852016-08-26 05:41:23 -070058AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
ossu9f38c212016-10-04 05:23:32 -070059 if (subtype_ != Subtype::kNormal) {
ossuf1b08da2016-09-23 02:19:43 -070060 // These are handled internally, so they have no AudioDecoder objects.
61 return nullptr;
62 }
kwiberg0fa0a972016-04-19 05:03:45 -070063 if (!decoder_) {
ossuf1b08da2016-09-23 02:19:43 -070064 // TODO(ossu): Keep a check here for now, since a number of tests create
65 // DecoderInfos without factories.
ossu84bc9852016-08-26 05:41:23 -070066 RTC_DCHECK(factory_);
Karl Wiberg08126342018-03-20 19:18:55 +010067 decoder_ = factory_->MakeAudioDecoder(audio_format_, codec_pair_id_);
kwiberg0fa0a972016-04-19 05:03:45 -070068 }
Jonas Olssonabbe8412018-04-03 13:40:05 +020069 RTC_DCHECK(decoder_) << "Failed to create: " << rtc::ToString(audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -070070 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000071}
72
ossuf1b08da2016-09-23 02:19:43 -070073bool DecoderDatabase::DecoderInfo::IsType(const char* name) const {
Niels Möller2edab4c2018-10-22 09:48:08 +020074 return absl::EqualsIgnoreCase(audio_format_.name, name);
ossuf1b08da2016-09-23 02:19:43 -070075}
76
77bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const {
78 return IsType(name.c_str());
ossu84bc9852016-08-26 05:41:23 -070079}
80
Danil Chapovalovb6021232018-06-19 13:26:36 +020081absl::optional<DecoderDatabase::DecoderInfo::CngDecoder>
ossuf1b08da2016-09-23 02:19:43 -070082DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
Niels Möller2edab4c2018-10-22 09:48:08 +020083 if (absl::EqualsIgnoreCase(format.name, "CN")) {
kwiberg5adaf732016-10-04 09:33:27 -070084 // CN has a 1:1 RTP clock rate to sample rate ratio.
85 const int sample_rate_hz = format.clockrate_hz;
86 RTC_DCHECK(sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
87 sample_rate_hz == 32000 || sample_rate_hz == 48000);
Oskar Sundbom12ab00b2017-11-16 15:31:38 +010088 return DecoderDatabase::DecoderInfo::CngDecoder{sample_rate_hz};
ossuf1b08da2016-09-23 02:19:43 -070089 } else {
Danil Chapovalovb6021232018-06-19 13:26:36 +020090 return absl::nullopt;
kwibergc0f2dcf2016-05-31 06:28:03 -070091 }
92}
93
ossu9f38c212016-10-04 05:23:32 -070094DecoderDatabase::DecoderInfo::Subtype
95DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
Niels Möller2edab4c2018-10-22 09:48:08 +020096 if (absl::EqualsIgnoreCase(format.name, "CN")) {
ossu9f38c212016-10-04 05:23:32 -070097 return Subtype::kComfortNoise;
Niels Möller2edab4c2018-10-22 09:48:08 +020098 } else if (absl::EqualsIgnoreCase(format.name, "telephone-event")) {
ossu9f38c212016-10-04 05:23:32 -070099 return Subtype::kDtmf;
Niels Möller2edab4c2018-10-22 09:48:08 +0200100 } else if (absl::EqualsIgnoreCase(format.name, "red")) {
ossu9f38c212016-10-04 05:23:32 -0700101 return Subtype::kRed;
102 }
103
104 return Subtype::kNormal;
105}
106
Yves Gerey665174f2018-06-19 15:03:05 +0200107bool DecoderDatabase::Empty() const {
108 return decoders_.empty();
109}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000110
Yves Gerey665174f2018-06-19 15:03:05 +0200111int DecoderDatabase::Size() const {
112 return static_cast<int>(decoders_.size());
113}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000114
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000115void DecoderDatabase::Reset() {
116 decoders_.clear();
ossu97ba30e2016-04-25 07:55:58 -0700117 active_decoder_type_ = -1;
118 active_cng_decoder_type_ = -1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000119}
120
kwiberg1c07c702017-03-27 07:15:49 -0700121std::vector<int> DecoderDatabase::SetCodecs(
122 const std::map<int, SdpAudioFormat>& codecs) {
123 // First collect all payload types that we'll remove or reassign, then remove
124 // them from the database.
125 std::vector<int> changed_payload_types;
126 for (const std::pair<uint8_t, const DecoderInfo&> kv : decoders_) {
127 auto i = codecs.find(kv.first);
128 if (i == codecs.end() || i->second != kv.second.GetFormat()) {
129 changed_payload_types.push_back(kv.first);
130 }
131 }
132 for (int pl_type : changed_payload_types) {
133 Remove(pl_type);
134 }
135
136 // Enter the new and changed payload type mappings into the database.
137 for (const auto& kv : codecs) {
138 const int& rtp_payload_type = kv.first;
139 const SdpAudioFormat& audio_format = kv.second;
140 RTC_DCHECK_GE(rtp_payload_type, 0);
141 RTC_DCHECK_LE(rtp_payload_type, 0x7f);
142 if (decoders_.count(rtp_payload_type) == 0) {
143 decoders_.insert(std::make_pair(
Karl Wiberg08126342018-03-20 19:18:55 +0100144 rtp_payload_type,
145 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
kwiberg1c07c702017-03-27 07:15:49 -0700146 } else {
147 // The mapping for this payload type hasn't changed.
148 }
149 }
150
151 return changed_payload_types;
152}
153
kwiberg5adaf732016-10-04 09:33:27 -0700154int DecoderDatabase::RegisterPayload(int rtp_payload_type,
155 const SdpAudioFormat& audio_format) {
156 if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) {
157 return kInvalidRtpPayloadType;
158 }
159 const auto ret = decoders_.insert(std::make_pair(
Karl Wiberg08126342018-03-20 19:18:55 +0100160 rtp_payload_type,
161 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
kwiberg5adaf732016-10-04 09:33:27 -0700162 if (ret.second == false) {
163 // Database already contains a decoder with type |rtp_payload_type|.
164 return kDecoderExists;
165 }
166 return kOK;
167}
168
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000169int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
170 if (decoders_.erase(rtp_payload_type) == 0) {
171 // No decoder with that |rtp_payload_type|.
172 return kDecoderNotFound;
173 }
ossu97ba30e2016-04-25 07:55:58 -0700174 if (active_decoder_type_ == rtp_payload_type) {
175 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000176 }
ossu97ba30e2016-04-25 07:55:58 -0700177 if (active_cng_decoder_type_ == rtp_payload_type) {
178 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000179 }
180 return kOK;
181}
182
kwiberg6b19b562016-09-20 04:02:25 -0700183void DecoderDatabase::RemoveAll() {
184 decoders_.clear();
185 active_decoder_type_ = -1; // No active decoder.
186 active_cng_decoder_type_ = -1; // No active CNG decoder.
187}
188
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000189const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
190 uint8_t rtp_payload_type) const {
191 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
192 if (it == decoders_.end()) {
193 // Decoder not found.
194 return NULL;
195 }
ossuf1b08da2016-09-23 02:19:43 -0700196 return &it->second;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000197}
198
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000199int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
200 bool* new_decoder) {
201 // Check that |rtp_payload_type| exists in the database.
Yves Gerey665174f2018-06-19 15:03:05 +0200202 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700203 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000204 // Decoder not found.
205 return kDecoderNotFound;
206 }
ossu84bc9852016-08-26 05:41:23 -0700207 RTC_CHECK(!info->IsComfortNoise());
208 RTC_DCHECK(new_decoder);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000209 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700210 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000211 // This is the first active decoder.
212 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700213 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000214 // Moving from one active decoder to another. Delete the first one.
Yves Gerey665174f2018-06-19 15:03:05 +0200215 const DecoderInfo* old_info = GetDecoderInfo(active_decoder_type_);
ossu84bc9852016-08-26 05:41:23 -0700216 RTC_DCHECK(old_info);
217 old_info->DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000218 *new_decoder = true;
219 }
ossu97ba30e2016-04-25 07:55:58 -0700220 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000221 return kOK;
222}
223
ossu84bc9852016-08-26 05:41:23 -0700224AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700225 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000226 // No active decoder.
227 return NULL;
228 }
ossu97ba30e2016-04-25 07:55:58 -0700229 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000230}
231
232int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
233 // Check that |rtp_payload_type| exists in the database.
Yves Gerey665174f2018-06-19 15:03:05 +0200234 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700235 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000236 // Decoder not found.
237 return kDecoderNotFound;
238 }
ossu97ba30e2016-04-25 07:55:58 -0700239 if (active_cng_decoder_type_ >= 0 &&
240 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000241 // Moving from one active CNG decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700242 RTC_DCHECK(active_cng_decoder_);
ossu97ba30e2016-04-25 07:55:58 -0700243 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000244 }
ossu97ba30e2016-04-25 07:55:58 -0700245 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000246 return kOK;
247}
248
ossu84bc9852016-08-26 05:41:23 -0700249ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700250 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000251 // No active CNG decoder.
252 return NULL;
253 }
ossu97ba30e2016-04-25 07:55:58 -0700254 if (!active_cng_decoder_) {
255 active_cng_decoder_.reset(new ComfortNoiseDecoder);
256 }
257 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000258}
259
ossu84bc9852016-08-26 05:41:23 -0700260AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200261 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700262 return info ? info->GetDecoder() : nullptr;
263}
264
ossuf1b08da2016-09-23 02:19:43 -0700265bool DecoderDatabase::IsType(uint8_t rtp_payload_type, const char* name) const {
266 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
267 return info && info->IsType(name);
268}
269
ossu84bc9852016-08-26 05:41:23 -0700270bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
ossuf1b08da2016-09-23 02:19:43 -0700271 const std::string& name) const {
272 return IsType(rtp_payload_type, name.c_str());
ossu84bc9852016-08-26 05:41:23 -0700273}
274
275bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200276 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700277 return info && info->IsComfortNoise();
278}
279
280bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200281 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700282 return info && info->IsDtmf();
283}
284
285bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200286 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700287 return info && info->IsRed();
288}
289
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000290int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
291 PacketList::const_iterator it;
292 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
ossua73f6c92016-10-24 08:25:28 -0700293 if (!GetDecoderInfo(it->payload_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000294 // Payload type is not found.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100295 RTC_LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
296 << static_cast<int>(it->payload_type);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000297 return kDecoderNotFound;
298 }
299 }
300 return kOK;
301}
302
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000303} // namespace webrtc