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 |