OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 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 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 if (!RentACodec::IsSupportedNumChannels(*maybe_codec_id, send_codec.channels) | 48 if (!RentACodec::IsSupportedNumChannels(*maybe_codec_id, send_codec.channels) |
49 .value_or(false)) { | 49 .value_or(false)) { |
50 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id, | 50 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id, |
51 "%d number of channels not supportedn for %s.", | 51 "%d number of channels not supportedn for %s.", |
52 send_codec.channels, send_codec.plname); | 52 send_codec.channels, send_codec.plname); |
53 return -1; | 53 return -1; |
54 } | 54 } |
55 return RentACodec::CodecIndexFromId(*maybe_codec_id).value_or(-1); | 55 return RentACodec::CodecIndexFromId(*maybe_codec_id).value_or(-1); |
56 } | 56 } |
57 | 57 |
58 bool IsIsac(const CodecInst& codec) { | |
59 return | |
60 #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) | |
61 !STR_CASE_CMP(codec.plname, "isac") || | |
62 #endif | |
63 false; | |
64 } | |
65 | |
66 bool IsOpus(const CodecInst& codec) { | 58 bool IsOpus(const CodecInst& codec) { |
67 return | 59 return |
68 #ifdef WEBRTC_CODEC_OPUS | 60 #ifdef WEBRTC_CODEC_OPUS |
69 !STR_CASE_CMP(codec.plname, "opus") || | 61 !STR_CASE_CMP(codec.plname, "opus") || |
70 #endif | 62 #endif |
71 false; | 63 false; |
72 } | 64 } |
73 | 65 |
74 bool IsPcmU(const CodecInst& codec) { | |
75 return !STR_CASE_CMP(codec.plname, "pcmu"); | |
76 } | |
77 | |
78 bool IsPcmA(const CodecInst& codec) { | |
79 return !STR_CASE_CMP(codec.plname, "pcma"); | |
80 } | |
81 | |
82 bool IsPcm16B(const CodecInst& codec) { | |
83 return !STR_CASE_CMP(codec.plname, "l16"); | |
84 } | |
85 | |
86 bool IsIlbc(const CodecInst& codec) { | |
87 return | |
88 #ifdef WEBRTC_CODEC_ILBC | |
89 !STR_CASE_CMP(codec.plname, "ilbc") || | |
90 #endif | |
91 false; | |
92 } | |
93 | |
94 bool IsG722(const CodecInst& codec) { | |
95 return | |
96 #ifdef WEBRTC_CODEC_G722 | |
97 !STR_CASE_CMP(codec.plname, "g722") || | |
98 #endif | |
99 false; | |
100 } | |
101 | |
102 bool CodecSupported(const CodecInst& codec) { | |
103 return IsOpus(codec) || IsPcmU(codec) || IsPcmA(codec) || IsPcm16B(codec) || | |
104 IsIlbc(codec) || IsG722(codec) || IsIsac(codec); | |
105 } | |
106 | |
107 const CodecInst kEmptyCodecInst = {-1, "noCodecRegistered", 0, 0, 0, 0}; | |
108 } // namespace | 66 } // namespace |
109 | 67 |
110 CodecManager::CodecManager() | 68 CodecManager::CodecManager() { |
111 : send_codec_inst_(kEmptyCodecInst), encoder_is_opus_(false) { | |
112 thread_checker_.DetachFromThread(); | 69 thread_checker_.DetachFromThread(); |
113 } | 70 } |
114 | 71 |
115 CodecManager::~CodecManager() = default; | 72 CodecManager::~CodecManager() = default; |
116 | 73 |
117 int CodecManager::RegisterEncoder(const CodecInst& send_codec) { | 74 bool CodecManager::RegisterEncoder(const CodecInst& send_codec) { |
118 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 75 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
119 int codec_id = IsValidSendCodec(send_codec); | 76 int codec_id = IsValidSendCodec(send_codec); |
120 | 77 |
121 // Check for reported errors from function IsValidSendCodec(). | 78 // Check for reported errors from function IsValidSendCodec(). |
122 if (codec_id < 0) { | 79 if (codec_id < 0) { |
123 return -1; | 80 return false; |
124 } | 81 } |
125 | 82 |
126 int dummy_id = 0; | 83 int dummy_id = 0; |
127 switch (RentACodec::RegisterRedPayloadType( | 84 switch (RentACodec::RegisterRedPayloadType( |
128 &codec_stack_params_.red_payload_types, send_codec)) { | 85 &codec_stack_params_.red_payload_types, send_codec)) { |
129 case RentACodec::RegistrationResult::kOk: | 86 case RentACodec::RegistrationResult::kOk: |
130 return 0; | 87 return true; |
131 case RentACodec::RegistrationResult::kBadFreq: | 88 case RentACodec::RegistrationResult::kBadFreq: |
132 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id, | 89 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id, |
133 "RegisterSendCodec() failed, invalid frequency for RED" | 90 "RegisterSendCodec() failed, invalid frequency for RED" |
134 " registration"); | 91 " registration"); |
135 return -1; | 92 return false; |
136 case RentACodec::RegistrationResult::kSkip: | 93 case RentACodec::RegistrationResult::kSkip: |
137 break; | 94 break; |
138 } | 95 } |
139 switch (RentACodec::RegisterCngPayloadType( | 96 switch (RentACodec::RegisterCngPayloadType( |
140 &codec_stack_params_.cng_payload_types, send_codec)) { | 97 &codec_stack_params_.cng_payload_types, send_codec)) { |
141 case RentACodec::RegistrationResult::kOk: | 98 case RentACodec::RegistrationResult::kOk: |
142 return 0; | 99 return true; |
143 case RentACodec::RegistrationResult::kBadFreq: | 100 case RentACodec::RegistrationResult::kBadFreq: |
144 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id, | 101 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id, |
145 "RegisterSendCodec() failed, invalid frequency for CNG" | 102 "RegisterSendCodec() failed, invalid frequency for CNG" |
146 " registration"); | 103 " registration"); |
147 return -1; | 104 return false; |
148 case RentACodec::RegistrationResult::kSkip: | 105 case RentACodec::RegistrationResult::kSkip: |
149 break; | 106 break; |
150 } | 107 } |
151 | 108 |
152 encoder_is_opus_ = IsOpus(send_codec); | 109 if (IsOpus(send_codec)) { |
153 if (encoder_is_opus_) { | |
154 // VAD/DTX not supported. | 110 // VAD/DTX not supported. |
155 codec_stack_params_.use_cng = false; | 111 codec_stack_params_.use_cng = false; |
156 } | 112 } |
157 | 113 |
158 // Recreate the encoder if anything except the send bitrate has changed. | 114 send_codec_inst_ = rtc::Optional<CodecInst>(send_codec); |
159 if (!CurrentEncoder() || send_codec_inst_.pltype != send_codec.pltype || | 115 codec_stack_params_.speech_encoder = nullptr; // Caller must recreate it. |
160 STR_CASE_CMP(send_codec_inst_.plname, send_codec.plname) != 0 || | 116 return true; |
161 send_codec_inst_.plfreq != send_codec.plfreq || | |
162 send_codec_inst_.pacsize != send_codec.pacsize || | |
163 send_codec_inst_.channels != send_codec.channels) { | |
164 RTC_DCHECK(CodecSupported(send_codec)); | |
165 AudioEncoder* enc = rent_a_codec_.RentEncoder(send_codec); | |
166 if (!enc) | |
167 return -1; | |
168 codec_stack_params_.speech_encoder = enc; | |
169 rent_a_codec_.RentEncoderStack(&codec_stack_params_); | |
170 RTC_DCHECK(CurrentEncoder()); | |
171 } | |
172 | |
173 send_codec_inst_ = send_codec; | |
174 CurrentEncoder()->SetTargetBitrate(send_codec_inst_.rate); | |
175 return 0; | |
176 } | 117 } |
177 | 118 |
178 void CodecManager::RegisterEncoder(AudioEncoder* external_speech_encoder) { | 119 CodecInst CodecManager::ForgeCodecInst( |
179 // Make up a CodecInst. | 120 const AudioEncoder* external_speech_encoder) { |
180 send_codec_inst_.channels = external_speech_encoder->NumChannels(); | 121 CodecInst ci; |
181 send_codec_inst_.plfreq = external_speech_encoder->SampleRateHz(); | 122 ci.channels = external_speech_encoder->NumChannels(); |
182 send_codec_inst_.pacsize = rtc::CheckedDivExact( | 123 ci.plfreq = external_speech_encoder->SampleRateHz(); |
| 124 ci.pacsize = rtc::CheckedDivExact( |
183 static_cast<int>(external_speech_encoder->Max10MsFramesInAPacket() * | 125 static_cast<int>(external_speech_encoder->Max10MsFramesInAPacket() * |
184 send_codec_inst_.plfreq), | 126 ci.plfreq), |
185 100); | 127 100); |
186 send_codec_inst_.pltype = -1; // Not valid. | 128 ci.pltype = -1; // Not valid. |
187 send_codec_inst_.rate = -1; // Not valid. | 129 ci.rate = -1; // Not valid. |
188 static const char kName[] = "external"; | 130 static const char kName[] = "external"; |
189 memcpy(send_codec_inst_.plname, kName, sizeof(kName)); | 131 memcpy(ci.plname, kName, sizeof(kName)); |
190 | 132 return ci; |
191 codec_stack_params_.speech_encoder = external_speech_encoder; | |
192 rent_a_codec_.RentEncoderStack(&codec_stack_params_); | |
193 } | |
194 | |
195 rtc::Optional<CodecInst> CodecManager::GetCodecInst() const { | |
196 int dummy_id = 0; | |
197 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, dummy_id, | |
198 "SendCodec()"); | |
199 | |
200 if (!CurrentEncoder()) { | |
201 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, dummy_id, | |
202 "SendCodec Failed, no codec is registered"); | |
203 return rtc::Optional<CodecInst>(); | |
204 } | |
205 return rtc::Optional<CodecInst>(send_codec_inst_); | |
206 } | 133 } |
207 | 134 |
208 bool CodecManager::SetCopyRed(bool enable) { | 135 bool CodecManager::SetCopyRed(bool enable) { |
209 if (enable && codec_stack_params_.use_codec_fec) { | 136 if (enable && codec_stack_params_.use_codec_fec) { |
210 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0, | 137 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0, |
211 "Codec internal FEC and RED cannot be co-enabled."); | 138 "Codec internal FEC and RED cannot be co-enabled."); |
212 return false; | 139 return false; |
213 } | 140 } |
214 if (enable && | 141 if (enable && send_codec_inst_ && |
215 codec_stack_params_.red_payload_types.count(send_codec_inst_.plfreq) < | 142 codec_stack_params_.red_payload_types.count(send_codec_inst_->plfreq) < |
216 1) { | 143 1) { |
217 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0, | 144 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0, |
218 "Cannot enable RED at %i Hz.", send_codec_inst_.plfreq); | 145 "Cannot enable RED at %i Hz.", send_codec_inst_->plfreq); |
219 return false; | 146 return false; |
220 } | 147 } |
221 if (codec_stack_params_.use_red != enable) { | 148 codec_stack_params_.use_red = enable; |
222 codec_stack_params_.use_red = enable; | |
223 if (CurrentEncoder()) | |
224 rent_a_codec_.RentEncoderStack(&codec_stack_params_); | |
225 } | |
226 return true; | 149 return true; |
227 } | 150 } |
228 | 151 |
229 int CodecManager::SetVAD(bool enable, ACMVADMode mode) { | 152 bool CodecManager::SetVAD(bool enable, ACMVADMode mode) { |
230 // Sanity check of the mode. | 153 // Sanity check of the mode. |
231 RTC_DCHECK(mode == VADNormal || mode == VADLowBitrate || mode == VADAggr || | 154 RTC_DCHECK(mode == VADNormal || mode == VADLowBitrate || mode == VADAggr || |
232 mode == VADVeryAggr); | 155 mode == VADVeryAggr); |
233 | 156 |
234 // Check that the send codec is mono. We don't support VAD/DTX for stereo | 157 // Check that the send codec is mono. We don't support VAD/DTX for stereo |
235 // sending. | 158 // sending. |
236 const bool stereo_send = | 159 const bool stereo_send = |
237 codec_stack_params_.speech_encoder | 160 codec_stack_params_.speech_encoder |
238 ? (codec_stack_params_.speech_encoder->NumChannels() != 1) | 161 ? (codec_stack_params_.speech_encoder->NumChannels() != 1) |
239 : false; | 162 : false; |
240 if (enable && stereo_send) { | 163 if (enable && stereo_send) { |
241 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0, | 164 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0, |
242 "VAD/DTX not supported for stereo sending"); | 165 "VAD/DTX not supported for stereo sending"); |
243 codec_stack_params_.use_cng = false; | 166 return false; |
244 return -1; | |
245 } | 167 } |
246 | 168 |
247 // If a send codec is registered, set VAD/DTX for the codec. | 169 if (CurrentEncoderIsOpus()) { |
248 if (IsOpus(send_codec_inst_)) { | 170 // VAD/DTX not supported, but don't fail. |
249 // VAD/DTX not supported. | 171 enable = false; |
250 codec_stack_params_.use_cng = false; | |
251 return 0; | |
252 } | 172 } |
253 | 173 |
254 if (codec_stack_params_.use_cng != enable || | 174 codec_stack_params_.use_cng = enable; |
255 codec_stack_params_.vad_mode != mode) { | 175 codec_stack_params_.vad_mode = mode; |
256 codec_stack_params_.use_cng = enable; | 176 return true; |
257 codec_stack_params_.vad_mode = mode; | |
258 if (codec_stack_params_.speech_encoder) | |
259 rent_a_codec_.RentEncoderStack(&codec_stack_params_); | |
260 } | |
261 return 0; | |
262 } | 177 } |
263 | 178 |
264 void CodecManager::VAD(bool* dtx_enabled, | 179 bool CodecManager::SetCodecFEC(bool enable_codec_fec) { |
265 bool* vad_enabled, | |
266 ACMVADMode* mode) const { | |
267 *dtx_enabled = *vad_enabled = codec_stack_params_.use_cng; | |
268 *mode = codec_stack_params_.vad_mode; | |
269 } | |
270 | |
271 int CodecManager::SetCodecFEC(bool enable_codec_fec) { | |
272 if (enable_codec_fec && codec_stack_params_.use_red) { | 180 if (enable_codec_fec && codec_stack_params_.use_red) { |
273 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0, | 181 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0, |
274 "Codec internal FEC and RED cannot be co-enabled."); | 182 "Codec internal FEC and RED cannot be co-enabled."); |
275 return -1; | 183 return false; |
276 } | 184 } |
277 | 185 |
278 RTC_CHECK(CurrentEncoder()); | 186 codec_stack_params_.use_codec_fec = enable_codec_fec; |
279 codec_stack_params_.use_codec_fec = | 187 return true; |
280 CurrentEncoder()->SetFec(enable_codec_fec) && enable_codec_fec; | |
281 return codec_stack_params_.use_codec_fec == enable_codec_fec ? 0 : -1; | |
282 } | 188 } |
283 | 189 |
284 AudioDecoder* CodecManager::GetAudioDecoder(const CodecInst& codec) { | 190 bool CodecManager::CurrentEncoderIsOpus() const { |
285 return IsIsac(codec) ? rent_a_codec_.RentIsacDecoder() : nullptr; | 191 return send_codec_inst_ ? IsOpus(*send_codec_inst_) : false; |
286 } | 192 } |
287 | 193 |
288 } // namespace acm2 | 194 } // namespace acm2 |
289 } // namespace webrtc | 195 } // namespace webrtc |
OLD | NEW |