Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 1122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1133 } | 1133 } |
| 1134 | 1134 |
| 1135 int WebRtcVoiceEngine::CreateVoEChannel() { | 1135 int WebRtcVoiceEngine::CreateVoEChannel() { |
| 1136 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1136 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 1137 return voe_wrapper_->base()->CreateChannel(voe_config_); | 1137 return voe_wrapper_->base()->CreateChannel(voe_config_); |
| 1138 } | 1138 } |
| 1139 | 1139 |
| 1140 class WebRtcVoiceMediaChannel::WebRtcAudioSendStream | 1140 class WebRtcVoiceMediaChannel::WebRtcAudioSendStream |
| 1141 : public AudioSource::Sink { | 1141 : public AudioSource::Sink { |
| 1142 public: | 1142 public: |
| 1143 WebRtcAudioSendStream(int ch, webrtc::AudioTransport* voe_audio_transport, | 1143 WebRtcAudioSendStream(int ch, |
| 1144 uint32_t ssrc, const std::string& c_name, | 1144 WebRtcVoiceEngine* engine, |
|
the sun
2016/04/01 08:29:06
WebRtcAudioReceive/SendStream should be thin proxy
| |
| 1145 webrtc::AudioTransport* voe_audio_transport, | |
| 1146 uint32_t ssrc, | |
| 1147 const std::string& c_name, | |
| 1145 const std::vector<webrtc::RtpExtension>& extensions, | 1148 const std::vector<webrtc::RtpExtension>& extensions, |
| 1146 webrtc::Call* call) | 1149 webrtc::Call* call) |
| 1147 : voe_audio_transport_(voe_audio_transport), | 1150 : engine_(engine), |
| 1151 voe_audio_transport_(voe_audio_transport), | |
| 1148 call_(call), | 1152 call_(call), |
| 1149 config_(nullptr) { | 1153 config_(nullptr) { |
| 1150 RTC_DCHECK_GE(ch, 0); | 1154 RTC_DCHECK_GE(ch, 0); |
| 1151 // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore: | 1155 // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore: |
| 1152 // RTC_DCHECK(voe_audio_transport); | 1156 // RTC_DCHECK(voe_audio_transport); |
| 1153 RTC_DCHECK(call); | 1157 RTC_DCHECK(call); |
| 1154 audio_capture_thread_checker_.DetachFromThread(); | 1158 audio_capture_thread_checker_.DetachFromThread(); |
| 1155 config_.rtp.ssrc = ssrc; | 1159 config_.rtp.ssrc = ssrc; |
| 1156 config_.rtp.c_name = c_name; | 1160 config_.rtp.c_name = c_name; |
| 1157 config_.voe_channel_id = ch; | 1161 config_.voe_channel_id = ch; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1250 source_ = nullptr; | 1254 source_ = nullptr; |
| 1251 UpdateSendState(); | 1255 UpdateSendState(); |
| 1252 } | 1256 } |
| 1253 | 1257 |
| 1254 // Accessor to the VoE channel ID. | 1258 // Accessor to the VoE channel ID. |
| 1255 int channel() const { | 1259 int channel() const { |
| 1256 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1260 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 1257 return config_.voe_channel_id; | 1261 return config_.voe_channel_id; |
| 1258 } | 1262 } |
| 1259 | 1263 |
| 1264 bool SetSendCodecs(const WebRtcVoiceMediaChannel::SendCodecSpec& spec); | |
| 1265 bool SetSendCodec(const webrtc::CodecInst& send_codec); | |
| 1266 void SetNack(bool nack_enabled); | |
| 1267 | |
| 1260 private: | 1268 private: |
| 1269 WebRtcVoiceEngine* engine() { return engine_; } | |
| 1270 int GetLastEngineError() { return engine()->GetLastEngineError(); } | |
| 1271 | |
| 1261 void UpdateSendState() { | 1272 void UpdateSendState() { |
| 1262 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1273 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 1263 RTC_DCHECK(stream_); | 1274 RTC_DCHECK(stream_); |
| 1264 if (send_ && source_ != nullptr) { | 1275 if (send_ && source_ != nullptr) { |
| 1265 stream_->Start(); | 1276 stream_->Start(); |
| 1266 } else { // !send || source_ = nullptr | 1277 } else { // !send || source_ = nullptr |
| 1267 stream_->Stop(); | 1278 stream_->Stop(); |
| 1268 } | 1279 } |
| 1269 } | 1280 } |
| 1270 | 1281 |
| 1271 rtc::ThreadChecker worker_thread_checker_; | 1282 rtc::ThreadChecker worker_thread_checker_; |
| 1272 rtc::ThreadChecker audio_capture_thread_checker_; | 1283 rtc::ThreadChecker audio_capture_thread_checker_; |
| 1284 WebRtcVoiceEngine* engine_ = nullptr; | |
| 1273 webrtc::AudioTransport* const voe_audio_transport_ = nullptr; | 1285 webrtc::AudioTransport* const voe_audio_transport_ = nullptr; |
| 1274 webrtc::Call* call_ = nullptr; | 1286 webrtc::Call* call_ = nullptr; |
| 1275 webrtc::AudioSendStream::Config config_; | 1287 webrtc::AudioSendStream::Config config_; |
| 1276 // The stream is owned by WebRtcAudioSendStream and may be reallocated if | 1288 // The stream is owned by WebRtcAudioSendStream and may be reallocated if |
| 1277 // configuration changes. | 1289 // configuration changes. |
| 1278 webrtc::AudioSendStream* stream_ = nullptr; | 1290 webrtc::AudioSendStream* stream_ = nullptr; |
| 1279 | 1291 |
| 1280 // Raw pointer to AudioSource owned by LocalAudioTrackHandler. | 1292 // Raw pointer to AudioSource owned by LocalAudioTrackHandler. |
| 1281 // PeerConnection will make sure invalidating the pointer before the object | 1293 // PeerConnection will make sure invalidating the pointer before the object |
| 1282 // goes away. | 1294 // goes away. |
| 1283 AudioSource* source_ = nullptr; | 1295 AudioSource* source_ = nullptr; |
| 1284 bool send_ = false; | 1296 bool send_ = false; |
| 1285 | 1297 |
| 1298 | |
| 1286 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream); | 1299 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream); |
| 1287 }; | 1300 }; |
| 1288 | 1301 |
| 1289 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { | 1302 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
| 1290 public: | 1303 public: |
| 1291 WebRtcAudioReceiveStream(int ch, | 1304 WebRtcAudioReceiveStream(int ch, |
| 1305 WebRtcVoiceEngine* engine, | |
| 1292 uint32_t remote_ssrc, | 1306 uint32_t remote_ssrc, |
| 1293 uint32_t local_ssrc, | 1307 uint32_t local_ssrc, |
| 1294 bool use_transport_cc, | 1308 bool use_transport_cc, |
| 1295 const std::string& sync_group, | 1309 const std::string& sync_group, |
| 1296 const std::vector<webrtc::RtpExtension>& extensions, | 1310 const std::vector<webrtc::RtpExtension>& extensions, |
| 1297 webrtc::Call* call) | 1311 webrtc::Call* call) |
| 1298 : call_(call), config_() { | 1312 : engine_(engine), call_(call), config_() { |
| 1299 RTC_DCHECK_GE(ch, 0); | 1313 RTC_DCHECK_GE(ch, 0); |
| 1300 RTC_DCHECK(call); | 1314 RTC_DCHECK(call); |
| 1301 config_.rtp.remote_ssrc = remote_ssrc; | 1315 config_.rtp.remote_ssrc = remote_ssrc; |
| 1302 config_.rtp.local_ssrc = local_ssrc; | 1316 config_.rtp.local_ssrc = local_ssrc; |
| 1303 config_.voe_channel_id = ch; | 1317 config_.voe_channel_id = ch; |
| 1304 config_.sync_group = sync_group; | 1318 config_.sync_group = sync_group; |
| 1305 RecreateAudioReceiveStream(use_transport_cc, extensions); | 1319 RecreateAudioReceiveStream(use_transport_cc, extensions); |
| 1306 } | 1320 } |
| 1307 | 1321 |
| 1308 ~WebRtcAudioReceiveStream() { | 1322 ~WebRtcAudioReceiveStream() { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1329 int channel() const { | 1343 int channel() const { |
| 1330 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1344 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 1331 return config_.voe_channel_id; | 1345 return config_.voe_channel_id; |
| 1332 } | 1346 } |
| 1333 | 1347 |
| 1334 void SetRawAudioSink(std::unique_ptr<webrtc::AudioSinkInterface> sink) { | 1348 void SetRawAudioSink(std::unique_ptr<webrtc::AudioSinkInterface> sink) { |
| 1335 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1349 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 1336 stream_->SetSink(std::move(sink)); | 1350 stream_->SetSink(std::move(sink)); |
| 1337 } | 1351 } |
| 1338 | 1352 |
| 1353 void SetNack(bool nack_enabled); | |
| 1354 | |
| 1339 private: | 1355 private: |
| 1356 WebRtcVoiceEngine* engine() { return engine_; } | |
| 1340 void RecreateAudioReceiveStream( | 1357 void RecreateAudioReceiveStream( |
| 1341 bool use_transport_cc, | 1358 bool use_transport_cc, |
| 1342 const std::vector<webrtc::RtpExtension>& extensions) { | 1359 const std::vector<webrtc::RtpExtension>& extensions) { |
| 1343 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1360 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 1344 if (stream_) { | 1361 if (stream_) { |
| 1345 call_->DestroyAudioReceiveStream(stream_); | 1362 call_->DestroyAudioReceiveStream(stream_); |
| 1346 stream_ = nullptr; | 1363 stream_ = nullptr; |
| 1347 } | 1364 } |
| 1348 config_.rtp.extensions = extensions; | 1365 config_.rtp.extensions = extensions; |
| 1349 config_.rtp.transport_cc = use_transport_cc; | 1366 config_.rtp.transport_cc = use_transport_cc; |
| 1350 RTC_DCHECK(!stream_); | 1367 RTC_DCHECK(!stream_); |
| 1351 stream_ = call_->CreateAudioReceiveStream(config_); | 1368 stream_ = call_->CreateAudioReceiveStream(config_); |
| 1352 RTC_CHECK(stream_); | 1369 RTC_CHECK(stream_); |
| 1353 } | 1370 } |
| 1354 | 1371 |
| 1355 rtc::ThreadChecker worker_thread_checker_; | 1372 rtc::ThreadChecker worker_thread_checker_; |
| 1373 WebRtcVoiceEngine* engine_ = nullptr; | |
| 1356 webrtc::Call* call_ = nullptr; | 1374 webrtc::Call* call_ = nullptr; |
| 1357 webrtc::AudioReceiveStream::Config config_; | 1375 webrtc::AudioReceiveStream::Config config_; |
| 1358 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if | 1376 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if |
| 1359 // configuration changes. | 1377 // configuration changes. |
| 1360 webrtc::AudioReceiveStream* stream_ = nullptr; | 1378 webrtc::AudioReceiveStream* stream_ = nullptr; |
| 1361 | 1379 |
| 1362 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream); | 1380 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream); |
| 1363 }; | 1381 }; |
| 1364 | 1382 |
| 1365 WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine, | 1383 WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine, |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1639 break; | 1657 break; |
| 1640 } | 1658 } |
| 1641 } | 1659 } |
| 1642 | 1660 |
| 1643 // Latch in the new state. | 1661 // Latch in the new state. |
| 1644 send_codec_spec_ = std::move(send_codec_spec); | 1662 send_codec_spec_ = std::move(send_codec_spec); |
| 1645 } | 1663 } |
| 1646 | 1664 |
| 1647 // Cache the codecs in order to configure the channel created later. | 1665 // Cache the codecs in order to configure the channel created later. |
| 1648 for (const auto& ch : send_streams_) { | 1666 for (const auto& ch : send_streams_) { |
| 1649 if (!SetSendCodecs(ch.second->channel())) { | 1667 if (!ch.second->SetSendCodecs(send_codec_spec_)) { |
| 1650 return false; | 1668 return false; |
| 1651 } | 1669 } |
| 1652 } | 1670 } |
| 1653 | 1671 |
| 1672 if (send_bitrate_setting_) { | |
| 1673 SetSendBitrateInternal(send_bitrate_bps_); | |
| 1674 } | |
| 1675 | |
| 1654 // Set nack status on receive channels. | 1676 // Set nack status on receive channels. |
| 1655 if (!send_streams_.empty()) { | 1677 if (!send_streams_.empty()) { |
| 1656 for (const auto& kv : recv_streams_) { | 1678 for (const auto& kv : recv_streams_) { |
| 1657 SetNack(kv.second->channel(), send_codec_spec_.nack_enabled); | 1679 kv.second->SetNack(send_codec_spec_.nack_enabled); |
| 1658 } | 1680 } |
| 1659 } | 1681 } |
| 1660 | 1682 |
| 1661 // Check if the transport cc feedback has changed on the preferred send codec, | 1683 // Check if the transport cc feedback has changed on the preferred send codec, |
| 1662 // and in that case reconfigure all receive streams. | 1684 // and in that case reconfigure all receive streams. |
| 1663 if (recv_transport_cc_enabled_ != send_codec_spec_.transport_cc_enabled) { | 1685 if (recv_transport_cc_enabled_ != send_codec_spec_.transport_cc_enabled) { |
| 1664 LOG(LS_INFO) << "Recreate all the receive streams because the send " | 1686 LOG(LS_INFO) << "Recreate all the receive streams because the send " |
| 1665 "codec has changed."; | 1687 "codec has changed."; |
| 1666 recv_transport_cc_enabled_ = send_codec_spec_.transport_cc_enabled; | 1688 recv_transport_cc_enabled_ = send_codec_spec_.transport_cc_enabled; |
| 1667 for (auto& kv : recv_streams_) { | 1689 for (auto& kv : recv_streams_) { |
| 1668 kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_); | 1690 kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_); |
| 1669 } | 1691 } |
| 1670 } | 1692 } |
| 1671 | 1693 |
| 1672 return true; | 1694 return true; |
| 1673 } | 1695 } |
| 1674 | 1696 |
| 1675 // Apply current codec settings to a single voe::Channel used for sending. | |
| 1676 bool WebRtcVoiceMediaChannel::SetSendCodecs(int channel) { | |
| 1677 // Disable VAD, FEC, and RED unless we know the other side wants them. | |
| 1678 engine()->voe()->codec()->SetVADStatus(channel, false); | |
| 1679 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); | |
| 1680 engine()->voe()->rtp()->SetREDStatus(channel, false); | |
| 1681 engine()->voe()->codec()->SetFECStatus(channel, false); | |
| 1682 | |
| 1683 if (send_codec_spec_.red_payload_type != -1) { | |
| 1684 // Enable redundant encoding of the specified codec. Treat any | |
| 1685 // failure as a fatal internal error. | |
| 1686 LOG(LS_INFO) << "Enabling RED on channel " << channel; | |
| 1687 if (engine()->voe()->rtp()->SetREDStatus(channel, true, | |
| 1688 send_codec_spec_.red_payload_type) == -1) { | |
| 1689 LOG_RTCERR3(SetREDStatus, channel, true, | |
| 1690 send_codec_spec_.red_payload_type); | |
| 1691 return false; | |
| 1692 } | |
| 1693 } | |
| 1694 | |
| 1695 SetNack(channel, send_codec_spec_.nack_enabled); | |
| 1696 | |
| 1697 // Set the codec immediately, since SetVADStatus() depends on whether | |
| 1698 // the current codec is mono or stereo. | |
| 1699 if (!SetSendCodec(channel, send_codec_spec_.codec_inst)) { | |
| 1700 return false; | |
| 1701 } | |
| 1702 | |
| 1703 // FEC should be enabled after SetSendCodec. | |
| 1704 if (send_codec_spec_.enable_codec_fec) { | |
| 1705 LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel " | |
| 1706 << channel; | |
| 1707 if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) { | |
| 1708 // Enable codec internal FEC. Treat any failure as fatal internal error. | |
| 1709 LOG_RTCERR2(SetFECStatus, channel, true); | |
| 1710 return false; | |
| 1711 } | |
| 1712 } | |
| 1713 | |
| 1714 if (IsCodec(send_codec_spec_.codec_inst, kOpusCodecName)) { | |
| 1715 // DTX and maxplaybackrate should be set after SetSendCodec. Because current | |
| 1716 // send codec has to be Opus. | |
| 1717 | |
| 1718 // Set Opus internal DTX. | |
| 1719 LOG(LS_INFO) << "Attempt to " | |
| 1720 << (send_codec_spec_.enable_opus_dtx ? "enable" : "disable") | |
| 1721 << " Opus DTX on channel " | |
| 1722 << channel; | |
| 1723 if (engine()->voe()->codec()->SetOpusDtx(channel, | |
| 1724 send_codec_spec_.enable_opus_dtx)) { | |
| 1725 LOG_RTCERR2(SetOpusDtx, channel, send_codec_spec_.enable_opus_dtx); | |
| 1726 return false; | |
| 1727 } | |
| 1728 | |
| 1729 // If opus_max_playback_rate <= 0, the default maximum playback rate | |
| 1730 // (48 kHz) will be used. | |
| 1731 if (send_codec_spec_.opus_max_playback_rate > 0) { | |
| 1732 LOG(LS_INFO) << "Attempt to set maximum playback rate to " | |
| 1733 << send_codec_spec_.opus_max_playback_rate | |
| 1734 << " Hz on channel " | |
| 1735 << channel; | |
| 1736 if (engine()->voe()->codec()->SetOpusMaxPlaybackRate( | |
| 1737 channel, send_codec_spec_.opus_max_playback_rate) == -1) { | |
| 1738 LOG_RTCERR2(SetOpusMaxPlaybackRate, channel, | |
| 1739 send_codec_spec_.opus_max_playback_rate); | |
| 1740 return false; | |
| 1741 } | |
| 1742 } | |
| 1743 } | |
| 1744 | |
| 1745 if (send_bitrate_setting_) { | |
| 1746 SetSendBitrateInternal(send_bitrate_bps_); | |
| 1747 } | |
| 1748 | |
| 1749 // Set the CN payloadtype and the VAD status. | |
| 1750 if (send_codec_spec_.cng_payload_type != -1) { | |
| 1751 // The CN payload type for 8000 Hz clockrate is fixed at 13. | |
| 1752 if (send_codec_spec_.cng_plfreq != 8000) { | |
| 1753 webrtc::PayloadFrequencies cn_freq; | |
| 1754 switch (send_codec_spec_.cng_plfreq) { | |
| 1755 case 16000: | |
| 1756 cn_freq = webrtc::kFreq16000Hz; | |
| 1757 break; | |
| 1758 case 32000: | |
| 1759 cn_freq = webrtc::kFreq32000Hz; | |
| 1760 break; | |
| 1761 default: | |
| 1762 RTC_NOTREACHED(); | |
| 1763 return false; | |
| 1764 } | |
| 1765 if (engine()->voe()->codec()->SetSendCNPayloadType( | |
| 1766 channel, send_codec_spec_.cng_payload_type, cn_freq) == -1) { | |
| 1767 LOG_RTCERR3(SetSendCNPayloadType, channel, | |
| 1768 send_codec_spec_.cng_payload_type, cn_freq); | |
| 1769 // TODO(ajm): This failure condition will be removed from VoE. | |
| 1770 // Restore the return here when we update to a new enough webrtc. | |
| 1771 // | |
| 1772 // Not returning false because the SetSendCNPayloadType will fail if | |
| 1773 // the channel is already sending. | |
| 1774 // This can happen if the remote description is applied twice, for | |
| 1775 // example in the case of ROAP on top of JSEP, where both side will | |
| 1776 // send the offer. | |
| 1777 } | |
| 1778 } | |
| 1779 | |
| 1780 // Only turn on VAD if we have a CN payload type that matches the | |
| 1781 // clockrate for the codec we are going to use. | |
| 1782 if (send_codec_spec_.cng_plfreq == send_codec_spec_.codec_inst.plfreq && | |
| 1783 send_codec_spec_.codec_inst.channels == 1) { | |
| 1784 // TODO(minyue): If CN frequency == 48000 Hz is allowed, consider the | |
| 1785 // interaction between VAD and Opus FEC. | |
| 1786 LOG(LS_INFO) << "Enabling VAD"; | |
| 1787 if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) { | |
| 1788 LOG_RTCERR2(SetVADStatus, channel, true); | |
| 1789 return false; | |
| 1790 } | |
| 1791 } | |
| 1792 } | |
| 1793 return true; | |
| 1794 } | |
| 1795 | |
| 1796 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { | |
| 1797 if (nack_enabled) { | |
| 1798 LOG(LS_INFO) << "Enabling NACK for channel " << channel; | |
| 1799 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); | |
| 1800 } else { | |
| 1801 LOG(LS_INFO) << "Disabling NACK for channel " << channel; | |
| 1802 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); | |
| 1803 } | |
| 1804 } | |
| 1805 | |
| 1806 bool WebRtcVoiceMediaChannel::SetSendCodec( | |
| 1807 int channel, const webrtc::CodecInst& send_codec) { | |
| 1808 LOG(LS_INFO) << "Send channel " << channel << " selected voice codec " | |
| 1809 << ToString(send_codec) << ", bitrate=" << send_codec.rate; | |
| 1810 | |
| 1811 webrtc::CodecInst current_codec = {0}; | |
| 1812 if (engine()->voe()->codec()->GetSendCodec(channel, current_codec) == 0 && | |
| 1813 (send_codec == current_codec)) { | |
| 1814 // Codec is already configured, we can return without setting it again. | |
| 1815 return true; | |
| 1816 } | |
| 1817 | |
| 1818 if (engine()->voe()->codec()->SetSendCodec(channel, send_codec) == -1) { | |
| 1819 LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec)); | |
| 1820 return false; | |
| 1821 } | |
| 1822 return true; | |
| 1823 } | |
| 1824 | |
| 1825 bool WebRtcVoiceMediaChannel::SetPlayout(bool playout) { | 1697 bool WebRtcVoiceMediaChannel::SetPlayout(bool playout) { |
| 1826 desired_playout_ = playout; | 1698 desired_playout_ = playout; |
| 1827 return ChangePlayout(desired_playout_); | 1699 return ChangePlayout(desired_playout_); |
| 1828 } | 1700 } |
| 1829 | 1701 |
| 1830 bool WebRtcVoiceMediaChannel::PausePlayout() { | 1702 bool WebRtcVoiceMediaChannel::PausePlayout() { |
| 1831 return ChangePlayout(false); | 1703 return ChangePlayout(false); |
| 1832 } | 1704 } |
| 1833 | 1705 |
| 1834 bool WebRtcVoiceMediaChannel::ResumePlayout() { | 1706 bool WebRtcVoiceMediaChannel::ResumePlayout() { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1932 // Create a new channel for sending audio data. | 1804 // Create a new channel for sending audio data. |
| 1933 int channel = CreateVoEChannel(); | 1805 int channel = CreateVoEChannel(); |
| 1934 if (channel == -1) { | 1806 if (channel == -1) { |
| 1935 return false; | 1807 return false; |
| 1936 } | 1808 } |
| 1937 | 1809 |
| 1938 // Save the channel to send_streams_, so that RemoveSendStream() can still | 1810 // Save the channel to send_streams_, so that RemoveSendStream() can still |
| 1939 // delete the channel in case failure happens below. | 1811 // delete the channel in case failure happens below. |
| 1940 webrtc::AudioTransport* audio_transport = | 1812 webrtc::AudioTransport* audio_transport = |
| 1941 engine()->voe()->base()->audio_transport(); | 1813 engine()->voe()->base()->audio_transport(); |
| 1942 send_streams_.insert(std::make_pair(ssrc, new WebRtcAudioSendStream( | 1814 WebRtcAudioSendStream* send_stream = |
| 1943 channel, audio_transport, ssrc, sp.cname, send_rtp_extensions_, call_))); | 1815 new WebRtcAudioSendStream(channel, engine(), audio_transport, ssrc, |
| 1816 sp.cname, send_rtp_extensions_, call_); | |
| 1817 send_streams_.insert(std::make_pair(ssrc, send_stream)); | |
| 1944 | 1818 |
| 1945 // Set the current codecs to be used for the new channel. We need to do this | 1819 // Set the current codecs to be used for the new channel. We need to do this |
| 1946 // after adding the channel to send_channels_, because of how max bitrate is | 1820 // after adding the channel to send_channels_, because of how max bitrate is |
| 1947 // currently being configured by SetSendCodec(). | 1821 // currently being configured by SetSendCodec(). |
| 1948 if (HasSendCodec() && !SetSendCodecs(channel)) { | 1822 if (HasSendCodec() && !send_stream->SetSendCodecs(send_codec_spec_)) { |
| 1949 RemoveSendStream(ssrc); | 1823 RemoveSendStream(ssrc); |
| 1950 return false; | 1824 return false; |
| 1951 } | 1825 } |
| 1952 | 1826 |
| 1827 if (send_bitrate_setting_) { | |
| 1828 SetSendBitrateInternal(send_bitrate_bps_); | |
| 1829 } | |
| 1830 | |
| 1953 // At this point the channel's local SSRC has been updated. If the channel is | 1831 // At this point the channel's local SSRC has been updated. If the channel is |
| 1954 // the first send channel make sure that all the receive channels are updated | 1832 // the first send channel make sure that all the receive channels are updated |
| 1955 // with the same SSRC in order to send receiver reports. | 1833 // with the same SSRC in order to send receiver reports. |
| 1956 if (send_streams_.size() == 1) { | 1834 if (send_streams_.size() == 1) { |
| 1957 receiver_reports_ssrc_ = ssrc; | 1835 receiver_reports_ssrc_ = ssrc; |
| 1958 for (const auto& stream : recv_streams_) { | 1836 for (const auto& stream : recv_streams_) { |
| 1959 int recv_channel = stream.second->channel(); | 1837 int recv_channel = stream.second->channel(); |
| 1960 if (engine()->voe()->rtp()->SetLocalSSRC(recv_channel, ssrc) != 0) { | 1838 if (engine()->voe()->rtp()->SetLocalSSRC(recv_channel, ssrc) != 0) { |
| 1961 LOG_RTCERR2(SetLocalSSRC, recv_channel, ssrc); | 1839 LOG_RTCERR2(SetLocalSSRC, recv_channel, ssrc); |
| 1962 return false; | 1840 return false; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2059 | 1937 |
| 2060 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); | 1938 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); |
| 2061 if (send_channel != -1) { | 1939 if (send_channel != -1) { |
| 2062 // Associate receive channel with first send channel (so the receive channel | 1940 // Associate receive channel with first send channel (so the receive channel |
| 2063 // can obtain RTT from the send channel) | 1941 // can obtain RTT from the send channel) |
| 2064 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); | 1942 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); |
| 2065 LOG(LS_INFO) << "VoiceEngine channel #" << channel | 1943 LOG(LS_INFO) << "VoiceEngine channel #" << channel |
| 2066 << " is associated with channel #" << send_channel << "."; | 1944 << " is associated with channel #" << send_channel << "."; |
| 2067 } | 1945 } |
| 2068 | 1946 |
| 2069 recv_streams_.insert(std::make_pair( | 1947 WebRtcAudioReceiveStream* recv_stream = new WebRtcAudioReceiveStream( |
| 2070 ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_, | 1948 channel, engine(), ssrc, receiver_reports_ssrc_, |
| 2071 recv_transport_cc_enabled_, | 1949 recv_transport_cc_enabled_, sp.sync_label, recv_rtp_extensions_, call_); |
| 2072 sp.sync_label, recv_rtp_extensions_, | 1950 recv_streams_.insert(std::make_pair(ssrc, recv_stream)); |
| 2073 call_))); | |
| 2074 | 1951 |
| 2075 SetNack(channel, send_codec_spec_.nack_enabled); | 1952 recv_stream->SetNack(send_codec_spec_.nack_enabled); |
| 2076 SetPlayout(channel, playout_); | 1953 SetPlayout(channel, playout_); |
| 2077 | 1954 |
| 2078 return true; | 1955 return true; |
| 2079 } | 1956 } |
| 2080 | 1957 |
| 2081 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { | 1958 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { |
| 2082 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveRecvStream"); | 1959 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveRecvStream"); |
| 2083 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1960 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 2084 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; | 1961 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; |
| 2085 | 1962 |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2394 if (bps <= 0) | 2271 if (bps <= 0) |
| 2395 return true; | 2272 return true; |
| 2396 | 2273 |
| 2397 webrtc::CodecInst codec = send_codec_spec_.codec_inst; | 2274 webrtc::CodecInst codec = send_codec_spec_.codec_inst; |
| 2398 bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec); | 2275 bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec); |
| 2399 | 2276 |
| 2400 if (is_multi_rate) { | 2277 if (is_multi_rate) { |
| 2401 // If codec is multi-rate then just set the bitrate. | 2278 // If codec is multi-rate then just set the bitrate. |
| 2402 codec.rate = bps; | 2279 codec.rate = bps; |
| 2403 for (const auto& ch : send_streams_) { | 2280 for (const auto& ch : send_streams_) { |
| 2404 if (!SetSendCodec(ch.second->channel(), codec)) { | 2281 if (!ch.second->SetSendCodec(codec)) { |
| 2405 LOG(LS_INFO) << "Failed to set codec " << codec.plname | 2282 LOG(LS_INFO) << "Failed to set codec " << codec.plname |
| 2406 << " to bitrate " << bps << " bps."; | 2283 << " to bitrate " << bps << " bps."; |
| 2407 return false; | 2284 return false; |
| 2408 } | 2285 } |
| 2409 } | 2286 } |
| 2410 return true; | 2287 return true; |
| 2411 } else { | 2288 } else { |
| 2412 // If codec is not multi-rate and |bps| is less than the fixed bitrate | 2289 // If codec is not multi-rate and |bps| is less than the fixed bitrate |
| 2413 // then fail. If codec is not multi-rate and |bps| exceeds or equal the | 2290 // then fail. If codec is not multi-rate and |bps| exceeds or equal the |
| 2414 // fixed bitrate then ignore. | 2291 // fixed bitrate then ignore. |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2548 if (engine()->voe()->base()->StartPlayout(channel) == -1) { | 2425 if (engine()->voe()->base()->StartPlayout(channel) == -1) { |
| 2549 LOG_RTCERR1(StartPlayout, channel); | 2426 LOG_RTCERR1(StartPlayout, channel); |
| 2550 return false; | 2427 return false; |
| 2551 } | 2428 } |
| 2552 } else { | 2429 } else { |
| 2553 LOG(LS_INFO) << "Stopping playout for channel #" << channel; | 2430 LOG(LS_INFO) << "Stopping playout for channel #" << channel; |
| 2554 engine()->voe()->base()->StopPlayout(channel); | 2431 engine()->voe()->base()->StopPlayout(channel); |
| 2555 } | 2432 } |
| 2556 return true; | 2433 return true; |
| 2557 } | 2434 } |
| 2435 | |
| 2436 // Apply current codec settings to a single voe::Channel used for sending. | |
| 2437 bool WebRtcVoiceMediaChannel::WebRtcAudioSendStream::SetSendCodecs( | |
| 2438 const WebRtcVoiceMediaChannel::SendCodecSpec& send_codec_spec) { | |
| 2439 // Disable VAD, FEC, and RED unless we know the other side wants them. | |
| 2440 engine()->voe()->codec()->SetVADStatus(channel(), false); | |
| 2441 engine()->voe()->rtp()->SetNACKStatus(channel(), false, 0); | |
| 2442 engine()->voe()->rtp()->SetREDStatus(channel(), false); | |
| 2443 engine()->voe()->codec()->SetFECStatus(channel(), false); | |
| 2444 | |
| 2445 if (send_codec_spec.red_payload_type != -1) { | |
| 2446 // Enable redundant encoding of the specified codec. Treat any | |
| 2447 // failure as a fatal internal error. | |
| 2448 LOG(LS_INFO) << "Enabling RED on channel " << channel(); | |
| 2449 if (engine()->voe()->rtp()->SetREDStatus( | |
| 2450 channel(), true, send_codec_spec.red_payload_type) == -1) { | |
| 2451 LOG_RTCERR3(SetREDStatus, channel(), true, | |
| 2452 send_codec_spec.red_payload_type); | |
| 2453 return false; | |
| 2454 } | |
| 2455 } | |
| 2456 | |
| 2457 SetNack(send_codec_spec.nack_enabled); | |
| 2458 | |
| 2459 // Set the codec immediately, since SetVADStatus() depends on whether | |
| 2460 // the current codec is mono or stereo. | |
| 2461 if (!SetSendCodec(send_codec_spec.codec_inst)) { | |
| 2462 return false; | |
| 2463 } | |
| 2464 | |
| 2465 // FEC should be enabled after SetSendCodec. | |
| 2466 if (send_codec_spec.enable_codec_fec) { | |
| 2467 LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel " | |
| 2468 << channel(); | |
| 2469 if (engine()->voe()->codec()->SetFECStatus(channel(), true) == -1) { | |
| 2470 // Enable codec internal FEC. Treat any failure as fatal internal error. | |
| 2471 LOG_RTCERR2(SetFECStatus, channel(), true); | |
| 2472 return false; | |
| 2473 } | |
| 2474 } | |
| 2475 | |
| 2476 if (IsCodec(send_codec_spec.codec_inst, kOpusCodecName)) { | |
| 2477 // DTX and maxplaybackrate should be set after SetSendCodec. Because current | |
| 2478 // send codec has to be Opus. | |
| 2479 | |
| 2480 // Set Opus internal DTX. | |
| 2481 LOG(LS_INFO) << "Attempt to " | |
| 2482 << (send_codec_spec.enable_opus_dtx ? "enable" : "disable") | |
| 2483 << " Opus DTX on channel " << channel(); | |
| 2484 if (engine()->voe()->codec()->SetOpusDtx( | |
| 2485 channel(), send_codec_spec.enable_opus_dtx)) { | |
| 2486 LOG_RTCERR2(SetOpusDtx, channel(), send_codec_spec.enable_opus_dtx); | |
| 2487 return false; | |
| 2488 } | |
| 2489 | |
| 2490 // If opus_max_playback_rate <= 0, the default maximum playback rate | |
| 2491 // (48 kHz) will be used. | |
| 2492 if (send_codec_spec.opus_max_playback_rate > 0) { | |
| 2493 LOG(LS_INFO) << "Attempt to set maximum playback rate to " | |
| 2494 << send_codec_spec.opus_max_playback_rate | |
| 2495 << " Hz on channel " << channel(); | |
| 2496 if (engine()->voe()->codec()->SetOpusMaxPlaybackRate( | |
| 2497 channel(), send_codec_spec.opus_max_playback_rate) == -1) { | |
| 2498 LOG_RTCERR2(SetOpusMaxPlaybackRate, channel(), | |
| 2499 send_codec_spec.opus_max_playback_rate); | |
| 2500 return false; | |
| 2501 } | |
| 2502 } | |
| 2503 } | |
| 2504 | |
| 2505 // Set the CN payloadtype and the VAD status. | |
| 2506 if (send_codec_spec.cng_payload_type != -1) { | |
| 2507 // The CN payload type for 8000 Hz clockrate is fixed at 13. | |
| 2508 if (send_codec_spec.cng_plfreq != 8000) { | |
| 2509 webrtc::PayloadFrequencies cn_freq; | |
| 2510 switch (send_codec_spec.cng_plfreq) { | |
| 2511 case 16000: | |
| 2512 cn_freq = webrtc::kFreq16000Hz; | |
| 2513 break; | |
| 2514 case 32000: | |
| 2515 cn_freq = webrtc::kFreq32000Hz; | |
| 2516 break; | |
| 2517 default: | |
| 2518 RTC_NOTREACHED(); | |
| 2519 return false; | |
| 2520 } | |
| 2521 if (engine()->voe()->codec()->SetSendCNPayloadType( | |
| 2522 channel(), send_codec_spec.cng_payload_type, cn_freq) == -1) { | |
| 2523 LOG_RTCERR3(SetSendCNPayloadType, channel(), | |
| 2524 send_codec_spec.cng_payload_type, cn_freq); | |
| 2525 // TODO(ajm): This failure condition will be removed from VoE. | |
| 2526 // Restore the return here when we update to a new enough webrtc. | |
| 2527 // | |
| 2528 // Not returning false because the SetSendCNPayloadType will fail if | |
| 2529 // the channel is already sending. | |
| 2530 // This can happen if the remote description is applied twice, for | |
| 2531 // example in the case of ROAP on top of JSEP, where both side will | |
| 2532 // send the offer. | |
| 2533 } | |
| 2534 } | |
| 2535 | |
| 2536 // Only turn on VAD if we have a CN payload type that matches the | |
| 2537 // clockrate for the codec we are going to use. | |
| 2538 if (send_codec_spec.cng_plfreq == send_codec_spec.codec_inst.plfreq && | |
| 2539 send_codec_spec.codec_inst.channels == 1) { | |
| 2540 // TODO(minyue): If CN frequency == 48000 Hz is allowed, consider the | |
| 2541 // interaction between VAD and Opus FEC. | |
| 2542 LOG(LS_INFO) << "Enabling VAD"; | |
| 2543 if (engine()->voe()->codec()->SetVADStatus(channel(), true) == -1) { | |
| 2544 LOG_RTCERR2(SetVADStatus, channel(), true); | |
| 2545 return false; | |
| 2546 } | |
| 2547 } | |
| 2548 } | |
| 2549 return true; | |
| 2550 } | |
| 2551 | |
| 2552 bool WebRtcVoiceMediaChannel::WebRtcAudioSendStream::SetSendCodec( | |
| 2553 const webrtc::CodecInst& send_codec) { | |
| 2554 LOG(LS_INFO) << "Send channel " << channel() << " selected voice codec " | |
| 2555 << ToString(send_codec) << ", bitrate=" << send_codec.rate; | |
| 2556 | |
| 2557 webrtc::CodecInst current_codec = {0}; | |
| 2558 if (engine()->voe()->codec()->GetSendCodec(channel(), current_codec) == 0 && | |
| 2559 (send_codec == current_codec)) { | |
| 2560 // Codec is already configured, we can return without setting it again. | |
| 2561 return true; | |
| 2562 } | |
| 2563 | |
| 2564 if (engine()->voe()->codec()->SetSendCodec(channel(), send_codec) == -1) { | |
| 2565 LOG_RTCERR2(SetSendCodec, channel(), ToString(send_codec)); | |
| 2566 return false; | |
| 2567 } | |
| 2568 return true; | |
| 2569 } | |
| 2570 | |
| 2571 void WebRtcVoiceMediaChannel::WebRtcAudioSendStream::SetNack( | |
| 2572 bool nack_enabled) { | |
| 2573 if (nack_enabled) { | |
| 2574 LOG(LS_INFO) << "Enabling NACK for channel " << channel(); | |
| 2575 engine()->voe()->rtp()->SetNACKStatus(channel(), true, kNackMaxPackets); | |
| 2576 } else { | |
| 2577 LOG(LS_INFO) << "Disabling NACK for channel " << channel(); | |
| 2578 engine()->voe()->rtp()->SetNACKStatus(channel(), false, 0); | |
| 2579 } | |
| 2580 } | |
| 2581 | |
| 2582 void WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream::SetNack( | |
| 2583 bool nack_enabled) { | |
| 2584 if (nack_enabled) { | |
| 2585 LOG(LS_INFO) << "Enabling NACK for channel " << channel(); | |
| 2586 engine()->voe()->rtp()->SetNACKStatus(channel(), true, kNackMaxPackets); | |
| 2587 } else { | |
| 2588 LOG(LS_INFO) << "Disabling NACK for channel " << channel(); | |
| 2589 engine()->voe()->rtp()->SetNACKStatus(channel(), false, 0); | |
| 2590 } | |
| 2591 } | |
| 2592 | |
| 2558 } // namespace cricket | 2593 } // namespace cricket |
| 2559 | 2594 |
| 2560 #endif // HAVE_WEBRTC_VOICE | 2595 #endif // HAVE_WEBRTC_VOICE |
| OLD | NEW |