| OLD | NEW |
| 1 /* | 1 /* |
| 2 * libjingle | 2 * libjingle |
| 3 * Copyright 2004 Google Inc. | 3 * Copyright 2004 Google Inc. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
| 9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 #include "webrtc/base/arraysize.h" | 46 #include "webrtc/base/arraysize.h" |
| 47 #include "webrtc/base/base64.h" | 47 #include "webrtc/base/base64.h" |
| 48 #include "webrtc/base/byteorder.h" | 48 #include "webrtc/base/byteorder.h" |
| 49 #include "webrtc/base/common.h" | 49 #include "webrtc/base/common.h" |
| 50 #include "webrtc/base/helpers.h" | 50 #include "webrtc/base/helpers.h" |
| 51 #include "webrtc/base/logging.h" | 51 #include "webrtc/base/logging.h" |
| 52 #include "webrtc/base/stringencode.h" | 52 #include "webrtc/base/stringencode.h" |
| 53 #include "webrtc/base/stringutils.h" | 53 #include "webrtc/base/stringutils.h" |
| 54 #include "webrtc/call/rtc_event_log.h" | 54 #include "webrtc/call/rtc_event_log.h" |
| 55 #include "webrtc/common.h" | 55 #include "webrtc/common.h" |
| 56 #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" |
| 56 #include "webrtc/modules/audio_processing/include/audio_processing.h" | 57 #include "webrtc/modules/audio_processing/include/audio_processing.h" |
| 57 #include "webrtc/system_wrappers/include/field_trial.h" | 58 #include "webrtc/system_wrappers/include/field_trial.h" |
| 58 #include "webrtc/system_wrappers/include/trace.h" | 59 #include "webrtc/system_wrappers/include/trace.h" |
| 59 | 60 |
| 60 namespace cricket { | 61 namespace cricket { |
| 61 namespace { | 62 namespace { |
| 62 | 63 |
| 63 const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo | | 64 const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo | |
| 64 webrtc::kTraceWarning | webrtc::kTraceError | | 65 webrtc::kTraceWarning | webrtc::kTraceError | |
| 65 webrtc::kTraceCritical; | 66 webrtc::kTraceCritical; |
| 66 const int kElevatedTraceFilter = kDefaultTraceFilter | webrtc::kTraceStateInfo | | 67 const int kElevatedTraceFilter = kDefaultTraceFilter | webrtc::kTraceStateInfo | |
| 67 webrtc::kTraceInfo; | 68 webrtc::kTraceInfo; |
| 68 | 69 |
| 69 const int kMaxNumPacketSize = 6; | |
| 70 struct CodecPref { | |
| 71 const char* name; | |
| 72 int clockrate; | |
| 73 int channels; | |
| 74 int payload_type; | |
| 75 bool is_multi_rate; | |
| 76 int packet_sizes_ms[kMaxNumPacketSize]; | |
| 77 }; | |
| 78 // Note: keep the supported packet sizes in ascending order. | |
| 79 const CodecPref kCodecPrefs[] = { | |
| 80 { kOpusCodecName, 48000, 2, 111, true, { 10, 20, 40, 60 } }, | |
| 81 { kIsacCodecName, 16000, 1, 103, true, { 30, 60 } }, | |
| 82 { kIsacCodecName, 32000, 1, 104, true, { 30 } }, | |
| 83 // G722 should be advertised as 8000 Hz because of the RFC "bug". | |
| 84 { kG722CodecName, 8000, 1, 9, false, { 10, 20, 30, 40, 50, 60 } }, | |
| 85 { kIlbcCodecName, 8000, 1, 102, false, { 20, 30, 40, 60 } }, | |
| 86 { kPcmuCodecName, 8000, 1, 0, false, { 10, 20, 30, 40, 50, 60 } }, | |
| 87 { kPcmaCodecName, 8000, 1, 8, false, { 10, 20, 30, 40, 50, 60 } }, | |
| 88 { kCnCodecName, 32000, 1, 106, false, { } }, | |
| 89 { kCnCodecName, 16000, 1, 105, false, { } }, | |
| 90 { kCnCodecName, 8000, 1, 13, false, { } }, | |
| 91 { kRedCodecName, 8000, 1, 127, false, { } }, | |
| 92 { kDtmfCodecName, 8000, 1, 126, false, { } }, | |
| 93 }; | |
| 94 | |
| 95 // For Linux/Mac, using the default device is done by specifying index 0 for | 70 // For Linux/Mac, using the default device is done by specifying index 0 for |
| 96 // VoE 4.0 and not -1 (which was the case for VoE 3.5). | 71 // VoE 4.0 and not -1 (which was the case for VoE 3.5). |
| 97 // | 72 // |
| 98 // On Windows Vista and newer, Microsoft introduced the concept of "Default | 73 // On Windows Vista and newer, Microsoft introduced the concept of "Default |
| 99 // Communications Device". This means that there are two types of default | 74 // Communications Device". This means that there are two types of default |
| 100 // devices (old Wave Audio style default and Default Communications Device). | 75 // devices (old Wave Audio style default and Default Communications Device). |
| 101 // | 76 // |
| 102 // On Windows systems which only support Wave Audio style default, uses either | 77 // On Windows systems which only support Wave Audio style default, uses either |
| 103 // -1 or 0 to select the default device. | 78 // -1 or 0 to select the default device. |
| 104 // | 79 // |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 return ss.str(); | 153 return ss.str(); |
| 179 } | 154 } |
| 180 | 155 |
| 181 std::string ToString(const webrtc::CodecInst& codec) { | 156 std::string ToString(const webrtc::CodecInst& codec) { |
| 182 std::stringstream ss; | 157 std::stringstream ss; |
| 183 ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels | 158 ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels |
| 184 << " (" << codec.pltype << ")"; | 159 << " (" << codec.pltype << ")"; |
| 185 return ss.str(); | 160 return ss.str(); |
| 186 } | 161 } |
| 187 | 162 |
| 188 void LogMultiline(rtc::LoggingSeverity sev, char* text) { | |
| 189 const char* delim = "\r\n"; | |
| 190 for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) { | |
| 191 LOG_V(sev) << tok; | |
| 192 } | |
| 193 } | |
| 194 | |
| 195 bool IsCodec(const AudioCodec& codec, const char* ref_name) { | 163 bool IsCodec(const AudioCodec& codec, const char* ref_name) { |
| 196 return (_stricmp(codec.name.c_str(), ref_name) == 0); | 164 return (_stricmp(codec.name.c_str(), ref_name) == 0); |
| 197 } | 165 } |
| 198 | 166 |
| 199 bool IsCodec(const webrtc::CodecInst& codec, const char* ref_name) { | 167 bool IsCodec(const webrtc::CodecInst& codec, const char* ref_name) { |
| 200 return (_stricmp(codec.plname, ref_name) == 0); | 168 return (_stricmp(codec.plname, ref_name) == 0); |
| 201 } | 169 } |
| 202 | 170 |
| 203 bool IsCodecMultiRate(const webrtc::CodecInst& codec) { | |
| 204 for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) { | |
| 205 if (IsCodec(codec, kCodecPrefs[i].name) && | |
| 206 kCodecPrefs[i].clockrate == codec.plfreq) { | |
| 207 return kCodecPrefs[i].is_multi_rate; | |
| 208 } | |
| 209 } | |
| 210 return false; | |
| 211 } | |
| 212 | |
| 213 bool FindCodec(const std::vector<AudioCodec>& codecs, | 171 bool FindCodec(const std::vector<AudioCodec>& codecs, |
| 214 const AudioCodec& codec, | 172 const AudioCodec& codec, |
| 215 AudioCodec* found_codec) { | 173 AudioCodec* found_codec) { |
| 216 for (const AudioCodec& c : codecs) { | 174 for (const AudioCodec& c : codecs) { |
| 217 if (c.Matches(codec)) { | 175 if (c.Matches(codec)) { |
| 218 if (found_codec != NULL) { | 176 if (found_codec != NULL) { |
| 219 *found_codec = c; | 177 *found_codec = c; |
| 220 } | 178 } |
| 221 return true; | 179 return true; |
| 222 } | 180 } |
| 223 } | 181 } |
| 224 return false; | 182 return false; |
| 225 } | 183 } |
| 226 | 184 |
| 227 bool VerifyUniquePayloadTypes(const std::vector<AudioCodec>& codecs) { | 185 bool VerifyUniquePayloadTypes(const std::vector<AudioCodec>& codecs) { |
| 228 if (codecs.empty()) { | 186 if (codecs.empty()) { |
| 229 return true; | 187 return true; |
| 230 } | 188 } |
| 231 std::vector<int> payload_types; | 189 std::vector<int> payload_types; |
| 232 for (const AudioCodec& codec : codecs) { | 190 for (const AudioCodec& codec : codecs) { |
| 233 payload_types.push_back(codec.id); | 191 payload_types.push_back(codec.id); |
| 234 } | 192 } |
| 235 std::sort(payload_types.begin(), payload_types.end()); | 193 std::sort(payload_types.begin(), payload_types.end()); |
| 236 auto it = std::unique(payload_types.begin(), payload_types.end()); | 194 auto it = std::unique(payload_types.begin(), payload_types.end()); |
| 237 return it == payload_types.end(); | 195 return it == payload_types.end(); |
| 238 } | 196 } |
| 239 | 197 |
| 240 bool IsNackEnabled(const AudioCodec& codec) { | 198 bool IsNackEnabled(const AudioCodec& codec) { |
| 241 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack, | 199 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack, |
| 242 kParamValueEmpty)); | 200 kParamValueEmpty)); |
| 243 } | 201 } |
| 244 | 202 |
| 245 int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) { | |
| 246 int selected_packet_size_ms = codec_pref.packet_sizes_ms[0]; | |
| 247 for (int packet_size_ms : codec_pref.packet_sizes_ms) { | |
| 248 if (packet_size_ms && packet_size_ms <= ptime_ms) { | |
| 249 selected_packet_size_ms = packet_size_ms; | |
| 250 } | |
| 251 } | |
| 252 return selected_packet_size_ms; | |
| 253 } | |
| 254 | |
| 255 // If the AudioCodec param kCodecParamPTime is set, then we will set it to codec | |
| 256 // pacsize if it's valid, or we will pick the next smallest value we support. | |
| 257 // TODO(Brave): Query supported packet sizes from ACM when the API is ready. | |
| 258 bool SetPTimeAsPacketSize(webrtc::CodecInst* codec, int ptime_ms) { | |
| 259 for (const CodecPref& codec_pref : kCodecPrefs) { | |
| 260 if ((IsCodec(*codec, codec_pref.name) && | |
| 261 codec_pref.clockrate == codec->plfreq) || | |
| 262 IsCodec(*codec, kG722CodecName)) { | |
| 263 int packet_size_ms = SelectPacketSize(codec_pref, ptime_ms); | |
| 264 if (packet_size_ms) { | |
| 265 // Convert unit from milli-seconds to samples. | |
| 266 codec->pacsize = (codec->plfreq / 1000) * packet_size_ms; | |
| 267 return true; | |
| 268 } | |
| 269 } | |
| 270 } | |
| 271 return false; | |
| 272 } | |
| 273 | |
| 274 // Return true if codec.params[feature] == "1", false otherwise. | 203 // Return true if codec.params[feature] == "1", false otherwise. |
| 275 bool IsCodecFeatureEnabled(const AudioCodec& codec, | 204 bool IsCodecFeatureEnabled(const AudioCodec& codec, const char* feature) { |
| 276 const char* feature) { | |
| 277 int value; | 205 int value; |
| 278 return codec.GetParam(feature, &value) && value == 1; | 206 return codec.GetParam(feature, &value) && value == 1; |
| 279 } | 207 } |
| 280 | 208 |
| 281 // Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate | 209 // Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate |
| 282 // otherwise. If the value (either from params or codec.bitrate) <=0, use the | 210 // otherwise. If the value (either from params or codec.bitrate) <=0, use the |
| 283 // default configuration. If the value is beyond feasible bit rate of Opus, | 211 // default configuration. If the value is beyond feasible bit rate of Opus, |
| 284 // clamp it. Returns the Opus bit rate for operation. | 212 // clamp it. Returns the Opus bit rate for operation. |
| 285 int GetOpusBitrate(const AudioCodec& codec, int max_playback_rate) { | 213 int GetOpusBitrate(const AudioCodec& codec, int max_playback_rate) { |
| 286 int bitrate = 0; | 214 int bitrate = 0; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 // If OPUS, change what we send according to the "stereo" codec | 261 // If OPUS, change what we send according to the "stereo" codec |
| 334 // parameter, and not the "channels" parameter. We set | 262 // parameter, and not the "channels" parameter. We set |
| 335 // voe_codec.channels to 2 if "stereo=1" and 1 otherwise. If | 263 // voe_codec.channels to 2 if "stereo=1" and 1 otherwise. If |
| 336 // the bitrate is not specified, i.e. is <= zero, we set it to the | 264 // the bitrate is not specified, i.e. is <= zero, we set it to the |
| 337 // appropriate default value for mono or stereo Opus. | 265 // appropriate default value for mono or stereo Opus. |
| 338 | 266 |
| 339 voe_codec->channels = IsCodecFeatureEnabled(codec, kCodecParamStereo) ? 2 : 1; | 267 voe_codec->channels = IsCodecFeatureEnabled(codec, kCodecParamStereo) ? 2 : 1; |
| 340 voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate); | 268 voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate); |
| 341 } | 269 } |
| 342 | 270 |
| 343 // Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC | |
| 344 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz | |
| 345 // codec. | |
| 346 void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { | |
| 347 if (IsCodec(*voe_codec, kG722CodecName)) { | |
| 348 // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine | |
| 349 // has changed, and this special case is no longer needed. | |
| 350 RTC_DCHECK(voe_codec->plfreq != new_plfreq); | |
| 351 voe_codec->plfreq = new_plfreq; | |
| 352 } | |
| 353 } | |
| 354 | |
| 355 // Gets the default set of options applied to the engine. Historically, these | 271 // Gets the default set of options applied to the engine. Historically, these |
| 356 // were supplied as a combination of flags from the channel manager (ec, agc, | 272 // were supplied as a combination of flags from the channel manager (ec, agc, |
| 357 // ns, and highpass) and the rest hardcoded in InitInternal. | 273 // ns, and highpass) and the rest hardcoded in InitInternal. |
| 358 AudioOptions GetDefaultEngineOptions() { | 274 AudioOptions GetDefaultEngineOptions() { |
| 359 AudioOptions options; | 275 AudioOptions options; |
| 360 options.echo_cancellation = rtc::Optional<bool>(true); | 276 options.echo_cancellation = rtc::Optional<bool>(true); |
| 361 options.auto_gain_control = rtc::Optional<bool>(true); | 277 options.auto_gain_control = rtc::Optional<bool>(true); |
| 362 options.noise_suppression = rtc::Optional<bool>(true); | 278 options.noise_suppression = rtc::Optional<bool>(true); |
| 363 options.highpass_filter = rtc::Optional<bool>(true); | 279 options.highpass_filter = rtc::Optional<bool>(true); |
| 364 options.stereo_swapping = rtc::Optional<bool>(false); | 280 options.stereo_swapping = rtc::Optional<bool>(false); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 386 for (const auto& extension : extensions) { | 302 for (const auto& extension : extensions) { |
| 387 if (extension.uri == kRtpAbsoluteSenderTimeHeaderExtension || | 303 if (extension.uri == kRtpAbsoluteSenderTimeHeaderExtension || |
| 388 extension.uri == kRtpAudioLevelHeaderExtension) { | 304 extension.uri == kRtpAudioLevelHeaderExtension) { |
| 389 result.push_back({extension.uri, extension.id}); | 305 result.push_back({extension.uri, extension.id}); |
| 390 } else { | 306 } else { |
| 391 LOG(LS_WARNING) << "Unsupported RTP extension: " << extension.ToString(); | 307 LOG(LS_WARNING) << "Unsupported RTP extension: " << extension.ToString(); |
| 392 } | 308 } |
| 393 } | 309 } |
| 394 return result; | 310 return result; |
| 395 } | 311 } |
| 396 } // namespace { | |
| 397 | 312 |
| 398 WebRtcVoiceEngine::WebRtcVoiceEngine() | 313 class WebRtcVoiceCodecs final { |
| 399 : voe_wrapper_(new VoEWrapper()), | 314 public: |
| 400 audio_state_(webrtc::AudioState::Create(MakeAudioStateConfig(voe()))) { | 315 // TODO(solenberg): Do this filtering once off-line, add a simple AudioCodec |
| 401 Construct(); | 316 // list and add a test which verifies VoE supports the listed codecs. |
| 402 } | 317 static std::vector<AudioCodec> SupportedCodecs() { |
| 403 | 318 LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; |
| 404 WebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper) | 319 std::vector<AudioCodec> result; |
| 405 : voe_wrapper_(voe_wrapper) { | 320 for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) { |
| 406 Construct(); | 321 // Change the sample rate of G722 to 8000 to match SDP. |
| 407 } | 322 MaybeFixupG722(&voe_codec, 8000); |
| 408 | |
| 409 void WebRtcVoiceEngine::Construct() { | |
| 410 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | |
| 411 LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine"; | |
| 412 | |
| 413 signal_thread_checker_.DetachFromThread(); | |
| 414 std::memset(&default_agc_config_, 0, sizeof(default_agc_config_)); | |
| 415 | |
| 416 webrtc::Trace::set_level_filter(kDefaultTraceFilter); | |
| 417 webrtc::Trace::SetTraceCallback(this); | |
| 418 | |
| 419 // Load our audio codec list. | |
| 420 ConstructCodecs(); | |
| 421 | |
| 422 // Load our RTP Header extensions. | |
| 423 rtp_header_extensions_.push_back( | |
| 424 RtpHeaderExtension(kRtpAudioLevelHeaderExtension, | |
| 425 kRtpAudioLevelHeaderExtensionDefaultId)); | |
| 426 rtp_header_extensions_.push_back( | |
| 427 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, | |
| 428 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); | |
| 429 if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe") == "Enabled") { | |
| 430 rtp_header_extensions_.push_back(RtpHeaderExtension( | |
| 431 kRtpTransportSequenceNumberHeaderExtension, | |
| 432 kRtpTransportSequenceNumberHeaderExtensionDefaultId)); | |
| 433 } | |
| 434 options_ = GetDefaultEngineOptions(); | |
| 435 } | |
| 436 | |
| 437 void WebRtcVoiceEngine::ConstructCodecs() { | |
| 438 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | |
| 439 LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; | |
| 440 int ncodecs = voe_wrapper_->codec()->NumOfCodecs(); | |
| 441 for (int i = 0; i < ncodecs; ++i) { | |
| 442 webrtc::CodecInst voe_codec; | |
| 443 if (GetVoeCodec(i, &voe_codec)) { | |
| 444 // Skip uncompressed formats. | 323 // Skip uncompressed formats. |
| 445 if (IsCodec(voe_codec, kL16CodecName)) { | 324 if (IsCodec(voe_codec, kL16CodecName)) { |
| 446 continue; | 325 continue; |
| 447 } | 326 } |
| 448 | 327 |
| 449 const CodecPref* pref = NULL; | 328 const CodecPref* pref = NULL; |
| 450 for (size_t j = 0; j < arraysize(kCodecPrefs); ++j) { | 329 for (size_t j = 0; j < arraysize(kCodecPrefs); ++j) { |
| 451 if (IsCodec(voe_codec, kCodecPrefs[j].name) && | 330 if (IsCodec(voe_codec, kCodecPrefs[j].name) && |
| 452 kCodecPrefs[j].clockrate == voe_codec.plfreq && | 331 kCodecPrefs[j].clockrate == voe_codec.plfreq && |
| 453 kCodecPrefs[j].channels == voe_codec.channels) { | 332 kCodecPrefs[j].channels == voe_codec.channels) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 476 } | 355 } |
| 477 if (kPreferredMaxPTime != kOpusDefaultMaxPTime) { | 356 if (kPreferredMaxPTime != kOpusDefaultMaxPTime) { |
| 478 codec.params[kCodecParamMaxPTime] = | 357 codec.params[kCodecParamMaxPTime] = |
| 479 rtc::ToString(kPreferredMaxPTime); | 358 rtc::ToString(kPreferredMaxPTime); |
| 480 } | 359 } |
| 481 codec.SetParam(kCodecParamUseInbandFec, 1); | 360 codec.SetParam(kCodecParamUseInbandFec, 1); |
| 482 | 361 |
| 483 // TODO(hellner): Add ptime, sprop-stereo, and stereo | 362 // TODO(hellner): Add ptime, sprop-stereo, and stereo |
| 484 // when they can be set to values other than the default. | 363 // when they can be set to values other than the default. |
| 485 } | 364 } |
| 486 codecs_.push_back(codec); | 365 result.push_back(codec); |
| 487 } else { | 366 } else { |
| 488 LOG(LS_WARNING) << "Unexpected codec: " << ToString(voe_codec); | 367 LOG(LS_WARNING) << "Unexpected codec: " << ToString(voe_codec); |
| 489 } | 368 } |
| 490 } | 369 } |
| 370 // Make sure they are in local preference order. |
| 371 std::sort(result.begin(), result.end(), &AudioCodec::Preferable); |
| 372 return result; |
| 491 } | 373 } |
| 492 // Make sure they are in local preference order. | 374 |
| 493 std::sort(codecs_.begin(), codecs_.end(), &AudioCodec::Preferable); | 375 static bool ToCodecInst(const AudioCodec& in, |
| 376 webrtc::CodecInst* out) { |
| 377 for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) { |
| 378 // Change the sample rate of G722 to 8000 to match SDP. |
| 379 MaybeFixupG722(&voe_codec, 8000); |
| 380 AudioCodec codec(voe_codec.pltype, voe_codec.plname, voe_codec.plfreq, |
| 381 voe_codec.rate, voe_codec.channels, 0); |
| 382 bool multi_rate = IsCodecMultiRate(voe_codec); |
| 383 // Allow arbitrary rates for ISAC to be specified. |
| 384 if (multi_rate) { |
| 385 // Set codec.bitrate to 0 so the check for codec.Matches() passes. |
| 386 codec.bitrate = 0; |
| 387 } |
| 388 if (codec.Matches(in)) { |
| 389 if (out) { |
| 390 // Fixup the payload type. |
| 391 voe_codec.pltype = in.id; |
| 392 |
| 393 // Set bitrate if specified. |
| 394 if (multi_rate && in.bitrate != 0) { |
| 395 voe_codec.rate = in.bitrate; |
| 396 } |
| 397 |
| 398 // Reset G722 sample rate to 16000 to match WebRTC. |
| 399 MaybeFixupG722(&voe_codec, 16000); |
| 400 |
| 401 // Apply codec-specific settings. |
| 402 if (IsCodec(codec, kIsacCodecName)) { |
| 403 // If ISAC and an explicit bitrate is not specified, |
| 404 // enable auto bitrate adjustment. |
| 405 voe_codec.rate = (in.bitrate > 0) ? in.bitrate : -1; |
| 406 } |
| 407 *out = voe_codec; |
| 408 } |
| 409 return true; |
| 410 } |
| 411 } |
| 412 return false; |
| 413 } |
| 414 |
| 415 static bool IsCodecMultiRate(const webrtc::CodecInst& codec) { |
| 416 for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) { |
| 417 if (IsCodec(codec, kCodecPrefs[i].name) && |
| 418 kCodecPrefs[i].clockrate == codec.plfreq) { |
| 419 return kCodecPrefs[i].is_multi_rate; |
| 420 } |
| 421 } |
| 422 return false; |
| 423 } |
| 424 |
| 425 // If the AudioCodec param kCodecParamPTime is set, then we will set it to |
| 426 // codec pacsize if it's valid, or we will pick the next smallest value we |
| 427 // support. |
| 428 // TODO(Brave): Query supported packet sizes from ACM when the API is ready. |
| 429 static bool SetPTimeAsPacketSize(webrtc::CodecInst* codec, int ptime_ms) { |
| 430 for (const CodecPref& codec_pref : kCodecPrefs) { |
| 431 if ((IsCodec(*codec, codec_pref.name) && |
| 432 codec_pref.clockrate == codec->plfreq) || |
| 433 IsCodec(*codec, kG722CodecName)) { |
| 434 int packet_size_ms = SelectPacketSize(codec_pref, ptime_ms); |
| 435 if (packet_size_ms) { |
| 436 // Convert unit from milli-seconds to samples. |
| 437 codec->pacsize = (codec->plfreq / 1000) * packet_size_ms; |
| 438 return true; |
| 439 } |
| 440 } |
| 441 } |
| 442 return false; |
| 443 } |
| 444 |
| 445 private: |
| 446 static const int kMaxNumPacketSize = 6; |
| 447 struct CodecPref { |
| 448 const char* name; |
| 449 int clockrate; |
| 450 int channels; |
| 451 int payload_type; |
| 452 bool is_multi_rate; |
| 453 int packet_sizes_ms[kMaxNumPacketSize]; |
| 454 }; |
| 455 // Note: keep the supported packet sizes in ascending order. |
| 456 static const CodecPref kCodecPrefs[12]; |
| 457 |
| 458 static int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) { |
| 459 int selected_packet_size_ms = codec_pref.packet_sizes_ms[0]; |
| 460 for (int packet_size_ms : codec_pref.packet_sizes_ms) { |
| 461 if (packet_size_ms && packet_size_ms <= ptime_ms) { |
| 462 selected_packet_size_ms = packet_size_ms; |
| 463 } |
| 464 } |
| 465 return selected_packet_size_ms; |
| 466 } |
| 467 |
| 468 // Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC |
| 469 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz |
| 470 // codec. |
| 471 static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { |
| 472 if (IsCodec(*voe_codec, kG722CodecName)) { |
| 473 // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine |
| 474 // has changed, and this special case is no longer needed. |
| 475 RTC_DCHECK(voe_codec->plfreq != new_plfreq); |
| 476 voe_codec->plfreq = new_plfreq; |
| 477 } |
| 478 } |
| 479 }; |
| 480 |
| 481 const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[12] = { |
| 482 { kOpusCodecName, 48000, 2, 111, true, { 10, 20, 40, 60 } }, |
| 483 { kIsacCodecName, 16000, 1, 103, true, { 30, 60 } }, |
| 484 { kIsacCodecName, 32000, 1, 104, true, { 30 } }, |
| 485 // G722 should be advertised as 8000 Hz because of the RFC "bug". |
| 486 { kG722CodecName, 8000, 1, 9, false, { 10, 20, 30, 40, 50, 60 } }, |
| 487 { kIlbcCodecName, 8000, 1, 102, false, { 20, 30, 40, 60 } }, |
| 488 { kPcmuCodecName, 8000, 1, 0, false, { 10, 20, 30, 40, 50, 60 } }, |
| 489 { kPcmaCodecName, 8000, 1, 8, false, { 10, 20, 30, 40, 50, 60 } }, |
| 490 { kCnCodecName, 32000, 1, 106, false, { } }, |
| 491 { kCnCodecName, 16000, 1, 105, false, { } }, |
| 492 { kCnCodecName, 8000, 1, 13, false, { } }, |
| 493 { kRedCodecName, 8000, 1, 127, false, { } }, |
| 494 { kDtmfCodecName, 8000, 1, 126, false, { } }, |
| 495 }; |
| 496 } // namespace { |
| 497 |
| 498 bool WebRtcVoiceEngine::ToCodecInst(const AudioCodec& in, |
| 499 webrtc::CodecInst* out) { |
| 500 return WebRtcVoiceCodecs::ToCodecInst(in, out); |
| 494 } | 501 } |
| 495 | 502 |
| 496 bool WebRtcVoiceEngine::GetVoeCodec(int index, webrtc::CodecInst* codec) { | 503 WebRtcVoiceEngine::WebRtcVoiceEngine() |
| 504 : voe_wrapper_(new VoEWrapper()), |
| 505 audio_state_(webrtc::AudioState::Create(MakeAudioStateConfig(voe()))) { |
| 506 Construct(); |
| 507 } |
| 508 |
| 509 WebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper) |
| 510 : voe_wrapper_(voe_wrapper) { |
| 511 Construct(); |
| 512 } |
| 513 |
| 514 void WebRtcVoiceEngine::Construct() { |
| 497 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 515 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 498 if (voe_wrapper_->codec()->GetCodec(index, *codec) == -1) { | 516 LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine"; |
| 499 return false; | 517 |
| 518 signal_thread_checker_.DetachFromThread(); |
| 519 std::memset(&default_agc_config_, 0, sizeof(default_agc_config_)); |
| 520 |
| 521 webrtc::Trace::set_level_filter(kDefaultTraceFilter); |
| 522 webrtc::Trace::SetTraceCallback(this); |
| 523 |
| 524 // Load our audio codec list. |
| 525 codecs_ = WebRtcVoiceCodecs::SupportedCodecs(); |
| 526 |
| 527 // Load our RTP Header extensions. |
| 528 rtp_header_extensions_.push_back( |
| 529 RtpHeaderExtension(kRtpAudioLevelHeaderExtension, |
| 530 kRtpAudioLevelHeaderExtensionDefaultId)); |
| 531 rtp_header_extensions_.push_back( |
| 532 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, |
| 533 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); |
| 534 if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe") == "Enabled") { |
| 535 rtp_header_extensions_.push_back(RtpHeaderExtension( |
| 536 kRtpTransportSequenceNumberHeaderExtension, |
| 537 kRtpTransportSequenceNumberHeaderExtensionDefaultId)); |
| 500 } | 538 } |
| 501 // Change the sample rate of G722 to 8000 to match SDP. | 539 options_ = GetDefaultEngineOptions(); |
| 502 MaybeFixupG722(codec, 8000); | |
| 503 return true; | |
| 504 } | 540 } |
| 505 | 541 |
| 506 WebRtcVoiceEngine::~WebRtcVoiceEngine() { | 542 WebRtcVoiceEngine::~WebRtcVoiceEngine() { |
| 507 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 543 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 508 LOG(LS_VERBOSE) << "WebRtcVoiceEngine::~WebRtcVoiceEngine"; | 544 LOG(LS_VERBOSE) << "WebRtcVoiceEngine::~WebRtcVoiceEngine"; |
| 509 if (adm_) { | 545 if (adm_) { |
| 510 voe_wrapper_.reset(); | 546 voe_wrapper_.reset(); |
| 511 adm_->Release(); | 547 adm_->Release(); |
| 512 adm_ = NULL; | 548 adm_ = NULL; |
| 513 } | 549 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 532 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 568 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 533 // Temporarily turn logging level up for the Init call | 569 // Temporarily turn logging level up for the Init call |
| 534 webrtc::Trace::set_level_filter(kElevatedTraceFilter); | 570 webrtc::Trace::set_level_filter(kElevatedTraceFilter); |
| 535 if (voe_wrapper_->base()->Init(adm_) == -1) { | 571 if (voe_wrapper_->base()->Init(adm_) == -1) { |
| 536 LOG_RTCERR0_EX(Init, voe_wrapper_->error()); | 572 LOG_RTCERR0_EX(Init, voe_wrapper_->error()); |
| 537 return false; | 573 return false; |
| 538 } | 574 } |
| 539 webrtc::Trace::set_level_filter(kDefaultTraceFilter); | 575 webrtc::Trace::set_level_filter(kDefaultTraceFilter); |
| 540 | 576 |
| 541 // Log the VoiceEngine version info | 577 // Log the VoiceEngine version info |
| 542 char buffer[1024] = ""; | 578 { |
| 543 voe_wrapper_->base()->GetVersion(buffer); | 579 char buffer[1024] = ""; |
| 544 LOG(LS_INFO) << "WebRtc VoiceEngine Version:"; | 580 voe_wrapper_->base()->GetVersion(buffer); |
| 545 LogMultiline(rtc::LS_INFO, buffer); | 581 LOG(LS_INFO) << "WebRtc VoiceEngine Version:"; |
| 582 const char* delim = "\r\n"; |
| 583 for (char* tok = strtok(buffer, delim); tok; tok = strtok(NULL, delim)) { |
| 584 LOG(LS_INFO) << tok; |
| 585 } |
| 586 } |
| 546 | 587 |
| 547 // Save the default AGC configuration settings. This must happen before | 588 // Save the default AGC configuration settings. This must happen before |
| 548 // calling SetOptions or the default will be overwritten. | 589 // calling SetOptions or the default will be overwritten. |
| 549 if (voe_wrapper_->processing()->GetAgcConfig(default_agc_config_) == -1) { | 590 if (voe_wrapper_->processing()->GetAgcConfig(default_agc_config_) == -1) { |
| 550 LOG_RTCERR0(GetAgcConfig); | 591 LOG_RTCERR0(GetAgcConfig); |
| 551 return false; | 592 return false; |
| 552 } | 593 } |
| 553 | 594 |
| 554 // Set defaults for options, so that ApplyOptions applies them explicitly | 595 // Set defaults for options, so that ApplyOptions applies them explicitly |
| 555 // when we clear option (channel) overrides. External clients can still | 596 // when we clear option (channel) overrides. External clients can still |
| (...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 unsigned int ulevel; | 1090 unsigned int ulevel; |
| 1050 return (voe_wrapper_->volume()->GetSpeechInputLevel(ulevel) != -1) ? | 1091 return (voe_wrapper_->volume()->GetSpeechInputLevel(ulevel) != -1) ? |
| 1051 static_cast<int>(ulevel) : -1; | 1092 static_cast<int>(ulevel) : -1; |
| 1052 } | 1093 } |
| 1053 | 1094 |
| 1054 const std::vector<AudioCodec>& WebRtcVoiceEngine::codecs() { | 1095 const std::vector<AudioCodec>& WebRtcVoiceEngine::codecs() { |
| 1055 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); | 1096 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
| 1056 return codecs_; | 1097 return codecs_; |
| 1057 } | 1098 } |
| 1058 | 1099 |
| 1059 bool WebRtcVoiceEngine::FindCodec(const AudioCodec& in) { | |
| 1060 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | |
| 1061 return FindWebRtcCodec(in, NULL); | |
| 1062 } | |
| 1063 | |
| 1064 // Get the VoiceEngine codec that matches |in|, with the supplied settings. | |
| 1065 bool WebRtcVoiceEngine::FindWebRtcCodec(const AudioCodec& in, | |
| 1066 webrtc::CodecInst* out) { | |
| 1067 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | |
| 1068 int ncodecs = voe_wrapper_->codec()->NumOfCodecs(); | |
| 1069 for (int i = 0; i < ncodecs; ++i) { | |
| 1070 webrtc::CodecInst voe_codec; | |
| 1071 if (GetVoeCodec(i, &voe_codec)) { | |
| 1072 AudioCodec codec(voe_codec.pltype, voe_codec.plname, voe_codec.plfreq, | |
| 1073 voe_codec.rate, voe_codec.channels, 0); | |
| 1074 bool multi_rate = IsCodecMultiRate(voe_codec); | |
| 1075 // Allow arbitrary rates for ISAC to be specified. | |
| 1076 if (multi_rate) { | |
| 1077 // Set codec.bitrate to 0 so the check for codec.Matches() passes. | |
| 1078 codec.bitrate = 0; | |
| 1079 } | |
| 1080 if (codec.Matches(in)) { | |
| 1081 if (out) { | |
| 1082 // Fixup the payload type. | |
| 1083 voe_codec.pltype = in.id; | |
| 1084 | |
| 1085 // Set bitrate if specified. | |
| 1086 if (multi_rate && in.bitrate != 0) { | |
| 1087 voe_codec.rate = in.bitrate; | |
| 1088 } | |
| 1089 | |
| 1090 // Reset G722 sample rate to 16000 to match WebRTC. | |
| 1091 MaybeFixupG722(&voe_codec, 16000); | |
| 1092 | |
| 1093 // Apply codec-specific settings. | |
| 1094 if (IsCodec(codec, kIsacCodecName)) { | |
| 1095 // If ISAC and an explicit bitrate is not specified, | |
| 1096 // enable auto bitrate adjustment. | |
| 1097 voe_codec.rate = (in.bitrate > 0) ? in.bitrate : -1; | |
| 1098 } | |
| 1099 *out = voe_codec; | |
| 1100 } | |
| 1101 return true; | |
| 1102 } | |
| 1103 } | |
| 1104 } | |
| 1105 return false; | |
| 1106 } | |
| 1107 | |
| 1108 const std::vector<RtpHeaderExtension>& | 1100 const std::vector<RtpHeaderExtension>& |
| 1109 WebRtcVoiceEngine::rtp_header_extensions() const { | 1101 WebRtcVoiceEngine::rtp_header_extensions() const { |
| 1110 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); | 1102 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
| 1111 return rtp_header_extensions_; | 1103 return rtp_header_extensions_; |
| 1112 } | 1104 } |
| 1113 | 1105 |
| 1114 int WebRtcVoiceEngine::GetLastEngineError() { | 1106 int WebRtcVoiceEngine::GetLastEngineError() { |
| 1115 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1107 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 1116 return voe_wrapper_->error(); | 1108 return voe_wrapper_->error(); |
| 1117 } | 1109 } |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1585 // never removed. | 1577 // never removed. |
| 1586 return true; | 1578 return true; |
| 1587 } | 1579 } |
| 1588 | 1580 |
| 1589 if (playout_) { | 1581 if (playout_) { |
| 1590 // Receive codecs can not be changed while playing. So we temporarily | 1582 // Receive codecs can not be changed while playing. So we temporarily |
| 1591 // pause playout. | 1583 // pause playout. |
| 1592 PausePlayout(); | 1584 PausePlayout(); |
| 1593 } | 1585 } |
| 1594 | 1586 |
| 1595 bool result = SetRecvCodecsInternal(new_codecs); | 1587 bool result = true; |
| 1588 for (const AudioCodec& codec : new_codecs) { |
| 1589 webrtc::CodecInst voe_codec; |
| 1590 if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { |
| 1591 LOG(LS_INFO) << ToString(codec); |
| 1592 voe_codec.pltype = codec.id; |
| 1593 for (const auto& ch : recv_streams_) { |
| 1594 if (engine()->voe()->codec()->SetRecPayloadType( |
| 1595 ch.second->channel(), voe_codec) == -1) { |
| 1596 LOG_RTCERR2(SetRecPayloadType, ch.second->channel(), |
| 1597 ToString(voe_codec)); |
| 1598 result = false; |
| 1599 } |
| 1600 } |
| 1601 } else { |
| 1602 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
| 1603 result = false; |
| 1604 break; |
| 1605 } |
| 1606 } |
| 1596 if (result) { | 1607 if (result) { |
| 1597 recv_codecs_ = codecs; | 1608 recv_codecs_ = codecs; |
| 1598 } | 1609 } |
| 1599 | 1610 |
| 1600 if (desired_playout_ && !playout_) { | 1611 if (desired_playout_ && !playout_) { |
| 1601 ResumePlayout(); | 1612 ResumePlayout(); |
| 1602 } | 1613 } |
| 1603 return result; | 1614 return result; |
| 1604 } | 1615 } |
| 1605 | 1616 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1620 bool nack_enabled = nack_enabled_; | 1631 bool nack_enabled = nack_enabled_; |
| 1621 bool enable_codec_fec = false; | 1632 bool enable_codec_fec = false; |
| 1622 bool enable_opus_dtx = false; | 1633 bool enable_opus_dtx = false; |
| 1623 int opus_max_playback_rate = 0; | 1634 int opus_max_playback_rate = 0; |
| 1624 | 1635 |
| 1625 // Set send codec (the first non-telephone-event/CN codec) | 1636 // Set send codec (the first non-telephone-event/CN codec) |
| 1626 for (const AudioCodec& codec : codecs) { | 1637 for (const AudioCodec& codec : codecs) { |
| 1627 // Ignore codecs we don't know about. The negotiation step should prevent | 1638 // Ignore codecs we don't know about. The negotiation step should prevent |
| 1628 // this, but double-check to be sure. | 1639 // this, but double-check to be sure. |
| 1629 webrtc::CodecInst voe_codec; | 1640 webrtc::CodecInst voe_codec; |
| 1630 if (!engine()->FindWebRtcCodec(codec, &voe_codec)) { | 1641 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { |
| 1631 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | 1642 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
| 1632 continue; | 1643 continue; |
| 1633 } | 1644 } |
| 1634 | 1645 |
| 1635 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { | 1646 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { |
| 1636 // Skip telephone-event/CN codec, which will be handled later. | 1647 // Skip telephone-event/CN codec, which will be handled later. |
| 1637 continue; | 1648 continue; |
| 1638 } | 1649 } |
| 1639 | 1650 |
| 1640 // We'll use the first codec in the list to actually send audio data. | 1651 // We'll use the first codec in the list to actually send audio data. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1661 // For Opus as the send codec, we are to determine inband FEC, maximum | 1672 // For Opus as the send codec, we are to determine inband FEC, maximum |
| 1662 // playback rate, and opus internal dtx. | 1673 // playback rate, and opus internal dtx. |
| 1663 if (IsCodec(codec, kOpusCodecName)) { | 1674 if (IsCodec(codec, kOpusCodecName)) { |
| 1664 GetOpusConfig(codec, &send_codec, &enable_codec_fec, | 1675 GetOpusConfig(codec, &send_codec, &enable_codec_fec, |
| 1665 &opus_max_playback_rate, &enable_opus_dtx); | 1676 &opus_max_playback_rate, &enable_opus_dtx); |
| 1666 } | 1677 } |
| 1667 | 1678 |
| 1668 // Set packet size if the AudioCodec param kCodecParamPTime is set. | 1679 // Set packet size if the AudioCodec param kCodecParamPTime is set. |
| 1669 int ptime_ms = 0; | 1680 int ptime_ms = 0; |
| 1670 if (codec.GetParam(kCodecParamPTime, &ptime_ms)) { | 1681 if (codec.GetParam(kCodecParamPTime, &ptime_ms)) { |
| 1671 if (!SetPTimeAsPacketSize(&send_codec, ptime_ms)) { | 1682 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) { |
| 1672 LOG(LS_WARNING) << "Failed to set packet size for codec " | 1683 LOG(LS_WARNING) << "Failed to set packet size for codec " |
| 1673 << send_codec.plname; | 1684 << send_codec.plname; |
| 1674 return false; | 1685 return false; |
| 1675 } | 1686 } |
| 1676 } | 1687 } |
| 1677 } | 1688 } |
| 1678 found_send_codec = true; | 1689 found_send_codec = true; |
| 1679 break; | 1690 break; |
| 1680 } | 1691 } |
| 1681 | 1692 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1739 | 1750 |
| 1740 if (send_bitrate_setting_) { | 1751 if (send_bitrate_setting_) { |
| 1741 SetSendBitrateInternal(send_bitrate_bps_); | 1752 SetSendBitrateInternal(send_bitrate_bps_); |
| 1742 } | 1753 } |
| 1743 | 1754 |
| 1744 // Loop through the codecs list again to config the telephone-event/CN codec. | 1755 // Loop through the codecs list again to config the telephone-event/CN codec. |
| 1745 for (const AudioCodec& codec : codecs) { | 1756 for (const AudioCodec& codec : codecs) { |
| 1746 // Ignore codecs we don't know about. The negotiation step should prevent | 1757 // Ignore codecs we don't know about. The negotiation step should prevent |
| 1747 // this, but double-check to be sure. | 1758 // this, but double-check to be sure. |
| 1748 webrtc::CodecInst voe_codec; | 1759 webrtc::CodecInst voe_codec; |
| 1749 if (!engine()->FindWebRtcCodec(codec, &voe_codec)) { | 1760 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { |
| 1750 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | 1761 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
| 1751 continue; | 1762 continue; |
| 1752 } | 1763 } |
| 1753 | 1764 |
| 1754 // Find the DTMF telephone event "codec" and tell VoiceEngine channels | 1765 // Find the DTMF telephone event "codec" and tell VoiceEngine channels |
| 1755 // about it. | 1766 // about it. |
| 1756 if (IsCodec(codec, kDtmfCodecName)) { | 1767 if (IsCodec(codec, kDtmfCodecName)) { |
| 1757 if (engine()->voe()->dtmf()->SetSendTelephoneEventPayloadType( | 1768 if (engine()->voe()->dtmf()->SetSendTelephoneEventPayloadType( |
| 1758 channel, codec.id) == -1) { | 1769 channel, codec.id) == -1) { |
| 1759 LOG_RTCERR2(SetSendTelephoneEventPayloadType, channel, codec.id); | 1770 LOG_RTCERR2(SetSendTelephoneEventPayloadType, channel, codec.id); |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2109 return false; | 2120 return false; |
| 2110 } | 2121 } |
| 2111 | 2122 |
| 2112 // Create a new channel for receiving audio data. | 2123 // Create a new channel for receiving audio data. |
| 2113 const int channel = CreateVoEChannel(); | 2124 const int channel = CreateVoEChannel(); |
| 2114 if (channel == -1) { | 2125 if (channel == -1) { |
| 2115 return false; | 2126 return false; |
| 2116 } | 2127 } |
| 2117 | 2128 |
| 2118 // Turn off all supported codecs. | 2129 // Turn off all supported codecs. |
| 2119 const int ncodecs = engine()->voe()->codec()->NumOfCodecs(); | 2130 // TODO(solenberg): Remove once "no codecs" is the default state of a stream. |
| 2120 for (int i = 0; i < ncodecs; ++i) { | 2131 for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) { |
| 2121 webrtc::CodecInst voe_codec; | 2132 voe_codec.pltype = -1; |
| 2122 if (engine()->voe()->codec()->GetCodec(i, voe_codec) != -1) { | 2133 if (engine()->voe()->codec()->SetRecPayloadType(channel, voe_codec) == -1) { |
| 2123 voe_codec.pltype = -1; | 2134 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); |
| 2124 if (engine()->voe()->codec()->SetRecPayloadType( | 2135 DeleteVoEChannel(channel); |
| 2125 channel, voe_codec) == -1) { | 2136 return false; |
| 2126 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); | |
| 2127 DeleteVoEChannel(channel); | |
| 2128 return false; | |
| 2129 } | |
| 2130 } | 2137 } |
| 2131 } | 2138 } |
| 2132 | 2139 |
| 2133 // Only enable those configured for this channel. | 2140 // Only enable those configured for this channel. |
| 2134 for (const auto& codec : recv_codecs_) { | 2141 for (const auto& codec : recv_codecs_) { |
| 2135 webrtc::CodecInst voe_codec; | 2142 webrtc::CodecInst voe_codec; |
| 2136 if (engine()->FindWebRtcCodec(codec, &voe_codec)) { | 2143 if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { |
| 2137 voe_codec.pltype = codec.id; | 2144 voe_codec.pltype = codec.id; |
| 2138 if (engine()->voe()->codec()->SetRecPayloadType( | 2145 if (engine()->voe()->codec()->SetRecPayloadType( |
| 2139 channel, voe_codec) == -1) { | 2146 channel, voe_codec) == -1) { |
| 2140 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); | 2147 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); |
| 2141 DeleteVoEChannel(channel); | 2148 DeleteVoEChannel(channel); |
| 2142 return false; | 2149 return false; |
| 2143 } | 2150 } |
| 2144 } | 2151 } |
| 2145 } | 2152 } |
| 2146 | 2153 |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2479 return true; | 2486 return true; |
| 2480 } | 2487 } |
| 2481 | 2488 |
| 2482 // Bitrate is auto by default. | 2489 // Bitrate is auto by default. |
| 2483 // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by | 2490 // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by |
| 2484 // SetMaxSendBandwith(0), the second call removes the previous limit. | 2491 // SetMaxSendBandwith(0), the second call removes the previous limit. |
| 2485 if (bps <= 0) | 2492 if (bps <= 0) |
| 2486 return true; | 2493 return true; |
| 2487 | 2494 |
| 2488 webrtc::CodecInst codec = *send_codec_; | 2495 webrtc::CodecInst codec = *send_codec_; |
| 2489 bool is_multi_rate = IsCodecMultiRate(codec); | 2496 bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec); |
| 2490 | 2497 |
| 2491 if (is_multi_rate) { | 2498 if (is_multi_rate) { |
| 2492 // If codec is multi-rate then just set the bitrate. | 2499 // If codec is multi-rate then just set the bitrate. |
| 2493 codec.rate = bps; | 2500 codec.rate = bps; |
| 2494 for (const auto& ch : send_streams_) { | 2501 for (const auto& ch : send_streams_) { |
| 2495 if (!SetSendCodec(ch.second->channel(), codec)) { | 2502 if (!SetSendCodec(ch.second->channel(), codec)) { |
| 2496 LOG(LS_INFO) << "Failed to set codec " << codec.plname | 2503 LOG(LS_INFO) << "Failed to set codec " << codec.plname |
| 2497 << " to bitrate " << bps << " bps."; | 2504 << " to bitrate " << bps << " bps."; |
| 2498 return false; | 2505 return false; |
| 2499 } | 2506 } |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2628 if (all_codecs.size() > 1) { | 2635 if (all_codecs.size() > 1) { |
| 2629 red_pt = all_codecs[1].id; | 2636 red_pt = all_codecs[1].id; |
| 2630 } | 2637 } |
| 2631 } | 2638 } |
| 2632 | 2639 |
| 2633 // Try to find red_pt in |codecs|. | 2640 // Try to find red_pt in |codecs|. |
| 2634 for (const AudioCodec& codec : all_codecs) { | 2641 for (const AudioCodec& codec : all_codecs) { |
| 2635 if (codec.id == red_pt) { | 2642 if (codec.id == red_pt) { |
| 2636 // If we find the right codec, that will be the codec we pass to | 2643 // If we find the right codec, that will be the codec we pass to |
| 2637 // SetSendCodec, with the desired payload type. | 2644 // SetSendCodec, with the desired payload type. |
| 2638 if (engine()->FindWebRtcCodec(codec, send_codec)) { | 2645 if (WebRtcVoiceEngine::ToCodecInst(codec, send_codec)) { |
| 2639 return true; | 2646 return true; |
| 2640 } else { | 2647 } else { |
| 2641 break; | 2648 break; |
| 2642 } | 2649 } |
| 2643 } | 2650 } |
| 2644 } | 2651 } |
| 2645 LOG(LS_WARNING) << "RED params " << red_params << " are invalid."; | 2652 LOG(LS_WARNING) << "RED params " << red_params << " are invalid."; |
| 2646 return false; | 2653 return false; |
| 2647 } | 2654 } |
| 2648 | 2655 |
| 2649 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { | 2656 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { |
| 2650 if (playout) { | 2657 if (playout) { |
| 2651 LOG(LS_INFO) << "Starting playout for channel #" << channel; | 2658 LOG(LS_INFO) << "Starting playout for channel #" << channel; |
| 2652 if (engine()->voe()->base()->StartPlayout(channel) == -1) { | 2659 if (engine()->voe()->base()->StartPlayout(channel) == -1) { |
| 2653 LOG_RTCERR1(StartPlayout, channel); | 2660 LOG_RTCERR1(StartPlayout, channel); |
| 2654 return false; | 2661 return false; |
| 2655 } | 2662 } |
| 2656 } else { | 2663 } else { |
| 2657 LOG(LS_INFO) << "Stopping playout for channel #" << channel; | 2664 LOG(LS_INFO) << "Stopping playout for channel #" << channel; |
| 2658 engine()->voe()->base()->StopPlayout(channel); | 2665 engine()->voe()->base()->StopPlayout(channel); |
| 2659 } | 2666 } |
| 2660 return true; | 2667 return true; |
| 2661 } | 2668 } |
| 2662 | |
| 2663 bool WebRtcVoiceMediaChannel::SetRecvCodecsInternal( | |
| 2664 const std::vector<AudioCodec>& new_codecs) { | |
| 2665 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | |
| 2666 for (const AudioCodec& codec : new_codecs) { | |
| 2667 webrtc::CodecInst voe_codec; | |
| 2668 if (engine()->FindWebRtcCodec(codec, &voe_codec)) { | |
| 2669 LOG(LS_INFO) << ToString(codec); | |
| 2670 voe_codec.pltype = codec.id; | |
| 2671 for (const auto& ch : recv_streams_) { | |
| 2672 if (engine()->voe()->codec()->SetRecPayloadType( | |
| 2673 ch.second->channel(), voe_codec) == -1) { | |
| 2674 LOG_RTCERR2(SetRecPayloadType, ch.second->channel(), | |
| 2675 ToString(voe_codec)); | |
| 2676 return false; | |
| 2677 } | |
| 2678 } | |
| 2679 } else { | |
| 2680 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | |
| 2681 return false; | |
| 2682 } | |
| 2683 } | |
| 2684 return true; | |
| 2685 } | |
| 2686 } // namespace cricket | 2669 } // namespace cricket |
| 2687 | 2670 |
| 2688 #endif // HAVE_WEBRTC_VOICE | 2671 #endif // HAVE_WEBRTC_VOICE |
| OLD | NEW |