1 /*
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
11 #include "modules/audio_coding/neteq/decoder_database.h"
12
13 #include <stddef.h>
14
15 #include <cstdint>
16 #include <list>
17 #include <type_traits>
18 #include <utility>
19
20 #include "absl/strings/match.h"
21 #include "absl/strings/string_view.h"
22 #include "api/audio_codecs/audio_decoder.h"
23 #include "rtc_base/checks.h"
24 #include "rtc_base/logging.h"
25 #include "rtc_base/strings/audio_format_to_string.h"
26
27 namespace webrtc {
28
DecoderDatabase(const rtc::scoped_refptr<AudioDecoderFactory> & decoder_factory,absl::optional<AudioCodecPairId> codec_pair_id)29 DecoderDatabase::DecoderDatabase(
30 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory,
31 absl::optional<AudioCodecPairId> codec_pair_id)
32 : active_decoder_type_(-1),
33 active_cng_decoder_type_(-1),
34 decoder_factory_(decoder_factory),
35 codec_pair_id_(codec_pair_id) {}
36
37 DecoderDatabase::~DecoderDatabase() = default;
38
DecoderInfo(const SdpAudioFormat & audio_format,absl::optional<AudioCodecPairId> codec_pair_id,AudioDecoderFactory * factory,absl::string_view codec_name)39 DecoderDatabase::DecoderInfo::DecoderInfo(
40 const SdpAudioFormat& audio_format,
41 absl::optional<AudioCodecPairId> codec_pair_id,
42 AudioDecoderFactory* factory,
43 absl::string_view codec_name)
44 : name_(codec_name),
45 audio_format_(audio_format),
46 codec_pair_id_(codec_pair_id),
47 factory_(factory),
48 cng_decoder_(CngDecoder::Create(audio_format)),
49 subtype_(SubtypeFromFormat(audio_format)) {}
50
DecoderInfo(const SdpAudioFormat & audio_format,absl::optional<AudioCodecPairId> codec_pair_id,AudioDecoderFactory * factory)51 DecoderDatabase::DecoderInfo::DecoderInfo(
52 const SdpAudioFormat& audio_format,
53 absl::optional<AudioCodecPairId> codec_pair_id,
54 AudioDecoderFactory* factory)
55 : DecoderInfo(audio_format, codec_pair_id, factory, audio_format.name) {}
56
57 DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
58 DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
59
GetDecoder() const60 AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
61 if (subtype_ != Subtype::kNormal) {
62 // These are handled internally, so they have no AudioDecoder objects.
63 return nullptr;
64 }
65 if (!decoder_) {
66 // TODO(ossu): Keep a check here for now, since a number of tests create
67 // DecoderInfos without factories.
68 RTC_DCHECK(factory_);
69 decoder_ = factory_->MakeAudioDecoder(audio_format_, codec_pair_id_);
70 }
71 RTC_DCHECK(decoder_) << "Failed to create: " << rtc::ToString(audio_format_);
72 return decoder_.get();
73 }
74
IsType(absl::string_view name) const75 bool DecoderDatabase::DecoderInfo::IsType(absl::string_view name) const {
76 return absl::EqualsIgnoreCase(audio_format_.name, name);
77 }
78
79 absl::optional<DecoderDatabase::DecoderInfo::CngDecoder>
Create(const SdpAudioFormat & format)80 DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
81 if (absl::EqualsIgnoreCase(format.name, "CN")) {
82 // 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);
86 return DecoderDatabase::DecoderInfo::CngDecoder{sample_rate_hz};
87 } else {
88 return absl::nullopt;
89 }
90 }
91
92 DecoderDatabase::DecoderInfo::Subtype
SubtypeFromFormat(const SdpAudioFormat & format)93 DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
94 if (absl::EqualsIgnoreCase(format.name, "CN")) {
95 return Subtype::kComfortNoise;
96 } else if (absl::EqualsIgnoreCase(format.name, "telephone-event")) {
97 return Subtype::kDtmf;
98 } else if (absl::EqualsIgnoreCase(format.name, "red")) {
99 return Subtype::kRed;
100 }
101
102 return Subtype::kNormal;
103 }
104
Empty() const105 bool DecoderDatabase::Empty() const {
106 return decoders_.empty();
107 }
108
Size() const109 int DecoderDatabase::Size() const {
110 return static_cast<int>(decoders_.size());
111 }
112
SetCodecs(const std::map<int,SdpAudioFormat> & codecs)113 std::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(
136 rtp_payload_type,
137 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
138 } else {
139 // The mapping for this payload type hasn't changed.
140 }
141 }
142
143 return changed_payload_types;
144 }
145
RegisterPayload(int rtp_payload_type,const SdpAudioFormat & audio_format)146 int 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(
152 rtp_payload_type,
153 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
154 if (ret.second == false) {
155 // Database already contains a decoder with type `rtp_payload_type`.
156 return kDecoderExists;
157 }
158 return kOK;
159 }
160
Remove(uint8_t rtp_payload_type)161 int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
162 if (decoders_.erase(rtp_payload_type) == 0) {
163 // No decoder with that `rtp_payload_type`.
164 return kDecoderNotFound;
165 }
166 if (active_decoder_type_ == rtp_payload_type) {
167 active_decoder_type_ = -1; // No active decoder.
168 }
169 if (active_cng_decoder_type_ == rtp_payload_type) {
170 active_cng_decoder_type_ = -1; // No active CNG decoder.
171 }
172 return kOK;
173 }
174
RemoveAll()175 void 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
GetDecoderInfo(uint8_t rtp_payload_type) const181 const 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 }
188 return &it->second;
189 }
190
SetActiveDecoder(uint8_t rtp_payload_type,bool * new_decoder)191 int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
192 bool* new_decoder) {
193 // Check that `rtp_payload_type` exists in the database.
194 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
195 if (!info) {
196 // Decoder not found.
197 return kDecoderNotFound;
198 }
199 RTC_CHECK(!info->IsComfortNoise());
200 RTC_DCHECK(new_decoder);
201 *new_decoder = false;
202 if (active_decoder_type_ < 0) {
203 // This is the first active decoder.
204 *new_decoder = true;
205 } else if (active_decoder_type_ != rtp_payload_type) {
206 // Moving from one active decoder to another. Delete the first one.
207 const DecoderInfo* old_info = GetDecoderInfo(active_decoder_type_);
208 RTC_DCHECK(old_info);
209 old_info->DropDecoder();
210 *new_decoder = true;
211 }
212 active_decoder_type_ = rtp_payload_type;
213 return kOK;
214 }
215
GetActiveDecoder() const216 AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
217 if (active_decoder_type_ < 0) {
218 // No active decoder.
219 return NULL;
220 }
221 return GetDecoder(active_decoder_type_);
222 }
223
SetActiveCngDecoder(uint8_t rtp_payload_type)224 int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
225 // Check that `rtp_payload_type` exists in the database.
226 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
227 if (!info) {
228 // Decoder not found.
229 return kDecoderNotFound;
230 }
231 if (active_cng_decoder_type_ >= 0 &&
232 active_cng_decoder_type_ != rtp_payload_type) {
233 // Moving from one active CNG decoder to another. Delete the first one.
234 RTC_DCHECK(active_cng_decoder_);
235 active_cng_decoder_.reset();
236 }
237 active_cng_decoder_type_ = rtp_payload_type;
238 return kOK;
239 }
240
GetActiveCngDecoder() const241 ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
242 if (active_cng_decoder_type_ < 0) {
243 // No active CNG decoder.
244 return NULL;
245 }
246 if (!active_cng_decoder_) {
247 active_cng_decoder_.reset(new ComfortNoiseDecoder);
248 }
249 return active_cng_decoder_.get();
250 }
251
GetDecoder(uint8_t rtp_payload_type) const252 AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
253 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
254 return info ? info->GetDecoder() : nullptr;
255 }
256
IsComfortNoise(uint8_t rtp_payload_type) const257 bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
258 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
259 return info && info->IsComfortNoise();
260 }
261
IsDtmf(uint8_t rtp_payload_type) const262 bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
263 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
264 return info && info->IsDtmf();
265 }
266
IsRed(uint8_t rtp_payload_type) const267 bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
268 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
269 return info && info->IsRed();
270 }
271
CheckPayloadTypes(const PacketList & packet_list) const272 int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
273 PacketList::const_iterator it;
274 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
275 if (!GetDecoderInfo(it->payload_type)) {
276 // Payload type is not found.
277 RTC_LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
278 << static_cast<int>(it->payload_type);
279 return kDecoderNotFound;
280 }
281 }
282 return kOK;
283 }
284
285 } // namespace webrtc
286