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

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, 10 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
« no previous file with comments | « talk/media/webrtc/webrtcvoiceengine.h ('k') | talk/media/webrtc/webrtcvoiceengine_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 RTC_DCHECK(voe_codec);
420 RTC_DCHECK(red_payload_type);
421 // Select the preferred send codec (the first non-telephone-event/CN codec).
422 for (const AudioCodec& codec : codecs) {
423 *red_payload_type = -1;
424 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) {
425 // Skip telephone-event/CN codec, which will be handled later.
426 continue;
427 }
428
429 // We'll use the first codec in the list to actually send audio data.
430 // Be sure to use the payload type requested by the remote side.
431 // "red", for RED audio, is a special case where the actual codec to be
432 // used is specified in params.
433 const AudioCodec* found_codec = &codec;
434 if (IsCodec(*found_codec, kRedCodecName)) {
435 // Parse out the RED parameters. If we fail, just ignore RED;
436 // we don't support all possible params/usage scenarios.
437 *red_payload_type = codec.id;
438 found_codec = GetRedSendCodec(*found_codec, codecs);
439 if (!found_codec) {
440 continue;
441 }
442 }
443 // Ignore codecs we don't know about. The negotiation step should prevent
444 // this, but double-check to be sure.
445 if (!ToCodecInst(*found_codec, voe_codec)) {
446 LOG(LS_WARNING) << "Unknown codec " << ToString(*found_codec);
447 continue;
448 }
449 return found_codec;
450 }
451 return nullptr;
452 }
453
418 private: 454 private:
419 static const int kMaxNumPacketSize = 6; 455 static const int kMaxNumPacketSize = 6;
420 struct CodecPref { 456 struct CodecPref {
421 const char* name; 457 const char* name;
422 int clockrate; 458 int clockrate;
423 size_t channels; 459 size_t channels;
424 int payload_type; 460 int payload_type;
425 bool is_multi_rate; 461 bool is_multi_rate;
426 int packet_sizes_ms[kMaxNumPacketSize]; 462 int packet_sizes_ms[kMaxNumPacketSize];
427 }; 463 };
(...skipping 14 matching lines...) Expand all
442 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz 478 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz
443 // codec. 479 // codec.
444 static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { 480 static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) {
445 if (IsCodec(*voe_codec, kG722CodecName)) { 481 if (IsCodec(*voe_codec, kG722CodecName)) {
446 // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine 482 // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine
447 // has changed, and this special case is no longer needed. 483 // has changed, and this special case is no longer needed.
448 RTC_DCHECK(voe_codec->plfreq != new_plfreq); 484 RTC_DCHECK(voe_codec->plfreq != new_plfreq);
449 voe_codec->plfreq = new_plfreq; 485 voe_codec->plfreq = new_plfreq;
450 } 486 }
451 } 487 }
488
489 static const AudioCodec* GetRedSendCodec(
490 const AudioCodec& red_codec,
491 const std::vector<AudioCodec>& all_codecs) {
492 // Get the RED encodings from the parameter with no name. This may
493 // change based on what is discussed on the Jingle list.
494 // The encoding parameter is of the form "a/b"; we only support where
495 // a == b. Verify this and parse out the value into red_pt.
496 // If the parameter value is absent (as it will be until we wire up the
497 // signaling of this message), use the second codec specified (i.e. the
498 // one after "red") as the encoding parameter.
499 int red_pt = -1;
500 std::string red_params;
501 CodecParameterMap::const_iterator it = red_codec.params.find("");
502 if (it != red_codec.params.end()) {
503 red_params = it->second;
504 std::vector<std::string> red_pts;
505 if (rtc::split(red_params, '/', &red_pts) != 2 ||
506 red_pts[0] != red_pts[1] || !rtc::FromString(red_pts[0], &red_pt)) {
507 LOG(LS_WARNING) << "RED params " << red_params << " not supported.";
508 return nullptr;
509 }
510 } else if (red_codec.params.empty()) {
511 LOG(LS_WARNING) << "RED params not present, using defaults";
512 if (all_codecs.size() > 1) {
513 red_pt = all_codecs[1].id;
514 }
515 }
516
517 // Try to find red_pt in |codecs|.
518 for (const AudioCodec& codec : all_codecs) {
519 if (codec.id == red_pt) {
520 return &codec;
521 }
522 }
523 LOG(LS_WARNING) << "RED params " << red_params << " are invalid.";
524 return nullptr;
525 }
452 }; 526 };
453 527
454 const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[12] = { 528 const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[12] = {
455 { kOpusCodecName, 48000, 2, 111, true, { 10, 20, 40, 60 } }, 529 { kOpusCodecName, 48000, 2, 111, true, { 10, 20, 40, 60 } },
456 { kIsacCodecName, 16000, 1, 103, true, { 30, 60 } }, 530 { kIsacCodecName, 16000, 1, 103, true, { 30, 60 } },
457 { kIsacCodecName, 32000, 1, 104, true, { 30 } }, 531 { kIsacCodecName, 32000, 1, 104, true, { 30 } },
458 // G722 should be advertised as 8000 Hz because of the RFC "bug". 532 // G722 should be advertised as 8000 Hz because of the RFC "bug".
459 { kG722CodecName, 8000, 1, 9, false, { 10, 20, 30, 40, 50, 60 } }, 533 { kG722CodecName, 8000, 1, 9, false, { 10, 20, 30, 40, 50, 60 } },
460 { kIlbcCodecName, 8000, 1, 102, false, { 20, 30, 40, 60 } }, 534 { kIlbcCodecName, 8000, 1, 102, false, { 20, 30, 40, 60 } },
461 { kPcmuCodecName, 8000, 1, 0, false, { 10, 20, 30, 40, 50, 60 } }, 535 { kPcmuCodecName, 8000, 1, 0, false, { 10, 20, 30, 40, 50, 60 } },
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 } 1010 }
937 1011
938 RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const { 1012 RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const {
939 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); 1013 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
940 RtpCapabilities capabilities; 1014 RtpCapabilities capabilities;
941 capabilities.header_extensions.push_back(RtpHeaderExtension( 1015 capabilities.header_extensions.push_back(RtpHeaderExtension(
942 kRtpAudioLevelHeaderExtension, kRtpAudioLevelHeaderExtensionDefaultId)); 1016 kRtpAudioLevelHeaderExtension, kRtpAudioLevelHeaderExtensionDefaultId));
943 capabilities.header_extensions.push_back( 1017 capabilities.header_extensions.push_back(
944 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, 1018 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
945 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); 1019 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
1020 if (webrtc::field_trial::FindFullName("WebRTC-Audio-SendSideBwe") ==
1021 "Enabled") {
1022 capabilities.header_extensions.push_back(RtpHeaderExtension(
1023 kRtpTransportSequenceNumberHeaderExtension,
1024 kRtpTransportSequenceNumberHeaderExtensionDefaultId));
1025 }
946 return capabilities; 1026 return capabilities;
947 } 1027 }
948 1028
949 int WebRtcVoiceEngine::GetLastEngineError() { 1029 int WebRtcVoiceEngine::GetLastEngineError() {
950 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1030 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
951 return voe_wrapper_->error(); 1031 return voe_wrapper_->error();
952 } 1032 }
953 1033
954 void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace, 1034 void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
955 int length) { 1035 int length) {
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler. 1291 // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler.
1212 // PeerConnection will make sure invalidating the pointer before the object 1292 // PeerConnection will make sure invalidating the pointer before the object
1213 // goes away. 1293 // goes away.
1214 AudioRenderer* renderer_ = nullptr; 1294 AudioRenderer* renderer_ = nullptr;
1215 1295
1216 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream); 1296 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
1217 }; 1297 };
1218 1298
1219 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { 1299 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
1220 public: 1300 public:
1221 WebRtcAudioReceiveStream(int ch, uint32_t remote_ssrc, uint32_t local_ssrc, 1301 WebRtcAudioReceiveStream(int ch,
1222 bool use_combined_bwe, const std::string& sync_group, 1302 uint32_t remote_ssrc,
1303 uint32_t local_ssrc,
1304 bool use_transport_cc,
1305 const std::string& sync_group,
1223 const std::vector<webrtc::RtpExtension>& extensions, 1306 const std::vector<webrtc::RtpExtension>& extensions,
1224 webrtc::Call* call) 1307 webrtc::Call* call)
1225 : call_(call), 1308 : call_(call), config_() {
1226 config_() {
1227 RTC_DCHECK_GE(ch, 0); 1309 RTC_DCHECK_GE(ch, 0);
1228 RTC_DCHECK(call); 1310 RTC_DCHECK(call);
1229 config_.rtp.remote_ssrc = remote_ssrc; 1311 config_.rtp.remote_ssrc = remote_ssrc;
1230 config_.rtp.local_ssrc = local_ssrc; 1312 config_.rtp.local_ssrc = local_ssrc;
1231 config_.voe_channel_id = ch; 1313 config_.voe_channel_id = ch;
1232 config_.sync_group = sync_group; 1314 config_.sync_group = sync_group;
1233 RecreateAudioReceiveStream(use_combined_bwe, extensions); 1315 RecreateAudioReceiveStream(use_transport_cc, extensions);
1234 } 1316 }
1235 1317
1236 ~WebRtcAudioReceiveStream() { 1318 ~WebRtcAudioReceiveStream() {
1237 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1319 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1238 call_->DestroyAudioReceiveStream(stream_); 1320 call_->DestroyAudioReceiveStream(stream_);
1239 } 1321 }
1240 1322
1241 void RecreateAudioReceiveStream( 1323 void RecreateAudioReceiveStream(
1242 const std::vector<webrtc::RtpExtension>& extensions) { 1324 const std::vector<webrtc::RtpExtension>& extensions) {
1243 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1325 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1244 RecreateAudioReceiveStream(config_.combined_audio_video_bwe, extensions); 1326 RecreateAudioReceiveStream(config_.rtp.transport_cc, extensions);
1245 } 1327 }
1246 void RecreateAudioReceiveStream(bool use_combined_bwe) { 1328 void RecreateAudioReceiveStream(bool use_transport_cc) {
1247 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1329 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1248 RecreateAudioReceiveStream(use_combined_bwe, config_.rtp.extensions); 1330 RecreateAudioReceiveStream(use_transport_cc, config_.rtp.extensions);
1249 } 1331 }
1250 1332
1251 webrtc::AudioReceiveStream::Stats GetStats() const { 1333 webrtc::AudioReceiveStream::Stats GetStats() const {
1252 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1334 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1253 RTC_DCHECK(stream_); 1335 RTC_DCHECK(stream_);
1254 return stream_->GetStats(); 1336 return stream_->GetStats();
1255 } 1337 }
1256 1338
1257 int channel() const { 1339 int channel() const {
1258 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1340 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1259 return config_.voe_channel_id; 1341 return config_.voe_channel_id;
1260 } 1342 }
1261 1343
1262 void SetRawAudioSink(rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) { 1344 void SetRawAudioSink(rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) {
1263 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1345 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1264 stream_->SetSink(std::move(sink)); 1346 stream_->SetSink(std::move(sink));
1265 } 1347 }
1266 1348
1267 private: 1349 private:
1268 void RecreateAudioReceiveStream(bool use_combined_bwe, 1350 void RecreateAudioReceiveStream(
1351 bool use_transport_cc,
1269 const std::vector<webrtc::RtpExtension>& extensions) { 1352 const std::vector<webrtc::RtpExtension>& extensions) {
1270 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1353 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1271 if (stream_) { 1354 if (stream_) {
1272 call_->DestroyAudioReceiveStream(stream_); 1355 call_->DestroyAudioReceiveStream(stream_);
1273 stream_ = nullptr; 1356 stream_ = nullptr;
1274 } 1357 }
1275 config_.rtp.extensions = extensions; 1358 config_.rtp.extensions = extensions;
1276 config_.combined_audio_video_bwe = use_combined_bwe; 1359 config_.rtp.transport_cc = use_transport_cc;
1277 RTC_DCHECK(!stream_); 1360 RTC_DCHECK(!stream_);
1278 stream_ = call_->CreateAudioReceiveStream(config_); 1361 stream_ = call_->CreateAudioReceiveStream(config_);
1279 RTC_CHECK(stream_); 1362 RTC_CHECK(stream_);
1280 } 1363 }
1281 1364
1282 rtc::ThreadChecker worker_thread_checker_; 1365 rtc::ThreadChecker worker_thread_checker_;
1283 webrtc::Call* call_ = nullptr; 1366 webrtc::Call* call_ = nullptr;
1284 webrtc::AudioReceiveStream::Config config_; 1367 webrtc::AudioReceiveStream::Config config_;
1285 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if 1368 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if
1286 // configuration changes. 1369 // configuration changes.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1362 } 1445 }
1363 std::vector<webrtc::RtpExtension> filtered_extensions = 1446 std::vector<webrtc::RtpExtension> filtered_extensions =
1364 FilterRtpExtensions(params.extensions, 1447 FilterRtpExtensions(params.extensions,
1365 webrtc::RtpExtension::IsSupportedForAudio, false); 1448 webrtc::RtpExtension::IsSupportedForAudio, false);
1366 if (recv_rtp_extensions_ != filtered_extensions) { 1449 if (recv_rtp_extensions_ != filtered_extensions) {
1367 recv_rtp_extensions_.swap(filtered_extensions); 1450 recv_rtp_extensions_.swap(filtered_extensions);
1368 for (auto& it : recv_streams_) { 1451 for (auto& it : recv_streams_) {
1369 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_); 1452 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_);
1370 } 1453 }
1371 } 1454 }
1372
1373 return true; 1455 return true;
1374 } 1456 }
1375 1457
1376 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { 1458 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
1377 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1459 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1378 LOG(LS_INFO) << "Setting voice channel options: " 1460 LOG(LS_INFO) << "Setting voice channel options: "
1379 << options.ToString(); 1461 << options.ToString();
1380 1462
1381 // Check if DSCP value is changed from previous. 1463 // Check if DSCP value is changed from previous.
1382 bool dscp_option_changed = (options_.dscp != options.dscp); 1464 bool dscp_option_changed = (options_.dscp != options.dscp);
(...skipping 11 matching lines...) Expand all
1394 if (dscp_option_changed) { 1476 if (dscp_option_changed) {
1395 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; 1477 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT;
1396 if (options_.dscp.value_or(false)) { 1478 if (options_.dscp.value_or(false)) {
1397 dscp = kAudioDscpValue; 1479 dscp = kAudioDscpValue;
1398 } 1480 }
1399 if (MediaChannel::SetDscp(dscp) != 0) { 1481 if (MediaChannel::SetDscp(dscp) != 0) {
1400 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; 1482 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel";
1401 } 1483 }
1402 } 1484 }
1403 1485
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: " 1486 LOG(LS_INFO) << "Set voice channel options. Current options: "
1411 << options_.ToString(); 1487 << options_.ToString();
1412 return true; 1488 return true;
1413 } 1489 }
1414 1490
1415 bool WebRtcVoiceMediaChannel::SetRecvCodecs( 1491 bool WebRtcVoiceMediaChannel::SetRecvCodecs(
1416 const std::vector<AudioCodec>& codecs) { 1492 const std::vector<AudioCodec>& codecs) {
1417 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1493 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1418 1494
1419 // Set the payload types to be used for incoming media. 1495 // Set the payload types to be used for incoming media.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1484 bool WebRtcVoiceMediaChannel::SetSendCodecs( 1560 bool WebRtcVoiceMediaChannel::SetSendCodecs(
1485 int channel, const std::vector<AudioCodec>& codecs) { 1561 int channel, const std::vector<AudioCodec>& codecs) {
1486 // Disable VAD, FEC, and RED unless we know the other side wants them. 1562 // Disable VAD, FEC, and RED unless we know the other side wants them.
1487 engine()->voe()->codec()->SetVADStatus(channel, false); 1563 engine()->voe()->codec()->SetVADStatus(channel, false);
1488 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 1564 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
1489 engine()->voe()->rtp()->SetREDStatus(channel, false); 1565 engine()->voe()->rtp()->SetREDStatus(channel, false);
1490 engine()->voe()->codec()->SetFECStatus(channel, false); 1566 engine()->voe()->codec()->SetFECStatus(channel, false);
1491 1567
1492 // Scan through the list to figure out the codec to use for sending, along 1568 // Scan through the list to figure out the codec to use for sending, along
1493 // with the proper configuration for VAD. 1569 // with the proper configuration for VAD.
1494 bool found_send_codec = false;
1495 webrtc::CodecInst send_codec; 1570 webrtc::CodecInst send_codec;
1496 memset(&send_codec, 0, sizeof(send_codec)); 1571 memset(&send_codec, 0, sizeof(send_codec));
1497 1572
1498 bool nack_enabled = nack_enabled_; 1573 bool nack_enabled = nack_enabled_;
1499 bool enable_codec_fec = false; 1574 bool enable_codec_fec = false;
1500 bool enable_opus_dtx = false; 1575 bool enable_opus_dtx = false;
1501 int opus_max_playback_rate = 0; 1576 int opus_max_playback_rate = 0;
1577 int red_payload_type = -1;
1502 1578
1503 // Set send codec (the first non-telephone-event/CN codec) 1579 // Set send codec (the first non-telephone-event/CN codec)
1504 for (const AudioCodec& codec : codecs) { 1580 const AudioCodec* codec = WebRtcVoiceCodecs::GetPreferredCodec(
1505 // Ignore codecs we don't know about. The negotiation step should prevent 1581 codecs, &send_codec, &red_payload_type);
1506 // this, but double-check to be sure. 1582 if (codec) {
1507 webrtc::CodecInst voe_codec; 1583 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 1584 // Enable redundant encoding of the specified codec. Treat any
1530 // failure as a fatal internal error. 1585 // failure as a fatal internal error.
1531 LOG(LS_INFO) << "Enabling RED on channel " << channel; 1586 LOG(LS_INFO) << "Enabling RED on channel " << channel;
1532 if (engine()->voe()->rtp()->SetREDStatus(channel, true, codec.id) == -1) { 1587 if (engine()->voe()->rtp()->SetREDStatus(channel, true,
1533 LOG_RTCERR3(SetREDStatus, channel, true, codec.id); 1588 red_payload_type) == -1) {
1589 LOG_RTCERR3(SetREDStatus, channel, true, red_payload_type);
1534 return false; 1590 return false;
1535 } 1591 }
1536 } else { 1592 } else {
1537 send_codec = voe_codec; 1593 nack_enabled = HasNack(*codec);
1538 nack_enabled = IsNackEnabled(codec);
1539 // For Opus as the send codec, we are to determine inband FEC, maximum 1594 // For Opus as the send codec, we are to determine inband FEC, maximum
1540 // playback rate, and opus internal dtx. 1595 // playback rate, and opus internal dtx.
1541 if (IsCodec(codec, kOpusCodecName)) { 1596 if (IsCodec(*codec, kOpusCodecName)) {
1542 GetOpusConfig(codec, &send_codec, &enable_codec_fec, 1597 GetOpusConfig(*codec, &send_codec, &enable_codec_fec,
1543 &opus_max_playback_rate, &enable_opus_dtx); 1598 &opus_max_playback_rate, &enable_opus_dtx);
1544 } 1599 }
1545 1600
1546 // Set packet size if the AudioCodec param kCodecParamPTime is set. 1601 // Set packet size if the AudioCodec param kCodecParamPTime is set.
1547 int ptime_ms = 0; 1602 int ptime_ms = 0;
1548 if (codec.GetParam(kCodecParamPTime, &ptime_ms)) { 1603 if (codec->GetParam(kCodecParamPTime, &ptime_ms)) {
1549 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) { 1604 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) {
1550 LOG(LS_WARNING) << "Failed to set packet size for codec " 1605 LOG(LS_WARNING) << "Failed to set packet size for codec "
1551 << send_codec.plname; 1606 << send_codec.plname;
1552 return false; 1607 return false;
1553 } 1608 }
1554 } 1609 }
1555 } 1610 }
1556 found_send_codec = true;
1557 break;
1558 } 1611 }
1559 1612
1560 if (nack_enabled_ != nack_enabled) { 1613 if (nack_enabled_ != nack_enabled) {
1561 SetNack(channel, nack_enabled); 1614 SetNack(channel, nack_enabled);
1562 nack_enabled_ = nack_enabled; 1615 nack_enabled_ = nack_enabled;
1563 } 1616 }
1564 1617 if (!codec) {
1565 if (!found_send_codec) {
1566 LOG(LS_WARNING) << "Received empty list of codecs."; 1618 LOG(LS_WARNING) << "Received empty list of codecs.";
1567 return false; 1619 return false;
1568 } 1620 }
1569 1621
1570 // Set the codec immediately, since SetVADStatus() depends on whether 1622 // Set the codec immediately, since SetVADStatus() depends on whether
1571 // the current codec is mono or stereo. 1623 // the current codec is mono or stereo.
1572 if (!SetSendCodec(channel, send_codec)) 1624 if (!SetSendCodec(channel, send_codec))
1573 return false; 1625 return false;
1574 1626
1575 // FEC should be enabled after SetSendCodec. 1627 // 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)) { 1755 if (!SetSendCodecs(ch.second->channel(), codecs)) {
1704 return false; 1756 return false;
1705 } 1757 }
1706 } 1758 }
1707 1759
1708 // Set nack status on receive channels and update |nack_enabled_|. 1760 // Set nack status on receive channels and update |nack_enabled_|.
1709 for (const auto& ch : recv_streams_) { 1761 for (const auto& ch : recv_streams_) {
1710 SetNack(ch.second->channel(), nack_enabled_); 1762 SetNack(ch.second->channel(), nack_enabled_);
1711 } 1763 }
1712 1764
1765 // Check if the transport cc feedback has changed on the preferred send codec,
1766 // and in that case reconfigure all receive streams.
1767 webrtc::CodecInst voe_codec;
1768 int red_payload_type;
1769 const AudioCodec* send_codec = WebRtcVoiceCodecs::GetPreferredCodec(
1770 send_codecs_, &voe_codec, &red_payload_type);
1771 if (send_codec) {
1772 bool transport_cc = HasTransportCc(*send_codec);
1773 if (transport_cc_enabled_ != transport_cc) {
1774 LOG(LS_INFO) << "Recreate all the receive streams because the send "
1775 "codec has changed.";
1776 transport_cc_enabled_ = transport_cc;
1777 for (auto& kv : recv_streams_) {
1778 RTC_DCHECK(kv.second != nullptr);
1779 kv.second->RecreateAudioReceiveStream(transport_cc_enabled_);
the sun 2016/01/29 12:35:34 It seems to me that this should be done in respons
stefan-webrtc 2016/01/29 13:51:51 Video does it this way, and I was given the follow
1780 }
1781 }
1782 }
1783
1713 return true; 1784 return true;
1714 } 1785 }
1715 1786
1716 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { 1787 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) {
1717 if (nack_enabled) { 1788 if (nack_enabled) {
1718 LOG(LS_INFO) << "Enabling NACK for channel " << channel; 1789 LOG(LS_INFO) << "Enabling NACK for channel " << channel;
1719 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); 1790 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets);
1720 } else { 1791 } else {
1721 LOG(LS_INFO) << "Disabling NACK for channel " << channel; 1792 LOG(LS_INFO) << "Disabling NACK for channel " << channel;
1722 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 1793 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
2009 2080
2010 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); 2081 const int send_channel = GetSendChannelId(receiver_reports_ssrc_);
2011 if (send_channel != -1) { 2082 if (send_channel != -1) {
2012 // Associate receive channel with first send channel (so the receive channel 2083 // Associate receive channel with first send channel (so the receive channel
2013 // can obtain RTT from the send channel) 2084 // can obtain RTT from the send channel)
2014 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); 2085 engine()->voe()->base()->AssociateSendChannel(channel, send_channel);
2015 LOG(LS_INFO) << "VoiceEngine channel #" << channel 2086 LOG(LS_INFO) << "VoiceEngine channel #" << channel
2016 << " is associated with channel #" << send_channel << "."; 2087 << " is associated with channel #" << send_channel << ".";
2017 } 2088 }
2018 2089
2019 recv_streams_.insert(std::make_pair(ssrc, new WebRtcAudioReceiveStream( 2090 transport_cc_enabled_ =
2020 channel, ssrc, receiver_reports_ssrc_, 2091 !send_codecs_.empty() ? HasTransportCc(send_codecs_[0]) : false;
the sun 2016/01/29 12:35:34 Likewise - we should be able to just look at exten
stefan-webrtc 2016/01/29 13:51:51 Same thing here, it's the receiver's send codec th
2021 options_.combined_audio_video_bwe.value_or(false), sp.sync_label, 2092
2022 recv_rtp_extensions_, call_))); 2093 recv_streams_.insert(std::make_pair(
2094 ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_,
2095 transport_cc_enabled_, sp.sync_label,
2096 recv_rtp_extensions_, call_)));
2023 2097
2024 SetNack(channel, nack_enabled_); 2098 SetNack(channel, nack_enabled_);
2025 SetPlayout(channel, playout_); 2099 SetPlayout(channel, playout_);
2026 2100
2027 return true; 2101 return true;
2028 } 2102 }
2029 2103
2030 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { 2104 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
2031 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2105 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2032 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; 2106 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
2470 2544
2471 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const { 2545 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
2472 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2546 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2473 const auto it = send_streams_.find(ssrc); 2547 const auto it = send_streams_.find(ssrc);
2474 if (it != send_streams_.end()) { 2548 if (it != send_streams_.end()) {
2475 return it->second->channel(); 2549 return it->second->channel();
2476 } 2550 }
2477 return -1; 2551 return -1;
2478 } 2552 }
2479 2553
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) { 2554 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) {
2525 if (playout) { 2555 if (playout) {
2526 LOG(LS_INFO) << "Starting playout for channel #" << channel; 2556 LOG(LS_INFO) << "Starting playout for channel #" << channel;
2527 if (engine()->voe()->base()->StartPlayout(channel) == -1) { 2557 if (engine()->voe()->base()->StartPlayout(channel) == -1) {
2528 LOG_RTCERR1(StartPlayout, channel); 2558 LOG_RTCERR1(StartPlayout, channel);
2529 return false; 2559 return false;
2530 } 2560 }
2531 } else { 2561 } else {
2532 LOG(LS_INFO) << "Stopping playout for channel #" << channel; 2562 LOG(LS_INFO) << "Stopping playout for channel #" << channel;
2533 engine()->voe()->base()->StopPlayout(channel); 2563 engine()->voe()->base()->StopPlayout(channel);
2534 } 2564 }
2535 return true; 2565 return true;
2536 } 2566 }
2537 } // namespace cricket 2567 } // namespace cricket
2538 2568
2539 #endif // HAVE_WEBRTC_VOICE 2569 #endif // HAVE_WEBRTC_VOICE
OLDNEW
« no previous file with comments | « talk/media/webrtc/webrtcvoiceengine.h ('k') | talk/media/webrtc/webrtcvoiceengine_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698