OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/audio_coding/neteq/decoder_database.h" | 11 #include "webrtc/modules/audio_coding/neteq/decoder_database.h" |
12 | 12 |
13 #include <utility> // pair | 13 #include <utility> // pair |
14 | 14 |
15 #include "webrtc/base/checks.h" | 15 #include "webrtc/base/checks.h" |
16 #include "webrtc/base/logging.h" | 16 #include "webrtc/base/logging.h" |
17 #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" | 17 #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" |
18 | 18 |
19 namespace webrtc { | 19 namespace webrtc { |
20 | 20 |
21 DecoderDatabase::DecoderDatabase( | 21 DecoderDatabase::DecoderDatabase( |
22 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) | 22 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) |
23 : active_decoder_type_(-1), | 23 : active_decoder_type_(-1), |
24 active_cng_decoder_type_(-1), | 24 active_cng_decoder_type_(-1), |
25 decoder_factory_(decoder_factory) {} | 25 decoder_factory_(decoder_factory) {} |
26 | 26 |
27 DecoderDatabase::~DecoderDatabase() = default; | 27 DecoderDatabase::~DecoderDatabase() = default; |
28 | 28 |
29 DecoderDatabase::DecoderInfo::DecoderInfo( | 29 DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format, |
30 NetEqDecoder ct, | 30 AudioDecoderFactory* factory) |
31 const std::string& nm, | 31 : audio_format_(audio_format), |
32 AudioDecoderFactory* factory) | |
33 : codec_type(ct), | |
34 name(nm), | |
35 audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)), | |
36 factory_(factory), | 32 factory_(factory), |
37 external_decoder_(nullptr), | 33 external_decoder_(nullptr), |
38 cng_decoder_(CngDecoder::Create(ct)) {} | 34 cng_decoder_(CngDecoder::Create(audio_format)) {} |
39 | 35 |
40 DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct, | 36 DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct, |
41 const std::string& nm, | 37 AudioDecoderFactory* factory) |
| 38 : audio_format_(*acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)), |
| 39 factory_(factory), |
| 40 external_decoder_(nullptr), |
| 41 cng_decoder_(CngDecoder::Create(audio_format_)) {} |
| 42 |
| 43 DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format, |
42 AudioDecoder* ext_dec) | 44 AudioDecoder* ext_dec) |
43 : codec_type(ct), | 45 : audio_format_(audio_format), |
44 name(nm), | 46 factory_(nullptr), |
45 audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)), | |
46 external_decoder_(ext_dec) { | 47 external_decoder_(ext_dec) { |
47 RTC_CHECK(ext_dec); | 48 RTC_CHECK(ext_dec); |
48 } | 49 } |
49 | 50 |
50 DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default; | 51 DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default; |
51 DecoderDatabase::DecoderInfo::~DecoderInfo() = default; | 52 DecoderDatabase::DecoderInfo::~DecoderInfo() = default; |
52 | 53 |
53 AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const { | 54 AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const { |
| 55 if (IsDtmf() || IsRed() || IsComfortNoise()) { |
| 56 // These are handled internally, so they have no AudioDecoder objects. |
| 57 return nullptr; |
| 58 } |
54 if (external_decoder_) { | 59 if (external_decoder_) { |
55 RTC_DCHECK(!decoder_); | 60 RTC_DCHECK(!decoder_); |
56 RTC_DCHECK(!cng_decoder_); | 61 RTC_DCHECK(!cng_decoder_); |
57 return external_decoder_; | 62 return external_decoder_; |
58 } | 63 } |
59 if (IsRed() || IsComfortNoise() || IsDtmf()) | |
60 return nullptr; | |
61 RTC_DCHECK(audio_format_); | |
62 if (!decoder_) { | 64 if (!decoder_) { |
| 65 // TODO(ossu): Keep a check here for now, since a number of tests create |
| 66 // DecoderInfos without factories. |
63 RTC_DCHECK(factory_); | 67 RTC_DCHECK(factory_); |
64 decoder_ = factory_->MakeAudioDecoder(*audio_format_); | 68 decoder_ = factory_->MakeAudioDecoder(audio_format_); |
65 } | 69 } |
66 RTC_DCHECK(decoder_) << "Failed to create: " << *audio_format_; | 70 RTC_DCHECK(decoder_) << "Failed to create: " << audio_format_; |
67 return decoder_.get(); | 71 return decoder_.get(); |
68 } | 72 } |
69 | 73 |
70 | |
71 bool DecoderDatabase::DecoderInfo::IsComfortNoise() const { | 74 bool DecoderDatabase::DecoderInfo::IsComfortNoise() const { |
72 return codec_type == NetEqDecoder::kDecoderCNGnb | 75 RTC_DCHECK_EQ(!!cng_decoder_, IsType("CN")); |
73 || codec_type == NetEqDecoder::kDecoderCNGwb | 76 return !!cng_decoder_; |
74 || codec_type == NetEqDecoder::kDecoderCNGswb32kHz | |
75 || codec_type == NetEqDecoder::kDecoderCNGswb48kHz; | |
76 } | 77 } |
77 | 78 |
78 bool DecoderDatabase::DecoderInfo::IsDtmf() const { | 79 bool DecoderDatabase::DecoderInfo::IsDtmf() const { |
79 return codec_type == NetEqDecoder::kDecoderAVT; | 80 return IsType("telephone-event"); |
80 } | 81 } |
81 | 82 |
82 bool DecoderDatabase::DecoderInfo::IsRed() const { | 83 bool DecoderDatabase::DecoderInfo::IsRed() const { |
83 return codec_type == NetEqDecoder::kDecoderRED; | 84 return IsType("red"); |
| 85 } |
| 86 |
| 87 bool DecoderDatabase::DecoderInfo::IsType(const char* name) const { |
| 88 return STR_CASE_CMP(audio_format_.name.c_str(), name) == 0; |
| 89 } |
| 90 |
| 91 bool DecoderDatabase::DecoderInfo::IsType(const std::string& name) const { |
| 92 return IsType(name.c_str()); |
84 } | 93 } |
85 | 94 |
86 rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder> | 95 rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder> |
87 DecoderDatabase::DecoderInfo::CngDecoder::Create(NetEqDecoder ct) { | 96 DecoderDatabase::DecoderInfo::CngDecoder::Create(const SdpAudioFormat& format) { |
88 const auto cng = [](int sample_rate_hz) { | 97 if (STR_CASE_CMP(format.name.c_str(), "CN") == 0) { |
89 return rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>( | 98 return rtc::Optional<CngDecoder>({format.clockrate_hz}); |
90 {sample_rate_hz}); | 99 } else { |
91 }; | 100 return rtc::Optional<CngDecoder>(); |
92 switch (ct) { | |
93 case NetEqDecoder::kDecoderCNGnb: | |
94 return cng(8000); | |
95 case NetEqDecoder::kDecoderCNGwb: | |
96 return cng(16000); | |
97 case NetEqDecoder::kDecoderCNGswb32kHz: | |
98 return cng(32000); | |
99 case NetEqDecoder::kDecoderCNGswb48kHz: | |
100 return cng(48000); | |
101 default: | |
102 return rtc::Optional<DecoderDatabase::DecoderInfo::CngDecoder>(); | |
103 } | 101 } |
104 } | 102 } |
105 | 103 |
106 bool DecoderDatabase::Empty() const { return decoders_.empty(); } | 104 bool DecoderDatabase::Empty() const { return decoders_.empty(); } |
107 | 105 |
108 int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); } | 106 int DecoderDatabase::Size() const { return static_cast<int>(decoders_.size()); } |
109 | 107 |
110 void DecoderDatabase::Reset() { | 108 void DecoderDatabase::Reset() { |
111 decoders_.clear(); | 109 decoders_.clear(); |
112 active_decoder_type_ = -1; | 110 active_decoder_type_ = -1; |
113 active_cng_decoder_type_ = -1; | 111 active_cng_decoder_type_ = -1; |
114 } | 112 } |
115 | 113 |
116 int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type, | 114 int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type, |
117 NetEqDecoder codec_type, | 115 NetEqDecoder codec_type, |
118 const std::string& name) { | 116 const std::string& name) { |
119 if (rtp_payload_type > 0x7F) { | 117 if (rtp_payload_type > 0x7F) { |
120 return kInvalidRtpPayloadType; | 118 return kInvalidRtpPayloadType; |
121 } | 119 } |
122 if (!CodecSupported(codec_type)) { | 120 // kCodecArbitrary is only supported through InsertExternal. |
| 121 if (codec_type == NetEqDecoder::kDecoderArbitrary || |
| 122 !CodecSupported(codec_type)) { |
123 return kCodecNotSupported; | 123 return kCodecNotSupported; |
124 } | 124 } |
125 DecoderInfo info(codec_type, name, decoder_factory_.get()); | 125 const auto opt_format = |
| 126 acm2::RentACodec::NetEqDecoderToSdpAudioFormat(codec_type); |
| 127 if (!opt_format) { |
| 128 return kCodecNotSupported; |
| 129 } |
| 130 DecoderInfo info(*opt_format, decoder_factory_); |
| 131 info.name = name; |
126 auto ret = | 132 auto ret = |
127 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info))); | 133 decoders_.insert(std::make_pair(rtp_payload_type, std::move(info))); |
128 if (ret.second == false) { | 134 if (ret.second == false) { |
129 // Database already contains a decoder with type |rtp_payload_type|. | 135 // Database already contains a decoder with type |rtp_payload_type|. |
130 return kDecoderExists; | 136 return kDecoderExists; |
131 } | 137 } |
132 return kOK; | 138 return kOK; |
133 } | 139 } |
134 | 140 |
135 int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type, | 141 int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type, |
136 NetEqDecoder codec_type, | 142 NetEqDecoder codec_type, |
137 const std::string& codec_name, | 143 const std::string& codec_name, |
138 AudioDecoder* decoder) { | 144 AudioDecoder* decoder) { |
139 if (rtp_payload_type > 0x7F) { | 145 if (rtp_payload_type > 0x7F) { |
140 return kInvalidRtpPayloadType; | 146 return kInvalidRtpPayloadType; |
141 } | 147 } |
142 if (!CodecSupported(codec_type)) { | |
143 return kCodecNotSupported; | |
144 } | |
145 if (!decoder) { | 148 if (!decoder) { |
146 return kInvalidPointer; | 149 return kInvalidPointer; |
147 } | 150 } |
| 151 |
| 152 const auto opt_db_format = |
| 153 acm2::RentACodec::NetEqDecoderToSdpAudioFormat(codec_type); |
| 154 const SdpAudioFormat format = opt_db_format.value_or({"arbitrary", 0, 0}); |
| 155 |
148 std::pair<DecoderMap::iterator, bool> ret; | 156 std::pair<DecoderMap::iterator, bool> ret; |
149 DecoderInfo info(codec_type, codec_name, decoder); | 157 DecoderInfo info(format, decoder); |
| 158 info.name = codec_name; |
150 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info))); | 159 ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info))); |
151 if (ret.second == false) { | 160 if (ret.second == false) { |
152 // Database already contains a decoder with type |rtp_payload_type|. | 161 // Database already contains a decoder with type |rtp_payload_type|. |
153 return kDecoderExists; | 162 return kDecoderExists; |
154 } | 163 } |
155 return kOK; | 164 return kOK; |
156 } | 165 } |
157 | 166 |
158 int DecoderDatabase::Remove(uint8_t rtp_payload_type) { | 167 int DecoderDatabase::Remove(uint8_t rtp_payload_type) { |
159 if (decoders_.erase(rtp_payload_type) == 0) { | 168 if (decoders_.erase(rtp_payload_type) == 0) { |
(...skipping 15 matching lines...) Expand all Loading... |
175 active_cng_decoder_type_ = -1; // No active CNG decoder. | 184 active_cng_decoder_type_ = -1; // No active CNG decoder. |
176 } | 185 } |
177 | 186 |
178 const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo( | 187 const DecoderDatabase::DecoderInfo* DecoderDatabase::GetDecoderInfo( |
179 uint8_t rtp_payload_type) const { | 188 uint8_t rtp_payload_type) const { |
180 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type); | 189 DecoderMap::const_iterator it = decoders_.find(rtp_payload_type); |
181 if (it == decoders_.end()) { | 190 if (it == decoders_.end()) { |
182 // Decoder not found. | 191 // Decoder not found. |
183 return NULL; | 192 return NULL; |
184 } | 193 } |
185 return &(*it).second; | 194 return &it->second; |
186 } | |
187 | |
188 uint8_t DecoderDatabase::GetRtpPayloadType( | |
189 NetEqDecoder codec_type) const { | |
190 DecoderMap::const_iterator it; | |
191 for (it = decoders_.begin(); it != decoders_.end(); ++it) { | |
192 if ((*it).second.codec_type == codec_type) { | |
193 // Match found. | |
194 return (*it).first; | |
195 } | |
196 } | |
197 // No match. | |
198 return kRtpPayloadTypeError; | |
199 } | 195 } |
200 | 196 |
201 int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type, | 197 int DecoderDatabase::SetActiveDecoder(uint8_t rtp_payload_type, |
202 bool* new_decoder) { | 198 bool* new_decoder) { |
203 // Check that |rtp_payload_type| exists in the database. | 199 // Check that |rtp_payload_type| exists in the database. |
204 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type); | 200 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type); |
205 if (!info) { | 201 if (!info) { |
206 // Decoder not found. | 202 // Decoder not found. |
207 return kDecoderNotFound; | 203 return kDecoderNotFound; |
208 } | 204 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 active_cng_decoder_.reset(new ComfortNoiseDecoder); | 253 active_cng_decoder_.reset(new ComfortNoiseDecoder); |
258 } | 254 } |
259 return active_cng_decoder_.get(); | 255 return active_cng_decoder_.get(); |
260 } | 256 } |
261 | 257 |
262 AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const { | 258 AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) const { |
263 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type); | 259 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type); |
264 return info ? info->GetDecoder() : nullptr; | 260 return info ? info->GetDecoder() : nullptr; |
265 } | 261 } |
266 | 262 |
| 263 bool DecoderDatabase::IsType(uint8_t rtp_payload_type, const char* name) const { |
| 264 const DecoderInfo* info = GetDecoderInfo(rtp_payload_type); |
| 265 return info && info->IsType(name); |
| 266 } |
| 267 |
267 bool DecoderDatabase::IsType(uint8_t rtp_payload_type, | 268 bool DecoderDatabase::IsType(uint8_t rtp_payload_type, |
268 NetEqDecoder codec_type) const { | 269 const std::string& name) const { |
269 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type); | 270 return IsType(rtp_payload_type, name.c_str()); |
270 return info && info->codec_type == codec_type; | |
271 } | 271 } |
272 | 272 |
273 bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const { | 273 bool DecoderDatabase::IsComfortNoise(uint8_t rtp_payload_type) const { |
274 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type); | 274 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type); |
275 return info && info->IsComfortNoise(); | 275 return info && info->IsComfortNoise(); |
276 } | 276 } |
277 | 277 |
278 bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const { | 278 bool DecoderDatabase::IsDtmf(uint8_t rtp_payload_type) const { |
279 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type); | 279 const DecoderInfo *info = GetDecoderInfo(rtp_payload_type); |
280 return info && info->IsDtmf(); | 280 return info && info->IsDtmf(); |
(...skipping 10 matching lines...) Expand all Loading... |
291 if (!GetDecoderInfo((*it)->header.payloadType)) { | 291 if (!GetDecoderInfo((*it)->header.payloadType)) { |
292 // Payload type is not found. | 292 // Payload type is not found. |
293 LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type " | 293 LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type " |
294 << static_cast<int>((*it)->header.payloadType); | 294 << static_cast<int>((*it)->header.payloadType); |
295 return kDecoderNotFound; | 295 return kDecoderNotFound; |
296 } | 296 } |
297 } | 297 } |
298 return kOK; | 298 return kOK; |
299 } | 299 } |
300 | 300 |
301 | |
302 } // namespace webrtc | 301 } // namespace webrtc |
OLD | NEW |