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 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate"; | 591 LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate"; |
592 initialized_ = false; | 592 initialized_ = false; |
593 | 593 |
594 StopAecDump(); | 594 StopAecDump(); |
595 | 595 |
596 voe_wrapper_->base()->Terminate(); | 596 voe_wrapper_->base()->Terminate(); |
597 } | 597 } |
598 | 598 |
599 VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(webrtc::Call* call, | 599 VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(webrtc::Call* call, |
600 const AudioOptions& options) { | 600 const AudioOptions& options) { |
601 WebRtcVoiceMediaChannel* ch = | 601 return new WebRtcVoiceMediaChannel(this, options, call); |
602 new WebRtcVoiceMediaChannel(this, options, call); | |
603 if (!ch->valid()) { | |
604 delete ch; | |
605 return nullptr; | |
606 } | |
607 return ch; | |
608 } | 602 } |
609 | 603 |
610 bool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) { | 604 bool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) { |
611 if (!ApplyOptions(options)) { | 605 if (!ApplyOptions(options)) { |
612 return false; | 606 return false; |
613 } | 607 } |
614 options_ = options; | 608 options_ = options; |
615 return true; | 609 return true; |
616 } | 610 } |
617 | 611 |
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1308 } | 1302 } |
1309 | 1303 |
1310 bool WebRtcVoiceEngine::StartRtcEventLog(rtc::PlatformFile file) { | 1304 bool WebRtcVoiceEngine::StartRtcEventLog(rtc::PlatformFile file) { |
1311 return voe_wrapper_->codec()->GetEventLog()->StartLogging(file); | 1305 return voe_wrapper_->codec()->GetEventLog()->StartLogging(file); |
1312 } | 1306 } |
1313 | 1307 |
1314 void WebRtcVoiceEngine::StopRtcEventLog() { | 1308 void WebRtcVoiceEngine::StopRtcEventLog() { |
1315 voe_wrapper_->codec()->GetEventLog()->StopLogging(); | 1309 voe_wrapper_->codec()->GetEventLog()->StopLogging(); |
1316 } | 1310 } |
1317 | 1311 |
1318 int WebRtcVoiceEngine::CreateVoiceChannel(VoEWrapper* voice_engine_wrapper) { | 1312 int WebRtcVoiceEngine::CreateVoEChannel() { |
1319 return voice_engine_wrapper->base()->CreateChannel(voe_config_); | 1313 return voe_wrapper_->base()->CreateChannel(voe_config_); |
1320 } | |
1321 | |
1322 int WebRtcVoiceEngine::CreateMediaVoiceChannel() { | |
1323 return CreateVoiceChannel(voe_wrapper_.get()); | |
1324 } | 1314 } |
1325 | 1315 |
1326 class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer | 1316 class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer |
1327 : public AudioRenderer::Sink { | 1317 : public AudioRenderer::Sink { |
1328 public: | 1318 public: |
1329 WebRtcVoiceChannelRenderer(int ch, | 1319 WebRtcVoiceChannelRenderer(int ch, |
1330 webrtc::AudioTransport* voe_audio_transport) | 1320 webrtc::AudioTransport* voe_audio_transport) |
1331 : channel_(ch), | 1321 : channel_(ch), |
1332 voe_audio_transport_(voe_audio_transport), | 1322 voe_audio_transport_(voe_audio_transport), |
1333 renderer_(NULL) {} | 1323 renderer_(NULL) {} |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1397 | 1387 |
1398 // Protects |renderer_| in Start(), Stop() and OnClose(). | 1388 // Protects |renderer_| in Start(), Stop() and OnClose(). |
1399 rtc::CriticalSection lock_; | 1389 rtc::CriticalSection lock_; |
1400 }; | 1390 }; |
1401 | 1391 |
1402 // WebRtcVoiceMediaChannel | 1392 // WebRtcVoiceMediaChannel |
1403 WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine, | 1393 WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine, |
1404 const AudioOptions& options, | 1394 const AudioOptions& options, |
1405 webrtc::Call* call) | 1395 webrtc::Call* call) |
1406 : engine_(engine), | 1396 : engine_(engine), |
1407 default_send_channel_id_(engine->CreateMediaVoiceChannel()), | |
1408 send_bitrate_setting_(false), | 1397 send_bitrate_setting_(false), |
1409 send_bitrate_bps_(0), | 1398 send_bitrate_bps_(0), |
1410 options_(), | 1399 options_(), |
1411 dtmf_allowed_(false), | 1400 dtmf_allowed_(false), |
1412 desired_playout_(false), | 1401 desired_playout_(false), |
1413 nack_enabled_(false), | 1402 nack_enabled_(false), |
1414 playout_(false), | 1403 playout_(false), |
1415 typing_noise_detected_(false), | 1404 typing_noise_detected_(false), |
1416 desired_send_(SEND_NOTHING), | 1405 desired_send_(SEND_NOTHING), |
1417 send_(SEND_NOTHING), | 1406 send_(SEND_NOTHING), |
1418 call_(call) { | 1407 call_(call) { |
1419 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1408 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 1409 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel"; |
| 1410 RTC_DCHECK(nullptr != call); |
1420 engine->RegisterChannel(this); | 1411 engine->RegisterChannel(this); |
1421 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel " | |
1422 << default_send_channel_id(); | |
1423 RTC_DCHECK(nullptr != call); | |
1424 ConfigureSendChannel(default_send_channel_id()); | |
1425 SetOptions(options); | 1412 SetOptions(options); |
1426 } | 1413 } |
1427 | 1414 |
1428 WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() { | 1415 WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() { |
1429 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1416 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
1430 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel " | 1417 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel"; |
1431 << default_send_channel_id(); | |
1432 | 1418 |
1433 // Remove any remaining send streams, the default channel will be deleted | 1419 // Remove any remaining send streams. |
1434 // later. | |
1435 while (!send_channels_.empty()) { | 1420 while (!send_channels_.empty()) { |
1436 RemoveSendStream(send_channels_.begin()->first); | 1421 RemoveSendStream(send_channels_.begin()->first); |
1437 } | 1422 } |
1438 | 1423 |
1439 // Unregister ourselves from the engine. | 1424 // Remove any remaining receive streams. |
1440 engine()->UnregisterChannel(this); | |
1441 | |
1442 // Remove any remaining streams. | |
1443 while (!receive_channels_.empty()) { | 1425 while (!receive_channels_.empty()) { |
1444 RemoveRecvStream(receive_channels_.begin()->first); | 1426 RemoveRecvStream(receive_channels_.begin()->first); |
1445 } | 1427 } |
1446 RTC_DCHECK(receive_streams_.empty()); | 1428 RTC_DCHECK(receive_streams_.empty()); |
1447 | 1429 |
1448 // Delete the default channel. | 1430 // Unregister ourselves from the engine. |
1449 DeleteChannel(default_send_channel_id()); | 1431 engine()->UnregisterChannel(this); |
1450 } | 1432 } |
1451 | 1433 |
1452 bool WebRtcVoiceMediaChannel::SetSendParameters( | 1434 bool WebRtcVoiceMediaChannel::SetSendParameters( |
1453 const AudioSendParameters& params) { | 1435 const AudioSendParameters& params) { |
1454 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1436 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
1455 // TODO(pthatcher): Refactor this to be more clean now that we have | 1437 // TODO(pthatcher): Refactor this to be more clean now that we have |
1456 // all the information at once. | 1438 // all the information at once. |
1457 return (SetSendCodecs(params.codecs) && | 1439 return (SetSendCodecs(params.codecs) && |
1458 SetSendRtpHeaderExtensions(params.extensions) && | 1440 SetSendRtpHeaderExtensions(params.extensions) && |
1459 SetMaxSendBandwidth(params.max_bandwidth_bps) && | 1441 SetMaxSendBandwidth(params.max_bandwidth_bps) && |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1778 | 1760 |
1779 // Cache the codecs in order to configure the channel created later. | 1761 // Cache the codecs in order to configure the channel created later. |
1780 send_codecs_ = codecs; | 1762 send_codecs_ = codecs; |
1781 for (const auto& ch : send_channels_) { | 1763 for (const auto& ch : send_channels_) { |
1782 if (!SetSendCodecs(ch.second->channel(), codecs)) { | 1764 if (!SetSendCodecs(ch.second->channel(), codecs)) { |
1783 return false; | 1765 return false; |
1784 } | 1766 } |
1785 } | 1767 } |
1786 | 1768 |
1787 // Set nack status on receive channels and update |nack_enabled_|. | 1769 // Set nack status on receive channels and update |nack_enabled_|. |
1788 SetNack(receive_channels_, nack_enabled_); | 1770 for (const auto& ch : receive_channels_) { |
| 1771 SetNack(ch.second->channel(), nack_enabled_); |
| 1772 } |
| 1773 |
1789 return true; | 1774 return true; |
1790 } | 1775 } |
1791 | 1776 |
1792 void WebRtcVoiceMediaChannel::SetNack(const ChannelMap& channels, | |
1793 bool nack_enabled) { | |
1794 for (const auto& ch : channels) { | |
1795 SetNack(ch.second->channel(), nack_enabled); | |
1796 } | |
1797 } | |
1798 | |
1799 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { | 1777 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { |
1800 if (nack_enabled) { | 1778 if (nack_enabled) { |
1801 LOG(LS_INFO) << "Enabling NACK for channel " << channel; | 1779 LOG(LS_INFO) << "Enabling NACK for channel " << channel; |
1802 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); | 1780 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); |
1803 } else { | 1781 } else { |
1804 LOG(LS_INFO) << "Disabling NACK for channel " << channel; | 1782 LOG(LS_INFO) << "Disabling NACK for channel " << channel; |
1805 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); | 1783 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); |
1806 } | 1784 } |
1807 } | 1785 } |
1808 | 1786 |
1809 bool WebRtcVoiceMediaChannel::SetSendCodec( | 1787 bool WebRtcVoiceMediaChannel::SetSendCodec( |
1810 const webrtc::CodecInst& send_codec) { | |
1811 LOG(LS_INFO) << "Selected voice codec " << ToString(send_codec) | |
1812 << ", bitrate=" << send_codec.rate; | |
1813 for (const auto& ch : send_channels_) { | |
1814 if (!SetSendCodec(ch.second->channel(), send_codec)) | |
1815 return false; | |
1816 } | |
1817 | |
1818 return true; | |
1819 } | |
1820 | |
1821 bool WebRtcVoiceMediaChannel::SetSendCodec( | |
1822 int channel, const webrtc::CodecInst& send_codec) { | 1788 int channel, const webrtc::CodecInst& send_codec) { |
1823 LOG(LS_INFO) << "Send channel " << channel << " selected voice codec " | 1789 LOG(LS_INFO) << "Send channel " << channel << " selected voice codec " |
1824 << ToString(send_codec) << ", bitrate=" << send_codec.rate; | 1790 << ToString(send_codec) << ", bitrate=" << send_codec.rate; |
1825 | 1791 |
1826 webrtc::CodecInst current_codec; | 1792 webrtc::CodecInst current_codec; |
1827 if (engine()->voe()->codec()->GetSendCodec(channel, current_codec) == 0 && | 1793 if (engine()->voe()->codec()->GetSendCodec(channel, current_codec) == 0 && |
1828 (send_codec == current_codec)) { | 1794 (send_codec == current_codec)) { |
1829 // Codec is already configured, we can return without setting it again. | 1795 // Codec is already configured, we can return without setting it again. |
1830 return true; | 1796 return true; |
1831 } | 1797 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1898 return true; | 1864 return true; |
1899 } | 1865 } |
1900 | 1866 |
1901 bool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions( | 1867 bool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions( |
1902 const std::vector<RtpHeaderExtension>& extensions) { | 1868 const std::vector<RtpHeaderExtension>& extensions) { |
1903 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1869 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
1904 if (send_extensions_ == extensions) { | 1870 if (send_extensions_ == extensions) { |
1905 return true; | 1871 return true; |
1906 } | 1872 } |
1907 | 1873 |
1908 // The default channel may or may not be in |send_channels_|. Set the rtp | |
1909 // header extensions for default channel regardless. | |
1910 | |
1911 if (!SetChannelSendRtpHeaderExtensions(default_send_channel_id(), | |
1912 extensions)) { | |
1913 return false; | |
1914 } | |
1915 | |
1916 // Loop through all send channels and enable/disable the extensions. | |
1917 for (const auto& ch : send_channels_) { | 1874 for (const auto& ch : send_channels_) { |
1918 if (!SetChannelSendRtpHeaderExtensions(ch.second->channel(), extensions)) { | 1875 if (!SetChannelSendRtpHeaderExtensions(ch.second->channel(), extensions)) { |
1919 return false; | 1876 return false; |
1920 } | 1877 } |
1921 } | 1878 } |
1922 | 1879 |
1923 send_extensions_ = extensions; | 1880 send_extensions_ = extensions; |
1924 return true; | 1881 return true; |
1925 } | 1882 } |
1926 | 1883 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2048 } | 2005 } |
2049 if (!MuteStream(ssrc, !enable)) { | 2006 if (!MuteStream(ssrc, !enable)) { |
2050 return false; | 2007 return false; |
2051 } | 2008 } |
2052 if (enable && options) { | 2009 if (enable && options) { |
2053 return SetOptions(*options); | 2010 return SetOptions(*options); |
2054 } | 2011 } |
2055 return true; | 2012 return true; |
2056 } | 2013 } |
2057 | 2014 |
2058 // TODO(ronghuawu): Change this method to return bool. | 2015 int WebRtcVoiceMediaChannel::CreateVoEChannel() { |
2059 void WebRtcVoiceMediaChannel::ConfigureSendChannel(int channel) { | 2016 int id = engine()->CreateVoEChannel(); |
2060 if (engine()->voe()->network()->RegisterExternalTransport( | 2017 if (id == -1) { |
2061 channel, *this) == -1) { | 2018 LOG_RTCERR0(CreateVoEChannel); |
2062 LOG_RTCERR2(RegisterExternalTransport, channel, this); | 2019 return -1; |
2063 } | 2020 } |
2064 | 2021 if (engine()->voe()->network()->RegisterExternalTransport(id, *this) == -1) { |
2065 // Enable RTCP (for quality stats and feedback messages) | 2022 LOG_RTCERR2(RegisterExternalTransport, id, this); |
2066 EnableRtcp(channel); | 2023 engine()->voe()->base()->DeleteChannel(id); |
2067 | 2024 return -1; |
2068 // Set RTP header extension for the new channel. | 2025 } |
2069 SetChannelSendRtpHeaderExtensions(channel, send_extensions_); | 2026 return id; |
2070 } | 2027 } |
2071 | 2028 |
2072 bool WebRtcVoiceMediaChannel::DeleteChannel(int channel) { | 2029 bool WebRtcVoiceMediaChannel::DeleteChannel(int channel) { |
2073 if (engine()->voe()->network()->DeRegisterExternalTransport(channel) == -1) { | 2030 if (engine()->voe()->network()->DeRegisterExternalTransport(channel) == -1) { |
2074 LOG_RTCERR1(DeRegisterExternalTransport, channel); | 2031 LOG_RTCERR1(DeRegisterExternalTransport, channel); |
2075 } | 2032 } |
2076 | |
2077 if (engine()->voe()->base()->DeleteChannel(channel) == -1) { | 2033 if (engine()->voe()->base()->DeleteChannel(channel) == -1) { |
2078 LOG_RTCERR1(DeleteChannel, channel); | 2034 LOG_RTCERR1(DeleteChannel, channel); |
2079 return false; | 2035 return false; |
2080 } | 2036 } |
2081 | |
2082 return true; | 2037 return true; |
2083 } | 2038 } |
2084 | 2039 |
2085 bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) { | 2040 bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) { |
2086 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2041 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2087 // If the default channel is already used for sending create a new channel | 2042 LOG(LS_INFO) << "AddSendStream: " << sp.ToString(); |
2088 // otherwise use the default channel for sending. | 2043 |
2089 int channel = GetSendChannelId(sp.first_ssrc()); | 2044 uint32_t ssrc = sp.first_ssrc(); |
2090 if (channel != -1) { | 2045 RTC_DCHECK(0 != ssrc); |
2091 LOG(LS_ERROR) << "Stream already exists with ssrc " << sp.first_ssrc(); | 2046 |
| 2047 if (GetSendChannelId(ssrc) != -1) { |
| 2048 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc; |
2092 return false; | 2049 return false; |
2093 } | 2050 } |
2094 | 2051 |
2095 bool default_channel_is_available = true; | 2052 // Create a new channel for sending audio data. |
2096 for (const auto& ch : send_channels_) { | 2053 int channel = CreateVoEChannel(); |
2097 if (IsDefaultChannel(ch.second->channel())) { | 2054 if (channel == -1) { |
2098 default_channel_is_available = false; | 2055 return false; |
2099 break; | |
2100 } | |
2101 } | 2056 } |
2102 if (default_channel_is_available) { | |
2103 channel = default_send_channel_id(); | |
2104 } else { | |
2105 // Create a new channel for sending audio data. | |
2106 channel = engine()->CreateMediaVoiceChannel(); | |
2107 if (channel == -1) { | |
2108 LOG_RTCERR0(CreateChannel); | |
2109 return false; | |
2110 } | |
2111 | 2057 |
2112 ConfigureSendChannel(channel); | 2058 // Enable RTCP (for quality stats and feedback messages). |
| 2059 if (engine()->voe()->rtp()->SetRTCPStatus(channel, true) == -1) { |
| 2060 LOG_RTCERR2(SetRTCPStatus, channel, 1); |
| 2061 } |
| 2062 |
| 2063 SetChannelSendRtpHeaderExtensions(channel, send_extensions_); |
| 2064 |
| 2065 // Set the local (send) SSRC. |
| 2066 if (engine()->voe()->rtp()->SetLocalSSRC(channel, ssrc) == -1) { |
| 2067 LOG_RTCERR2(SetLocalSSRC, channel, ssrc); |
| 2068 DeleteChannel(channel); |
| 2069 return false; |
| 2070 } |
| 2071 |
| 2072 if (engine()->voe()->rtp()->SetRTCP_CNAME(channel, sp.cname.c_str()) == -1) { |
| 2073 LOG_RTCERR2(SetRTCP_CNAME, channel, sp.cname); |
| 2074 DeleteChannel(channel); |
| 2075 return false; |
2113 } | 2076 } |
2114 | 2077 |
2115 // Save the channel to send_channels_, so that RemoveSendStream() can still | 2078 // Save the channel to send_channels_, so that RemoveSendStream() can still |
2116 // delete the channel in case failure happens below. | 2079 // delete the channel in case failure happens below. |
2117 webrtc::AudioTransport* audio_transport = | 2080 webrtc::AudioTransport* audio_transport = |
2118 engine()->voe()->base()->audio_transport(); | 2081 engine()->voe()->base()->audio_transport(); |
2119 send_channels_.insert( | 2082 send_channels_.insert( |
2120 std::make_pair(sp.first_ssrc(), | 2083 std::make_pair(ssrc, |
2121 new WebRtcVoiceChannelRenderer(channel, audio_transport))); | 2084 new WebRtcVoiceChannelRenderer(channel, audio_transport))); |
2122 | 2085 |
2123 // Set the send (local) SSRC. | 2086 // Set the current codecs to be used for the new channel. We need to do this |
2124 // If there are multiple send SSRCs, we can only set the first one here, and | 2087 // after adding the channel to send_channels_, because of how max bitrate is |
2125 // the rest of the SSRC(s) need to be set after SetSendCodec has been called | 2088 // currently being configured by SetSendCodec(). |
2126 // (with a codec requires multiple SSRC(s)). | 2089 if (!send_codecs_.empty() && !SetSendCodecs(channel, send_codecs_)) { |
2127 if (engine()->voe()->rtp()->SetLocalSSRC(channel, sp.first_ssrc()) == -1) { | 2090 RemoveSendStream(ssrc); |
2128 LOG_RTCERR2(SetSendSSRC, channel, sp.first_ssrc()); | |
2129 return false; | 2091 return false; |
2130 } | 2092 } |
2131 | 2093 |
2132 // At this point the channel's local SSRC has been updated. If the channel is | 2094 // At this point the channel's local SSRC has been updated. If the channel is |
2133 // the default channel make sure that all the receive channels are updated as | 2095 // the first send channel make sure that all the receive channels are updated |
2134 // well. Receive channels have to have the same SSRC as the default channel in | 2096 // with the same SSRC in order to send receiver reports. |
2135 // order to send receiver reports with this SSRC. | 2097 if (send_channels_.size() == 1) { |
2136 if (IsDefaultChannel(channel)) { | 2098 receiver_reports_ssrc_ = ssrc; |
2137 for (const auto& ch : receive_channels_) { | 2099 for (const auto& ch : receive_channels_) { |
2138 if (engine()->voe()->rtp()->SetLocalSSRC(ch.second->channel(), | 2100 int recv_channel = ch.second->channel(); |
2139 sp.first_ssrc()) != 0) { | 2101 if (engine()->voe()->rtp()->SetLocalSSRC(recv_channel, ssrc) != 0) { |
2140 LOG_RTCERR2(SetLocalSSRC, ch.second->channel(), sp.first_ssrc()); | 2102 LOG_RTCERR2(SetLocalSSRC, ch.second->channel(), ssrc); |
2141 return false; | 2103 return false; |
2142 } | 2104 } |
| 2105 engine()->voe()->base()->AssociateSendChannel(recv_channel, channel); |
| 2106 LOG(LS_INFO) << "VoiceEngine channel #" << recv_channel |
| 2107 << " is associated with channel #" << channel << "."; |
2143 } | 2108 } |
2144 } | 2109 } |
2145 | 2110 |
2146 if (engine()->voe()->rtp()->SetRTCP_CNAME(channel, sp.cname.c_str()) == -1) { | |
2147 LOG_RTCERR2(SetRTCP_CNAME, channel, sp.cname); | |
2148 return false; | |
2149 } | |
2150 | |
2151 // Set the current codecs to be used for the new channel. | |
2152 if (!send_codecs_.empty() && !SetSendCodecs(channel, send_codecs_)) | |
2153 return false; | |
2154 | |
2155 return ChangeSend(channel, desired_send_); | 2111 return ChangeSend(channel, desired_send_); |
2156 } | 2112 } |
2157 | 2113 |
2158 bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) { | 2114 bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) { |
| 2115 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2159 ChannelMap::iterator it = send_channels_.find(ssrc); | 2116 ChannelMap::iterator it = send_channels_.find(ssrc); |
2160 if (it == send_channels_.end()) { | 2117 if (it == send_channels_.end()) { |
2161 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc | 2118 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc |
2162 << " which doesn't exist."; | 2119 << " which doesn't exist."; |
2163 return false; | 2120 return false; |
2164 } | 2121 } |
2165 | 2122 |
2166 int channel = it->second->channel(); | 2123 int channel = it->second->channel(); |
2167 ChangeSend(channel, SEND_NOTHING); | 2124 ChangeSend(channel, SEND_NOTHING); |
2168 | 2125 |
2169 // Delete the WebRtcVoiceChannelRenderer object connected to the channel, | 2126 // Delete the WebRtcVoiceChannelRenderer object connected to the channel, |
2170 // this will disconnect the audio renderer with the send channel. | 2127 // this will disconnect the audio renderer with the send channel. |
2171 delete it->second; | 2128 delete it->second; |
2172 send_channels_.erase(it); | 2129 send_channels_.erase(it); |
2173 | 2130 |
2174 if (IsDefaultChannel(channel)) { | 2131 // Clean up and delete the send channel. |
2175 // Do not delete the default channel since the receive channels depend on | 2132 LOG(LS_INFO) << "Removing audio send stream " << ssrc |
2176 // the default channel, recycle it instead. | 2133 << " with VoiceEngine channel #" << channel << "."; |
2177 ChangeSend(channel, SEND_NOTHING); | 2134 if (!DeleteChannel(channel)) { |
2178 } else { | 2135 return false; |
2179 // Clean up and delete the send channel. | |
2180 LOG(LS_INFO) << "Removing audio send stream " << ssrc | |
2181 << " with VoiceEngine channel #" << channel << "."; | |
2182 if (!DeleteChannel(channel)) | |
2183 return false; | |
2184 } | 2136 } |
2185 | 2137 if (send_channels_.empty()) { |
2186 if (send_channels_.empty()) | |
2187 ChangeSend(SEND_NOTHING); | 2138 ChangeSend(SEND_NOTHING); |
2188 | 2139 } |
2189 return true; | 2140 return true; |
2190 } | 2141 } |
2191 | 2142 |
2192 bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { | 2143 bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { |
2193 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2144 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2194 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString(); | 2145 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString(); |
2195 | 2146 |
2196 if (!ValidateStreamParams(sp)) { | 2147 if (!ValidateStreamParams(sp)) { |
2197 return false; | 2148 return false; |
2198 } | 2149 } |
(...skipping 10 matching lines...) Expand all Loading... |
2209 RemoveRecvStream(ssrc); | 2160 RemoveRecvStream(ssrc); |
2210 } | 2161 } |
2211 | 2162 |
2212 if (receive_channels_.find(ssrc) != receive_channels_.end()) { | 2163 if (receive_channels_.find(ssrc) != receive_channels_.end()) { |
2213 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc; | 2164 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc; |
2214 return false; | 2165 return false; |
2215 } | 2166 } |
2216 RTC_DCHECK(receive_stream_params_.find(ssrc) == receive_stream_params_.end()); | 2167 RTC_DCHECK(receive_stream_params_.find(ssrc) == receive_stream_params_.end()); |
2217 | 2168 |
2218 // Create a new channel for receiving audio data. | 2169 // Create a new channel for receiving audio data. |
2219 int channel = engine()->CreateMediaVoiceChannel(); | 2170 int channel = CreateVoEChannel(); |
2220 if (channel == -1) { | 2171 if (channel == -1) { |
2221 LOG_RTCERR0(CreateChannel); | |
2222 return false; | 2172 return false; |
2223 } | 2173 } |
2224 if (!ConfigureRecvChannel(channel)) { | 2174 if (!ConfigureRecvChannel(channel)) { |
2225 DeleteChannel(channel); | 2175 DeleteChannel(channel); |
2226 return false; | 2176 return false; |
2227 } | 2177 } |
2228 | 2178 |
2229 webrtc::AudioTransport* audio_transport = | 2179 webrtc::AudioTransport* audio_transport = |
2230 engine()->voe()->base()->audio_transport(); | 2180 engine()->voe()->base()->audio_transport(); |
2231 WebRtcVoiceChannelRenderer* channel_renderer = | 2181 WebRtcVoiceChannelRenderer* channel_renderer = |
2232 new WebRtcVoiceChannelRenderer(channel, audio_transport); | 2182 new WebRtcVoiceChannelRenderer(channel, audio_transport); |
2233 receive_channels_.insert(std::make_pair(ssrc, channel_renderer)); | 2183 receive_channels_.insert(std::make_pair(ssrc, channel_renderer)); |
2234 receive_stream_params_[ssrc] = sp; | 2184 receive_stream_params_[ssrc] = sp; |
2235 AddAudioReceiveStream(ssrc); | 2185 AddAudioReceiveStream(ssrc); |
2236 | 2186 |
2237 LOG(LS_INFO) << "New audio stream " << ssrc | 2187 LOG(LS_INFO) << "New audio stream " << ssrc |
2238 << " registered to VoiceEngine channel #" | 2188 << " registered to VoiceEngine channel #" |
2239 << channel << "."; | 2189 << channel << "."; |
2240 return true; | 2190 return true; |
2241 } | 2191 } |
2242 | 2192 |
2243 bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) { | 2193 bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) { |
2244 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2194 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2245 // Configure to use external transport. | 2195 |
2246 if (engine()->voe()->network()->RegisterExternalTransport( | 2196 int send_channel = GetSendChannelId(receiver_reports_ssrc_); |
2247 channel, *this) == -1) { | 2197 if (send_channel != -1) { |
2248 LOG_RTCERR2(SetExternalTransport, channel, this); | 2198 // Associate receive channel with first send channel (so the receive channel |
| 2199 // can obtain RTT from the send channel) |
| 2200 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); |
| 2201 LOG(LS_INFO) << "VoiceEngine channel #" << channel |
| 2202 << " is associated with channel #" << send_channel << "."; |
| 2203 } |
| 2204 if (engine()->voe()->rtp()->SetLocalSSRC(channel, |
| 2205 receiver_reports_ssrc_) == -1) { |
| 2206 LOG_RTCERR1(SetLocalSSRC, channel); |
2249 return false; | 2207 return false; |
2250 } | 2208 } |
2251 | 2209 |
2252 // Use the same SSRC as our default send channel, so the RTCP reports are | |
2253 // correct. | |
2254 unsigned int send_ssrc = 0; | |
2255 webrtc::VoERTP_RTCP* rtp = engine()->voe()->rtp(); | |
2256 if (rtp->GetLocalSSRC(default_send_channel_id(), send_ssrc) == -1) { | |
2257 LOG_RTCERR1(GetSendSSRC, channel); | |
2258 return false; | |
2259 } | |
2260 if (rtp->SetLocalSSRC(channel, send_ssrc) == -1) { | |
2261 LOG_RTCERR1(SetSendSSRC, channel); | |
2262 return false; | |
2263 } | |
2264 | |
2265 // Associate receive channel to default send channel (so the receive channel | |
2266 // can obtain RTT from the send channel). | |
2267 engine()->voe()->base()->AssociateSendChannel(channel, | |
2268 default_send_channel_id()); | |
2269 LOG(LS_INFO) << "VoiceEngine channel #" | |
2270 << channel << " is associated with channel #" | |
2271 << default_send_channel_id() << "."; | |
2272 | |
2273 // Turn off all supported codecs. | 2210 // Turn off all supported codecs. |
2274 int ncodecs = engine()->voe()->codec()->NumOfCodecs(); | 2211 int ncodecs = engine()->voe()->codec()->NumOfCodecs(); |
2275 for (int i = 0; i < ncodecs; ++i) { | 2212 for (int i = 0; i < ncodecs; ++i) { |
2276 webrtc::CodecInst voe_codec; | 2213 webrtc::CodecInst voe_codec; |
2277 if (engine()->voe()->codec()->GetCodec(i, voe_codec) != -1) { | 2214 if (engine()->voe()->codec()->GetCodec(i, voe_codec) != -1) { |
2278 voe_codec.pltype = -1; | 2215 voe_codec.pltype = -1; |
2279 if (engine()->voe()->codec()->SetRecPayloadType( | 2216 if (engine()->voe()->codec()->SetRecPayloadType( |
2280 channel, voe_codec) == -1) { | 2217 channel, voe_codec) == -1) { |
2281 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); | 2218 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); |
2282 return false; | 2219 return false; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2435 } | 2372 } |
2436 | 2373 |
2437 bool WebRtcVoiceMediaChannel::CanInsertDtmf() { | 2374 bool WebRtcVoiceMediaChannel::CanInsertDtmf() { |
2438 return dtmf_allowed_; | 2375 return dtmf_allowed_; |
2439 } | 2376 } |
2440 | 2377 |
2441 bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, | 2378 bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, |
2442 int event, | 2379 int event, |
2443 int duration, | 2380 int duration, |
2444 int flags) { | 2381 int flags) { |
| 2382 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2445 if (!dtmf_allowed_) { | 2383 if (!dtmf_allowed_) { |
2446 return false; | 2384 return false; |
2447 } | 2385 } |
2448 | 2386 |
2449 // Send the event. | 2387 // Send the event. |
2450 if (flags & cricket::DF_SEND) { | 2388 if (flags & cricket::DF_SEND) { |
2451 int channel = -1; | 2389 int channel = -1; |
2452 if (ssrc == 0) { | 2390 if (ssrc == 0) { |
2453 bool default_channel_is_inuse = false; | 2391 if (send_channels_.size() > 0) { |
2454 for (const auto& ch : send_channels_) { | |
2455 if (IsDefaultChannel(ch.second->channel())) { | |
2456 default_channel_is_inuse = true; | |
2457 break; | |
2458 } | |
2459 } | |
2460 if (default_channel_is_inuse) { | |
2461 channel = default_send_channel_id(); | |
2462 } else if (!send_channels_.empty()) { | |
2463 channel = send_channels_.begin()->second->channel(); | 2392 channel = send_channels_.begin()->second->channel(); |
2464 } | 2393 } |
2465 } else { | 2394 } else { |
2466 channel = GetSendChannelId(ssrc); | 2395 channel = GetSendChannelId(ssrc); |
2467 } | 2396 } |
2468 if (channel == -1) { | 2397 if (channel == -1) { |
2469 LOG(LS_WARNING) << "InsertDtmf - The specified ssrc " | 2398 LOG(LS_WARNING) << "InsertDtmf - The specified ssrc " |
2470 << ssrc << " is not in use."; | 2399 << ssrc << " is not in use."; |
2471 return false; | 2400 return false; |
2472 } | 2401 } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2570 // SR may continue RR and any RR entry may correspond to any one of the send | 2499 // SR may continue RR and any RR entry may correspond to any one of the send |
2571 // channels. So all RTCP packets must be forwarded all send channels. VoE | 2500 // channels. So all RTCP packets must be forwarded all send channels. VoE |
2572 // will filter out RR internally. | 2501 // will filter out RR internally. |
2573 for (const auto& ch : send_channels_) { | 2502 for (const auto& ch : send_channels_) { |
2574 engine()->voe()->network()->ReceivedRTCPPacket( | 2503 engine()->voe()->network()->ReceivedRTCPPacket( |
2575 ch.second->channel(), packet->data(), packet->size()); | 2504 ch.second->channel(), packet->data(), packet->size()); |
2576 } | 2505 } |
2577 } | 2506 } |
2578 | 2507 |
2579 bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) { | 2508 bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) { |
2580 int channel = | 2509 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2581 (ssrc == 0) ? default_send_channel_id() : GetSendChannelId(ssrc); | 2510 int channel = GetSendChannelId(ssrc); |
2582 if (channel == -1) { | 2511 if (channel == -1) { |
2583 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use."; | 2512 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use."; |
2584 return false; | 2513 return false; |
2585 } | 2514 } |
2586 if (engine()->voe()->volume()->SetInputMute(channel, muted) == -1) { | 2515 if (engine()->voe()->volume()->SetInputMute(channel, muted) == -1) { |
2587 LOG_RTCERR2(SetInputMute, channel, muted); | 2516 LOG_RTCERR2(SetInputMute, channel, muted); |
2588 return false; | 2517 return false; |
2589 } | 2518 } |
2590 // We set the AGC to mute state only when all the channels are muted. | 2519 // We set the AGC to mute state only when all the channels are muted. |
2591 // This implementation is not ideal, instead we should signal the AGC when | 2520 // This implementation is not ideal, instead we should signal the AGC when |
2592 // the mic channel is muted/unmuted. We can't do it today because there | 2521 // the mic channel is muted/unmuted. We can't do it today because there |
2593 // is no good way to know which stream is mapping to the mic channel. | 2522 // is no good way to know which stream is mapping to the mic channel. |
2594 bool all_muted = muted; | 2523 bool all_muted = muted; |
2595 for (const auto& ch : send_channels_) { | 2524 for (const auto& ch : send_channels_) { |
2596 if (!all_muted) { | 2525 if (!all_muted) { |
2597 break; | 2526 break; |
2598 } | 2527 } |
2599 if (engine()->voe()->volume()->GetInputMute(ch.second->channel(), | 2528 if (engine()->voe()->volume()->GetInputMute(ch.second->channel(), |
2600 all_muted)) { | 2529 all_muted)) { |
2601 LOG_RTCERR1(GetInputMute, ch.second->channel()); | 2530 LOG_RTCERR1(GetInputMute, ch.second->channel()); |
2602 return false; | 2531 return false; |
2603 } | 2532 } |
2604 } | 2533 } |
2605 | 2534 |
2606 webrtc::AudioProcessing* ap = engine()->voe()->base()->audio_processing(); | 2535 webrtc::AudioProcessing* ap = engine()->voe()->base()->audio_processing(); |
2607 if (ap) | 2536 if (ap) { |
2608 ap->set_output_will_be_muted(all_muted); | 2537 ap->set_output_will_be_muted(all_muted); |
| 2538 } |
2609 return true; | 2539 return true; |
2610 } | 2540 } |
2611 | 2541 |
2612 // TODO(minyue): SetMaxSendBandwidth() is subject to be renamed to | 2542 // TODO(minyue): SetMaxSendBandwidth() is subject to be renamed to |
2613 // SetMaxSendBitrate() in future. | 2543 // SetMaxSendBitrate() in future. |
2614 bool WebRtcVoiceMediaChannel::SetMaxSendBandwidth(int bps) { | 2544 bool WebRtcVoiceMediaChannel::SetMaxSendBandwidth(int bps) { |
2615 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBandwidth."; | 2545 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBandwidth."; |
2616 | |
2617 return SetSendBitrateInternal(bps); | 2546 return SetSendBitrateInternal(bps); |
2618 } | 2547 } |
2619 | 2548 |
2620 bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) { | 2549 bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) { |
2621 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBitrateInternal."; | 2550 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBitrateInternal."; |
2622 | 2551 |
2623 send_bitrate_setting_ = true; | 2552 send_bitrate_setting_ = true; |
2624 send_bitrate_bps_ = bps; | 2553 send_bitrate_bps_ = bps; |
2625 | 2554 |
2626 if (!send_codec_) { | 2555 if (!send_codec_) { |
2627 LOG(LS_INFO) << "The send codec has not been set up yet. " | 2556 LOG(LS_INFO) << "The send codec has not been set up yet. " |
2628 << "The send bitrate setting will be applied later."; | 2557 << "The send bitrate setting will be applied later."; |
2629 return true; | 2558 return true; |
2630 } | 2559 } |
2631 | 2560 |
2632 // Bitrate is auto by default. | 2561 // Bitrate is auto by default. |
2633 // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by | 2562 // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by |
2634 // SetMaxSendBandwith(0), the second call removes the previous limit. | 2563 // SetMaxSendBandwith(0), the second call removes the previous limit. |
2635 if (bps <= 0) | 2564 if (bps <= 0) |
2636 return true; | 2565 return true; |
2637 | 2566 |
2638 webrtc::CodecInst codec = *send_codec_; | 2567 webrtc::CodecInst codec = *send_codec_; |
2639 bool is_multi_rate = IsCodecMultiRate(codec); | 2568 bool is_multi_rate = IsCodecMultiRate(codec); |
2640 | 2569 |
2641 if (is_multi_rate) { | 2570 if (is_multi_rate) { |
2642 // If codec is multi-rate then just set the bitrate. | 2571 // If codec is multi-rate then just set the bitrate. |
2643 codec.rate = bps; | 2572 codec.rate = bps; |
2644 if (!SetSendCodec(codec)) { | 2573 for (const auto& ch : send_channels_) { |
2645 LOG(LS_INFO) << "Failed to set codec " << codec.plname | 2574 if (!SetSendCodec(ch.second->channel(), codec)) { |
2646 << " to bitrate " << bps << " bps."; | 2575 LOG(LS_INFO) << "Failed to set codec " << codec.plname |
2647 return false; | 2576 << " to bitrate " << bps << " bps."; |
| 2577 return false; |
| 2578 } |
2648 } | 2579 } |
2649 return true; | 2580 return true; |
2650 } else { | 2581 } else { |
2651 // If codec is not multi-rate and |bps| is less than the fixed bitrate | 2582 // If codec is not multi-rate and |bps| is less than the fixed bitrate |
2652 // then fail. If codec is not multi-rate and |bps| exceeds or equal the | 2583 // then fail. If codec is not multi-rate and |bps| exceeds or equal the |
2653 // fixed bitrate then ignore. | 2584 // fixed bitrate then ignore. |
2654 if (bps < codec.rate) { | 2585 if (bps < codec.rate) { |
2655 LOG(LS_INFO) << "Failed to set codec " << codec.plname | 2586 LOG(LS_INFO) << "Failed to set codec " << codec.plname |
2656 << " to bitrate " << bps << " bps" | 2587 << " to bitrate " << bps << " bps" |
2657 << ", requires at least " << codec.rate << " bps."; | 2588 << ", requires at least " << codec.rate << " bps."; |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2913 return true; | 2844 return true; |
2914 } else { | 2845 } else { |
2915 break; | 2846 break; |
2916 } | 2847 } |
2917 } | 2848 } |
2918 } | 2849 } |
2919 LOG(LS_WARNING) << "RED params " << red_params << " are invalid."; | 2850 LOG(LS_WARNING) << "RED params " << red_params << " are invalid."; |
2920 return false; | 2851 return false; |
2921 } | 2852 } |
2922 | 2853 |
2923 bool WebRtcVoiceMediaChannel::EnableRtcp(int channel) { | |
2924 if (engine()->voe()->rtp()->SetRTCPStatus(channel, true) == -1) { | |
2925 LOG_RTCERR2(SetRTCPStatus, channel, 1); | |
2926 return false; | |
2927 } | |
2928 // TODO(juberti): Enable VQMon and RTCP XR reports, once we know what | |
2929 // what we want to do with them. | |
2930 // engine()->voe().EnableVQMon(default_send_channel_id(), true); | |
2931 // engine()->voe().EnableRTCP_XR(default_send_channel_id(), true); | |
2932 return true; | |
2933 } | |
2934 | |
2935 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { | 2854 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { |
2936 if (playout) { | 2855 if (playout) { |
2937 LOG(LS_INFO) << "Starting playout for channel #" << channel; | 2856 LOG(LS_INFO) << "Starting playout for channel #" << channel; |
2938 if (engine()->voe()->base()->StartPlayout(channel) == -1) { | 2857 if (engine()->voe()->base()->StartPlayout(channel) == -1) { |
2939 LOG_RTCERR1(StartPlayout, channel); | 2858 LOG_RTCERR1(StartPlayout, channel); |
2940 return false; | 2859 return false; |
2941 } | 2860 } |
2942 } else { | 2861 } else { |
2943 LOG(LS_INFO) << "Stopping playout for channel #" << channel; | 2862 LOG(LS_INFO) << "Stopping playout for channel #" << channel; |
2944 engine()->voe()->base()->StopPlayout(channel); | 2863 engine()->voe()->base()->StopPlayout(channel); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3052 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | 2971 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
3053 return false; | 2972 return false; |
3054 } | 2973 } |
3055 } | 2974 } |
3056 return true; | 2975 return true; |
3057 } | 2976 } |
3058 | 2977 |
3059 } // namespace cricket | 2978 } // namespace cricket |
3060 | 2979 |
3061 #endif // HAVE_WEBRTC_VOICE | 2980 #endif // HAVE_WEBRTC_VOICE |
OLD | NEW |