OLD | NEW |
---|---|
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2004 Google Inc. | 3 * Copyright 2004 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |