Line data Source code
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 "webrtc/modules/audio_coding/neteq/decoder_database.h"
12 :
13 : #include <utility> // pair
14 :
15 : #include "webrtc/base/checks.h"
16 : #include "webrtc/base/logging.h"
17 : #include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
18 :
19 : namespace webrtc {
20 :
21 0 : DecoderDatabase::DecoderDatabase(
22 0 : const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory)
23 : : active_decoder_type_(-1),
24 : active_cng_decoder_type_(-1),
25 0 : decoder_factory_(decoder_factory) {}
26 :
27 : DecoderDatabase::~DecoderDatabase() = default;
28 :
29 0 : DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
30 : AudioDecoderFactory* factory,
31 0 : const std::string& codec_name)
32 : : name_(codec_name),
33 : audio_format_(audio_format),
34 : factory_(factory),
35 : external_decoder_(nullptr),
36 : cng_decoder_(CngDecoder::Create(audio_format)),
37 0 : subtype_(SubtypeFromFormat(audio_format)) {}
38 :
39 0 : DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
40 0 : AudioDecoderFactory* factory)
41 0 : : DecoderInfo(audio_format, factory, audio_format.name) {}
42 :
43 0 : DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct,
44 0 : AudioDecoderFactory* factory)
45 0 : : DecoderInfo(*acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct),
46 0 : factory) {}
47 :
48 0 : DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
49 : AudioDecoder* ext_dec,
50 0 : const std::string& codec_name)
51 : : name_(codec_name),
52 : audio_format_(audio_format),
53 : factory_(nullptr),
54 : external_decoder_(ext_dec),
55 0 : subtype_(Subtype::kNormal) {
56 0 : RTC_CHECK(ext_dec);
57 0 : }
58 :
59 : DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
60 : DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
61 :
62 0 : AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
63 0 : if (subtype_ != Subtype::kNormal) {
64 : // These are handled internally, so they have no AudioDecoder objects.
65 0 : return nullptr;
66 : }
67 0 : if (external_decoder_) {
68 0 : RTC_DCHECK(!decoder_);
69 0 : RTC_DCHECK(!cng_decoder_);
70 0 : return external_decoder_;
71 : }
72 0 : if (!decoder_) {
73 : // TODO(ossu): Keep a check here for now, since a number of tests create
74 : // DecoderInfos without factories.
75 0 : RTC_DCHECK(factory_);
76 0 : decoder_ = factory_->MakeAudioDecoder(audio_format_);
77 : }
78 0 : RTC_DCHECK(decoder_) << "Failed to create: " << audio_format_;
79 0 : return decoder_.get();
80 : }
81 :
82 0 : bool DecoderDatabase::DecoderInfo::IsType(const char* name) const {
83 0 : return STR_CASE_CMP(audio_format_.name.c_str(), name) == 0;
84 : }
85 :
86 0 : bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const {
87 0 : return IsType(name.c_str());
88 : }
89 :
90 : rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>
91 0 : DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) {
92 0 : if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
93 : // CN has a 1:1 RTP clock rate to sample rate ratio.
94 0 : const int sample_rate_hz = format.clockrate_hz;
95 0 : RTC_DCHECK(sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
96 0 : sample_rate_hz == 32000 || sample_rate_hz == 48000);
97 : return rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>(
98 0 : {sample_rate_hz});
99 : } else {
100 0 : return rtc::Optional<CngDecoder>();
101 : }
102 : }
103 :
104 : DecoderDatabase::DecoderInfo::Subtype
105 0 : DecoderDatabase::DecoderInfo::SubtypeFromFormat(const SdpAudioFormat& format) {
106 0 : if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) {
107 0 : return Subtype::kComfortNoise;
108 0 : } else if (STR_CASE_CMP(format.name.c_str(), "telephone-event") == 0) {
109 0 : return Subtype::kDtmf;
110 0 : } else if (STR_CASE_CMP(format.name.c_str(), "red") == 0) {
111 0 : return Subtype::kRed;
112 : }
113 :
114 0 : return Subtype::kNormal;
115 : }
116 :
117 0 : bool DecoderDatabase::Empty() const { return decoders_.empty(); }
118 :
119 0 : int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); }
120 :
121 0 : void DecoderDatabase::Reset() {
122 0 : decoders_.clear();
123 0 : active_decoder_type_ = -1;
124 0 : active_cng_decoder_type_ = -1;
125 0 : }
126 :
127 0 : int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
128 : NetEqDecoder codec_type,
129 : const std::string& name) {
130 0 : if (rtp_payload_type > 0x7F) {
131 0 : return kInvalidRtpPayloadType;
132 : }
133 : // kCodecArbitrary is only supported through InsertExternal.
134 0 : if (codec_type == NetEqDecoder::kDecoderArbitrary ||
135 0 : !CodecSupported(codec_type)) {
136 0 : return kCodecNotSupported;
137 : }
138 : const auto opt_format =
139 0 : acm2::RentACodec::NetEqDecoderToSdpAudioFormat(codec_type);
140 0 : if (!opt_format) {
141 0 : return kCodecNotSupported;
142 : }
143 0 : DecoderInfo info(*opt_format, decoder_factory_, name);
144 : auto ret =
145 0 : decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
146 0 : if (ret.second == false) {
147 : // Database already contains a decoder with type |rtp_payload_type|.
148 0 : return kDecoderExists;
149 : }
150 0 : return kOK;
151 : }
152 :
153 0 : int DecoderDatabase::RegisterPayload(int rtp_payload_type,
154 : const SdpAudioFormat& audio_format) {
155 0 : if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) {
156 0 : return kInvalidRtpPayloadType;
157 : }
158 0 : const auto ret = decoders_.insert(std::make_pair(
159 0 : rtp_payload_type, DecoderInfo(audio_format, decoder_factory_.get())));
160 0 : if (ret.second == false) {
161 : // Database already contains a decoder with type |rtp_payload_type|.
162 0 : return kDecoderExists;
163 : }
164 0 : return kOK;
165 : }
166 :
167 0 : int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
168 : NetEqDecoder codec_type,
169 : const std::string& codec_name,
170 : AudioDecoder* decoder) {
171 0 : if (rtp_payload_type > 0x7F) {
172 0 : return kInvalidRtpPayloadType;
173 : }
174 0 : if (!decoder) {
175 0 : return kInvalidPointer;
176 : }
177 :
178 : const auto opt_db_format =
179 0 : acm2::RentACodec::NetEqDecoderToSdpAudioFormat(codec_type);
180 0 : const SdpAudioFormat format = opt_db_format.value_or({"arbitrary", 0, 0});
181 :
182 0 : std::pair<DecoderMap::iterator, bool> ret;
183 0 : DecoderInfo info(format, decoder, codec_name);
184 0 : ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
185 0 : if (ret.second == false) {
186 : // Database already contains a decoder with type |rtp_payload_type|.
187 0 : return kDecoderExists;
188 : }
189 0 : return kOK;
190 : }
191 :
192 0 : int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
193 0 : if (decoders_.erase(rtp_payload_type) == 0) {
194 : // No decoder with that |rtp_payload_type|.
195 0 : return kDecoderNotFound;
196 : }
197 0 : if (active_decoder_type_ == rtp_payload_type) {
198 0 : active_decoder_type_ = -1; // No active decoder.
199 : }
200 0 : if (active_cng_decoder_type_ == rtp_payload_type) {
201 0 : active_cng_decoder_type_ = -1; // No active CNG decoder.
202 : }
203 0 : return kOK;
204 : }
205 :
206 0 : void DecoderDatabase::RemoveAll() {
207 0 : decoders_.clear();
208 0 : active_decoder_type_ = -1; // No active decoder.
209 0 : active_cng_decoder_type_ = -1; // No active CNG decoder.
210 0 : }
211 :
212 0 : const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo(
213 : uint8_t rtp_payload_type) const {
214 0 : DecoderMap::const_iterator it = decoders_.find(rtp_payload_type);
215 0 : if (it == decoders_.end()) {
216 : // Decoder not found.
217 0 : return NULL;
218 : }
219 0 : return &it->second;
220 : }
221 :
222 0 : int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type,
223 : bool* new_decoder) {
224 : // Check that |rtp_payload_type| exists in the database.
225 0 : const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
226 0 : if (!info) {
227 : // Decoder not found.
228 0 : return kDecoderNotFound;
229 : }
230 0 : RTC_CHECK(!info->IsComfortNoise());
231 0 : RTC_DCHECK(new_decoder);
232 0 : *new_decoder = false;
233 0 : if (active_decoder_type_ < 0) {
234 : // This is the first active decoder.
235 0 : *new_decoder = true;
236 0 : } else if (active_decoder_type_ != rtp_payload_type) {
237 : // Moving from one active decoder to another. Delete the first one.
238 0 : const DecoderInfo *old_info = GetDecoderInfo(active_decoder_type_);
239 0 : RTC_DCHECK(old_info);
240 0 : old_info->DropDecoder();
241 0 : *new_decoder = true;
242 : }
243 0 : active_decoder_type_ = rtp_payload_type;
244 0 : return kOK;
245 : }
246 :
247 0 : AudioDecoder* DecoderDatabase::GetActiveDecoder() const {
248 0 : if (active_decoder_type_ < 0) {
249 : // No active decoder.
250 0 : return NULL;
251 : }
252 0 : return GetDecoder(active_decoder_type_);
253 : }
254 :
255 0 : int DecoderDatabase::SetActiveCngDecoder(uint8_t rtp_payload_type) {
256 : // Check that |rtp_payload_type| exists in the database.
257 0 : const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
258 0 : if (!info) {
259 : // Decoder not found.
260 0 : return kDecoderNotFound;
261 : }
262 0 : if (active_cng_decoder_type_ >= 0 &&
263 0 : active_cng_decoder_type_ != rtp_payload_type) {
264 : // Moving from one active CNG decoder to another. Delete the first one.
265 0 : RTC_DCHECK(active_cng_decoder_);
266 0 : active_cng_decoder_.reset();
267 : }
268 0 : active_cng_decoder_type_ = rtp_payload_type;
269 0 : return kOK;
270 : }
271 :
272 0 : ComfortNoiseDecoder* DecoderDatabase::GetActiveCngDecoder() const {
273 0 : if (active_cng_decoder_type_ < 0) {
274 : // No active CNG decoder.
275 0 : return NULL;
276 : }
277 0 : if (!active_cng_decoder_) {
278 0 : active_cng_decoder_.reset(new ComfortNoiseDecoder);
279 : }
280 0 : return active_cng_decoder_.get();
281 : }
282 :
283 0 : AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const {
284 0 : const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
285 0 : return info ? info->GetDecoder() : nullptr;
286 : }
287 :
288 0 : bool DecoderDatabase::IsType(uint8_t rtp_payload_type, const char* name) const {
289 0 : const DecoderInfo* info = GetDecoderInfo(rtp_payload_type);
290 0 : return info && info->IsType(name);
291 : }
292 :
293 0 : bool DecoderDatabase::IsType(uint8_t rtp_payload_type,
294 : const std::string& name) const {
295 0 : return IsType(rtp_payload_type, name.c_str());
296 : }
297 :
298 0 : bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const {
299 0 : const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
300 0 : return info && info->IsComfortNoise();
301 : }
302 :
303 0 : bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const {
304 0 : const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
305 0 : return info && info->IsDtmf();
306 : }
307 :
308 0 : bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
309 0 : const DecoderInfo *info = GetDecoderInfo(rtp_payload_type);
310 0 : return info && info->IsRed();
311 : }
312 :
313 0 : int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
314 0 : PacketList::const_iterator it;
315 0 : for (it = packet_list.begin(); it != packet_list.end(); ++it) {
316 0 : if (!GetDecoderInfo(it->payload_type)) {
317 : // Payload type is not found.
318 0 : LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
319 0 : << static_cast<int>(it->payload_type);
320 0 : return kDecoderNotFound;
321 : }
322 : }
323 0 : return kOK;
324 : }
325 :
326 : } // namespace webrtc
|