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

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: Remove extension filter test which is no longer needed. 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 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 592 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 } 933 }
937 934
938 RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const { 935 RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const {
939 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); 936 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
940 RtpCapabilities capabilities; 937 RtpCapabilities capabilities;
941 capabilities.header_extensions.push_back(RtpHeaderExtension( 938 capabilities.header_extensions.push_back(RtpHeaderExtension(
942 kRtpAudioLevelHeaderExtension, kRtpAudioLevelHeaderExtensionDefaultId)); 939 kRtpAudioLevelHeaderExtension, kRtpAudioLevelHeaderExtensionDefaultId));
943 capabilities.header_extensions.push_back( 940 capabilities.header_extensions.push_back(
944 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, 941 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
945 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); 942 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
943 if (webrtc::field_trial::FindFullName("WebRTC-Audio-SendSideBwe") ==
944 "Enabled") {
945 capabilities.header_extensions.push_back(RtpHeaderExtension(
946 kRtpTransportSequenceNumberHeaderExtension,
947 kRtpTransportSequenceNumberHeaderExtensionDefaultId));
948 }
946 return capabilities; 949 return capabilities;
947 } 950 }
948 951
949 int WebRtcVoiceEngine::GetLastEngineError() { 952 int WebRtcVoiceEngine::GetLastEngineError() {
950 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 953 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
951 return voe_wrapper_->error(); 954 return voe_wrapper_->error();
952 } 955 }
953 956
954 void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace, 957 void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
955 int length) { 958 int length) {
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler. 1214 // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler.
1212 // PeerConnection will make sure invalidating the pointer before the object 1215 // PeerConnection will make sure invalidating the pointer before the object
1213 // goes away. 1216 // goes away.
1214 AudioRenderer* renderer_ = nullptr; 1217 AudioRenderer* renderer_ = nullptr;
1215 1218
1216 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream); 1219 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
1217 }; 1220 };
1218 1221
1219 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { 1222 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
1220 public: 1223 public:
1221 WebRtcAudioReceiveStream(int ch, uint32_t remote_ssrc, uint32_t local_ssrc, 1224 WebRtcAudioReceiveStream(int ch,
1222 bool use_combined_bwe, const std::string& sync_group, 1225 uint32_t remote_ssrc,
1226 uint32_t local_ssrc,
1227 bool use_transport_cc,
1228 const std::string& sync_group,
1223 const std::vector<webrtc::RtpExtension>& extensions, 1229 const std::vector<webrtc::RtpExtension>& extensions,
1224 webrtc::Call* call) 1230 webrtc::Call* call)
1225 : call_(call), 1231 : call_(call), config_() {
1226 config_() {
1227 RTC_DCHECK_GE(ch, 0); 1232 RTC_DCHECK_GE(ch, 0);
1228 RTC_DCHECK(call); 1233 RTC_DCHECK(call);
1229 config_.rtp.remote_ssrc = remote_ssrc; 1234 config_.rtp.remote_ssrc = remote_ssrc;
1230 config_.rtp.local_ssrc = local_ssrc; 1235 config_.rtp.local_ssrc = local_ssrc;
1231 config_.voe_channel_id = ch; 1236 config_.voe_channel_id = ch;
1232 config_.sync_group = sync_group; 1237 config_.sync_group = sync_group;
1233 RecreateAudioReceiveStream(use_combined_bwe, extensions); 1238 RecreateAudioReceiveStream(use_transport_cc, extensions);
1234 } 1239 }
1235 1240
1236 ~WebRtcAudioReceiveStream() { 1241 ~WebRtcAudioReceiveStream() {
1237 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1242 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1238 call_->DestroyAudioReceiveStream(stream_); 1243 call_->DestroyAudioReceiveStream(stream_);
1239 } 1244 }
1240 1245
1246 void RecreateAudioReceiveStream() {
the sun 2016/01/21 13:26:24 Why do we need to recreate the stream if no config
stefan-webrtc 2016/01/21 15:09:09 I don't really know, but apparently tests are brea
the sun 2016/01/22 10:45:16 Then there is something with how the stream is bei
stefan-webrtc 2016/01/23 16:52:14 You are right, and the problem is that the tests a
1247 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1248 RecreateAudioReceiveStream(config_.rtp.transport_cc,
1249 config_.rtp.extensions);
1250 }
1241 void RecreateAudioReceiveStream( 1251 void RecreateAudioReceiveStream(
1242 const std::vector<webrtc::RtpExtension>& extensions) { 1252 const std::vector<webrtc::RtpExtension>& extensions) {
1243 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1253 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1244 RecreateAudioReceiveStream(config_.combined_audio_video_bwe, extensions); 1254 RecreateAudioReceiveStream(config_.rtp.transport_cc, extensions);
1245 } 1255 }
1246 void RecreateAudioReceiveStream(bool use_combined_bwe) { 1256 void RecreateAudioReceiveStream(bool use_transport_cc) {
1247 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1257 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1248 RecreateAudioReceiveStream(use_combined_bwe, config_.rtp.extensions); 1258 RecreateAudioReceiveStream(use_transport_cc, config_.rtp.extensions);
1249 } 1259 }
1250 1260
1251 webrtc::AudioReceiveStream::Stats GetStats() const { 1261 webrtc::AudioReceiveStream::Stats GetStats() const {
1252 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1262 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1253 RTC_DCHECK(stream_); 1263 RTC_DCHECK(stream_);
1254 return stream_->GetStats(); 1264 return stream_->GetStats();
1255 } 1265 }
1256 1266
1257 int channel() const { 1267 int channel() const {
1258 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1268 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1259 return config_.voe_channel_id; 1269 return config_.voe_channel_id;
1260 } 1270 }
1261 1271
1262 void SetRawAudioSink(rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) { 1272 void SetRawAudioSink(rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) {
1263 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1273 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1264 stream_->SetSink(std::move(sink)); 1274 stream_->SetSink(std::move(sink));
1265 } 1275 }
1266 1276
1267 private: 1277 private:
1268 void RecreateAudioReceiveStream(bool use_combined_bwe, 1278 void RecreateAudioReceiveStream(
1279 bool use_transport_cc,
1269 const std::vector<webrtc::RtpExtension>& extensions) { 1280 const std::vector<webrtc::RtpExtension>& extensions) {
1270 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1281 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1271 if (stream_) { 1282 if (stream_) {
1272 call_->DestroyAudioReceiveStream(stream_); 1283 call_->DestroyAudioReceiveStream(stream_);
1273 stream_ = nullptr; 1284 stream_ = nullptr;
1274 } 1285 }
1275 config_.rtp.extensions = extensions; 1286 config_.rtp.extensions = extensions;
1276 config_.combined_audio_video_bwe = use_combined_bwe; 1287 config_.rtp.transport_cc = use_transport_cc;
1277 RTC_DCHECK(!stream_); 1288 RTC_DCHECK(!stream_);
1278 stream_ = call_->CreateAudioReceiveStream(config_); 1289 stream_ = call_->CreateAudioReceiveStream(config_);
1279 RTC_CHECK(stream_); 1290 RTC_CHECK(stream_);
1280 } 1291 }
1281 1292
1282 rtc::ThreadChecker worker_thread_checker_; 1293 rtc::ThreadChecker worker_thread_checker_;
1283 webrtc::Call* call_ = nullptr; 1294 webrtc::Call* call_ = nullptr;
1284 webrtc::AudioReceiveStream::Config config_; 1295 webrtc::AudioReceiveStream::Config config_;
1285 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if 1296 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if
1286 // configuration changes. 1297 // configuration changes.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1362 } 1373 }
1363 std::vector<webrtc::RtpExtension> filtered_extensions = 1374 std::vector<webrtc::RtpExtension> filtered_extensions =
1364 FilterRtpExtensions(params.extensions, 1375 FilterRtpExtensions(params.extensions,
1365 webrtc::RtpExtension::IsSupportedForAudio, false); 1376 webrtc::RtpExtension::IsSupportedForAudio, false);
1366 if (recv_rtp_extensions_ != filtered_extensions) { 1377 if (recv_rtp_extensions_ != filtered_extensions) {
1367 recv_rtp_extensions_.swap(filtered_extensions); 1378 recv_rtp_extensions_.swap(filtered_extensions);
1368 for (auto& it : recv_streams_) { 1379 for (auto& it : recv_streams_) {
1369 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_); 1380 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_);
1370 } 1381 }
1371 } 1382 }
1372
1373 return true; 1383 return true;
1374 } 1384 }
1375 1385
1376 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { 1386 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
1377 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1387 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1378 LOG(LS_INFO) << "Setting voice channel options: " 1388 LOG(LS_INFO) << "Setting voice channel options: "
1379 << options.ToString(); 1389 << options.ToString();
1380 1390
1381 // Check if DSCP value is changed from previous. 1391 // Check if DSCP value is changed from previous.
1382 bool dscp_option_changed = (options_.dscp != options.dscp); 1392 bool dscp_option_changed = (options_.dscp != options.dscp);
(...skipping 13 matching lines...) Expand all
1396 if (options_.dscp.value_or(false)) { 1406 if (options_.dscp.value_or(false)) {
1397 dscp = kAudioDscpValue; 1407 dscp = kAudioDscpValue;
1398 } 1408 }
1399 if (MediaChannel::SetDscp(dscp) != 0) { 1409 if (MediaChannel::SetDscp(dscp) != 0) {
1400 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; 1410 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel";
1401 } 1411 }
1402 } 1412 }
1403 1413
1404 // TODO(solenberg): Don't recreate unless options changed. 1414 // TODO(solenberg): Don't recreate unless options changed.
1405 for (auto& it : recv_streams_) { 1415 for (auto& it : recv_streams_) {
1406 it.second->RecreateAudioReceiveStream( 1416 it.second->RecreateAudioReceiveStream();
the sun 2016/01/21 13:26:24 Not needed anymore. At least not in the current fo
stefan-webrtc 2016/01/21 15:09:09 See above
1407 options_.combined_audio_video_bwe.value_or(false));
1408 } 1417 }
1409 1418
1410 LOG(LS_INFO) << "Set voice channel options. Current options: " 1419 LOG(LS_INFO) << "Set voice channel options. Current options: "
1411 << options_.ToString(); 1420 << options_.ToString();
1412 return true; 1421 return true;
1413 } 1422 }
1414 1423
1415 bool WebRtcVoiceMediaChannel::SetRecvCodecs( 1424 bool WebRtcVoiceMediaChannel::SetRecvCodecs(
1416 const std::vector<AudioCodec>& codecs) { 1425 const std::vector<AudioCodec>& codecs) {
1417 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1426 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1484 bool WebRtcVoiceMediaChannel::SetSendCodecs( 1493 bool WebRtcVoiceMediaChannel::SetSendCodecs(
1485 int channel, const std::vector<AudioCodec>& codecs) { 1494 int channel, const std::vector<AudioCodec>& codecs) {
1486 // Disable VAD, FEC, and RED unless we know the other side wants them. 1495 // Disable VAD, FEC, and RED unless we know the other side wants them.
1487 engine()->voe()->codec()->SetVADStatus(channel, false); 1496 engine()->voe()->codec()->SetVADStatus(channel, false);
1488 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 1497 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
1489 engine()->voe()->rtp()->SetREDStatus(channel, false); 1498 engine()->voe()->rtp()->SetREDStatus(channel, false);
1490 engine()->voe()->codec()->SetFECStatus(channel, false); 1499 engine()->voe()->codec()->SetFECStatus(channel, false);
1491 1500
1492 // Scan through the list to figure out the codec to use for sending, along 1501 // Scan through the list to figure out the codec to use for sending, along
1493 // with the proper configuration for VAD. 1502 // with the proper configuration for VAD.
1494 bool found_send_codec = false;
1495 webrtc::CodecInst send_codec; 1503 webrtc::CodecInst send_codec;
1496 memset(&send_codec, 0, sizeof(send_codec)); 1504 memset(&send_codec, 0, sizeof(send_codec));
1497 1505
1498 bool nack_enabled = nack_enabled_; 1506 bool nack_enabled = nack_enabled_;
1499 bool enable_codec_fec = false; 1507 bool enable_codec_fec = false;
1500 bool enable_opus_dtx = false; 1508 bool enable_opus_dtx = false;
1501 int opus_max_playback_rate = 0; 1509 int opus_max_playback_rate = 0;
1510 int red_payload_type = -1;
1502 1511
1503 // Set send codec (the first non-telephone-event/CN codec) 1512 // Set send codec (the first non-telephone-event/CN codec)
1504 for (const AudioCodec& codec : codecs) { 1513 const AudioCodec* codec =
1505 // Ignore codecs we don't know about. The negotiation step should prevent 1514 GetPreferredCodec(codecs, &send_codec, &red_payload_type);
1506 // this, but double-check to be sure. 1515 if (codec) {
1507 webrtc::CodecInst voe_codec; 1516 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 1517 // Enable redundant encoding of the specified codec. Treat any
1530 // failure as a fatal internal error. 1518 // failure as a fatal internal error.
1531 LOG(LS_INFO) << "Enabling RED on channel " << channel; 1519 LOG(LS_INFO) << "Enabling RED on channel " << channel;
1532 if (engine()->voe()->rtp()->SetREDStatus(channel, true, codec.id) == -1) { 1520 if (engine()->voe()->rtp()->SetREDStatus(channel, true,
1533 LOG_RTCERR3(SetREDStatus, channel, true, codec.id); 1521 red_payload_type) == -1) {
1522 LOG_RTCERR3(SetREDStatus, channel, true, red_payload_type);
1534 return false; 1523 return false;
1535 } 1524 }
1536 } else { 1525 } else {
1537 send_codec = voe_codec; 1526 nack_enabled = HasNack(*codec);
1538 nack_enabled = IsNackEnabled(codec);
1539 // For Opus as the send codec, we are to determine inband FEC, maximum 1527 // For Opus as the send codec, we are to determine inband FEC, maximum
1540 // playback rate, and opus internal dtx. 1528 // playback rate, and opus internal dtx.
1541 if (IsCodec(codec, kOpusCodecName)) { 1529 if (IsCodec(*codec, kOpusCodecName)) {
1542 GetOpusConfig(codec, &send_codec, &enable_codec_fec, 1530 GetOpusConfig(*codec, &send_codec, &enable_codec_fec,
1543 &opus_max_playback_rate, &enable_opus_dtx); 1531 &opus_max_playback_rate, &enable_opus_dtx);
1544 } 1532 }
1545 1533
1546 // Set packet size if the AudioCodec param kCodecParamPTime is set. 1534 // Set packet size if the AudioCodec param kCodecParamPTime is set.
1547 int ptime_ms = 0; 1535 int ptime_ms = 0;
1548 if (codec.GetParam(kCodecParamPTime, &ptime_ms)) { 1536 if (codec->GetParam(kCodecParamPTime, &ptime_ms)) {
1549 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) { 1537 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) {
1550 LOG(LS_WARNING) << "Failed to set packet size for codec " 1538 LOG(LS_WARNING) << "Failed to set packet size for codec "
1551 << send_codec.plname; 1539 << send_codec.plname;
1552 return false; 1540 return false;
1553 } 1541 }
1554 } 1542 }
1555 } 1543 }
1556 found_send_codec = true;
1557 break;
1558 } 1544 }
1559 1545
1560 if (nack_enabled_ != nack_enabled) { 1546 if (nack_enabled_ != nack_enabled) {
1561 SetNack(channel, nack_enabled); 1547 SetNack(channel, nack_enabled);
1562 nack_enabled_ = nack_enabled; 1548 nack_enabled_ = nack_enabled;
1563 } 1549 }
1564 1550 if (!codec) {
1565 if (!found_send_codec) {
1566 LOG(LS_WARNING) << "Received empty list of codecs."; 1551 LOG(LS_WARNING) << "Received empty list of codecs.";
1567 return false; 1552 return false;
1568 } 1553 }
1569 1554
1570 // Set the codec immediately, since SetVADStatus() depends on whether 1555 // Set the codec immediately, since SetVADStatus() depends on whether
1571 // the current codec is mono or stereo. 1556 // the current codec is mono or stereo.
1572 if (!SetSendCodec(channel, send_codec)) 1557 if (!SetSendCodec(channel, send_codec))
1573 return false; 1558 return false;
1574 1559
1575 // FEC should be enabled after SetSendCodec. 1560 // FEC should be enabled after SetSendCodec.
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1674 if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) { 1659 if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) {
1675 LOG_RTCERR2(SetVADStatus, channel, true); 1660 LOG_RTCERR2(SetVADStatus, channel, true);
1676 return false; 1661 return false;
1677 } 1662 }
1678 } 1663 }
1679 } 1664 }
1680 } 1665 }
1681 return true; 1666 return true;
1682 } 1667 }
1683 1668
1669 const AudioCodec* WebRtcVoiceMediaChannel::GetPreferredCodec(
the sun 2016/01/21 13:26:24 IIUC this function and GetRedSendCodec() do not us
stefan-webrtc 2016/01/21 15:09:09 Done.
1670 const std::vector<AudioCodec>& codecs,
1671 webrtc::CodecInst* voe_codec,
1672 int* red_payload_type) const {
1673 // Set send codec (the first non-telephone-event/CN codec)
1674 for (const AudioCodec& codec : codecs) {
1675 *red_payload_type = -1;
1676 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) {
1677 // Skip telephone-event/CN codec, which will be handled later.
1678 continue;
1679 }
1680
1681 // We'll use the first codec in the list to actually send audio data.
1682 // Be sure to use the payload type requested by the remote side.
1683 // "red", for RED audio, is a special case where the actual codec to be
1684 // used is specified in params.
1685 const AudioCodec* found_codec = &codec;
1686 if (IsCodec(*found_codec, kRedCodecName)) {
1687 // Parse out the RED parameters. If we fail, just ignore RED;
1688 // we don't support all possible params/usage scenarios.
1689 *red_payload_type = codec.id;
1690 found_codec = GetRedSendCodec(*found_codec, codecs);
1691 if (!found_codec) {
1692 continue;
1693 }
1694 }
1695 // Ignore codecs we don't know about. The negotiation step should prevent
1696 // this, but double-check to be sure.
1697 if (!WebRtcVoiceEngine::ToCodecInst(*found_codec, voe_codec)) {
1698 LOG(LS_WARNING) << "Unknown codec " << ToString(*found_codec);
1699 continue;
1700 }
1701 return found_codec;
1702 }
1703 return nullptr;
1704 }
1705
1684 bool WebRtcVoiceMediaChannel::SetSendCodecs( 1706 bool WebRtcVoiceMediaChannel::SetSendCodecs(
1685 const std::vector<AudioCodec>& codecs) { 1707 const std::vector<AudioCodec>& codecs) {
1686 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1708 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1687 // TODO(solenberg): Validate input - that payload types don't overlap, are 1709 // TODO(solenberg): Validate input - that payload types don't overlap, are
1688 // within range, filter out codecs we don't support, 1710 // within range, filter out codecs we don't support,
1689 // redundant codecs etc. 1711 // redundant codecs etc.
1690 1712
1691 // Find the DTMF telephone event "codec" payload type. 1713 // Find the DTMF telephone event "codec" payload type.
1692 dtmf_payload_type_ = rtc::Optional<int>(); 1714 dtmf_payload_type_ = rtc::Optional<int>();
1693 for (const AudioCodec& codec : codecs) { 1715 for (const AudioCodec& codec : codecs) {
1694 if (IsCodec(codec, kDtmfCodecName)) { 1716 if (IsCodec(codec, kDtmfCodecName)) {
1695 dtmf_payload_type_ = rtc::Optional<int>(codec.id); 1717 dtmf_payload_type_ = rtc::Optional<int>(codec.id);
1696 break; 1718 break;
1697 } 1719 }
1698 } 1720 }
1699 1721
1700 // Cache the codecs in order to configure the channel created later. 1722 // Cache the codecs in order to configure the channel created later.
1701 send_codecs_ = codecs; 1723 send_codecs_ = codecs;
1702 for (const auto& ch : send_streams_) { 1724 for (const auto& ch : send_streams_) {
1703 if (!SetSendCodecs(ch.second->channel(), codecs)) { 1725 if (!SetSendCodecs(ch.second->channel(), codecs)) {
1704 return false; 1726 return false;
1705 } 1727 }
1706 } 1728 }
1707 1729
1708 // Set nack status on receive channels and update |nack_enabled_|. 1730 // Set nack status on receive channels and update |nack_enabled_|.
1709 for (const auto& ch : recv_streams_) { 1731 for (const auto& ch : recv_streams_) {
1710 SetNack(ch.second->channel(), nack_enabled_); 1732 SetNack(ch.second->channel(), nack_enabled_);
1711 } 1733 }
1712 1734
1735 // Check if the transport cc feedback has changed on the preferred send codec,
1736 // and in that case reconfigure all receive streams.
1737 webrtc::CodecInst voe_codec;
1738 int red_payload_type;
1739 const AudioCodec* send_codec =
1740 GetPreferredCodec(send_codecs_, &voe_codec, &red_payload_type);
1741 if (send_codec) {
1742 bool transport_cc = HasTransportCc(*send_codec);
1743 if (transport_cc_enabled_ != transport_cc) {
1744 LOG(LS_INFO) << "Recreate all the receive streams because the send "
1745 "codec has changed.";
1746 transport_cc_enabled_ = transport_cc;
1747 for (auto& kv : recv_streams_) {
1748 RTC_DCHECK(kv.second != nullptr);
1749 kv.second->RecreateAudioReceiveStream(transport_cc_enabled_);
1750 }
1751 }
1752 }
1753
1713 return true; 1754 return true;
1714 } 1755 }
1715 1756
1716 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { 1757 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) {
1717 if (nack_enabled) { 1758 if (nack_enabled) {
1718 LOG(LS_INFO) << "Enabling NACK for channel " << channel; 1759 LOG(LS_INFO) << "Enabling NACK for channel " << channel;
1719 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); 1760 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets);
1720 } else { 1761 } else {
1721 LOG(LS_INFO) << "Disabling NACK for channel " << channel; 1762 LOG(LS_INFO) << "Disabling NACK for channel " << channel;
1722 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 1763 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
2009 2050
2010 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); 2051 const int send_channel = GetSendChannelId(receiver_reports_ssrc_);
2011 if (send_channel != -1) { 2052 if (send_channel != -1) {
2012 // Associate receive channel with first send channel (so the receive channel 2053 // Associate receive channel with first send channel (so the receive channel
2013 // can obtain RTT from the send channel) 2054 // can obtain RTT from the send channel)
2014 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); 2055 engine()->voe()->base()->AssociateSendChannel(channel, send_channel);
2015 LOG(LS_INFO) << "VoiceEngine channel #" << channel 2056 LOG(LS_INFO) << "VoiceEngine channel #" << channel
2016 << " is associated with channel #" << send_channel << "."; 2057 << " is associated with channel #" << send_channel << ".";
2017 } 2058 }
2018 2059
2019 recv_streams_.insert(std::make_pair(ssrc, new WebRtcAudioReceiveStream( 2060 transport_cc_enabled_ =
2020 channel, ssrc, receiver_reports_ssrc_, 2061 !send_codecs_.empty() ? HasTransportCc(send_codecs_[0]) : false;
2021 options_.combined_audio_video_bwe.value_or(false), sp.sync_label, 2062
2022 recv_rtp_extensions_, call_))); 2063 recv_streams_.insert(std::make_pair(
2064 ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_,
2065 transport_cc_enabled_, sp.sync_label,
2066 recv_rtp_extensions_, call_)));
2023 2067
2024 SetNack(channel, nack_enabled_); 2068 SetNack(channel, nack_enabled_);
2025 SetPlayout(channel, playout_); 2069 SetPlayout(channel, playout_);
2026 2070
2027 return true; 2071 return true;
2028 } 2072 }
2029 2073
2030 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { 2074 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
2031 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2075 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2032 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; 2076 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
2470 2514
2471 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const { 2515 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
2472 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2516 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2473 const auto it = send_streams_.find(ssrc); 2517 const auto it = send_streams_.find(ssrc);
2474 if (it != send_streams_.end()) { 2518 if (it != send_streams_.end()) {
2475 return it->second->channel(); 2519 return it->second->channel();
2476 } 2520 }
2477 return -1; 2521 return -1;
2478 } 2522 }
2479 2523
2480 bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec, 2524 const AudioCodec* WebRtcVoiceMediaChannel::GetRedSendCodec(
2481 const std::vector<AudioCodec>& all_codecs, webrtc::CodecInst* send_codec) { 2525 const AudioCodec& red_codec,
2526 const std::vector<AudioCodec>& all_codecs) const {
2482 // Get the RED encodings from the parameter with no name. This may 2527 // Get the RED encodings from the parameter with no name. This may
2483 // change based on what is discussed on the Jingle list. 2528 // change based on what is discussed on the Jingle list.
2484 // The encoding parameter is of the form "a/b"; we only support where 2529 // 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. 2530 // 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 2531 // 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 2532 // signaling of this message), use the second codec specified (i.e. the
2488 // one after "red") as the encoding parameter. 2533 // one after "red") as the encoding parameter.
2489 int red_pt = -1; 2534 int red_pt = -1;
2490 std::string red_params; 2535 std::string red_params;
2491 CodecParameterMap::const_iterator it = red_codec.params.find(""); 2536 CodecParameterMap::const_iterator it = red_codec.params.find("");
2492 if (it != red_codec.params.end()) { 2537 if (it != red_codec.params.end()) {
2493 red_params = it->second; 2538 red_params = it->second;
2494 std::vector<std::string> red_pts; 2539 std::vector<std::string> red_pts;
2495 if (rtc::split(red_params, '/', &red_pts) != 2 || 2540 if (rtc::split(red_params, '/', &red_pts) != 2 ||
2496 red_pts[0] != red_pts[1] || 2541 red_pts[0] != red_pts[1] ||
2497 !rtc::FromString(red_pts[0], &red_pt)) { 2542 !rtc::FromString(red_pts[0], &red_pt)) {
2498 LOG(LS_WARNING) << "RED params " << red_params << " not supported."; 2543 LOG(LS_WARNING) << "RED params " << red_params << " not supported.";
2499 return false; 2544 return nullptr;
2500 } 2545 }
2501 } else if (red_codec.params.empty()) { 2546 } else if (red_codec.params.empty()) {
2502 LOG(LS_WARNING) << "RED params not present, using defaults"; 2547 LOG(LS_WARNING) << "RED params not present, using defaults";
2503 if (all_codecs.size() > 1) { 2548 if (all_codecs.size() > 1) {
2504 red_pt = all_codecs[1].id; 2549 red_pt = all_codecs[1].id;
2505 } 2550 }
2506 } 2551 }
2507 2552
2508 // Try to find red_pt in |codecs|. 2553 // Try to find red_pt in |codecs|.
2509 for (const AudioCodec& codec : all_codecs) { 2554 for (const AudioCodec& codec : all_codecs) {
2510 if (codec.id == red_pt) { 2555 if (codec.id == red_pt) {
2511 // If we find the right codec, that will be the codec we pass to 2556 return &codec;
2512 // SetSendCodec, with the desired payload type.
2513 if (WebRtcVoiceEngine::ToCodecInst(codec, send_codec)) {
2514 return true;
2515 } else {
2516 break;
2517 }
2518 } 2557 }
2519 } 2558 }
2520 LOG(LS_WARNING) << "RED params " << red_params << " are invalid."; 2559 LOG(LS_WARNING) << "RED params " << red_params << " are invalid.";
2521 return false; 2560 return nullptr;
2522 } 2561 }
2523 2562
2524 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { 2563 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) {
2525 if (playout) { 2564 if (playout) {
2526 LOG(LS_INFO) << "Starting playout for channel #" << channel; 2565 LOG(LS_INFO) << "Starting playout for channel #" << channel;
2527 if (engine()->voe()->base()->StartPlayout(channel) == -1) { 2566 if (engine()->voe()->base()->StartPlayout(channel) == -1) {
2528 LOG_RTCERR1(StartPlayout, channel); 2567 LOG_RTCERR1(StartPlayout, channel);
2529 return false; 2568 return false;
2530 } 2569 }
2531 } else { 2570 } else {
2532 LOG(LS_INFO) << "Stopping playout for channel #" << channel; 2571 LOG(LS_INFO) << "Stopping playout for channel #" << channel;
2533 engine()->voe()->base()->StopPlayout(channel); 2572 engine()->voe()->base()->StopPlayout(channel);
2534 } 2573 }
2535 return true; 2574 return true;
2536 } 2575 }
2537 } // namespace cricket 2576 } // namespace cricket
2538 2577
2539 #endif // HAVE_WEBRTC_VOICE 2578 #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