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 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
197 } | 197 } |
198 std::vector<int> payload_types; | 198 std::vector<int> payload_types; |
199 for (const AudioCodec& codec : codecs) { | 199 for (const AudioCodec& codec : codecs) { |
200 payload_types.push_back(codec.id); | 200 payload_types.push_back(codec.id); |
201 } | 201 } |
202 std::sort(payload_types.begin(), payload_types.end()); | 202 std::sort(payload_types.begin(), payload_types.end()); |
203 auto it = std::unique(payload_types.begin(), payload_types.end()); | 203 auto it = std::unique(payload_types.begin(), payload_types.end()); |
204 return it == payload_types.end(); | 204 return it == payload_types.end(); |
205 } | 205 } |
206 | 206 |
207 bool IsNackEnabled(const AudioCodec& codec) { | |
208 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack, | |
209 kParamValueEmpty)); | |
210 } | |
211 | |
212 // Return true if codec.params[feature] == "1", false otherwise. | 207 // Return true if codec.params[feature] == "1", false otherwise. |
213 bool IsCodecFeatureEnabled(const AudioCodec& codec, const char* feature) { | 208 bool IsCodecFeatureEnabled(const AudioCodec& codec, const char* feature) { |
214 int value; | 209 int value; |
215 return codec.GetParam(feature, &value) && value == 1; | 210 return codec.GetParam(feature, &value) && value == 1; |
216 } | 211 } |
217 | 212 |
218 // Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate | 213 // Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate |
219 // otherwise. If the value (either from params or codec.bitrate) <=0, use the | 214 // otherwise. If the value (either from params or codec.bitrate) <=0, use the |
220 // default configuration. If the value is beyond feasible bit rate of Opus, | 215 // default configuration. If the value is beyond feasible bit rate of Opus, |
221 // clamp it. Returns the Opus bit rate for operation. | 216 // clamp it. Returns the Opus bit rate for operation. |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
324 // Only add fmtp parameters that differ from the spec. | 319 // Only add fmtp parameters that differ from the spec. |
325 if (kPreferredMinPTime != kOpusDefaultMinPTime) { | 320 if (kPreferredMinPTime != kOpusDefaultMinPTime) { |
326 codec.params[kCodecParamMinPTime] = | 321 codec.params[kCodecParamMinPTime] = |
327 rtc::ToString(kPreferredMinPTime); | 322 rtc::ToString(kPreferredMinPTime); |
328 } | 323 } |
329 if (kPreferredMaxPTime != kOpusDefaultMaxPTime) { | 324 if (kPreferredMaxPTime != kOpusDefaultMaxPTime) { |
330 codec.params[kCodecParamMaxPTime] = | 325 codec.params[kCodecParamMaxPTime] = |
331 rtc::ToString(kPreferredMaxPTime); | 326 rtc::ToString(kPreferredMaxPTime); |
332 } | 327 } |
333 codec.SetParam(kCodecParamUseInbandFec, 1); | 328 codec.SetParam(kCodecParamUseInbandFec, 1); |
329 codec.AddFeedbackParam( | |
330 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty)); | |
334 | 331 |
335 // TODO(hellner): Add ptime, sprop-stereo, and stereo | 332 // TODO(hellner): Add ptime, sprop-stereo, and stereo |
336 // when they can be set to values other than the default. | 333 // when they can be set to values other than the default. |
337 } | 334 } |
338 result.push_back(codec); | 335 result.push_back(codec); |
339 } else { | 336 } else { |
340 LOG(LS_WARNING) << "Unexpected codec: " << ToString(voe_codec); | 337 LOG(LS_WARNING) << "Unexpected codec: " << ToString(voe_codec); |
341 } | 338 } |
342 } | 339 } |
343 // Make sure they are in local preference order. | 340 // Make sure they are in local preference order. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
408 if (packet_size_ms) { | 405 if (packet_size_ms) { |
409 // Convert unit from milli-seconds to samples. | 406 // Convert unit from milli-seconds to samples. |
410 codec->pacsize = (codec->plfreq / 1000) * packet_size_ms; | 407 codec->pacsize = (codec->plfreq / 1000) * packet_size_ms; |
411 return true; | 408 return true; |
412 } | 409 } |
413 } | 410 } |
414 } | 411 } |
415 return false; | 412 return false; |
416 } | 413 } |
417 | 414 |
415 static const AudioCodec* GetPreferredCodec( | |
416 const std::vector<AudioCodec>& codecs, | |
417 webrtc::CodecInst* voe_codec, | |
418 int* red_payload_type) { | |
the sun
2016/01/26 10:26:55
RTC_DCHECK(voe_codec);
RTC_DCHECK(red_payload_type
stefan-webrtc
2016/01/26 11:40:54
Done.
| |
419 // Set send codec (the first non-telephone-event/CN codec) | |
the sun
2016/01/26 10:26:55
Bad comment - we don't set the send codec here, we
stefan-webrtc
2016/01/26 11:40:54
Done.
| |
420 for (const AudioCodec& codec : codecs) { | |
421 *red_payload_type = -1; | |
422 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { | |
423 // Skip telephone-event/CN codec, which will be handled later. | |
424 continue; | |
425 } | |
426 | |
427 // We'll use the first codec in the list to actually send audio data. | |
428 // Be sure to use the payload type requested by the remote side. | |
429 // "red", for RED audio, is a special case where the actual codec to be | |
430 // used is specified in params. | |
431 const AudioCodec* found_codec = &codec; | |
432 if (IsCodec(*found_codec, kRedCodecName)) { | |
433 // Parse out the RED parameters. If we fail, just ignore RED; | |
434 // we don't support all possible params/usage scenarios. | |
435 *red_payload_type = codec.id; | |
436 found_codec = GetRedSendCodec(*found_codec, codecs); | |
437 if (!found_codec) { | |
438 continue; | |
439 } | |
440 } | |
441 // Ignore codecs we don't know about. The negotiation step should prevent | |
442 // this, but double-check to be sure. | |
443 if (!WebRtcVoiceEngine::ToCodecInst(*found_codec, voe_codec)) { | |
the sun
2016/01/26 10:26:55
Remove "WebRtcVoiceEngine::"
stefan-webrtc
2016/01/26 11:40:54
Done.
| |
444 LOG(LS_WARNING) << "Unknown codec " << ToString(*found_codec); | |
445 continue; | |
446 } | |
447 return found_codec; | |
448 } | |
449 return nullptr; | |
450 } | |
451 | |
418 private: | 452 private: |
419 static const int kMaxNumPacketSize = 6; | 453 static const int kMaxNumPacketSize = 6; |
420 struct CodecPref { | 454 struct CodecPref { |
421 const char* name; | 455 const char* name; |
422 int clockrate; | 456 int clockrate; |
423 size_t channels; | 457 size_t channels; |
424 int payload_type; | 458 int payload_type; |
425 bool is_multi_rate; | 459 bool is_multi_rate; |
426 int packet_sizes_ms[kMaxNumPacketSize]; | 460 int packet_sizes_ms[kMaxNumPacketSize]; |
427 }; | 461 }; |
(...skipping 14 matching lines...) Expand all Loading... | |
442 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz | 476 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz |
443 // codec. | 477 // codec. |
444 static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { | 478 static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { |
445 if (IsCodec(*voe_codec, kG722CodecName)) { | 479 if (IsCodec(*voe_codec, kG722CodecName)) { |
446 // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine | 480 // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine |
447 // has changed, and this special case is no longer needed. | 481 // has changed, and this special case is no longer needed. |
448 RTC_DCHECK(voe_codec->plfreq != new_plfreq); | 482 RTC_DCHECK(voe_codec->plfreq != new_plfreq); |
449 voe_codec->plfreq = new_plfreq; | 483 voe_codec->plfreq = new_plfreq; |
450 } | 484 } |
451 } | 485 } |
486 | |
487 static const AudioCodec* GetRedSendCodec( | |
488 const AudioCodec& red_codec, | |
489 const std::vector<AudioCodec>& all_codecs) { | |
490 // Get the RED encodings from the parameter with no name. This may | |
491 // change based on what is discussed on the Jingle list. | |
492 // The encoding parameter is of the form "a/b"; we only support where | |
493 // a == b. Verify this and parse out the value into red_pt. | |
494 // If the parameter value is absent (as it will be until we wire up the | |
495 // signaling of this message), use the second codec specified (i.e. the | |
496 // one after "red") as the encoding parameter. | |
497 int red_pt = -1; | |
498 std::string red_params; | |
499 CodecParameterMap::const_iterator it = red_codec.params.find(""); | |
500 if (it != red_codec.params.end()) { | |
501 red_params = it->second; | |
502 std::vector<std::string> red_pts; | |
503 if (rtc::split(red_params, '/', &red_pts) != 2 || | |
504 red_pts[0] != red_pts[1] || !rtc::FromString(red_pts[0], &red_pt)) { | |
505 LOG(LS_WARNING) << "RED params " << red_params << " not supported."; | |
506 return nullptr; | |
507 } | |
508 } else if (red_codec.params.empty()) { | |
509 LOG(LS_WARNING) << "RED params not present, using defaults"; | |
510 if (all_codecs.size() > 1) { | |
511 red_pt = all_codecs[1].id; | |
512 } | |
513 } | |
514 | |
515 // Try to find red_pt in |codecs|. | |
516 for (const AudioCodec& codec : all_codecs) { | |
517 if (codec.id == red_pt) { | |
518 return &codec; | |
519 } | |
520 } | |
521 LOG(LS_WARNING) << "RED params " << red_params << " are invalid."; | |
522 return nullptr; | |
523 } | |
452 }; | 524 }; |
453 | 525 |
454 const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[12] = { | 526 const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[12] = { |
455 { kOpusCodecName, 48000, 2, 111, true, { 10, 20, 40, 60 } }, | 527 { kOpusCodecName, 48000, 2, 111, true, { 10, 20, 40, 60 } }, |
456 { kIsacCodecName, 16000, 1, 103, true, { 30, 60 } }, | 528 { kIsacCodecName, 16000, 1, 103, true, { 30, 60 } }, |
457 { kIsacCodecName, 32000, 1, 104, true, { 30 } }, | 529 { kIsacCodecName, 32000, 1, 104, true, { 30 } }, |
458 // G722 should be advertised as 8000 Hz because of the RFC "bug". | 530 // G722 should be advertised as 8000 Hz because of the RFC "bug". |
459 { kG722CodecName, 8000, 1, 9, false, { 10, 20, 30, 40, 50, 60 } }, | 531 { kG722CodecName, 8000, 1, 9, false, { 10, 20, 30, 40, 50, 60 } }, |
460 { kIlbcCodecName, 8000, 1, 102, false, { 20, 30, 40, 60 } }, | 532 { kIlbcCodecName, 8000, 1, 102, false, { 20, 30, 40, 60 } }, |
461 { kPcmuCodecName, 8000, 1, 0, false, { 10, 20, 30, 40, 50, 60 } }, | 533 { kPcmuCodecName, 8000, 1, 0, false, { 10, 20, 30, 40, 50, 60 } }, |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
936 } | 1008 } |
937 | 1009 |
938 RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const { | 1010 RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const { |
939 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); | 1011 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
940 RtpCapabilities capabilities; | 1012 RtpCapabilities capabilities; |
941 capabilities.header_extensions.push_back(RtpHeaderExtension( | 1013 capabilities.header_extensions.push_back(RtpHeaderExtension( |
942 kRtpAudioLevelHeaderExtension, kRtpAudioLevelHeaderExtensionDefaultId)); | 1014 kRtpAudioLevelHeaderExtension, kRtpAudioLevelHeaderExtensionDefaultId)); |
943 capabilities.header_extensions.push_back( | 1015 capabilities.header_extensions.push_back( |
944 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, | 1016 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, |
945 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); | 1017 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); |
1018 if (webrtc::field_trial::FindFullName("WebRTC-Audio-SendSideBwe") == | |
1019 "Enabled") { | |
1020 capabilities.header_extensions.push_back(RtpHeaderExtension( | |
1021 kRtpTransportSequenceNumberHeaderExtension, | |
1022 kRtpTransportSequenceNumberHeaderExtensionDefaultId)); | |
1023 } | |
946 return capabilities; | 1024 return capabilities; |
947 } | 1025 } |
948 | 1026 |
949 int WebRtcVoiceEngine::GetLastEngineError() { | 1027 int WebRtcVoiceEngine::GetLastEngineError() { |
950 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1028 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
951 return voe_wrapper_->error(); | 1029 return voe_wrapper_->error(); |
952 } | 1030 } |
953 | 1031 |
954 void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace, | 1032 void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace, |
955 int length) { | 1033 int length) { |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1211 // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler. | 1289 // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler. |
1212 // PeerConnection will make sure invalidating the pointer before the object | 1290 // PeerConnection will make sure invalidating the pointer before the object |
1213 // goes away. | 1291 // goes away. |
1214 AudioRenderer* renderer_ = nullptr; | 1292 AudioRenderer* renderer_ = nullptr; |
1215 | 1293 |
1216 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream); | 1294 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream); |
1217 }; | 1295 }; |
1218 | 1296 |
1219 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { | 1297 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
1220 public: | 1298 public: |
1221 WebRtcAudioReceiveStream(int ch, uint32_t remote_ssrc, uint32_t local_ssrc, | 1299 WebRtcAudioReceiveStream(int ch, |
1222 bool use_combined_bwe, const std::string& sync_group, | 1300 uint32_t remote_ssrc, |
1301 uint32_t local_ssrc, | |
1302 bool use_transport_cc, | |
1303 const std::string& sync_group, | |
1223 const std::vector<webrtc::RtpExtension>& extensions, | 1304 const std::vector<webrtc::RtpExtension>& extensions, |
1224 webrtc::Call* call) | 1305 webrtc::Call* call) |
1225 : call_(call), | 1306 : call_(call), config_() { |
1226 config_() { | |
1227 RTC_DCHECK_GE(ch, 0); | 1307 RTC_DCHECK_GE(ch, 0); |
1228 RTC_DCHECK(call); | 1308 RTC_DCHECK(call); |
1229 config_.rtp.remote_ssrc = remote_ssrc; | 1309 config_.rtp.remote_ssrc = remote_ssrc; |
1230 config_.rtp.local_ssrc = local_ssrc; | 1310 config_.rtp.local_ssrc = local_ssrc; |
1231 config_.voe_channel_id = ch; | 1311 config_.voe_channel_id = ch; |
1232 config_.sync_group = sync_group; | 1312 config_.sync_group = sync_group; |
1233 RecreateAudioReceiveStream(use_combined_bwe, extensions); | 1313 RecreateAudioReceiveStream(use_transport_cc, extensions); |
1234 } | 1314 } |
1235 | 1315 |
1236 ~WebRtcAudioReceiveStream() { | 1316 ~WebRtcAudioReceiveStream() { |
1237 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1317 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1238 call_->DestroyAudioReceiveStream(stream_); | 1318 call_->DestroyAudioReceiveStream(stream_); |
1239 } | 1319 } |
1240 | 1320 |
1241 void RecreateAudioReceiveStream( | 1321 void RecreateAudioReceiveStream( |
1242 const std::vector<webrtc::RtpExtension>& extensions) { | 1322 const std::vector<webrtc::RtpExtension>& extensions) { |
1243 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1323 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1244 RecreateAudioReceiveStream(config_.combined_audio_video_bwe, extensions); | 1324 RecreateAudioReceiveStream(config_.rtp.transport_cc, extensions); |
1245 } | 1325 } |
1246 void RecreateAudioReceiveStream(bool use_combined_bwe) { | 1326 void RecreateAudioReceiveStream(bool use_transport_cc) { |
1247 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1327 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1248 RecreateAudioReceiveStream(use_combined_bwe, config_.rtp.extensions); | 1328 RecreateAudioReceiveStream(use_transport_cc, config_.rtp.extensions); |
1249 } | 1329 } |
1250 | 1330 |
1251 webrtc::AudioReceiveStream::Stats GetStats() const { | 1331 webrtc::AudioReceiveStream::Stats GetStats() const { |
1252 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1332 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1253 RTC_DCHECK(stream_); | 1333 RTC_DCHECK(stream_); |
1254 return stream_->GetStats(); | 1334 return stream_->GetStats(); |
1255 } | 1335 } |
1256 | 1336 |
1257 int channel() const { | 1337 int channel() const { |
1258 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1338 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1259 return config_.voe_channel_id; | 1339 return config_.voe_channel_id; |
1260 } | 1340 } |
1261 | 1341 |
1262 void SetRawAudioSink(rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) { | 1342 void SetRawAudioSink(rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) { |
1263 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1343 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1264 stream_->SetSink(std::move(sink)); | 1344 stream_->SetSink(std::move(sink)); |
1265 } | 1345 } |
1266 | 1346 |
1267 private: | 1347 private: |
1268 void RecreateAudioReceiveStream(bool use_combined_bwe, | 1348 void RecreateAudioReceiveStream( |
1349 bool use_transport_cc, | |
1269 const std::vector<webrtc::RtpExtension>& extensions) { | 1350 const std::vector<webrtc::RtpExtension>& extensions) { |
1270 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1351 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1271 if (stream_) { | 1352 if (stream_) { |
1272 call_->DestroyAudioReceiveStream(stream_); | 1353 call_->DestroyAudioReceiveStream(stream_); |
1273 stream_ = nullptr; | 1354 stream_ = nullptr; |
1274 } | 1355 } |
1275 config_.rtp.extensions = extensions; | 1356 config_.rtp.extensions = extensions; |
1276 config_.combined_audio_video_bwe = use_combined_bwe; | 1357 config_.rtp.transport_cc = use_transport_cc; |
1277 RTC_DCHECK(!stream_); | 1358 RTC_DCHECK(!stream_); |
1278 stream_ = call_->CreateAudioReceiveStream(config_); | 1359 stream_ = call_->CreateAudioReceiveStream(config_); |
1279 RTC_CHECK(stream_); | 1360 RTC_CHECK(stream_); |
1280 } | 1361 } |
1281 | 1362 |
1282 rtc::ThreadChecker worker_thread_checker_; | 1363 rtc::ThreadChecker worker_thread_checker_; |
1283 webrtc::Call* call_ = nullptr; | 1364 webrtc::Call* call_ = nullptr; |
1284 webrtc::AudioReceiveStream::Config config_; | 1365 webrtc::AudioReceiveStream::Config config_; |
1285 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if | 1366 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if |
1286 // configuration changes. | 1367 // configuration changes. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1362 } | 1443 } |
1363 std::vector<webrtc::RtpExtension> filtered_extensions = | 1444 std::vector<webrtc::RtpExtension> filtered_extensions = |
1364 FilterRtpExtensions(params.extensions, | 1445 FilterRtpExtensions(params.extensions, |
1365 webrtc::RtpExtension::IsSupportedForAudio, false); | 1446 webrtc::RtpExtension::IsSupportedForAudio, false); |
1366 if (recv_rtp_extensions_ != filtered_extensions) { | 1447 if (recv_rtp_extensions_ != filtered_extensions) { |
1367 recv_rtp_extensions_.swap(filtered_extensions); | 1448 recv_rtp_extensions_.swap(filtered_extensions); |
1368 for (auto& it : recv_streams_) { | 1449 for (auto& it : recv_streams_) { |
1369 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_); | 1450 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_); |
1370 } | 1451 } |
1371 } | 1452 } |
1372 | |
1373 return true; | 1453 return true; |
1374 } | 1454 } |
1375 | 1455 |
1376 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { | 1456 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { |
1377 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1457 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1378 LOG(LS_INFO) << "Setting voice channel options: " | 1458 LOG(LS_INFO) << "Setting voice channel options: " |
1379 << options.ToString(); | 1459 << options.ToString(); |
1380 | 1460 |
1381 // Check if DSCP value is changed from previous. | 1461 // Check if DSCP value is changed from previous. |
1382 bool dscp_option_changed = (options_.dscp != options.dscp); | 1462 bool dscp_option_changed = (options_.dscp != options.dscp); |
(...skipping 11 matching lines...) Expand all Loading... | |
1394 if (dscp_option_changed) { | 1474 if (dscp_option_changed) { |
1395 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; | 1475 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; |
1396 if (options_.dscp.value_or(false)) { | 1476 if (options_.dscp.value_or(false)) { |
1397 dscp = kAudioDscpValue; | 1477 dscp = kAudioDscpValue; |
1398 } | 1478 } |
1399 if (MediaChannel::SetDscp(dscp) != 0) { | 1479 if (MediaChannel::SetDscp(dscp) != 0) { |
1400 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; | 1480 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; |
1401 } | 1481 } |
1402 } | 1482 } |
1403 | 1483 |
1404 // TODO(solenberg): Don't recreate unless options changed. | |
1405 for (auto& it : recv_streams_) { | |
1406 it.second->RecreateAudioReceiveStream( | |
1407 options_.combined_audio_video_bwe.value_or(false)); | |
1408 } | |
1409 | |
1410 LOG(LS_INFO) << "Set voice channel options. Current options: " | 1484 LOG(LS_INFO) << "Set voice channel options. Current options: " |
1411 << options_.ToString(); | 1485 << options_.ToString(); |
1412 return true; | 1486 return true; |
1413 } | 1487 } |
1414 | 1488 |
1415 bool WebRtcVoiceMediaChannel::SetRecvCodecs( | 1489 bool WebRtcVoiceMediaChannel::SetRecvCodecs( |
1416 const std::vector<AudioCodec>& codecs) { | 1490 const std::vector<AudioCodec>& codecs) { |
1417 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1491 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1418 | 1492 |
1419 // Set the payload types to be used for incoming media. | 1493 // Set the payload types to be used for incoming media. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1484 bool WebRtcVoiceMediaChannel::SetSendCodecs( | 1558 bool WebRtcVoiceMediaChannel::SetSendCodecs( |
1485 int channel, const std::vector<AudioCodec>& codecs) { | 1559 int channel, const std::vector<AudioCodec>& codecs) { |
1486 // Disable VAD, FEC, and RED unless we know the other side wants them. | 1560 // Disable VAD, FEC, and RED unless we know the other side wants them. |
1487 engine()->voe()->codec()->SetVADStatus(channel, false); | 1561 engine()->voe()->codec()->SetVADStatus(channel, false); |
1488 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); | 1562 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); |
1489 engine()->voe()->rtp()->SetREDStatus(channel, false); | 1563 engine()->voe()->rtp()->SetREDStatus(channel, false); |
1490 engine()->voe()->codec()->SetFECStatus(channel, false); | 1564 engine()->voe()->codec()->SetFECStatus(channel, false); |
1491 | 1565 |
1492 // Scan through the list to figure out the codec to use for sending, along | 1566 // Scan through the list to figure out the codec to use for sending, along |
1493 // with the proper configuration for VAD. | 1567 // with the proper configuration for VAD. |
1494 bool found_send_codec = false; | |
1495 webrtc::CodecInst send_codec; | 1568 webrtc::CodecInst send_codec; |
1496 memset(&send_codec, 0, sizeof(send_codec)); | 1569 memset(&send_codec, 0, sizeof(send_codec)); |
1497 | 1570 |
1498 bool nack_enabled = nack_enabled_; | 1571 bool nack_enabled = nack_enabled_; |
1499 bool enable_codec_fec = false; | 1572 bool enable_codec_fec = false; |
1500 bool enable_opus_dtx = false; | 1573 bool enable_opus_dtx = false; |
1501 int opus_max_playback_rate = 0; | 1574 int opus_max_playback_rate = 0; |
1575 int red_payload_type = -1; | |
1502 | 1576 |
1503 // Set send codec (the first non-telephone-event/CN codec) | 1577 // Set send codec (the first non-telephone-event/CN codec) |
1504 for (const AudioCodec& codec : codecs) { | 1578 const AudioCodec* codec = WebRtcVoiceCodecs::GetPreferredCodec( |
1505 // Ignore codecs we don't know about. The negotiation step should prevent | 1579 codecs, &send_codec, &red_payload_type); |
1506 // this, but double-check to be sure. | 1580 if (codec) { |
1507 webrtc::CodecInst voe_codec; | 1581 if (red_payload_type != -1) { |
1508 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { | |
1509 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | |
1510 continue; | |
1511 } | |
1512 | |
1513 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { | |
1514 // Skip telephone-event/CN codec, which will be handled later. | |
1515 continue; | |
1516 } | |
1517 | |
1518 // We'll use the first codec in the list to actually send audio data. | |
1519 // Be sure to use the payload type requested by the remote side. | |
1520 // "red", for RED audio, is a special case where the actual codec to be | |
1521 // used is specified in params. | |
1522 if (IsCodec(codec, kRedCodecName)) { | |
1523 // Parse out the RED parameters. If we fail, just ignore RED; | |
1524 // we don't support all possible params/usage scenarios. | |
1525 if (!GetRedSendCodec(codec, codecs, &send_codec)) { | |
1526 continue; | |
1527 } | |
1528 | |
1529 // Enable redundant encoding of the specified codec. Treat any | 1582 // Enable redundant encoding of the specified codec. Treat any |
1530 // failure as a fatal internal error. | 1583 // failure as a fatal internal error. |
1531 LOG(LS_INFO) << "Enabling RED on channel " << channel; | 1584 LOG(LS_INFO) << "Enabling RED on channel " << channel; |
1532 if (engine()->voe()->rtp()->SetREDStatus(channel, true, codec.id) == -1) { | 1585 if (engine()->voe()->rtp()->SetREDStatus(channel, true, |
1533 LOG_RTCERR3(SetREDStatus, channel, true, codec.id); | 1586 red_payload_type) == -1) { |
1587 LOG_RTCERR3(SetREDStatus, channel, true, red_payload_type); | |
1534 return false; | 1588 return false; |
1535 } | 1589 } |
1536 } else { | 1590 } else { |
1537 send_codec = voe_codec; | 1591 nack_enabled = HasNack(*codec); |
1538 nack_enabled = IsNackEnabled(codec); | |
1539 // For Opus as the send codec, we are to determine inband FEC, maximum | 1592 // For Opus as the send codec, we are to determine inband FEC, maximum |
1540 // playback rate, and opus internal dtx. | 1593 // playback rate, and opus internal dtx. |
1541 if (IsCodec(codec, kOpusCodecName)) { | 1594 if (IsCodec(*codec, kOpusCodecName)) { |
1542 GetOpusConfig(codec, &send_codec, &enable_codec_fec, | 1595 GetOpusConfig(*codec, &send_codec, &enable_codec_fec, |
1543 &opus_max_playback_rate, &enable_opus_dtx); | 1596 &opus_max_playback_rate, &enable_opus_dtx); |
1544 } | 1597 } |
1545 | 1598 |
1546 // Set packet size if the AudioCodec param kCodecParamPTime is set. | 1599 // Set packet size if the AudioCodec param kCodecParamPTime is set. |
1547 int ptime_ms = 0; | 1600 int ptime_ms = 0; |
1548 if (codec.GetParam(kCodecParamPTime, &ptime_ms)) { | 1601 if (codec->GetParam(kCodecParamPTime, &ptime_ms)) { |
1549 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) { | 1602 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) { |
1550 LOG(LS_WARNING) << "Failed to set packet size for codec " | 1603 LOG(LS_WARNING) << "Failed to set packet size for codec " |
1551 << send_codec.plname; | 1604 << send_codec.plname; |
1552 return false; | 1605 return false; |
1553 } | 1606 } |
1554 } | 1607 } |
1555 } | 1608 } |
1556 found_send_codec = true; | |
1557 break; | |
1558 } | 1609 } |
1559 | 1610 |
1560 if (nack_enabled_ != nack_enabled) { | 1611 if (nack_enabled_ != nack_enabled) { |
1561 SetNack(channel, nack_enabled); | 1612 SetNack(channel, nack_enabled); |
1562 nack_enabled_ = nack_enabled; | 1613 nack_enabled_ = nack_enabled; |
1563 } | 1614 } |
1564 | 1615 if (!codec) { |
1565 if (!found_send_codec) { | |
1566 LOG(LS_WARNING) << "Received empty list of codecs."; | 1616 LOG(LS_WARNING) << "Received empty list of codecs."; |
1567 return false; | 1617 return false; |
1568 } | 1618 } |
1569 | 1619 |
1570 // Set the codec immediately, since SetVADStatus() depends on whether | 1620 // Set the codec immediately, since SetVADStatus() depends on whether |
1571 // the current codec is mono or stereo. | 1621 // the current codec is mono or stereo. |
1572 if (!SetSendCodec(channel, send_codec)) | 1622 if (!SetSendCodec(channel, send_codec)) |
1573 return false; | 1623 return false; |
1574 | 1624 |
1575 // FEC should be enabled after SetSendCodec. | 1625 // FEC should be enabled after SetSendCodec. |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1703 if (!SetSendCodecs(ch.second->channel(), codecs)) { | 1753 if (!SetSendCodecs(ch.second->channel(), codecs)) { |
1704 return false; | 1754 return false; |
1705 } | 1755 } |
1706 } | 1756 } |
1707 | 1757 |
1708 // Set nack status on receive channels and update |nack_enabled_|. | 1758 // Set nack status on receive channels and update |nack_enabled_|. |
1709 for (const auto& ch : recv_streams_) { | 1759 for (const auto& ch : recv_streams_) { |
1710 SetNack(ch.second->channel(), nack_enabled_); | 1760 SetNack(ch.second->channel(), nack_enabled_); |
1711 } | 1761 } |
1712 | 1762 |
1763 // Check if the transport cc feedback has changed on the preferred send codec, | |
1764 // and in that case reconfigure all receive streams. | |
the sun
2016/01/26 10:26:55
Is this then assuming that because we changed send
stefan-webrtc
2016/01/26 11:40:54
Yes, I think it does. Note that this is on the rec
| |
1765 webrtc::CodecInst voe_codec; | |
1766 int red_payload_type; | |
1767 const AudioCodec* send_codec = WebRtcVoiceCodecs::GetPreferredCodec( | |
1768 send_codecs_, &voe_codec, &red_payload_type); | |
1769 if (send_codec) { | |
1770 bool transport_cc = HasTransportCc(*send_codec); | |
1771 if (transport_cc_enabled_ != transport_cc) { | |
1772 LOG(LS_INFO) << "Recreate all the receive streams because the send " | |
1773 "codec has changed."; | |
1774 transport_cc_enabled_ = transport_cc; | |
1775 for (auto& kv : recv_streams_) { | |
1776 RTC_DCHECK(kv.second != nullptr); | |
1777 kv.second->RecreateAudioReceiveStream(transport_cc_enabled_); | |
1778 } | |
1779 } | |
1780 } | |
1781 | |
1713 return true; | 1782 return true; |
1714 } | 1783 } |
1715 | 1784 |
1716 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { | 1785 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { |
1717 if (nack_enabled) { | 1786 if (nack_enabled) { |
1718 LOG(LS_INFO) << "Enabling NACK for channel " << channel; | 1787 LOG(LS_INFO) << "Enabling NACK for channel " << channel; |
1719 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); | 1788 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); |
1720 } else { | 1789 } else { |
1721 LOG(LS_INFO) << "Disabling NACK for channel " << channel; | 1790 LOG(LS_INFO) << "Disabling NACK for channel " << channel; |
1722 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); | 1791 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2009 | 2078 |
2010 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); | 2079 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); |
2011 if (send_channel != -1) { | 2080 if (send_channel != -1) { |
2012 // Associate receive channel with first send channel (so the receive channel | 2081 // Associate receive channel with first send channel (so the receive channel |
2013 // can obtain RTT from the send channel) | 2082 // can obtain RTT from the send channel) |
2014 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); | 2083 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); |
2015 LOG(LS_INFO) << "VoiceEngine channel #" << channel | 2084 LOG(LS_INFO) << "VoiceEngine channel #" << channel |
2016 << " is associated with channel #" << send_channel << "."; | 2085 << " is associated with channel #" << send_channel << "."; |
2017 } | 2086 } |
2018 | 2087 |
2019 recv_streams_.insert(std::make_pair(ssrc, new WebRtcAudioReceiveStream( | 2088 transport_cc_enabled_ = |
2020 channel, ssrc, receiver_reports_ssrc_, | 2089 !send_codecs_.empty() ? HasTransportCc(send_codecs_[0]) : false; |
2021 options_.combined_audio_video_bwe.value_or(false), sp.sync_label, | 2090 |
2022 recv_rtp_extensions_, call_))); | 2091 recv_streams_.insert(std::make_pair( |
2092 ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_, | |
2093 transport_cc_enabled_, sp.sync_label, | |
2094 recv_rtp_extensions_, call_))); | |
2023 | 2095 |
2024 SetNack(channel, nack_enabled_); | 2096 SetNack(channel, nack_enabled_); |
2025 SetPlayout(channel, playout_); | 2097 SetPlayout(channel, playout_); |
2026 | 2098 |
2027 return true; | 2099 return true; |
2028 } | 2100 } |
2029 | 2101 |
2030 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { | 2102 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { |
2031 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 2103 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
2032 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; | 2104 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2470 | 2542 |
2471 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const { | 2543 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const { |
2472 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 2544 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
2473 const auto it = send_streams_.find(ssrc); | 2545 const auto it = send_streams_.find(ssrc); |
2474 if (it != send_streams_.end()) { | 2546 if (it != send_streams_.end()) { |
2475 return it->second->channel(); | 2547 return it->second->channel(); |
2476 } | 2548 } |
2477 return -1; | 2549 return -1; |
2478 } | 2550 } |
2479 | 2551 |
2480 bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec, | |
2481 const std::vector<AudioCodec>& all_codecs, webrtc::CodecInst* send_codec) { | |
2482 // Get the RED encodings from the parameter with no name. This may | |
2483 // change based on what is discussed on the Jingle list. | |
2484 // The encoding parameter is of the form "a/b"; we only support where | |
2485 // a == b. Verify this and parse out the value into red_pt. | |
2486 // If the parameter value is absent (as it will be until we wire up the | |
2487 // signaling of this message), use the second codec specified (i.e. the | |
2488 // one after "red") as the encoding parameter. | |
2489 int red_pt = -1; | |
2490 std::string red_params; | |
2491 CodecParameterMap::const_iterator it = red_codec.params.find(""); | |
2492 if (it != red_codec.params.end()) { | |
2493 red_params = it->second; | |
2494 std::vector<std::string> red_pts; | |
2495 if (rtc::split(red_params, '/', &red_pts) != 2 || | |
2496 red_pts[0] != red_pts[1] || | |
2497 !rtc::FromString(red_pts[0], &red_pt)) { | |
2498 LOG(LS_WARNING) << "RED params " << red_params << " not supported."; | |
2499 return false; | |
2500 } | |
2501 } else if (red_codec.params.empty()) { | |
2502 LOG(LS_WARNING) << "RED params not present, using defaults"; | |
2503 if (all_codecs.size() > 1) { | |
2504 red_pt = all_codecs[1].id; | |
2505 } | |
2506 } | |
2507 | |
2508 // Try to find red_pt in |codecs|. | |
2509 for (const AudioCodec& codec : all_codecs) { | |
2510 if (codec.id == red_pt) { | |
2511 // If we find the right codec, that will be the codec we pass to | |
2512 // SetSendCodec, with the desired payload type. | |
2513 if (WebRtcVoiceEngine::ToCodecInst(codec, send_codec)) { | |
2514 return true; | |
2515 } else { | |
2516 break; | |
2517 } | |
2518 } | |
2519 } | |
2520 LOG(LS_WARNING) << "RED params " << red_params << " are invalid."; | |
2521 return false; | |
2522 } | |
2523 | |
2524 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { | 2552 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { |
2525 if (playout) { | 2553 if (playout) { |
2526 LOG(LS_INFO) << "Starting playout for channel #" << channel; | 2554 LOG(LS_INFO) << "Starting playout for channel #" << channel; |
2527 if (engine()->voe()->base()->StartPlayout(channel) == -1) { | 2555 if (engine()->voe()->base()->StartPlayout(channel) == -1) { |
2528 LOG_RTCERR1(StartPlayout, channel); | 2556 LOG_RTCERR1(StartPlayout, channel); |
2529 return false; | 2557 return false; |
2530 } | 2558 } |
2531 } else { | 2559 } else { |
2532 LOG(LS_INFO) << "Stopping playout for channel #" << channel; | 2560 LOG(LS_INFO) << "Stopping playout for channel #" << channel; |
2533 engine()->voe()->base()->StopPlayout(channel); | 2561 engine()->voe()->base()->StopPlayout(channel); |
2534 } | 2562 } |
2535 return true; | 2563 return true; |
2536 } | 2564 } |
2537 } // namespace cricket | 2565 } // namespace cricket |
2538 | 2566 |
2539 #endif // HAVE_WEBRTC_VOICE | 2567 #endif // HAVE_WEBRTC_VOICE |
OLD | NEW |