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

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: 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
« 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 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 } 187 }
188 std::vector<int> payload_types; 188 std::vector<int> payload_types;
189 for (const AudioCodec& codec : codecs) { 189 for (const AudioCodec& codec : codecs) {
190 payload_types.push_back(codec.id); 190 payload_types.push_back(codec.id);
191 } 191 }
192 std::sort(payload_types.begin(), payload_types.end()); 192 std::sort(payload_types.begin(), payload_types.end());
193 auto it = std::unique(payload_types.begin(), payload_types.end()); 193 auto it = std::unique(payload_types.begin(), payload_types.end());
194 return it == payload_types.end(); 194 return it == payload_types.end();
195 } 195 }
196 196
197 bool IsNackEnabled(const AudioCodec& codec) {
198 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack,
199 kParamValueEmpty));
200 }
201
202 // Return true if codec.params[feature] == "1", false otherwise. 197 // Return true if codec.params[feature] == "1", false otherwise.
203 bool IsCodecFeatureEnabled(const AudioCodec& codec, const char* feature) { 198 bool IsCodecFeatureEnabled(const AudioCodec& codec, const char* feature) {
204 int value; 199 int value;
205 return codec.GetParam(feature, &value) && value == 1; 200 return codec.GetParam(feature, &value) && value == 1;
206 } 201 }
207 202
208 // Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate 203 // Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate
209 // otherwise. If the value (either from params or codec.bitrate) <=0, use the 204 // otherwise. If the value (either from params or codec.bitrate) <=0, use the
210 // default configuration. If the value is beyond feasible bit rate of Opus, 205 // default configuration. If the value is beyond feasible bit rate of Opus,
211 // clamp it. Returns the Opus bit rate for operation. 206 // clamp it. Returns the Opus bit rate for operation.
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 // Only add fmtp parameters that differ from the spec. 309 // Only add fmtp parameters that differ from the spec.
315 if (kPreferredMinPTime != kOpusDefaultMinPTime) { 310 if (kPreferredMinPTime != kOpusDefaultMinPTime) {
316 codec.params[kCodecParamMinPTime] = 311 codec.params[kCodecParamMinPTime] =
317 rtc::ToString(kPreferredMinPTime); 312 rtc::ToString(kPreferredMinPTime);
318 } 313 }
319 if (kPreferredMaxPTime != kOpusDefaultMaxPTime) { 314 if (kPreferredMaxPTime != kOpusDefaultMaxPTime) {
320 codec.params[kCodecParamMaxPTime] = 315 codec.params[kCodecParamMaxPTime] =
321 rtc::ToString(kPreferredMaxPTime); 316 rtc::ToString(kPreferredMaxPTime);
322 } 317 }
323 codec.SetParam(kCodecParamUseInbandFec, 1); 318 codec.SetParam(kCodecParamUseInbandFec, 1);
319 codec.AddFeedbackParam(
320 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
324 321
325 // TODO(hellner): Add ptime, sprop-stereo, and stereo 322 // TODO(hellner): Add ptime, sprop-stereo, and stereo
326 // when they can be set to values other than the default. 323 // when they can be set to values other than the default.
327 } 324 }
328 result.push_back(codec); 325 result.push_back(codec);
329 } else { 326 } else {
330 LOG(LS_WARNING) << "Unexpected codec: " << ToString(voe_codec); 327 LOG(LS_WARNING) << "Unexpected codec: " << ToString(voe_codec);
331 } 328 }
332 } 329 }
333 // Make sure they are in local preference order. 330 // Make sure they are in local preference order.
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 } 923 }
927 924
928 RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const { 925 RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const {
929 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); 926 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
930 RtpCapabilities capabilities; 927 RtpCapabilities capabilities;
931 capabilities.header_extensions.push_back(RtpHeaderExtension( 928 capabilities.header_extensions.push_back(RtpHeaderExtension(
932 kRtpAudioLevelHeaderExtension, kRtpAudioLevelHeaderExtensionDefaultId)); 929 kRtpAudioLevelHeaderExtension, kRtpAudioLevelHeaderExtensionDefaultId));
933 capabilities.header_extensions.push_back( 930 capabilities.header_extensions.push_back(
934 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, 931 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
935 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); 932 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
933 if (webrtc::field_trial::FindFullName("WebRTC-Audio-SendSideBwe") ==
934 "Enabled") {
935 capabilities.header_extensions.push_back(RtpHeaderExtension(
936 kRtpTransportSequenceNumberHeaderExtension,
937 kRtpTransportSequenceNumberHeaderExtensionDefaultId));
938 }
936 return capabilities; 939 return capabilities;
937 } 940 }
938 941
939 int WebRtcVoiceEngine::GetLastEngineError() { 942 int WebRtcVoiceEngine::GetLastEngineError() {
940 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 943 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
941 return voe_wrapper_->error(); 944 return voe_wrapper_->error();
942 } 945 }
943 946
944 void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace, 947 void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
945 int length) { 948 int length) {
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1201 // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler. 1204 // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler.
1202 // PeerConnection will make sure invalidating the pointer before the object 1205 // PeerConnection will make sure invalidating the pointer before the object
1203 // goes away. 1206 // goes away.
1204 AudioRenderer* renderer_ = nullptr; 1207 AudioRenderer* renderer_ = nullptr;
1205 1208
1206 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream); 1209 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
1207 }; 1210 };
1208 1211
1209 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { 1212 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
1210 public: 1213 public:
1211 WebRtcAudioReceiveStream(int ch, uint32_t remote_ssrc, uint32_t local_ssrc, 1214 WebRtcAudioReceiveStream(int ch,
1212 bool use_combined_bwe, const std::string& sync_group, 1215 uint32_t remote_ssrc,
1216 uint32_t local_ssrc,
1217 bool use_combined_bwe,
1218 bool use_transport_cc,
1219 const std::string& sync_group,
1213 const std::vector<webrtc::RtpExtension>& extensions, 1220 const std::vector<webrtc::RtpExtension>& extensions,
1214 webrtc::Call* call) 1221 webrtc::Call* call)
1215 : call_(call), 1222 : call_(call), config_() {
1216 config_() {
1217 RTC_DCHECK_GE(ch, 0); 1223 RTC_DCHECK_GE(ch, 0);
1218 RTC_DCHECK(call); 1224 RTC_DCHECK(call);
1219 config_.rtp.remote_ssrc = remote_ssrc; 1225 config_.rtp.remote_ssrc = remote_ssrc;
1220 config_.rtp.local_ssrc = local_ssrc; 1226 config_.rtp.local_ssrc = local_ssrc;
1221 config_.voe_channel_id = ch; 1227 config_.voe_channel_id = ch;
1222 config_.sync_group = sync_group; 1228 config_.sync_group = sync_group;
1223 RecreateAudioReceiveStream(use_combined_bwe, extensions); 1229 RecreateAudioReceiveStream(use_combined_bwe, use_transport_cc, extensions);
1224 } 1230 }
1225 1231
1226 ~WebRtcAudioReceiveStream() { 1232 ~WebRtcAudioReceiveStream() {
1227 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1233 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1228 call_->DestroyAudioReceiveStream(stream_); 1234 call_->DestroyAudioReceiveStream(stream_);
1229 } 1235 }
1230 1236
1231 void RecreateAudioReceiveStream( 1237 void RecreateAudioReceiveStream(
1232 const std::vector<webrtc::RtpExtension>& extensions) { 1238 const std::vector<webrtc::RtpExtension>& extensions) {
1233 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1239 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1234 RecreateAudioReceiveStream(config_.combined_audio_video_bwe, extensions); 1240 RecreateAudioReceiveStream(config_.combined_audio_video_bwe,
1241 config_.rtp.transport_cc, extensions);
1235 } 1242 }
1236 void RecreateAudioReceiveStream(bool use_combined_bwe) { 1243 void RecreateAudioReceiveStream(bool use_combined_bwe) {
1237 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1244 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1238 RecreateAudioReceiveStream(use_combined_bwe, config_.rtp.extensions); 1245 RecreateAudioReceiveStream(use_combined_bwe, config_.rtp.transport_cc,
1246 config_.rtp.extensions);
1247 }
1248 void RecreateAudioReceiveStreamWithTransportCc(bool use_transport_cc) {
1249 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1250 RecreateAudioReceiveStream(config_.combined_audio_video_bwe,
1251 use_transport_cc, config_.rtp.extensions);
1239 } 1252 }
1240 1253
1241 webrtc::AudioReceiveStream::Stats GetStats() const { 1254 webrtc::AudioReceiveStream::Stats GetStats() const {
1242 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1255 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1243 RTC_DCHECK(stream_); 1256 RTC_DCHECK(stream_);
1244 return stream_->GetStats(); 1257 return stream_->GetStats();
1245 } 1258 }
1246 1259
1247 int channel() const { 1260 int channel() const {
1248 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1261 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1249 return config_.voe_channel_id; 1262 return config_.voe_channel_id;
1250 } 1263 }
1251 1264
1252 void SetRawAudioSink(rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) { 1265 void SetRawAudioSink(rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) {
1253 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1266 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1254 stream_->SetSink(std::move(sink)); 1267 stream_->SetSink(std::move(sink));
1255 } 1268 }
1256 1269
1257 private: 1270 private:
1258 void RecreateAudioReceiveStream(bool use_combined_bwe, 1271 void RecreateAudioReceiveStream(
1272 bool use_combined_bwe,
1273 bool use_transport_cc,
1259 const std::vector<webrtc::RtpExtension>& extensions) { 1274 const std::vector<webrtc::RtpExtension>& extensions) {
1260 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1275 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1261 if (stream_) { 1276 if (stream_) {
1262 call_->DestroyAudioReceiveStream(stream_); 1277 call_->DestroyAudioReceiveStream(stream_);
1263 stream_ = nullptr; 1278 stream_ = nullptr;
1264 } 1279 }
1265 config_.rtp.extensions = extensions; 1280 config_.rtp.extensions = extensions;
1281 config_.rtp.transport_cc = use_transport_cc;
1266 config_.combined_audio_video_bwe = use_combined_bwe; 1282 config_.combined_audio_video_bwe = use_combined_bwe;
1267 RTC_DCHECK(!stream_); 1283 RTC_DCHECK(!stream_);
1268 stream_ = call_->CreateAudioReceiveStream(config_); 1284 stream_ = call_->CreateAudioReceiveStream(config_);
1269 RTC_CHECK(stream_); 1285 RTC_CHECK(stream_);
1270 } 1286 }
1271 1287
1272 rtc::ThreadChecker worker_thread_checker_; 1288 rtc::ThreadChecker worker_thread_checker_;
1273 webrtc::Call* call_ = nullptr; 1289 webrtc::Call* call_ = nullptr;
1274 webrtc::AudioReceiveStream::Config config_; 1290 webrtc::AudioReceiveStream::Config config_;
1275 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if 1291 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1352 } 1368 }
1353 std::vector<webrtc::RtpExtension> filtered_extensions = 1369 std::vector<webrtc::RtpExtension> filtered_extensions =
1354 FilterRtpExtensions(params.extensions, 1370 FilterRtpExtensions(params.extensions,
1355 webrtc::RtpExtension::IsSupportedForAudio, false); 1371 webrtc::RtpExtension::IsSupportedForAudio, false);
1356 if (recv_rtp_extensions_ != filtered_extensions) { 1372 if (recv_rtp_extensions_ != filtered_extensions) {
1357 recv_rtp_extensions_.swap(filtered_extensions); 1373 recv_rtp_extensions_.swap(filtered_extensions);
1358 for (auto& it : recv_streams_) { 1374 for (auto& it : recv_streams_) {
1359 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_); 1375 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_);
1360 } 1376 }
1361 } 1377 }
1362
1363 return true; 1378 return true;
1364 } 1379 }
1365 1380
1366 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { 1381 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
1367 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1382 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1368 LOG(LS_INFO) << "Setting voice channel options: " 1383 LOG(LS_INFO) << "Setting voice channel options: "
1369 << options.ToString(); 1384 << options.ToString();
1370 1385
1371 // Check if DSCP value is changed from previous. 1386 // Check if DSCP value is changed from previous.
1372 bool dscp_option_changed = (options_.dscp != options.dscp); 1387 bool dscp_option_changed = (options_.dscp != options.dscp);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 bool WebRtcVoiceMediaChannel::SetSendCodecs( 1489 bool WebRtcVoiceMediaChannel::SetSendCodecs(
1475 int channel, const std::vector<AudioCodec>& codecs) { 1490 int channel, const std::vector<AudioCodec>& codecs) {
1476 // Disable VAD, FEC, and RED unless we know the other side wants them. 1491 // Disable VAD, FEC, and RED unless we know the other side wants them.
1477 engine()->voe()->codec()->SetVADStatus(channel, false); 1492 engine()->voe()->codec()->SetVADStatus(channel, false);
1478 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 1493 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
1479 engine()->voe()->rtp()->SetREDStatus(channel, false); 1494 engine()->voe()->rtp()->SetREDStatus(channel, false);
1480 engine()->voe()->codec()->SetFECStatus(channel, false); 1495 engine()->voe()->codec()->SetFECStatus(channel, false);
1481 1496
1482 // Scan through the list to figure out the codec to use for sending, along 1497 // Scan through the list to figure out the codec to use for sending, along
1483 // with the proper configuration for VAD. 1498 // with the proper configuration for VAD.
1484 bool found_send_codec = false;
1485 webrtc::CodecInst send_codec; 1499 webrtc::CodecInst send_codec;
1486 memset(&send_codec, 0, sizeof(send_codec)); 1500 memset(&send_codec, 0, sizeof(send_codec));
1487 1501
1488 bool nack_enabled = nack_enabled_; 1502 bool nack_enabled = nack_enabled_;
1489 bool enable_codec_fec = false; 1503 bool enable_codec_fec = false;
1490 bool enable_opus_dtx = false; 1504 bool enable_opus_dtx = false;
1491 int opus_max_playback_rate = 0; 1505 int opus_max_playback_rate = 0;
1506 int red_payload_type = -1;
1492 1507
1493 // Set send codec (the first non-telephone-event/CN codec) 1508 // Set send codec (the first non-telephone-event/CN codec)
1494 for (const AudioCodec& codec : codecs) { 1509 const AudioCodec* codec =
1495 // Ignore codecs we don't know about. The negotiation step should prevent 1510 GetPreferredCodec(codecs, &send_codec, &red_payload_type);
1496 // this, but double-check to be sure. 1511 if (codec) {
1497 webrtc::CodecInst voe_codec; 1512 if (red_payload_type != -1) {
1498 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
1499 LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
1500 continue;
1501 }
1502
1503 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) {
1504 // Skip telephone-event/CN codec, which will be handled later.
1505 continue;
1506 }
1507
1508 // We'll use the first codec in the list to actually send audio data.
1509 // Be sure to use the payload type requested by the remote side.
1510 // "red", for RED audio, is a special case where the actual codec to be
1511 // used is specified in params.
1512 if (IsCodec(codec, kRedCodecName)) {
1513 // Parse out the RED parameters. If we fail, just ignore RED;
1514 // we don't support all possible params/usage scenarios.
1515 if (!GetRedSendCodec(codec, codecs, &send_codec)) {
1516 continue;
1517 }
1518
1519 // Enable redundant encoding of the specified codec. Treat any 1513 // Enable redundant encoding of the specified codec. Treat any
1520 // failure as a fatal internal error. 1514 // failure as a fatal internal error.
1521 LOG(LS_INFO) << "Enabling RED on channel " << channel; 1515 LOG(LS_INFO) << "Enabling RED on channel " << channel;
1522 if (engine()->voe()->rtp()->SetREDStatus(channel, true, codec.id) == -1) { 1516 if (engine()->voe()->rtp()->SetREDStatus(channel, true,
1523 LOG_RTCERR3(SetREDStatus, channel, true, codec.id); 1517 red_payload_type) == -1) {
1518 LOG_RTCERR3(SetREDStatus, channel, true, red_payload_type);
1524 return false; 1519 return false;
1525 } 1520 }
1526 } else { 1521 } else {
1527 send_codec = voe_codec; 1522 nack_enabled = HasNack(*codec);
1528 nack_enabled = IsNackEnabled(codec);
1529 // For Opus as the send codec, we are to determine inband FEC, maximum 1523 // For Opus as the send codec, we are to determine inband FEC, maximum
1530 // playback rate, and opus internal dtx. 1524 // playback rate, and opus internal dtx.
1531 if (IsCodec(codec, kOpusCodecName)) { 1525 if (IsCodec(*codec, kOpusCodecName)) {
1532 GetOpusConfig(codec, &send_codec, &enable_codec_fec, 1526 GetOpusConfig(*codec, &send_codec, &enable_codec_fec,
1533 &opus_max_playback_rate, &enable_opus_dtx); 1527 &opus_max_playback_rate, &enable_opus_dtx);
1534 } 1528 }
1535 1529
1536 // Set packet size if the AudioCodec param kCodecParamPTime is set. 1530 // Set packet size if the AudioCodec param kCodecParamPTime is set.
1537 int ptime_ms = 0; 1531 int ptime_ms = 0;
1538 if (codec.GetParam(kCodecParamPTime, &ptime_ms)) { 1532 if (codec->GetParam(kCodecParamPTime, &ptime_ms)) {
1539 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) { 1533 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) {
1540 LOG(LS_WARNING) << "Failed to set packet size for codec " 1534 LOG(LS_WARNING) << "Failed to set packet size for codec "
1541 << send_codec.plname; 1535 << send_codec.plname;
1542 return false; 1536 return false;
1543 } 1537 }
1544 } 1538 }
1545 } 1539 }
1546 found_send_codec = true;
1547 break;
1548 } 1540 }
1549 1541
1550 if (nack_enabled_ != nack_enabled) { 1542 if (nack_enabled_ != nack_enabled) {
1551 SetNack(channel, nack_enabled); 1543 SetNack(channel, nack_enabled);
1552 nack_enabled_ = nack_enabled; 1544 nack_enabled_ = nack_enabled;
1553 } 1545 }
1554 1546 if (!codec) {
1555 if (!found_send_codec) {
1556 LOG(LS_WARNING) << "Received empty list of codecs."; 1547 LOG(LS_WARNING) << "Received empty list of codecs.";
1557 return false; 1548 return false;
1558 } 1549 }
1559 1550
1560 // Set the codec immediately, since SetVADStatus() depends on whether 1551 // Set the codec immediately, since SetVADStatus() depends on whether
1561 // the current codec is mono or stereo. 1552 // the current codec is mono or stereo.
1562 if (!SetSendCodec(channel, send_codec)) 1553 if (!SetSendCodec(channel, send_codec))
1563 return false; 1554 return false;
1564 1555
1565 // FEC should be enabled after SetSendCodec. 1556 // FEC should be enabled after SetSendCodec.
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1664 if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) { 1655 if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) {
1665 LOG_RTCERR2(SetVADStatus, channel, true); 1656 LOG_RTCERR2(SetVADStatus, channel, true);
1666 return false; 1657 return false;
1667 } 1658 }
1668 } 1659 }
1669 } 1660 }
1670 } 1661 }
1671 return true; 1662 return true;
1672 } 1663 }
1673 1664
1665 const AudioCodec* WebRtcVoiceMediaChannel::GetPreferredCodec(
1666 const std::vector<AudioCodec>& codecs,
1667 webrtc::CodecInst* voe_codec,
1668 int* red_payload_type) const {
1669 // Set send codec (the first non-telephone-event/CN codec)
1670 for (const AudioCodec& codec : codecs) {
1671 *red_payload_type = -1;
1672 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) {
1673 // Skip telephone-event/CN codec, which will be handled later.
1674 continue;
1675 }
1676
1677 // We'll use the first codec in the list to actually send audio data.
1678 // Be sure to use the payload type requested by the remote side.
1679 // "red", for RED audio, is a special case where the actual codec to be
1680 // used is specified in params.
1681 const AudioCodec* found_codec = &codec;
1682 if (IsCodec(*found_codec, kRedCodecName)) {
1683 // Parse out the RED parameters. If we fail, just ignore RED;
1684 // we don't support all possible params/usage scenarios.
1685 *red_payload_type = codec.id;
1686 found_codec = GetRedSendCodec(*found_codec, codecs);
1687 if (!found_codec) {
1688 continue;
1689 }
1690 }
1691 // Ignore codecs we don't know about. The negotiation step should prevent
1692 // this, but double-check to be sure.
1693 if (!WebRtcVoiceEngine::ToCodecInst(*found_codec, voe_codec)) {
1694 LOG(LS_WARNING) << "Unknown codec " << ToString(*found_codec);
1695 continue;
1696 }
1697 return found_codec;
1698 }
1699 return nullptr;
1700 }
1701
1674 bool WebRtcVoiceMediaChannel::SetSendCodecs( 1702 bool WebRtcVoiceMediaChannel::SetSendCodecs(
1675 const std::vector<AudioCodec>& codecs) { 1703 const std::vector<AudioCodec>& codecs) {
1676 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1704 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1677 // TODO(solenberg): Validate input - that payload types don't overlap, are 1705 // TODO(solenberg): Validate input - that payload types don't overlap, are
1678 // within range, filter out codecs we don't support, 1706 // within range, filter out codecs we don't support,
1679 // redundant codecs etc. 1707 // redundant codecs etc.
1680 1708
1681 // Find the DTMF telephone event "codec" payload type. 1709 // Find the DTMF telephone event "codec" payload type.
1682 dtmf_payload_type_ = rtc::Optional<int>(); 1710 dtmf_payload_type_ = rtc::Optional<int>();
1683 for (const AudioCodec& codec : codecs) { 1711 for (const AudioCodec& codec : codecs) {
1684 if (IsCodec(codec, kDtmfCodecName)) { 1712 if (IsCodec(codec, kDtmfCodecName)) {
1685 dtmf_payload_type_ = rtc::Optional<int>(codec.id); 1713 dtmf_payload_type_ = rtc::Optional<int>(codec.id);
1686 break; 1714 break;
1687 } 1715 }
1688 } 1716 }
1689 1717
1690 // Cache the codecs in order to configure the channel created later. 1718 // Cache the codecs in order to configure the channel created later.
1691 send_codecs_ = codecs; 1719 send_codecs_ = codecs;
1692 for (const auto& ch : send_streams_) { 1720 for (const auto& ch : send_streams_) {
1693 if (!SetSendCodecs(ch.second->channel(), codecs)) { 1721 if (!SetSendCodecs(ch.second->channel(), codecs)) {
1694 return false; 1722 return false;
1695 } 1723 }
1696 } 1724 }
1697 1725
1698 // Set nack status on receive channels and update |nack_enabled_|. 1726 // Set nack status on receive channels and update |nack_enabled_|.
1699 for (const auto& ch : recv_streams_) { 1727 for (const auto& ch : recv_streams_) {
1700 SetNack(ch.second->channel(), nack_enabled_); 1728 SetNack(ch.second->channel(), nack_enabled_);
1701 } 1729 }
1702 1730
1731 // Check if the transport cc feedback has changed on the preferred send codec,
1732 // and in that case reconfigure all receive streams.
1733 webrtc::CodecInst voe_codec;
1734 int red_payload_type;
1735 const AudioCodec* send_codec =
1736 GetPreferredCodec(send_codecs_, &voe_codec, &red_payload_type);
1737 if (send_codec) {
1738 bool transport_cc = HasTransportCc(*send_codec);
1739 if (transport_cc_enabled_ != transport_cc) {
1740 LOG(LS_INFO) << "Recreate all the receive streams because the send "
1741 "codec has changed.";
1742 transport_cc_enabled_ = transport_cc;
1743 for (auto& kv : recv_streams_) {
1744 RTC_DCHECK(kv.second != nullptr);
1745 kv.second->RecreateAudioReceiveStreamWithTransportCc(
1746 transport_cc_enabled_);
1747 }
1748 }
1749 }
stefan-webrtc 2016/01/18 15:32:32 I think this should work, as it is what we are doi
1750
1703 return true; 1751 return true;
1704 } 1752 }
1705 1753
1706 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { 1754 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) {
1707 if (nack_enabled) { 1755 if (nack_enabled) {
1708 LOG(LS_INFO) << "Enabling NACK for channel " << channel; 1756 LOG(LS_INFO) << "Enabling NACK for channel " << channel;
1709 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); 1757 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets);
1710 } else { 1758 } else {
1711 LOG(LS_INFO) << "Disabling NACK for channel " << channel; 1759 LOG(LS_INFO) << "Disabling NACK for channel " << channel;
1712 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 1760 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
1999 2047
2000 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); 2048 const int send_channel = GetSendChannelId(receiver_reports_ssrc_);
2001 if (send_channel != -1) { 2049 if (send_channel != -1) {
2002 // Associate receive channel with first send channel (so the receive channel 2050 // Associate receive channel with first send channel (so the receive channel
2003 // can obtain RTT from the send channel) 2051 // can obtain RTT from the send channel)
2004 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); 2052 engine()->voe()->base()->AssociateSendChannel(channel, send_channel);
2005 LOG(LS_INFO) << "VoiceEngine channel #" << channel 2053 LOG(LS_INFO) << "VoiceEngine channel #" << channel
2006 << " is associated with channel #" << send_channel << "."; 2054 << " is associated with channel #" << send_channel << ".";
2007 } 2055 }
2008 2056
2009 recv_streams_.insert(std::make_pair(ssrc, new WebRtcAudioReceiveStream( 2057 transport_cc_enabled_ =
2010 channel, ssrc, receiver_reports_ssrc_, 2058 !send_codecs_.empty() ? HasTransportCc(send_codecs_[0]) : false;
2011 options_.combined_audio_video_bwe.value_or(false), sp.sync_label, 2059
2012 recv_rtp_extensions_, call_))); 2060 recv_streams_.insert(std::make_pair(
2061 ssrc,
2062 new WebRtcAudioReceiveStream(
2063 channel, ssrc, receiver_reports_ssrc_,
2064 options_.combined_audio_video_bwe.value_or(false),
2065 transport_cc_enabled_, sp.sync_label, recv_rtp_extensions_, call_)));
2013 2066
2014 SetNack(channel, nack_enabled_); 2067 SetNack(channel, nack_enabled_);
2015 SetPlayout(channel, playout_); 2068 SetPlayout(channel, playout_);
2016 2069
2017 return true; 2070 return true;
2018 } 2071 }
2019 2072
2020 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { 2073 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
2021 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2074 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2022 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; 2075 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
2445 2498
2446 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const { 2499 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
2447 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2500 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2448 const auto it = send_streams_.find(ssrc); 2501 const auto it = send_streams_.find(ssrc);
2449 if (it != send_streams_.end()) { 2502 if (it != send_streams_.end()) {
2450 return it->second->channel(); 2503 return it->second->channel();
2451 } 2504 }
2452 return -1; 2505 return -1;
2453 } 2506 }
2454 2507
2455 bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec, 2508 const AudioCodec* WebRtcVoiceMediaChannel::GetRedSendCodec(
2456 const std::vector<AudioCodec>& all_codecs, webrtc::CodecInst* send_codec) { 2509 const AudioCodec& red_codec,
2510 const std::vector<AudioCodec>& all_codecs) const {
2457 // Get the RED encodings from the parameter with no name. This may 2511 // Get the RED encodings from the parameter with no name. This may
2458 // change based on what is discussed on the Jingle list. 2512 // change based on what is discussed on the Jingle list.
2459 // The encoding parameter is of the form "a/b"; we only support where 2513 // The encoding parameter is of the form "a/b"; we only support where
2460 // a == b. Verify this and parse out the value into red_pt. 2514 // a == b. Verify this and parse out the value into red_pt.
2461 // If the parameter value is absent (as it will be until we wire up the 2515 // If the parameter value is absent (as it will be until we wire up the
2462 // signaling of this message), use the second codec specified (i.e. the 2516 // signaling of this message), use the second codec specified (i.e. the
2463 // one after "red") as the encoding parameter. 2517 // one after "red") as the encoding parameter.
2464 int red_pt = -1; 2518 int red_pt = -1;
2465 std::string red_params; 2519 std::string red_params;
2466 CodecParameterMap::const_iterator it = red_codec.params.find(""); 2520 CodecParameterMap::const_iterator it = red_codec.params.find("");
2467 if (it != red_codec.params.end()) { 2521 if (it != red_codec.params.end()) {
2468 red_params = it->second; 2522 red_params = it->second;
2469 std::vector<std::string> red_pts; 2523 std::vector<std::string> red_pts;
2470 if (rtc::split(red_params, '/', &red_pts) != 2 || 2524 if (rtc::split(red_params, '/', &red_pts) != 2 ||
2471 red_pts[0] != red_pts[1] || 2525 red_pts[0] != red_pts[1] ||
2472 !rtc::FromString(red_pts[0], &red_pt)) { 2526 !rtc::FromString(red_pts[0], &red_pt)) {
2473 LOG(LS_WARNING) << "RED params " << red_params << " not supported."; 2527 LOG(LS_WARNING) << "RED params " << red_params << " not supported.";
2474 return false; 2528 return nullptr;
2475 } 2529 }
2476 } else if (red_codec.params.empty()) { 2530 } else if (red_codec.params.empty()) {
2477 LOG(LS_WARNING) << "RED params not present, using defaults"; 2531 LOG(LS_WARNING) << "RED params not present, using defaults";
2478 if (all_codecs.size() > 1) { 2532 if (all_codecs.size() > 1) {
2479 red_pt = all_codecs[1].id; 2533 red_pt = all_codecs[1].id;
2480 } 2534 }
2481 } 2535 }
2482 2536
2483 // Try to find red_pt in |codecs|. 2537 // Try to find red_pt in |codecs|.
2484 for (const AudioCodec& codec : all_codecs) { 2538 for (const AudioCodec& codec : all_codecs) {
2485 if (codec.id == red_pt) { 2539 if (codec.id == red_pt) {
2486 // If we find the right codec, that will be the codec we pass to 2540 return &codec;
2487 // SetSendCodec, with the desired payload type.
2488 if (WebRtcVoiceEngine::ToCodecInst(codec, send_codec)) {
2489 return true;
2490 } else {
2491 break;
2492 }
2493 } 2541 }
2494 } 2542 }
2495 LOG(LS_WARNING) << "RED params " << red_params << " are invalid."; 2543 LOG(LS_WARNING) << "RED params " << red_params << " are invalid.";
2496 return false; 2544 return nullptr;
2497 } 2545 }
2498 2546
2499 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { 2547 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) {
2500 if (playout) { 2548 if (playout) {
2501 LOG(LS_INFO) << "Starting playout for channel #" << channel; 2549 LOG(LS_INFO) << "Starting playout for channel #" << channel;
2502 if (engine()->voe()->base()->StartPlayout(channel) == -1) { 2550 if (engine()->voe()->base()->StartPlayout(channel) == -1) {
2503 LOG_RTCERR1(StartPlayout, channel); 2551 LOG_RTCERR1(StartPlayout, channel);
2504 return false; 2552 return false;
2505 } 2553 }
2506 } else { 2554 } else {
2507 LOG(LS_INFO) << "Stopping playout for channel #" << channel; 2555 LOG(LS_INFO) << "Stopping playout for channel #" << channel;
2508 engine()->voe()->base()->StopPlayout(channel); 2556 engine()->voe()->base()->StopPlayout(channel);
2509 } 2557 }
2510 return true; 2558 return true;
2511 } 2559 }
2512 } // namespace cricket 2560 } // namespace cricket
2513 2561
2514 #endif // HAVE_WEBRTC_VOICE 2562 #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