Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(359)

Side by Side Diff: talk/media/webrtc/webrtcvoiceengine.cc

Issue 1604563002: Add send-side BWE to WebRtcVoiceEngine under a finch experiment. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Comments addressed. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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) {
419 // Set send codec (the first non-telephone-event/CN codec)
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)) {
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
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
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
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
1321 void RecreateAudioReceiveStream() {
1322 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1323 RecreateAudioReceiveStream(config_.rtp.transport_cc,
1324 config_.rtp.extensions);
1325 }
1241 void RecreateAudioReceiveStream( 1326 void RecreateAudioReceiveStream(
1242 const std::vector<webrtc::RtpExtension>& extensions) { 1327 const std::vector<webrtc::RtpExtension>& extensions) {
1243 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1328 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1244 RecreateAudioReceiveStream(config_.combined_audio_video_bwe, extensions); 1329 RecreateAudioReceiveStream(config_.rtp.transport_cc, extensions);
1245 } 1330 }
1246 void RecreateAudioReceiveStream(bool use_combined_bwe) { 1331 void RecreateAudioReceiveStream(bool use_transport_cc) {
1247 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1332 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1248 RecreateAudioReceiveStream(use_combined_bwe, config_.rtp.extensions); 1333 RecreateAudioReceiveStream(use_transport_cc, config_.rtp.extensions);
1249 } 1334 }
1250 1335
1251 webrtc::AudioReceiveStream::Stats GetStats() const { 1336 webrtc::AudioReceiveStream::Stats GetStats() const {
1252 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1337 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1253 RTC_DCHECK(stream_); 1338 RTC_DCHECK(stream_);
1254 return stream_->GetStats(); 1339 return stream_->GetStats();
1255 } 1340 }
1256 1341
1257 int channel() const { 1342 int channel() const {
1258 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1343 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1259 return config_.voe_channel_id; 1344 return config_.voe_channel_id;
1260 } 1345 }
1261 1346
1262 void SetRawAudioSink(rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) { 1347 void SetRawAudioSink(rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) {
1263 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1348 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1264 stream_->SetSink(std::move(sink)); 1349 stream_->SetSink(std::move(sink));
1265 } 1350 }
1266 1351
1267 private: 1352 private:
1268 void RecreateAudioReceiveStream(bool use_combined_bwe, 1353 void RecreateAudioReceiveStream(
1354 bool use_transport_cc,
1269 const std::vector<webrtc::RtpExtension>& extensions) { 1355 const std::vector<webrtc::RtpExtension>& extensions) {
1270 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1356 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1271 if (stream_) { 1357 if (stream_) {
1272 call_->DestroyAudioReceiveStream(stream_); 1358 call_->DestroyAudioReceiveStream(stream_);
1273 stream_ = nullptr; 1359 stream_ = nullptr;
1274 } 1360 }
1275 config_.rtp.extensions = extensions; 1361 config_.rtp.extensions = extensions;
1276 config_.combined_audio_video_bwe = use_combined_bwe; 1362 config_.rtp.transport_cc = use_transport_cc;
1277 RTC_DCHECK(!stream_); 1363 RTC_DCHECK(!stream_);
1278 stream_ = call_->CreateAudioReceiveStream(config_); 1364 stream_ = call_->CreateAudioReceiveStream(config_);
1279 RTC_CHECK(stream_); 1365 RTC_CHECK(stream_);
1280 } 1366 }
1281 1367
1282 rtc::ThreadChecker worker_thread_checker_; 1368 rtc::ThreadChecker worker_thread_checker_;
1283 webrtc::Call* call_ = nullptr; 1369 webrtc::Call* call_ = nullptr;
1284 webrtc::AudioReceiveStream::Config config_; 1370 webrtc::AudioReceiveStream::Config config_;
1285 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if 1371 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if
1286 // configuration changes. 1372 // configuration changes.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1362 } 1448 }
1363 std::vector<webrtc::RtpExtension> filtered_extensions = 1449 std::vector<webrtc::RtpExtension> filtered_extensions =
1364 FilterRtpExtensions(params.extensions, 1450 FilterRtpExtensions(params.extensions,
1365 webrtc::RtpExtension::IsSupportedForAudio, false); 1451 webrtc::RtpExtension::IsSupportedForAudio, false);
1366 if (recv_rtp_extensions_ != filtered_extensions) { 1452 if (recv_rtp_extensions_ != filtered_extensions) {
1367 recv_rtp_extensions_.swap(filtered_extensions); 1453 recv_rtp_extensions_.swap(filtered_extensions);
1368 for (auto& it : recv_streams_) { 1454 for (auto& it : recv_streams_) {
1369 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_); 1455 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_);
1370 } 1456 }
1371 } 1457 }
1372
1373 return true; 1458 return true;
1374 } 1459 }
1375 1460
1376 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { 1461 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
1377 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1462 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1378 LOG(LS_INFO) << "Setting voice channel options: " 1463 LOG(LS_INFO) << "Setting voice channel options: "
1379 << options.ToString(); 1464 << options.ToString();
1380 1465
1381 // Check if DSCP value is changed from previous. 1466 // Check if DSCP value is changed from previous.
1382 bool dscp_option_changed = (options_.dscp != options.dscp); 1467 bool dscp_option_changed = (options_.dscp != options.dscp);
(...skipping 13 matching lines...) Expand all
1396 if (options_.dscp.value_or(false)) { 1481 if (options_.dscp.value_or(false)) {
1397 dscp = kAudioDscpValue; 1482 dscp = kAudioDscpValue;
1398 } 1483 }
1399 if (MediaChannel::SetDscp(dscp) != 0) { 1484 if (MediaChannel::SetDscp(dscp) != 0) {
1400 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; 1485 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel";
1401 } 1486 }
1402 } 1487 }
1403 1488
1404 // TODO(solenberg): Don't recreate unless options changed. 1489 // TODO(solenberg): Don't recreate unless options changed.
1405 for (auto& it : recv_streams_) { 1490 for (auto& it : recv_streams_) {
1406 it.second->RecreateAudioReceiveStream( 1491 it.second->RecreateAudioReceiveStream();
1407 options_.combined_audio_video_bwe.value_or(false));
1408 } 1492 }
1409 1493
1410 LOG(LS_INFO) << "Set voice channel options. Current options: " 1494 LOG(LS_INFO) << "Set voice channel options. Current options: "
1411 << options_.ToString(); 1495 << options_.ToString();
1412 return true; 1496 return true;
1413 } 1497 }
1414 1498
1415 bool WebRtcVoiceMediaChannel::SetRecvCodecs( 1499 bool WebRtcVoiceMediaChannel::SetRecvCodecs(
1416 const std::vector<AudioCodec>& codecs) { 1500 const std::vector<AudioCodec>& codecs) {
1417 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1501 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1484 bool WebRtcVoiceMediaChannel::SetSendCodecs( 1568 bool WebRtcVoiceMediaChannel::SetSendCodecs(
1485 int channel, const std::vector<AudioCodec>& codecs) { 1569 int channel, const std::vector<AudioCodec>& codecs) {
1486 // Disable VAD, FEC, and RED unless we know the other side wants them. 1570 // Disable VAD, FEC, and RED unless we know the other side wants them.
1487 engine()->voe()->codec()->SetVADStatus(channel, false); 1571 engine()->voe()->codec()->SetVADStatus(channel, false);
1488 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 1572 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
1489 engine()->voe()->rtp()->SetREDStatus(channel, false); 1573 engine()->voe()->rtp()->SetREDStatus(channel, false);
1490 engine()->voe()->codec()->SetFECStatus(channel, false); 1574 engine()->voe()->codec()->SetFECStatus(channel, false);
1491 1575
1492 // Scan through the list to figure out the codec to use for sending, along 1576 // Scan through the list to figure out the codec to use for sending, along
1493 // with the proper configuration for VAD. 1577 // with the proper configuration for VAD.
1494 bool found_send_codec = false;
1495 webrtc::CodecInst send_codec; 1578 webrtc::CodecInst send_codec;
1496 memset(&send_codec, 0, sizeof(send_codec)); 1579 memset(&send_codec, 0, sizeof(send_codec));
1497 1580
1498 bool nack_enabled = nack_enabled_; 1581 bool nack_enabled = nack_enabled_;
1499 bool enable_codec_fec = false; 1582 bool enable_codec_fec = false;
1500 bool enable_opus_dtx = false; 1583 bool enable_opus_dtx = false;
1501 int opus_max_playback_rate = 0; 1584 int opus_max_playback_rate = 0;
1585 int red_payload_type = -1;
1502 1586
1503 // Set send codec (the first non-telephone-event/CN codec) 1587 // Set send codec (the first non-telephone-event/CN codec)
1504 for (const AudioCodec& codec : codecs) { 1588 const AudioCodec* codec = WebRtcVoiceCodecs::GetPreferredCodec(
1505 // Ignore codecs we don't know about. The negotiation step should prevent 1589 codecs, &send_codec, &red_payload_type);
1506 // this, but double-check to be sure. 1590 if (codec) {
1507 webrtc::CodecInst voe_codec; 1591 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 1592 // Enable redundant encoding of the specified codec. Treat any
1530 // failure as a fatal internal error. 1593 // failure as a fatal internal error.
1531 LOG(LS_INFO) << "Enabling RED on channel " << channel; 1594 LOG(LS_INFO) << "Enabling RED on channel " << channel;
1532 if (engine()->voe()->rtp()->SetREDStatus(channel, true, codec.id) == -1) { 1595 if (engine()->voe()->rtp()->SetREDStatus(channel, true,
1533 LOG_RTCERR3(SetREDStatus, channel, true, codec.id); 1596 red_payload_type) == -1) {
1597 LOG_RTCERR3(SetREDStatus, channel, true, red_payload_type);
1534 return false; 1598 return false;
1535 } 1599 }
1536 } else { 1600 } else {
1537 send_codec = voe_codec; 1601 nack_enabled = HasNack(*codec);
1538 nack_enabled = IsNackEnabled(codec);
1539 // For Opus as the send codec, we are to determine inband FEC, maximum 1602 // For Opus as the send codec, we are to determine inband FEC, maximum
1540 // playback rate, and opus internal dtx. 1603 // playback rate, and opus internal dtx.
1541 if (IsCodec(codec, kOpusCodecName)) { 1604 if (IsCodec(*codec, kOpusCodecName)) {
1542 GetOpusConfig(codec, &send_codec, &enable_codec_fec, 1605 GetOpusConfig(*codec, &send_codec, &enable_codec_fec,
1543 &opus_max_playback_rate, &enable_opus_dtx); 1606 &opus_max_playback_rate, &enable_opus_dtx);
1544 } 1607 }
1545 1608
1546 // Set packet size if the AudioCodec param kCodecParamPTime is set. 1609 // Set packet size if the AudioCodec param kCodecParamPTime is set.
1547 int ptime_ms = 0; 1610 int ptime_ms = 0;
1548 if (codec.GetParam(kCodecParamPTime, &ptime_ms)) { 1611 if (codec->GetParam(kCodecParamPTime, &ptime_ms)) {
1549 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) { 1612 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) {
1550 LOG(LS_WARNING) << "Failed to set packet size for codec " 1613 LOG(LS_WARNING) << "Failed to set packet size for codec "
1551 << send_codec.plname; 1614 << send_codec.plname;
1552 return false; 1615 return false;
1553 } 1616 }
1554 } 1617 }
1555 } 1618 }
1556 found_send_codec = true;
1557 break;
1558 } 1619 }
1559 1620
1560 if (nack_enabled_ != nack_enabled) { 1621 if (nack_enabled_ != nack_enabled) {
1561 SetNack(channel, nack_enabled); 1622 SetNack(channel, nack_enabled);
1562 nack_enabled_ = nack_enabled; 1623 nack_enabled_ = nack_enabled;
1563 } 1624 }
1564 1625 if (!codec) {
1565 if (!found_send_codec) {
1566 LOG(LS_WARNING) << "Received empty list of codecs."; 1626 LOG(LS_WARNING) << "Received empty list of codecs.";
1567 return false; 1627 return false;
1568 } 1628 }
1569 1629
1570 // Set the codec immediately, since SetVADStatus() depends on whether 1630 // Set the codec immediately, since SetVADStatus() depends on whether
1571 // the current codec is mono or stereo. 1631 // the current codec is mono or stereo.
1572 if (!SetSendCodec(channel, send_codec)) 1632 if (!SetSendCodec(channel, send_codec))
1573 return false; 1633 return false;
1574 1634
1575 // FEC should be enabled after SetSendCodec. 1635 // FEC should be enabled after SetSendCodec.
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1703 if (!SetSendCodecs(ch.second->channel(), codecs)) { 1763 if (!SetSendCodecs(ch.second->channel(), codecs)) {
1704 return false; 1764 return false;
1705 } 1765 }
1706 } 1766 }
1707 1767
1708 // Set nack status on receive channels and update |nack_enabled_|. 1768 // Set nack status on receive channels and update |nack_enabled_|.
1709 for (const auto& ch : recv_streams_) { 1769 for (const auto& ch : recv_streams_) {
1710 SetNack(ch.second->channel(), nack_enabled_); 1770 SetNack(ch.second->channel(), nack_enabled_);
1711 } 1771 }
1712 1772
1773 // Check if the transport cc feedback has changed on the preferred send codec,
1774 // and in that case reconfigure all receive streams.
1775 webrtc::CodecInst voe_codec;
1776 int red_payload_type;
1777 const AudioCodec* send_codec = WebRtcVoiceCodecs::GetPreferredCodec(
1778 send_codecs_, &voe_codec, &red_payload_type);
1779 if (send_codec) {
1780 bool transport_cc = HasTransportCc(*send_codec);
1781 if (transport_cc_enabled_ != transport_cc) {
1782 LOG(LS_INFO) << "Recreate all the receive streams because the send "
1783 "codec has changed.";
1784 transport_cc_enabled_ = transport_cc;
1785 for (auto& kv : recv_streams_) {
1786 RTC_DCHECK(kv.second != nullptr);
1787 kv.second->RecreateAudioReceiveStream(transport_cc_enabled_);
1788 }
1789 }
1790 }
1791
1713 return true; 1792 return true;
1714 } 1793 }
1715 1794
1716 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { 1795 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) {
1717 if (nack_enabled) { 1796 if (nack_enabled) {
1718 LOG(LS_INFO) << "Enabling NACK for channel " << channel; 1797 LOG(LS_INFO) << "Enabling NACK for channel " << channel;
1719 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); 1798 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets);
1720 } else { 1799 } else {
1721 LOG(LS_INFO) << "Disabling NACK for channel " << channel; 1800 LOG(LS_INFO) << "Disabling NACK for channel " << channel;
1722 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 1801 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
2009 2088
2010 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); 2089 const int send_channel = GetSendChannelId(receiver_reports_ssrc_);
2011 if (send_channel != -1) { 2090 if (send_channel != -1) {
2012 // Associate receive channel with first send channel (so the receive channel 2091 // Associate receive channel with first send channel (so the receive channel
2013 // can obtain RTT from the send channel) 2092 // can obtain RTT from the send channel)
2014 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); 2093 engine()->voe()->base()->AssociateSendChannel(channel, send_channel);
2015 LOG(LS_INFO) << "VoiceEngine channel #" << channel 2094 LOG(LS_INFO) << "VoiceEngine channel #" << channel
2016 << " is associated with channel #" << send_channel << "."; 2095 << " is associated with channel #" << send_channel << ".";
2017 } 2096 }
2018 2097
2019 recv_streams_.insert(std::make_pair(ssrc, new WebRtcAudioReceiveStream( 2098 transport_cc_enabled_ =
2020 channel, ssrc, receiver_reports_ssrc_, 2099 !send_codecs_.empty() ? HasTransportCc(send_codecs_[0]) : false;
2021 options_.combined_audio_video_bwe.value_or(false), sp.sync_label, 2100
2022 recv_rtp_extensions_, call_))); 2101 recv_streams_.insert(std::make_pair(
2102 ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_,
2103 transport_cc_enabled_, sp.sync_label,
2104 recv_rtp_extensions_, call_)));
2023 2105
2024 SetNack(channel, nack_enabled_); 2106 SetNack(channel, nack_enabled_);
2025 SetPlayout(channel, playout_); 2107 SetPlayout(channel, playout_);
2026 2108
2027 return true; 2109 return true;
2028 } 2110 }
2029 2111
2030 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { 2112 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
2031 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2113 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2032 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; 2114 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
2470 2552
2471 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const { 2553 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
2472 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2554 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2473 const auto it = send_streams_.find(ssrc); 2555 const auto it = send_streams_.find(ssrc);
2474 if (it != send_streams_.end()) { 2556 if (it != send_streams_.end()) {
2475 return it->second->channel(); 2557 return it->second->channel();
2476 } 2558 }
2477 return -1; 2559 return -1;
2478 } 2560 }
2479 2561
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) { 2562 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) {
2525 if (playout) { 2563 if (playout) {
2526 LOG(LS_INFO) << "Starting playout for channel #" << channel; 2564 LOG(LS_INFO) << "Starting playout for channel #" << channel;
2527 if (engine()->voe()->base()->StartPlayout(channel) == -1) { 2565 if (engine()->voe()->base()->StartPlayout(channel) == -1) {
2528 LOG_RTCERR1(StartPlayout, channel); 2566 LOG_RTCERR1(StartPlayout, channel);
2529 return false; 2567 return false;
2530 } 2568 }
2531 } else { 2569 } else {
2532 LOG(LS_INFO) << "Stopping playout for channel #" << channel; 2570 LOG(LS_INFO) << "Stopping playout for channel #" << channel;
2533 engine()->voe()->base()->StopPlayout(channel); 2571 engine()->voe()->base()->StopPlayout(channel);
2534 } 2572 }
2535 return true; 2573 return true;
2536 } 2574 }
2537 } // namespace cricket 2575 } // namespace cricket
2538 2576
2539 #endif // HAVE_WEBRTC_VOICE 2577 #endif // HAVE_WEBRTC_VOICE
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698