blob: 1fd8c03ca24a63ba55590aacac34a05c03f5c6ba [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
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000013#include <utility> // pair
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "api/audio_codecs/audio_decoder.h"
16#include "rtc_base/checks.h"
17#include "rtc_base/logging.h"
Jonas Olssonabbe8412018-04-03 13:40:05 +020018#include "rtc_base/strings/audio_format_to_string.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000019
20namespace webrtc {
21
kwiberg5178ee82016-05-03 01:39:01 -070022DecoderDatabase::DecoderDatabase(
Karl Wiberg08126342018-03-20 19:18:55 +010023 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory,
Danil Chapovalovb6021232018-06-19 13:26:36 +020024 absl::optional<AudioCodecPairId> codec_pair_id)
kwiberg5178ee82016-05-03 01:39:01 -070025 : active_decoder_type_(-1),
26 active_cng_decoder_type_(-1),
Karl Wiberg08126342018-03-20 19:18:55 +010027 decoder_factory_(decoder_factory),
28 codec_pair_id_(codec_pair_id) {}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000029
ossu97ba30e2016-04-25 07:55:58 -070030DecoderDatabase::~DecoderDatabase() = default;
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +000031
Karl Wiberg08126342018-03-20 19:18:55 +010032DecoderDatabase::DecoderInfo::DecoderInfo(
33 const SdpAudioFormat& audio_format,
Danil Chapovalovb6021232018-06-19 13:26:36 +020034 absl::optional<AudioCodecPairId> codec_pair_id,
Karl Wiberg08126342018-03-20 19:18:55 +010035 AudioDecoderFactory* factory,
36 const std::string& codec_name)
kwiberge9413062016-11-03 05:29:05 -070037 : name_(codec_name),
38 audio_format_(audio_format),
Karl Wiberg08126342018-03-20 19:18:55 +010039 codec_pair_id_(codec_pair_id),
ossu84bc9852016-08-26 05:41:23 -070040 factory_(factory),
kwiberg342f7402016-06-16 03:18:00 -070041 external_decoder_(nullptr),
ossu9f38c212016-10-04 05:23:32 -070042 cng_decoder_(CngDecoder::Create(audio_format)),
43 subtype_(SubtypeFromFormat(audio_format)) {}
kwibergc0f2dcf2016-05-31 06:28:03 -070044
Karl Wiberg08126342018-03-20 19:18:55 +010045DecoderDatabase::DecoderInfo::DecoderInfo(
46 const SdpAudioFormat& audio_format,
Danil Chapovalovb6021232018-06-19 13:26:36 +020047 absl::optional<AudioCodecPairId> codec_pair_id,
Karl Wiberg08126342018-03-20 19:18:55 +010048 AudioDecoderFactory* factory)
49 : DecoderInfo(audio_format, codec_pair_id, factory, audio_format.name) {}
kwiberge9413062016-11-03 05:29:05 -070050
Karl Wiberg08126342018-03-20 19:18:55 +010051DecoderDatabase::DecoderInfo::DecoderInfo(
52 NetEqDecoder ct,
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(*NetEqDecoderToSdpAudioFormat(ct), codec_pair_id, factory) {}
ossuf1b08da2016-09-23 02:19:43 -070056
57DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
kwiberge9413062016-11-03 05:29:05 -070058 AudioDecoder* ext_dec,
59 const std::string& codec_name)
60 : name_(codec_name),
61 audio_format_(audio_format),
Danil Chapovalovb6021232018-06-19 13:26:36 +020062 codec_pair_id_(absl::nullopt),
ossuf1b08da2016-09-23 02:19:43 -070063 factory_(nullptr),
ossu9f38c212016-10-04 05:23:32 -070064 external_decoder_(ext_dec),
65 subtype_(Subtype::kNormal) {
kwibergc0f2dcf2016-05-31 06:28:03 -070066 RTC_CHECK(ext_dec);
67}
kwiberg0fa0a972016-04-19 05:03:45 -070068
69DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
70DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
71
Karl Wiberg31fbb542017-10-16 12:42:38 +020072bool DecoderDatabase::DecoderInfo::CanGetDecoder() const {
73 if (subtype_ == Subtype::kNormal && !external_decoder_ && !decoder_) {
74 // TODO(ossu): Keep a check here for now, since a number of tests create
75 // DecoderInfos without factories.
76 RTC_DCHECK(factory_);
77 return factory_->IsSupportedDecoder(audio_format_);
78 } else {
79 return true;
80 }
81}
82
ossu84bc9852016-08-26 05:41:23 -070083AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
ossu9f38c212016-10-04 05:23:32 -070084 if (subtype_ != Subtype::kNormal) {
ossuf1b08da2016-09-23 02:19:43 -070085 // These are handled internally, so they have no AudioDecoder objects.
86 return nullptr;
87 }
kwiberg342f7402016-06-16 03:18:00 -070088 if (external_decoder_) {
kwiberg0fa0a972016-04-19 05:03:45 -070089 RTC_DCHECK(!decoder_);
kwiberg342f7402016-06-16 03:18:00 -070090 RTC_DCHECK(!cng_decoder_);
91 return external_decoder_;
kwiberg0fa0a972016-04-19 05:03:45 -070092 }
93 if (!decoder_) {
ossuf1b08da2016-09-23 02:19:43 -070094 // TODO(ossu): Keep a check here for now, since a number of tests create
95 // DecoderInfos without factories.
ossu84bc9852016-08-26 05:41:23 -070096 RTC_DCHECK(factory_);
Karl Wiberg08126342018-03-20 19:18:55 +010097 decoder_ = factory_->MakeAudioDecoder(audio_format_, codec_pair_id_);
kwiberg0fa0a972016-04-19 05:03:45 -070098 }
Jonas Olssonabbe8412018-04-03 13:40:05 +020099 RTC_DCHECK(decoder_) << "Failed to create: " << rtc::ToString(audio_format_);
kwiberg0fa0a972016-04-19 05:03:45 -0700100 return decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000101}
102
ossuf1b08da2016-09-23 02:19:43 -0700103bool DecoderDatabase::DecoderInfo::IsType(const char* name) const {
104 return STR_CASE_CMP(audio_format_.name.c_str(), name) == 0;
105}
106
107bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const {
108 return IsType(name.c_str());
ossu84bc9852016-08-26 05:41:23 -0700109}
110
Danil Chapovalovb6021232018-06-19 13:26:36 +0200111absl::optional<DecoderDatabase::DecoderInfo::CngDecoder>
ossuf1b08da2016-09-23 02:19:43 -0700112DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
113 if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
kwiberg5adaf732016-10-04 09:33:27 -0700114 // CN has a 1:1 RTP clock rate to sample rate ratio.
115 const int sample_rate_hz = format.clockrate_hz;
116 RTC_DCHECK(sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
117 sample_rate_hz == 32000 || sample_rate_hz == 48000);
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100118 return DecoderDatabase::DecoderInfo::CngDecoder{sample_rate_hz};
ossuf1b08da2016-09-23 02:19:43 -0700119 } else {
Danil Chapovalovb6021232018-06-19 13:26:36 +0200120 return absl::nullopt;
kwibergc0f2dcf2016-05-31 06:28:03 -0700121 }
122}
123
ossu9f38c212016-10-04 05:23:32 -0700124DecoderDatabase::DecoderInfo::Subtype
125DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
126 if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
127 return Subtype::kComfortNoise;
128 } else if (STR_CASE_CMP(format.name.c_str(), "telephone-event") == 0) {
129 return Subtype::kDtmf;
130 } else if (STR_CASE_CMP(format.name.c_str(), "red") == 0) {
131 return Subtype::kRed;
132 }
133
134 return Subtype::kNormal;
135}
136
Yves Gerey665174f2018-06-19 15:03:05 +0200137bool DecoderDatabase::Empty() const {
138 return decoders_.empty();
139}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000140
Yves Gerey665174f2018-06-19 15:03:05 +0200141int DecoderDatabase::Size() const {
142 return static_cast<int>(decoders_.size());
143}
pbos@webrtc.org2d1a55c2013-07-31 15:54:00 +0000144
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000145void DecoderDatabase::Reset() {
146 decoders_.clear();
ossu97ba30e2016-04-25 07:55:58 -0700147 active_decoder_type_ = -1;
148 active_cng_decoder_type_ = -1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000149}
150
kwiberg1c07c702017-03-27 07:15:49 -0700151std::vector<int> DecoderDatabase::SetCodecs(
152 const std::map<int, SdpAudioFormat>& codecs) {
153 // First collect all payload types that we'll remove or reassign, then remove
154 // them from the database.
155 std::vector<int> changed_payload_types;
156 for (const std::pair<uint8_t, const DecoderInfo&> kv : decoders_) {
157 auto i = codecs.find(kv.first);
158 if (i == codecs.end() || i->second != kv.second.GetFormat()) {
159 changed_payload_types.push_back(kv.first);
160 }
161 }
162 for (int pl_type : changed_payload_types) {
163 Remove(pl_type);
164 }
165
166 // Enter the new and changed payload type mappings into the database.
167 for (const auto& kv : codecs) {
168 const int& rtp_payload_type = kv.first;
169 const SdpAudioFormat& audio_format = kv.second;
170 RTC_DCHECK_GE(rtp_payload_type, 0);
171 RTC_DCHECK_LE(rtp_payload_type, 0x7f);
172 if (decoders_.count(rtp_payload_type) == 0) {
173 decoders_.insert(std::make_pair(
Karl Wiberg08126342018-03-20 19:18:55 +0100174 rtp_payload_type,
175 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
kwiberg1c07c702017-03-27 07:15:49 -0700176 } else {
177 // The mapping for this payload type hasn't changed.
178 }
179 }
180
181 return changed_payload_types;
182}
183
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000184int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800185 NetEqDecoder codec_type,
186 const std::string& name) {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000187 if (rtp_payload_type > 0x7F) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000188 return kInvalidRtpPayloadType;
189 }
Karl Wiberg31fbb542017-10-16 12:42:38 +0200190 if (codec_type == NetEqDecoder::kDecoderArbitrary) {
191 return kCodecNotSupported; // Only supported through InsertExternal.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000192 }
kwiberg65cb70d2017-03-03 06:16:28 -0800193 const auto opt_format = NetEqDecoderToSdpAudioFormat(codec_type);
ossuf1b08da2016-09-23 02:19:43 -0700194 if (!opt_format) {
195 return kCodecNotSupported;
196 }
Karl Wiberg08126342018-03-20 19:18:55 +0100197 DecoderInfo info(*opt_format, codec_pair_id_, decoder_factory_, name);
Karl Wiberg31fbb542017-10-16 12:42:38 +0200198 if (!info.CanGetDecoder()) {
199 return kCodecNotSupported;
200 }
kwiberg0fa0a972016-04-19 05:03:45 -0700201 auto ret =
202 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000203 if (ret.second == false) {
204 // Database already contains a decoder with type |rtp_payload_type|.
205 return kDecoderExists;
206 }
207 return kOK;
208}
209
kwiberg5adaf732016-10-04 09:33:27 -0700210int DecoderDatabase::RegisterPayload(int rtp_payload_type,
211 const SdpAudioFormat& audio_format) {
212 if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) {
213 return kInvalidRtpPayloadType;
214 }
215 const auto ret = decoders_.insert(std::make_pair(
Karl Wiberg08126342018-03-20 19:18:55 +0100216 rtp_payload_type,
217 DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
kwiberg5adaf732016-10-04 09:33:27 -0700218 if (ret.second == false) {
219 // Database already contains a decoder with type |rtp_payload_type|.
220 return kDecoderExists;
221 }
222 return kOK;
223}
224
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000225int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
226 NetEqDecoder codec_type,
henrik.lundin4cf61dd2015-12-09 06:20:58 -0800227 const std::string& codec_name,
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000228 AudioDecoder* decoder) {
229 if (rtp_payload_type > 0x7F) {
230 return kInvalidRtpPayloadType;
231 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000232 if (!decoder) {
233 return kInvalidPointer;
234 }
ossuf1b08da2016-09-23 02:19:43 -0700235
kwiberg65cb70d2017-03-03 06:16:28 -0800236 const auto opt_db_format = NetEqDecoderToSdpAudioFormat(codec_type);
Danil Chapovalov8aba6b42018-04-17 10:10:57 +0200237 const SdpAudioFormat format =
238 opt_db_format.value_or(SdpAudioFormat("arbitrary", 0, 0));
ossuf1b08da2016-09-23 02:19:43 -0700239
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000240 std::pair<DecoderMap::iterator, bool> ret;
kwiberge9413062016-11-03 05:29:05 -0700241 DecoderInfo info(format, decoder, codec_name);
kwiberg0fa0a972016-04-19 05:03:45 -0700242 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000243 if (ret.second == false) {
244 // Database already contains a decoder with type |rtp_payload_type|.
245 return kDecoderExists;
246 }
247 return kOK;
248}
249
250int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
251 if (decoders_.erase(rtp_payload_type) == 0) {
252 // No decoder with that |rtp_payload_type|.
253 return kDecoderNotFound;
254 }
ossu97ba30e2016-04-25 07:55:58 -0700255 if (active_decoder_type_ == rtp_payload_type) {
256 active_decoder_type_ = -1; // No active decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000257 }
ossu97ba30e2016-04-25 07:55:58 -0700258 if (active_cng_decoder_type_ == rtp_payload_type) {
259 active_cng_decoder_type_ = -1; // No active CNG decoder.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000260 }
261 return kOK;
262}
263
kwiberg6b19b562016-09-20 04:02:25 -0700264void DecoderDatabase::RemoveAll() {
265 decoders_.clear();
266 active_decoder_type_ = -1; // No active decoder.
267 active_cng_decoder_type_ = -1; // No active CNG decoder.
268}
269
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000270const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
271 uint8_t rtp_payload_type) const {
272 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
273 if (it == decoders_.end()) {
274 // Decoder not found.
275 return NULL;
276 }
ossuf1b08da2016-09-23 02:19:43 -0700277 return &it->second;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000278}
279
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000280int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
281 bool* new_decoder) {
282 // Check that |rtp_payload_type| exists in the database.
Yves Gerey665174f2018-06-19 15:03:05 +0200283 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700284 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000285 // Decoder not found.
286 return kDecoderNotFound;
287 }
ossu84bc9852016-08-26 05:41:23 -0700288 RTC_CHECK(!info->IsComfortNoise());
289 RTC_DCHECK(new_decoder);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000290 *new_decoder = false;
ossu97ba30e2016-04-25 07:55:58 -0700291 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000292 // This is the first active decoder.
293 *new_decoder = true;
ossu97ba30e2016-04-25 07:55:58 -0700294 } else if (active_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000295 // Moving from one active decoder to another. Delete the first one.
Yves Gerey665174f2018-06-19 15:03:05 +0200296 const DecoderInfo* old_info = GetDecoderInfo(active_decoder_type_);
ossu84bc9852016-08-26 05:41:23 -0700297 RTC_DCHECK(old_info);
298 old_info->DropDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000299 *new_decoder = true;
300 }
ossu97ba30e2016-04-25 07:55:58 -0700301 active_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000302 return kOK;
303}
304
ossu84bc9852016-08-26 05:41:23 -0700305AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700306 if (active_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000307 // No active decoder.
308 return NULL;
309 }
ossu97ba30e2016-04-25 07:55:58 -0700310 return GetDecoder(active_decoder_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000311}
312
313int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
314 // Check that |rtp_payload_type| exists in the database.
Yves Gerey665174f2018-06-19 15:03:05 +0200315 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700316 if (!info) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000317 // Decoder not found.
318 return kDecoderNotFound;
319 }
ossu97ba30e2016-04-25 07:55:58 -0700320 if (active_cng_decoder_type_ >= 0 &&
321 active_cng_decoder_type_ != rtp_payload_type) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000322 // Moving from one active CNG decoder to another. Delete the first one.
ossu84bc9852016-08-26 05:41:23 -0700323 RTC_DCHECK(active_cng_decoder_);
ossu97ba30e2016-04-25 07:55:58 -0700324 active_cng_decoder_.reset();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000325 }
ossu97ba30e2016-04-25 07:55:58 -0700326 active_cng_decoder_type_ = rtp_payload_type;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000327 return kOK;
328}
329
ossu84bc9852016-08-26 05:41:23 -0700330ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
ossu97ba30e2016-04-25 07:55:58 -0700331 if (active_cng_decoder_type_ < 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000332 // No active CNG decoder.
333 return NULL;
334 }
ossu97ba30e2016-04-25 07:55:58 -0700335 if (!active_cng_decoder_) {
336 active_cng_decoder_.reset(new ComfortNoiseDecoder);
337 }
338 return active_cng_decoder_.get();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000339}
340
ossu84bc9852016-08-26 05:41:23 -0700341AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200342 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700343 return info ? info->GetDecoder() : nullptr;
344}
345
ossuf1b08da2016-09-23 02:19:43 -0700346bool DecoderDatabase::IsType(uint8_t rtp_payload_type, const char* name) const {
347 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
348 return info && info->IsType(name);
349}
350
ossu84bc9852016-08-26 05:41:23 -0700351bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
ossuf1b08da2016-09-23 02:19:43 -0700352 const std::string& name) const {
353 return IsType(rtp_payload_type, name.c_str());
ossu84bc9852016-08-26 05:41:23 -0700354}
355
356bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200357 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700358 return info && info->IsComfortNoise();
359}
360
361bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200362 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700363 return info && info->IsDtmf();
364}
365
366bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200367 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
ossu84bc9852016-08-26 05:41:23 -0700368 return info && info->IsRed();
369}
370
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000371int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
372 PacketList::const_iterator it;
373 for (it = packet_list.begin(); it != packet_list.end(); ++it) {
ossua73f6c92016-10-24 08:25:28 -0700374 if (!GetDecoderInfo(it->payload_type)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000375 // Payload type is not found.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100376 RTC_LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
377 << static_cast<int>(it->payload_type);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000378 return kDecoderNotFound;
379 }
380 }
381 return kOK;
382}
383
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000384} // namespace webrtc