blob: 3447ced1da3549bfa4fb17abb2b9b7514f0b5756 [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>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Yves Gerey988cc082018-10-23 12:03:01 +020015#include <cstdint>
16#include <list>
17#include <type_traits>
18#include <utility>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000019
Niels Möller2edab4c2018-10-22 09:48:08 +020020#include "absl/strings/match.h"
Ali Tofigh714e3cb2022-07-20 12:53:07 +020021#include "absl/strings/string_view.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "api/audio_codecs/audio_decoder.h"
23#include "rtc_base/checks.h"
24#include "rtc_base/logging.h"
Jonas Olssonabbe8412018-04-03 13:40:05 +020025#include "rtc_base/strings/audio_format_to_string.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000026
27namespace webrtc {
28
kwiberg5178ee82016-05-03 01:39:01 -070029DecoderDatabase::DecoderDatabase(
Karl Wiberg08126342018-03-20 19:18:55 +010030 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory,
Danil Chapovalovb6021232018-06-19 13:26:36 +020031 absl::optional<AudioCodecPairId> codec_pair_id)
kwiberg5178ee82016-05-03 01:39:01 -070032 : active_decoder_type_(-1),
33 active_cng_decoder_type_(-1),
Karl Wiberg08126342018-03-20 19:18:55 +010034 decoder_factory_(decoder_factory),
35 codec_pair_id_(codec_pair_id) {}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000036
ossu97ba30e2016-04-25 07:55:58 -070037DecoderDatabase::~DecoderDatabase() = default;
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000038
Karl Wiberg08126342018-03-20 19:18:55 +010039DecoderDatabase::DecoderInfo::DecoderInfo(
40 const SdpAudioFormat& audio_format,
Danil Chapovalovb6021232018-06-19 13:26:36 +020041 absl::optional<AudioCodecPairId> codec_pair_id,
Karl Wiberg08126342018-03-20 19:18:55 +010042 AudioDecoderFactory* factory,
Ali Tofigh714e3cb2022-07-20 12:53:07 +020043 absl::string_view codec_name)
kwiberge9413062016-11-03 05:29:05 -070044 : name_(codec_name),
45 audio_format_(audio_format),
Karl Wiberg08126342018-03-20 19:18:55 +010046 codec_pair_id_(codec_pair_id),
ossu84bc9852016-08-26 05:41:23 -070047 factory_(factory),
ossu9f38c212016-10-04 05:23:32 -070048 cng_decoder_(CngDecoder::Create(audio_format)),
49 subtype_(SubtypeFromFormat(audio_format)) {}
kwibergc0f2dcf2016-05-31 06:28:03 -070050
Karl Wiberg08126342018-03-20 19:18:55 +010051DecoderDatabase::DecoderInfo::DecoderInfo(
52 const SdpAudioFormat& audio_format,
Danil Chapovalovb6021232018-06-19 13:26:36 +020053 absl::optional<AudioCodecPairId> codec_pair_id,
Karl Wiberg08126342018-03-20 19:18:55 +010054 AudioDecoderFactory* factory)
55 : DecoderInfo(audio_format, codec_pair_id, factory, audio_format.name) {}
kwiberge9413062016-11-03 05:29:05 -070056
kwiberg0fa0a972016-04-19 05:03:45 -070057DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
58DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
59
ossu84bc9852016-08-26 05:41:23 -070060AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
ossu9f38c212016-10-04 05:23:32 -070061 if (subtype_ != Subtype::kNormal) {
ossuf1b08da2016-09-23 02:19:43 -070062 // These are handled internally, so they have no AudioDecoder objects.
63 return nullptr;
64 }
kwiberg0fa0a972016-04-19 05:03:45 -070065 if (!decoder_) {
ossuf1b08da2016-09-23 02:19:43 -070066 // TODO(ossu): Keep a check here for now, since a number of tests create
67 // DecoderInfos without factories.
ossu84bc9852016-08-26 05:41:23 -070068 RTC_DCHECK(factory_);
Karl Wiberg08126342018-03-20 19:18:55 +010069 decoder_ = factory_->MakeAudioDecoder(audio_format_, codec_pair_id_);
kwiberg0fa0a972016-04-19 05:03:45 -070070 }
Jonas Olssonabbe8412018-04-03 13:40:05 +020071 RTC_DCHECK(decoder_) << "Failed to create: " << rtc::ToString(audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -070072 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000073}
74
Ali Tofigh714e3cb2022-07-20 12:53:07 +020075bool DecoderDatabase::DecoderInfo::IsType(absl::string_view name) const {
Niels Möller2edab4c2018-10-22 09:48:08 +020076 return absl::EqualsIgnoreCase(audio_format_.name, name);
ossuf1b08da2016-09-23 02:19:43 -070077}
78
Danil Chapovalovb6021232018-06-19 13:26:36 +020079absl::optional<DecoderDatabase::DecoderInfo::CngDecoder>
ossuf1b08da2016-09-23 02:19:43 -070080DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
Niels Möller2edab4c2018-10-22 09:48:08 +020081 if (absl::EqualsIgnoreCase(format.name, "CN")) {
kwiberg5adaf732016-10-04 09:33:27 -070082 // CN has a 1:1 RTP clock rate to sample rate ratio.
83 const int sample_rate_hz = format.clockrate_hz;
84 RTC_DCHECK(sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
85 sample_rate_hz == 32000 || sample_rate_hz == 48000);
Oskar Sundbom12ab00b2017-11-16 15:31:38 +010086 return DecoderDatabase::DecoderInfo::CngDecoder{sample_rate_hz};
ossuf1b08da2016-09-23 02:19:43 -070087 } else {
Danil Chapovalovb6021232018-06-19 13:26:36 +020088 return absl::nullopt;
kwibergc0f2dcf2016-05-31 06:28:03 -070089 }
90}
91
ossu9f38c212016-10-04 05:23:32 -070092DecoderDatabase::DecoderInfo::Subtype
93DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
Niels Möller2edab4c2018-10-22 09:48:08 +020094 if (absl::EqualsIgnoreCase(format.name, "CN")) {
ossu9f38c212016-10-04 05:23:32 -070095 return Subtype::kComfortNoise;
Niels Möller2edab4c2018-10-22 09:48:08 +020096 } else if (absl::EqualsIgnoreCase(format.name, "telephone-event")) {
ossu9f38c212016-10-04 05:23:32 -070097 return Subtype::kDtmf;
Niels Möller2edab4c2018-10-22 09:48:08 +020098 } else if (absl::EqualsIgnoreCase(format.name, "red")) {
ossu9f38c212016-10-04 05:23:32 -070099 return Subtype::kRed;
100 }
101
102 return Subtype::kNormal;
103}
104
Yves Gerey665174f2018-06-19 15:03:05 +0200105bool DecoderDatabase::Empty() const {
106 return decoders_.empty();
107}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000108
Yves Gerey665174f2018-06-19 15:03:05 +0200109int DecoderDatabase::Size() const {
110 return static_cast<int>(decoders_.size());
111}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000112
kwiberg1c07c702017-03-27 07:15:49 -0700113std::vector<int> DecoderDatabase::SetCodecs(
114 const std::map<int, SdpAudioFormat>& codecs) {
115 // First collect all payload types that we'll remove or reassign, then remove
116 // them from the database.
117 std::vector<int> changed_payload_types;
118 for (const std::pair<uint8_t, const DecoderInfo&> kv : decoders_) {
119 auto i = codecs.find(kv.first);
120 if (i == codecs.end() || i->second != kv.second.GetFormat()) {
121 changed_payload_types.push_back(kv.first);
122 }
123 }
124 for (int pl_type : changed_payload_types) {
125 Remove(pl_type);
126 }
127
128 // Enter the new and changed payload type mappings into the database.
129 for (const auto& kv : codecs) {
130 const int& rtp_payload_type = kv.first;
131 const SdpAudioFormat& audio_format = kv.second;
132 RTC_DCHECK_GE(rtp_payload_type, 0);
133 RTC_DCHECK_LE(rtp_payload_type, 0x7f);
134 if (decoders_.count(rtp_payload_type) == 0) {
135 decoders_.insert(std::make_pair(
Karl Wiberg08126342018-03-20 19:18:55 +0100136 rtp_payload_type,
137 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
kwiberg1c07c702017-03-27 07:15:49 -0700138 } else {
139 // The mapping for this payload type hasn't changed.
140 }
141 }
142
143 return changed_payload_types;
144}
145
kwiberg5adaf732016-10-04 09:33:27 -0700146int DecoderDatabase::RegisterPayload(int rtp_payload_type,
147 const SdpAudioFormat& audio_format) {
148 if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) {
149 return kInvalidRtpPayloadType;
150 }
151 const auto ret = decoders_.insert(std::make_pair(
Karl Wiberg08126342018-03-20 19:18:55 +0100152 rtp_payload_type,
153 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
kwiberg5adaf732016-10-04 09:33:27 -0700154 if (ret.second == false) {
Artem Titovd00ce742021-07-28 20:00:17 +0200155 // Database already contains a decoder with type `rtp_payload_type`.
kwiberg5adaf732016-10-04 09:33:27 -0700156 return kDecoderExists;
157 }
158 return kOK;
159}
160
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000161int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
162 if (decoders_.erase(rtp_payload_type) == 0) {
Artem Titovd00ce742021-07-28 20:00:17 +0200163 // No decoder with that `rtp_payload_type`.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000164 return kDecoderNotFound;
165 }
ossu97ba30e2016-04-25 07:55:58 -0700166 if (active_decoder_type_ == rtp_payload_type) {
167 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000168 }
ossu97ba30e2016-04-25 07:55:58 -0700169 if (active_cng_decoder_type_ == rtp_payload_type) {
170 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000171 }
172 return kOK;
173}
174
kwiberg6b19b562016-09-20 04:02:25 -0700175void DecoderDatabase::RemoveAll() {
176 decoders_.clear();
177 active_decoder_type_ = -1; // No active decoder.
178 active_cng_decoder_type_ = -1; // No active CNG decoder.
179}
180
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000181const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
182 uint8_t rtp_payload_type) const {
183 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
184 if (it == decoders_.end()) {
185 // Decoder not found.
186 return NULL;
187 }
ossuf1b08da2016-09-23 02:19:43 -0700188 return &it->second;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000189}
190
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000191int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
192 bool* new_decoder) {
Artem Titovd00ce742021-07-28 20:00:17 +0200193 // Check that `rtp_payload_type` exists in the database.
Yves Gerey665174f2018-06-19 15:03:05 +0200194 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700195 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000196 // Decoder not found.
197 return kDecoderNotFound;
198 }
ossu84bc9852016-08-26 05:41:23 -0700199 RTC_CHECK(!info->IsComfortNoise());
200 RTC_DCHECK(new_decoder);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000201 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700202 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000203 // This is the first active decoder.
204 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700205 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000206 // Moving from one active decoder to another. Delete the first one.
Yves Gerey665174f2018-06-19 15:03:05 +0200207 const DecoderInfo* old_info = GetDecoderInfo(active_decoder_type_);
ossu84bc9852016-08-26 05:41:23 -0700208 RTC_DCHECK(old_info);
209 old_info->DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000210 *new_decoder = true;
211 }
ossu97ba30e2016-04-25 07:55:58 -0700212 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000213 return kOK;
214}
215
ossu84bc9852016-08-26 05:41:23 -0700216AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700217 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000218 // No active decoder.
219 return NULL;
220 }
ossu97ba30e2016-04-25 07:55:58 -0700221 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000222}
223
224int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
Artem Titovd00ce742021-07-28 20:00:17 +0200225 // Check that `rtp_payload_type` exists in the database.
Yves Gerey665174f2018-06-19 15:03:05 +0200226 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700227 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000228 // Decoder not found.
229 return kDecoderNotFound;
230 }
ossu97ba30e2016-04-25 07:55:58 -0700231 if (active_cng_decoder_type_ >= 0 &&
232 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000233 // Moving from one active CNG decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700234 RTC_DCHECK(active_cng_decoder_);
ossu97ba30e2016-04-25 07:55:58 -0700235 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000236 }
ossu97ba30e2016-04-25 07:55:58 -0700237 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000238 return kOK;
239}
240
ossu84bc9852016-08-26 05:41:23 -0700241ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700242 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000243 // No active CNG decoder.
244 return NULL;
245 }
ossu97ba30e2016-04-25 07:55:58 -0700246 if (!active_cng_decoder_) {
247 active_cng_decoder_.reset(new ComfortNoiseDecoder);
248 }
249 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000250}
251
ossu84bc9852016-08-26 05:41:23 -0700252AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200253 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700254 return info ? info->GetDecoder() : nullptr;
255}
256
ossu84bc9852016-08-26 05:41:23 -0700257bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200258 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700259 return info && info->IsComfortNoise();
260}
261
262bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200263 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700264 return info && info->IsDtmf();
265}
266
267bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200268 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700269 return info && info->IsRed();
270}
271
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000272int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
273 PacketList::const_iterator it;
274 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
ossua73f6c92016-10-24 08:25:28 -0700275 if (!GetDecoderInfo(it->payload_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000276 // Payload type is not found.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100277 RTC_LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
278 << static_cast<int>(it->payload_type);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000279 return kDecoderNotFound;
280 }
281 }
282 return kOK;
283}
284
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000285} // namespace webrtc