| 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 |