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 "api/audio_codecs/audio_decoder.h"
22 #include "rtc_base/checks.h"
23 #include "rtc_base/logging.h"
24 #include "rtc_base/strings/audio_format_to_string.h"
25
26 namespace webrtc {
27
DecoderDatabase(const rtc::scoped_refptr<AudioDecoderFactory> & decoder_factory,absl::optional<AudioCodecPairId> codec_pair_id)28 DecoderDatabase::DecoderDatabase(
29 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory,
30 absl::optional<AudioCodecPairId> codec_pair_id)
31 : active_decoder_type_(-1),
32 active_cng_decoder_type_(-1),
33 decoder_factory_(decoder_factory),
34 codec_pair_id_(codec_pair_id) {}
35
36 DecoderDatabase::~DecoderDatabase() = default;
37
DecoderInfo(const SdpAudioFormat & audio_format,absl::optional<AudioCodecPairId> codec_pair_id,AudioDecoderFactory * factory,const std::string & codec_name)38 DecoderDatabase::DecoderInfo::DecoderInfo(
39 const SdpAudioFormat& audio_format,
40 absl::optional<AudioCodecPairId> codec_pair_id,
41 AudioDecoderFactory* factory,
42 const std::string& codec_name)
43 : name_(codec_name),
44 audio_format_(audio_format),
45 codec_pair_id_(codec_pair_id),
46 factory_(factory),
47 cng_decoder_(CngDecoder::Create(audio_format)),
48 subtype_(SubtypeFromFormat(audio_format)) {}
49
DecoderInfo(const SdpAudioFormat & audio_format,absl::optional<AudioCodecPairId> codec_pair_id,AudioDecoderFactory * factory)50 DecoderDatabase::DecoderInfo::DecoderInfo(
51 const SdpAudioFormat& audio_format,
52 absl::optional<AudioCodecPairId> codec_pair_id,
53 AudioDecoderFactory* factory)
54 : DecoderInfo(audio_format, codec_pair_id, factory, audio_format.name) {}
55
56 DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
57 DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
58
GetDecoder() const59 AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
60 if (subtype_ != Subtype::kNormal) {
61 // These are handled internally, so they have no AudioDecoder objects.
62 return nullptr;
63 }
64 if (!decoder_) {
65 // TODO(ossu): Keep a check here for now, since a number of tests create
66 // DecoderInfos without factories.
67 RTC_DCHECK(factory_);
68 decoder_ = factory_->MakeAudioDecoder(audio_format_, codec_pair_id_);
69 }
70 RTC_DCHECK(decoder_) << "Failed to create: " << rtc::ToString(audio_format_);
71 return decoder_.get();
72 }
73
IsType(const char * name) const74 bool DecoderDatabase::DecoderInfo::IsType(const char* name) const {
75 return absl::EqualsIgnoreCase(audio_format_.name, name);
76 }
77
IsType(const std::string & name) const78 bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const {
79 return IsType(name.c_str());
80 }
81
82 absl::optional<DecoderDatabase::DecoderInfo::CngDecoder>
Create(const SdpAudioFormat & format)83 DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
84 if (absl::EqualsIgnoreCase(format.name, "CN")) {
85 // 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);
89 return DecoderDatabase::DecoderInfo::CngDecoder{sample_rate_hz};
90 } else {
91 return absl::nullopt;
92 }
93 }
94
95 DecoderDatabase::DecoderInfo::Subtype
SubtypeFromFormat(const SdpAudioFormat & format)96 DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
97 if (absl::EqualsIgnoreCase(format.name, "CN")) {
98 return Subtype::kComfortNoise;
99 } else if (absl::EqualsIgnoreCase(format.name, "telephone-event")) {
100 return Subtype::kDtmf;
101 } else if (absl::EqualsIgnoreCase(format.name, "red")) {
102 return Subtype::kRed;
103 }
104
105 return Subtype::kNormal;
106 }
107
Empty() const108 bool DecoderDatabase::Empty() const {
109 return decoders_.empty();
110 }
111
Size() const112 int DecoderDatabase::Size() const {
113 return static_cast<int>(decoders_.size());
114 }
115
Reset()116 void DecoderDatabase::Reset() {
117 decoders_.clear();
118 active_decoder_type_ = -1;
119 active_cng_decoder_type_ = -1;
120 }
121
SetCodecs(const std::map<int,SdpAudioFormat> & codecs)122 std::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(
145 rtp_payload_type,
146 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
147 } else {
148 // The mapping for this payload type hasn't changed.
149 }
150 }
151
152 return changed_payload_types;
153 }
154
RegisterPayload(int rtp_payload_type,const SdpAudioFormat & audio_format)155 int 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(
161 rtp_payload_type,
162 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
163 if (ret.second == false) {
164 // Database already contains a decoder with type |rtp_payload_type|.
165 return kDecoderExists;
166 }
167 return kOK;
168 }
169
Remove(uint8_t rtp_payload_type)170 int 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 }
175 if (active_decoder_type_ == rtp_payload_type) {
176 active_decoder_type_ = -1; // No active decoder.
177 }
178 if (active_cng_decoder_type_ == rtp_payload_type) {
179 active_cng_decoder_type_ = -1; // No active CNG decoder.
180 }
181 return kOK;
182 }
183
RemoveAll()184 void 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
GetDecoderInfo(uint8_t rtp_payload_type) const190 const 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 }
197 return &it->second;
198 }
199
SetActiveDecoder(uint8_t rtp_payload_type,bool * new_decoder)200 int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
201 bool* new_decoder) {
202 // Check that |rtp_payload_type| exists in the database.
203 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
204 if (!info) {
205 // Decoder not found.
206 return kDecoderNotFound;
207 }
208 RTC_CHECK(!info->IsComfortNoise());
209 RTC_DCHECK(new_decoder);
210 *new_decoder = false;
211 if (active_decoder_type_ < 0) {
212 // This is the first active decoder.
213 *new_decoder = true;
214 } else if (active_decoder_type_ != rtp_payload_type) {
215 // Moving from one active decoder to another. Delete the first one.
216 const DecoderInfo* old_info = GetDecoderInfo(active_decoder_type_);
217 RTC_DCHECK(old_info);
218 old_info->DropDecoder();
219 *new_decoder = true;
220 }
221 active_decoder_type_ = rtp_payload_type;
222 return kOK;
223 }
224
GetActiveDecoder() const225 AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
226 if (active_decoder_type_ < 0) {
227 // No active decoder.
228 return NULL;
229 }
230 return GetDecoder(active_decoder_type_);
231 }
232
SetActiveCngDecoder(uint8_t rtp_payload_type)233 int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
234 // Check that |rtp_payload_type| exists in the database.
235 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
236 if (!info) {
237 // Decoder not found.
238 return kDecoderNotFound;
239 }
240 if (active_cng_decoder_type_ >= 0 &&
241 active_cng_decoder_type_ != rtp_payload_type) {
242 // Moving from one active CNG decoder to another. Delete the first one.
243 RTC_DCHECK(active_cng_decoder_);
244 active_cng_decoder_.reset();
245 }
246 active_cng_decoder_type_ = rtp_payload_type;
247 return kOK;
248 }
249
GetActiveCngDecoder() const250 ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
251 if (active_cng_decoder_type_ < 0) {
252 // No active CNG decoder.
253 return NULL;
254 }
255 if (!active_cng_decoder_) {
256 active_cng_decoder_.reset(new ComfortNoiseDecoder);
257 }
258 return active_cng_decoder_.get();
259 }
260
GetDecoder(uint8_t rtp_payload_type) const261 AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
262 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
263 return info ? info->GetDecoder() : nullptr;
264 }
265
IsType(uint8_t rtp_payload_type,const char * name) const266 bool 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
IsType(uint8_t rtp_payload_type,const std::string & name) const271 bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
272 const std::string& name) const {
273 return IsType(rtp_payload_type, name.c_str());
274 }
275
IsComfortNoise(uint8_t rtp_payload_type) const276 bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
277 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
278 return info && info->IsComfortNoise();
279 }
280
IsDtmf(uint8_t rtp_payload_type) const281 bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
282 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
283 return info && info->IsDtmf();
284 }
285
IsRed(uint8_t rtp_payload_type) const286 bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
287 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
288 return info && info->IsRed();
289 }
290
CheckPayloadTypes(const PacketList & packet_list) const291 int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
292 PacketList::const_iterator it;
293 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
294 if (!GetDecoderInfo(it->payload_type)) {
295 // Payload type is not found.
296 RTC_LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
297 << static_cast<int>(it->payload_type);
298 return kDecoderNotFound;
299 }
300 }
301 return kOK;
302 }
303
304 } // namespace webrtc
305