Make the audio channel communicate network state changes to the call.
This change enables voice-only calls to keep track of the network state. This is only a partial fix - the last modality to change state controls the state for the entire call, so a call with a failed video transport will also stop sending audio packets. Handling this condition correctly would require the call to keep track of network state for each media type separately, and take care of conditions such as a failed video channel getting removed, while a functioning audio channel remains. BUG=webrtc:5307 Review URL: https://codereview.webrtc.org/1757683002 Cr-Commit-Position: refs/heads/master@{#12093}
This commit is contained in:
parent
01bcbd0df6
commit
7a43d253f9
@ -133,7 +133,12 @@ class Call {
|
|||||||
// implemented.
|
// implemented.
|
||||||
virtual void SetBitrateConfig(
|
virtual void SetBitrateConfig(
|
||||||
const Config::BitrateConfig& bitrate_config) = 0;
|
const Config::BitrateConfig& bitrate_config) = 0;
|
||||||
virtual void SignalNetworkState(NetworkState state) = 0;
|
|
||||||
|
// TODO(skvlad): When the unbundled case with multiple streams for the same
|
||||||
|
// media type going over different networks is supported, track the state
|
||||||
|
// for each stream separately. Right now it's global per media type.
|
||||||
|
virtual void SignalChannelNetworkState(MediaType media,
|
||||||
|
NetworkState state) = 0;
|
||||||
|
|
||||||
virtual void OnSentPacket(const rtc::SentPacket& sent_packet) = 0;
|
virtual void OnSentPacket(const rtc::SentPacket& sent_packet) = 0;
|
||||||
|
|
||||||
|
|||||||
@ -86,7 +86,8 @@ class Call : public webrtc::Call, public PacketReceiver,
|
|||||||
|
|
||||||
void SetBitrateConfig(
|
void SetBitrateConfig(
|
||||||
const webrtc::Call::Config::BitrateConfig& bitrate_config) override;
|
const webrtc::Call::Config::BitrateConfig& bitrate_config) override;
|
||||||
void SignalNetworkState(NetworkState state) override;
|
|
||||||
|
void SignalChannelNetworkState(MediaType media, NetworkState state) override;
|
||||||
|
|
||||||
void OnSentPacket(const rtc::SentPacket& sent_packet) override;
|
void OnSentPacket(const rtc::SentPacket& sent_packet) override;
|
||||||
|
|
||||||
@ -116,6 +117,7 @@ class Call : public webrtc::Call, public PacketReceiver,
|
|||||||
|
|
||||||
void UpdateSendHistograms() EXCLUSIVE_LOCKS_REQUIRED(&bitrate_crit_);
|
void UpdateSendHistograms() EXCLUSIVE_LOCKS_REQUIRED(&bitrate_crit_);
|
||||||
void UpdateReceiveHistograms();
|
void UpdateReceiveHistograms();
|
||||||
|
void UpdateAggregateNetworkState();
|
||||||
|
|
||||||
Clock* const clock_;
|
Clock* const clock_;
|
||||||
|
|
||||||
@ -127,7 +129,8 @@ class Call : public webrtc::Call, public PacketReceiver,
|
|||||||
Call::Config config_;
|
Call::Config config_;
|
||||||
rtc::ThreadChecker configuration_thread_checker_;
|
rtc::ThreadChecker configuration_thread_checker_;
|
||||||
|
|
||||||
bool network_enabled_;
|
NetworkState audio_network_state_;
|
||||||
|
NetworkState video_network_state_;
|
||||||
|
|
||||||
std::unique_ptr<RWLockWrapper> receive_crit_;
|
std::unique_ptr<RWLockWrapper> receive_crit_;
|
||||||
// Audio and Video receive streams are owned by the client that creates them.
|
// Audio and Video receive streams are owned by the client that creates them.
|
||||||
@ -189,7 +192,8 @@ Call::Call(const Call::Config& config)
|
|||||||
call_stats_(new CallStats(clock_)),
|
call_stats_(new CallStats(clock_)),
|
||||||
bitrate_allocator_(new BitrateAllocator()),
|
bitrate_allocator_(new BitrateAllocator()),
|
||||||
config_(config),
|
config_(config),
|
||||||
network_enabled_(true),
|
audio_network_state_(kNetworkUp),
|
||||||
|
video_network_state_(kNetworkUp),
|
||||||
receive_crit_(RWLockWrapper::CreateRWLock()),
|
receive_crit_(RWLockWrapper::CreateRWLock()),
|
||||||
send_crit_(RWLockWrapper::CreateRWLock()),
|
send_crit_(RWLockWrapper::CreateRWLock()),
|
||||||
received_video_bytes_(0),
|
received_video_bytes_(0),
|
||||||
@ -317,14 +321,14 @@ webrtc::AudioSendStream* Call::CreateAudioSendStream(
|
|||||||
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
|
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
|
||||||
AudioSendStream* send_stream = new AudioSendStream(
|
AudioSendStream* send_stream = new AudioSendStream(
|
||||||
config, config_.audio_state, congestion_controller_.get());
|
config, config_.audio_state, congestion_controller_.get());
|
||||||
if (!network_enabled_)
|
|
||||||
send_stream->SignalNetworkState(kNetworkDown);
|
|
||||||
{
|
{
|
||||||
WriteLockScoped write_lock(*send_crit_);
|
WriteLockScoped write_lock(*send_crit_);
|
||||||
RTC_DCHECK(audio_send_ssrcs_.find(config.rtp.ssrc) ==
|
RTC_DCHECK(audio_send_ssrcs_.find(config.rtp.ssrc) ==
|
||||||
audio_send_ssrcs_.end());
|
audio_send_ssrcs_.end());
|
||||||
audio_send_ssrcs_[config.rtp.ssrc] = send_stream;
|
audio_send_ssrcs_[config.rtp.ssrc] = send_stream;
|
||||||
}
|
}
|
||||||
|
send_stream->SignalNetworkState(audio_network_state_);
|
||||||
|
UpdateAggregateNetworkState();
|
||||||
return send_stream;
|
return send_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,6 +347,7 @@ void Call::DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) {
|
|||||||
audio_send_stream->config().rtp.ssrc);
|
audio_send_stream->config().rtp.ssrc);
|
||||||
RTC_DCHECK(num_deleted == 1);
|
RTC_DCHECK(num_deleted == 1);
|
||||||
}
|
}
|
||||||
|
UpdateAggregateNetworkState();
|
||||||
delete audio_send_stream;
|
delete audio_send_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,6 +364,8 @@ webrtc::AudioReceiveStream* Call::CreateAudioReceiveStream(
|
|||||||
audio_receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream;
|
audio_receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream;
|
||||||
ConfigureSync(config.sync_group);
|
ConfigureSync(config.sync_group);
|
||||||
}
|
}
|
||||||
|
receive_stream->SignalNetworkState(audio_network_state_);
|
||||||
|
UpdateAggregateNetworkState();
|
||||||
return receive_stream;
|
return receive_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,6 +389,7 @@ void Call::DestroyAudioReceiveStream(
|
|||||||
ConfigureSync(sync_group);
|
ConfigureSync(sync_group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UpdateAggregateNetworkState();
|
||||||
delete audio_receive_stream;
|
delete audio_receive_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,20 +405,18 @@ webrtc::VideoSendStream* Call::CreateVideoSendStream(
|
|||||||
num_cpu_cores_, module_process_thread_.get(), call_stats_.get(),
|
num_cpu_cores_, module_process_thread_.get(), call_stats_.get(),
|
||||||
congestion_controller_.get(), bitrate_allocator_.get(), &remb_, config,
|
congestion_controller_.get(), bitrate_allocator_.get(), &remb_, config,
|
||||||
encoder_config, suspended_video_send_ssrcs_);
|
encoder_config, suspended_video_send_ssrcs_);
|
||||||
|
{
|
||||||
if (!network_enabled_)
|
|
||||||
send_stream->SignalNetworkState(kNetworkDown);
|
|
||||||
|
|
||||||
WriteLockScoped write_lock(*send_crit_);
|
WriteLockScoped write_lock(*send_crit_);
|
||||||
for (uint32_t ssrc : config.rtp.ssrcs) {
|
for (uint32_t ssrc : config.rtp.ssrcs) {
|
||||||
RTC_DCHECK(video_send_ssrcs_.find(ssrc) == video_send_ssrcs_.end());
|
RTC_DCHECK(video_send_ssrcs_.find(ssrc) == video_send_ssrcs_.end());
|
||||||
video_send_ssrcs_[ssrc] = send_stream;
|
video_send_ssrcs_[ssrc] = send_stream;
|
||||||
}
|
}
|
||||||
video_send_streams_.insert(send_stream);
|
video_send_streams_.insert(send_stream);
|
||||||
|
}
|
||||||
|
send_stream->SignalNetworkState(video_network_state_);
|
||||||
|
UpdateAggregateNetworkState();
|
||||||
if (event_log_)
|
if (event_log_)
|
||||||
event_log_->LogVideoSendStreamConfig(config);
|
event_log_->LogVideoSendStreamConfig(config);
|
||||||
|
|
||||||
return send_stream;
|
return send_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,6 +451,7 @@ void Call::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) {
|
|||||||
suspended_video_send_ssrcs_[it->first] = it->second;
|
suspended_video_send_ssrcs_[it->first] = it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateAggregateNetworkState();
|
||||||
delete send_stream_impl;
|
delete send_stream_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,7 +462,7 @@ webrtc::VideoReceiveStream* Call::CreateVideoReceiveStream(
|
|||||||
VideoReceiveStream* receive_stream = new VideoReceiveStream(
|
VideoReceiveStream* receive_stream = new VideoReceiveStream(
|
||||||
num_cpu_cores_, congestion_controller_.get(), config, voice_engine(),
|
num_cpu_cores_, congestion_controller_.get(), config, voice_engine(),
|
||||||
module_process_thread_.get(), call_stats_.get(), &remb_);
|
module_process_thread_.get(), call_stats_.get(), &remb_);
|
||||||
|
{
|
||||||
WriteLockScoped write_lock(*receive_crit_);
|
WriteLockScoped write_lock(*receive_crit_);
|
||||||
RTC_DCHECK(video_receive_ssrcs_.find(config.rtp.remote_ssrc) ==
|
RTC_DCHECK(video_receive_ssrcs_.find(config.rtp.remote_ssrc) ==
|
||||||
video_receive_ssrcs_.end());
|
video_receive_ssrcs_.end());
|
||||||
@ -468,13 +475,11 @@ webrtc::VideoReceiveStream* Call::CreateVideoReceiveStream(
|
|||||||
video_receive_streams_.insert(receive_stream);
|
video_receive_streams_.insert(receive_stream);
|
||||||
|
|
||||||
ConfigureSync(config.sync_group);
|
ConfigureSync(config.sync_group);
|
||||||
|
}
|
||||||
if (!network_enabled_)
|
receive_stream->SignalNetworkState(video_network_state_);
|
||||||
receive_stream->SignalNetworkState(kNetworkDown);
|
UpdateAggregateNetworkState();
|
||||||
|
|
||||||
if (event_log_)
|
if (event_log_)
|
||||||
event_log_->LogVideoReceiveStreamConfig(config);
|
event_log_->LogVideoReceiveStreamConfig(config);
|
||||||
|
|
||||||
return receive_stream;
|
return receive_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,6 +508,7 @@ void Call::DestroyVideoReceiveStream(
|
|||||||
RTC_CHECK(receive_stream_impl != nullptr);
|
RTC_CHECK(receive_stream_impl != nullptr);
|
||||||
ConfigureSync(receive_stream_impl->config().sync_group);
|
ConfigureSync(receive_stream_impl->config().sync_group);
|
||||||
}
|
}
|
||||||
|
UpdateAggregateNetworkState();
|
||||||
delete receive_stream_impl;
|
delete receive_stream_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,27 +555,74 @@ void Call::SetBitrateConfig(
|
|||||||
bitrate_config.max_bitrate_bps);
|
bitrate_config.max_bitrate_bps);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Call::SignalNetworkState(NetworkState state) {
|
void Call::SignalChannelNetworkState(MediaType media, NetworkState state) {
|
||||||
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
|
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
|
||||||
network_enabled_ = state == kNetworkUp;
|
switch (media) {
|
||||||
congestion_controller_->SignalNetworkState(state);
|
case MediaType::AUDIO:
|
||||||
|
audio_network_state_ = state;
|
||||||
|
break;
|
||||||
|
case MediaType::VIDEO:
|
||||||
|
video_network_state_ = state;
|
||||||
|
break;
|
||||||
|
case MediaType::ANY:
|
||||||
|
case MediaType::DATA:
|
||||||
|
RTC_NOTREACHED();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateAggregateNetworkState();
|
||||||
{
|
{
|
||||||
ReadLockScoped write_lock(*send_crit_);
|
ReadLockScoped read_lock(*send_crit_);
|
||||||
for (auto& kv : audio_send_ssrcs_) {
|
for (auto& kv : audio_send_ssrcs_) {
|
||||||
kv.second->SignalNetworkState(state);
|
kv.second->SignalNetworkState(audio_network_state_);
|
||||||
}
|
}
|
||||||
for (auto& kv : video_send_ssrcs_) {
|
for (auto& kv : video_send_ssrcs_) {
|
||||||
kv.second->SignalNetworkState(state);
|
kv.second->SignalNetworkState(video_network_state_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ReadLockScoped write_lock(*receive_crit_);
|
ReadLockScoped read_lock(*receive_crit_);
|
||||||
|
for (auto& kv : audio_receive_ssrcs_) {
|
||||||
|
kv.second->SignalNetworkState(audio_network_state_);
|
||||||
|
}
|
||||||
for (auto& kv : video_receive_ssrcs_) {
|
for (auto& kv : video_receive_ssrcs_) {
|
||||||
kv.second->SignalNetworkState(state);
|
kv.second->SignalNetworkState(video_network_state_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Call::UpdateAggregateNetworkState() {
|
||||||
|
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
|
||||||
|
|
||||||
|
bool have_audio = false;
|
||||||
|
bool have_video = false;
|
||||||
|
{
|
||||||
|
ReadLockScoped read_lock(*send_crit_);
|
||||||
|
if (audio_send_ssrcs_.size() > 0)
|
||||||
|
have_audio = true;
|
||||||
|
if (video_send_ssrcs_.size() > 0)
|
||||||
|
have_video = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ReadLockScoped read_lock(*receive_crit_);
|
||||||
|
if (audio_receive_ssrcs_.size() > 0)
|
||||||
|
have_audio = true;
|
||||||
|
if (video_receive_ssrcs_.size() > 0)
|
||||||
|
have_video = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkState aggregate_state = kNetworkDown;
|
||||||
|
if ((have_video && video_network_state_ == kNetworkUp) ||
|
||||||
|
(have_audio && audio_network_state_ == kNetworkUp)) {
|
||||||
|
aggregate_state = kNetworkUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(LS_INFO) << "UpdateAggregateNetworkState: aggregate_state="
|
||||||
|
<< (aggregate_state == kNetworkUp ? "up" : "down");
|
||||||
|
|
||||||
|
congestion_controller_->SignalNetworkState(aggregate_state);
|
||||||
|
}
|
||||||
|
|
||||||
void Call::OnSentPacket(const rtc::SentPacket& sent_packet) {
|
void Call::OnSentPacket(const rtc::SentPacket& sent_packet) {
|
||||||
if (first_packet_sent_ms_ == -1)
|
if (first_packet_sent_ms_ == -1)
|
||||||
first_packet_sent_ms_ = clock_->TimeInMilliseconds();
|
first_packet_sent_ms_ = clock_->TimeInMilliseconds();
|
||||||
|
|||||||
@ -233,7 +233,8 @@ void FakeVideoReceiveStream::SetStats(
|
|||||||
|
|
||||||
FakeCall::FakeCall(const webrtc::Call::Config& config)
|
FakeCall::FakeCall(const webrtc::Call::Config& config)
|
||||||
: config_(config),
|
: config_(config),
|
||||||
network_state_(webrtc::kNetworkUp),
|
audio_network_state_(webrtc::kNetworkUp),
|
||||||
|
video_network_state_(webrtc::kNetworkUp),
|
||||||
num_created_send_streams_(0),
|
num_created_send_streams_(0),
|
||||||
num_created_receive_streams_(0) {}
|
num_created_receive_streams_(0) {}
|
||||||
|
|
||||||
@ -282,8 +283,22 @@ const FakeAudioReceiveStream* FakeCall::GetAudioReceiveStream(uint32_t ssrc) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
webrtc::NetworkState FakeCall::GetNetworkState() const {
|
webrtc::NetworkState FakeCall::GetNetworkState(webrtc::MediaType media) const {
|
||||||
return network_state_;
|
switch (media) {
|
||||||
|
case webrtc::MediaType::AUDIO:
|
||||||
|
return audio_network_state_;
|
||||||
|
case webrtc::MediaType::VIDEO:
|
||||||
|
return video_network_state_;
|
||||||
|
case webrtc::MediaType::DATA:
|
||||||
|
case webrtc::MediaType::ANY:
|
||||||
|
ADD_FAILURE() << "GetNetworkState called with unknown parameter.";
|
||||||
|
return webrtc::kNetworkDown;
|
||||||
|
}
|
||||||
|
// Even though all the values for the enum class are listed above,the compiler
|
||||||
|
// will emit a warning as the method may be called with a value outside of the
|
||||||
|
// valid enum range, unless this case is also handled.
|
||||||
|
ADD_FAILURE() << "GetNetworkState called with unknown parameter.";
|
||||||
|
return webrtc::kNetworkDown;
|
||||||
}
|
}
|
||||||
|
|
||||||
webrtc::AudioSendStream* FakeCall::CreateAudioSendStream(
|
webrtc::AudioSendStream* FakeCall::CreateAudioSendStream(
|
||||||
@ -299,7 +314,7 @@ void FakeCall::DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) {
|
|||||||
audio_send_streams_.end(),
|
audio_send_streams_.end(),
|
||||||
static_cast<FakeAudioSendStream*>(send_stream));
|
static_cast<FakeAudioSendStream*>(send_stream));
|
||||||
if (it == audio_send_streams_.end()) {
|
if (it == audio_send_streams_.end()) {
|
||||||
ADD_FAILURE() << "DestroyAudioSendStream called with unknown paramter.";
|
ADD_FAILURE() << "DestroyAudioSendStream called with unknown parameter.";
|
||||||
} else {
|
} else {
|
||||||
delete *it;
|
delete *it;
|
||||||
audio_send_streams_.erase(it);
|
audio_send_streams_.erase(it);
|
||||||
@ -319,7 +334,7 @@ void FakeCall::DestroyAudioReceiveStream(
|
|||||||
audio_receive_streams_.end(),
|
audio_receive_streams_.end(),
|
||||||
static_cast<FakeAudioReceiveStream*>(receive_stream));
|
static_cast<FakeAudioReceiveStream*>(receive_stream));
|
||||||
if (it == audio_receive_streams_.end()) {
|
if (it == audio_receive_streams_.end()) {
|
||||||
ADD_FAILURE() << "DestroyAudioReceiveStream called with unknown paramter.";
|
ADD_FAILURE() << "DestroyAudioReceiveStream called with unknown parameter.";
|
||||||
} else {
|
} else {
|
||||||
delete *it;
|
delete *it;
|
||||||
audio_receive_streams_.erase(it);
|
audio_receive_streams_.erase(it);
|
||||||
@ -341,7 +356,7 @@ void FakeCall::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) {
|
|||||||
video_send_streams_.end(),
|
video_send_streams_.end(),
|
||||||
static_cast<FakeVideoSendStream*>(send_stream));
|
static_cast<FakeVideoSendStream*>(send_stream));
|
||||||
if (it == video_send_streams_.end()) {
|
if (it == video_send_streams_.end()) {
|
||||||
ADD_FAILURE() << "DestroyVideoSendStream called with unknown paramter.";
|
ADD_FAILURE() << "DestroyVideoSendStream called with unknown parameter.";
|
||||||
} else {
|
} else {
|
||||||
delete *it;
|
delete *it;
|
||||||
video_send_streams_.erase(it);
|
video_send_streams_.erase(it);
|
||||||
@ -361,7 +376,7 @@ void FakeCall::DestroyVideoReceiveStream(
|
|||||||
video_receive_streams_.end(),
|
video_receive_streams_.end(),
|
||||||
static_cast<FakeVideoReceiveStream*>(receive_stream));
|
static_cast<FakeVideoReceiveStream*>(receive_stream));
|
||||||
if (it == video_receive_streams_.end()) {
|
if (it == video_receive_streams_.end()) {
|
||||||
ADD_FAILURE() << "DestroyVideoReceiveStream called with unknown paramter.";
|
ADD_FAILURE() << "DestroyVideoReceiveStream called with unknown parameter.";
|
||||||
} else {
|
} else {
|
||||||
delete *it;
|
delete *it;
|
||||||
video_receive_streams_.erase(it);
|
video_receive_streams_.erase(it);
|
||||||
@ -422,8 +437,20 @@ void FakeCall::SetBitrateConfig(
|
|||||||
config_.bitrate_config = bitrate_config;
|
config_.bitrate_config = bitrate_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeCall::SignalNetworkState(webrtc::NetworkState state) {
|
void FakeCall::SignalChannelNetworkState(webrtc::MediaType media,
|
||||||
network_state_ = state;
|
webrtc::NetworkState state) {
|
||||||
|
switch (media) {
|
||||||
|
case webrtc::MediaType::AUDIO:
|
||||||
|
audio_network_state_ = state;
|
||||||
|
break;
|
||||||
|
case webrtc::MediaType::VIDEO:
|
||||||
|
video_network_state_ = state;
|
||||||
|
break;
|
||||||
|
case webrtc::MediaType::DATA:
|
||||||
|
case webrtc::MediaType::ANY:
|
||||||
|
ADD_FAILURE()
|
||||||
|
<< "SignalChannelNetworkState called with unknown parameter.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeCall::OnSentPacket(const rtc::SentPacket& sent_packet) {
|
void FakeCall::OnSentPacket(const rtc::SentPacket& sent_packet) {
|
||||||
|
|||||||
@ -200,7 +200,7 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
|
|||||||
const FakeAudioReceiveStream* GetAudioReceiveStream(uint32_t ssrc);
|
const FakeAudioReceiveStream* GetAudioReceiveStream(uint32_t ssrc);
|
||||||
|
|
||||||
rtc::SentPacket last_sent_packet() const { return last_sent_packet_; }
|
rtc::SentPacket last_sent_packet() const { return last_sent_packet_; }
|
||||||
webrtc::NetworkState GetNetworkState() const;
|
webrtc::NetworkState GetNetworkState(webrtc::MediaType media) const;
|
||||||
int GetNumCreatedSendStreams() const;
|
int GetNumCreatedSendStreams() const;
|
||||||
int GetNumCreatedReceiveStreams() const;
|
int GetNumCreatedReceiveStreams() const;
|
||||||
void SetStats(const webrtc::Call::Stats& stats);
|
void SetStats(const webrtc::Call::Stats& stats);
|
||||||
@ -235,11 +235,13 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
|
|||||||
|
|
||||||
void SetBitrateConfig(
|
void SetBitrateConfig(
|
||||||
const webrtc::Call::Config::BitrateConfig& bitrate_config) override;
|
const webrtc::Call::Config::BitrateConfig& bitrate_config) override;
|
||||||
void SignalNetworkState(webrtc::NetworkState state) override;
|
void SignalChannelNetworkState(webrtc::MediaType media,
|
||||||
|
webrtc::NetworkState state) override;
|
||||||
void OnSentPacket(const rtc::SentPacket& sent_packet) override;
|
void OnSentPacket(const rtc::SentPacket& sent_packet) override;
|
||||||
|
|
||||||
webrtc::Call::Config config_;
|
webrtc::Call::Config config_;
|
||||||
webrtc::NetworkState network_state_;
|
webrtc::NetworkState audio_network_state_;
|
||||||
|
webrtc::NetworkState video_network_state_;
|
||||||
rtc::SentPacket last_sent_packet_;
|
rtc::SentPacket last_sent_packet_;
|
||||||
webrtc::Call::Stats stats_;
|
webrtc::Call::Stats stats_;
|
||||||
std::vector<FakeVideoSendStream*> video_send_streams_;
|
std::vector<FakeVideoSendStream*> video_send_streams_;
|
||||||
|
|||||||
@ -1421,7 +1421,9 @@ void WebRtcVideoChannel2::OnRtcpReceived(
|
|||||||
|
|
||||||
void WebRtcVideoChannel2::OnReadyToSend(bool ready) {
|
void WebRtcVideoChannel2::OnReadyToSend(bool ready) {
|
||||||
LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
|
LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
|
||||||
call_->SignalNetworkState(ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
|
call_->SignalChannelNetworkState(
|
||||||
|
webrtc::MediaType::VIDEO,
|
||||||
|
ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebRtcVideoChannel2::MuteStream(uint32_t ssrc, bool mute) {
|
bool WebRtcVideoChannel2::MuteStream(uint32_t ssrc, bool mute) {
|
||||||
|
|||||||
@ -2656,13 +2656,22 @@ TEST_F(WebRtcVideoChannel2Test, TestSetRecvRtcpReducedSize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebRtcVideoChannel2Test, OnReadyToSendSignalsNetworkState) {
|
TEST_F(WebRtcVideoChannel2Test, OnReadyToSendSignalsNetworkState) {
|
||||||
EXPECT_EQ(webrtc::kNetworkUp, fake_call_->GetNetworkState());
|
EXPECT_EQ(webrtc::kNetworkUp,
|
||||||
|
fake_call_->GetNetworkState(webrtc::MediaType::VIDEO));
|
||||||
|
EXPECT_EQ(webrtc::kNetworkUp,
|
||||||
|
fake_call_->GetNetworkState(webrtc::MediaType::AUDIO));
|
||||||
|
|
||||||
channel_->OnReadyToSend(false);
|
channel_->OnReadyToSend(false);
|
||||||
EXPECT_EQ(webrtc::kNetworkDown, fake_call_->GetNetworkState());
|
EXPECT_EQ(webrtc::kNetworkDown,
|
||||||
|
fake_call_->GetNetworkState(webrtc::MediaType::VIDEO));
|
||||||
|
EXPECT_EQ(webrtc::kNetworkUp,
|
||||||
|
fake_call_->GetNetworkState(webrtc::MediaType::AUDIO));
|
||||||
|
|
||||||
channel_->OnReadyToSend(true);
|
channel_->OnReadyToSend(true);
|
||||||
EXPECT_EQ(webrtc::kNetworkUp, fake_call_->GetNetworkState());
|
EXPECT_EQ(webrtc::kNetworkUp,
|
||||||
|
fake_call_->GetNetworkState(webrtc::MediaType::VIDEO));
|
||||||
|
EXPECT_EQ(webrtc::kNetworkUp,
|
||||||
|
fake_call_->GetNetworkState(webrtc::MediaType::AUDIO));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebRtcVideoChannel2Test, GetStatsReportsSentCodecName) {
|
TEST_F(WebRtcVideoChannel2Test, GetStatsReportsSentCodecName) {
|
||||||
|
|||||||
@ -2419,6 +2419,14 @@ bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebRtcVoiceMediaChannel::OnReadyToSend(bool ready) {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
|
LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
|
||||||
|
call_->SignalChannelNetworkState(
|
||||||
|
webrtc::MediaType::AUDIO,
|
||||||
|
ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
|
||||||
|
}
|
||||||
|
|
||||||
bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
|
bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
|
||||||
TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetStats");
|
TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetStats");
|
||||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
|
|||||||
@ -183,7 +183,7 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
|
|||||||
const rtc::PacketTime& packet_time) override;
|
const rtc::PacketTime& packet_time) override;
|
||||||
void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet,
|
void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet,
|
||||||
const rtc::PacketTime& packet_time) override;
|
const rtc::PacketTime& packet_time) override;
|
||||||
void OnReadyToSend(bool ready) override {}
|
void OnReadyToSend(bool ready) override;
|
||||||
bool GetStats(VoiceMediaInfo* info) override;
|
bool GetStats(VoiceMediaInfo* info) override;
|
||||||
|
|
||||||
void SetRawAudioSink(
|
void SetRawAudioSink(
|
||||||
|
|||||||
@ -3193,6 +3193,29 @@ TEST_F(WebRtcVoiceEngineTestFake, SetRawAudioSinkDefaultRecvStream) {
|
|||||||
EXPECT_NE(nullptr, GetRecvStream(0x01).sink());
|
EXPECT_NE(nullptr, GetRecvStream(0x01).sink());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that, just like the video channel, the voice channel communicates the
|
||||||
|
// network state to the call.
|
||||||
|
TEST_F(WebRtcVoiceEngineTestFake, OnReadyToSendSignalsNetworkState) {
|
||||||
|
EXPECT_TRUE(SetupEngine());
|
||||||
|
|
||||||
|
EXPECT_EQ(webrtc::kNetworkUp,
|
||||||
|
call_.GetNetworkState(webrtc::MediaType::AUDIO));
|
||||||
|
EXPECT_EQ(webrtc::kNetworkUp,
|
||||||
|
call_.GetNetworkState(webrtc::MediaType::VIDEO));
|
||||||
|
|
||||||
|
channel_->OnReadyToSend(false);
|
||||||
|
EXPECT_EQ(webrtc::kNetworkDown,
|
||||||
|
call_.GetNetworkState(webrtc::MediaType::AUDIO));
|
||||||
|
EXPECT_EQ(webrtc::kNetworkUp,
|
||||||
|
call_.GetNetworkState(webrtc::MediaType::VIDEO));
|
||||||
|
|
||||||
|
channel_->OnReadyToSend(true);
|
||||||
|
EXPECT_EQ(webrtc::kNetworkUp,
|
||||||
|
call_.GetNetworkState(webrtc::MediaType::AUDIO));
|
||||||
|
EXPECT_EQ(webrtc::kNetworkUp,
|
||||||
|
call_.GetNetworkState(webrtc::MediaType::VIDEO));
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that the library initializes and shuts down properly.
|
// Tests that the library initializes and shuts down properly.
|
||||||
TEST(WebRtcVoiceEngineTest, StartupShutdown) {
|
TEST(WebRtcVoiceEngineTest, StartupShutdown) {
|
||||||
cricket::WebRtcVoiceEngine engine;
|
cricket::WebRtcVoiceEngine engine;
|
||||||
|
|||||||
@ -76,6 +76,35 @@ class EndToEndTest : public test::CallTest {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RequiredTransport : public Transport {
|
||||||
|
public:
|
||||||
|
RequiredTransport(bool rtp_required, bool rtcp_required)
|
||||||
|
: need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
|
||||||
|
~RequiredTransport() {
|
||||||
|
if (need_rtp_) {
|
||||||
|
ADD_FAILURE() << "Expected RTP packet not sent.";
|
||||||
|
}
|
||||||
|
if (need_rtcp_) {
|
||||||
|
ADD_FAILURE() << "Expected RTCP packet not sent.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool SendRtp(const uint8_t* packet,
|
||||||
|
size_t length,
|
||||||
|
const PacketOptions& options) override {
|
||||||
|
need_rtp_ = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SendRtcp(const uint8_t* packet, size_t length) override {
|
||||||
|
need_rtcp_ = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool need_rtp_;
|
||||||
|
bool need_rtcp_;
|
||||||
|
};
|
||||||
|
|
||||||
void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
|
void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
|
||||||
void ReceivesPliAndRecovers(int rtp_history_ms);
|
void ReceivesPliAndRecovers(int rtp_history_ms);
|
||||||
void RespectsRtcpMode(RtcpMode rtcp_mode);
|
void RespectsRtcpMode(RtcpMode rtcp_mode);
|
||||||
@ -83,6 +112,13 @@ class EndToEndTest : public test::CallTest {
|
|||||||
void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
|
void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
|
||||||
void TestRtpStatePreservation(bool use_rtx);
|
void TestRtpStatePreservation(bool use_rtx);
|
||||||
void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
|
void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
|
||||||
|
void VerifyNewVideoSendStreamsRespectNetworkState(
|
||||||
|
MediaType network_to_bring_down,
|
||||||
|
VideoEncoder* encoder,
|
||||||
|
Transport* transport);
|
||||||
|
void VerifyNewVideoReceiveStreamsRespectNetworkState(
|
||||||
|
MediaType network_to_bring_down,
|
||||||
|
Transport* transport);
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
|
TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
|
||||||
@ -3193,8 +3229,16 @@ TEST_F(EndToEndTest, RespectsNetworkState) {
|
|||||||
// Wait for packets from both sender/receiver.
|
// Wait for packets from both sender/receiver.
|
||||||
WaitForPacketsOrSilence(false, false);
|
WaitForPacketsOrSilence(false, false);
|
||||||
|
|
||||||
|
// Sender-side network down for audio; there should be no effect on video
|
||||||
|
sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
|
||||||
|
WaitForPacketsOrSilence(false, false);
|
||||||
|
|
||||||
|
// Receiver-side network down for audio; no change expected
|
||||||
|
receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
|
||||||
|
WaitForPacketsOrSilence(false, false);
|
||||||
|
|
||||||
// Sender-side network down.
|
// Sender-side network down.
|
||||||
sender_call_->SignalNetworkState(kNetworkDown);
|
sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
|
||||||
{
|
{
|
||||||
rtc::CritScope lock(&test_crit_);
|
rtc::CritScope lock(&test_crit_);
|
||||||
// After network goes down we shouldn't be encoding more frames.
|
// After network goes down we shouldn't be encoding more frames.
|
||||||
@ -3204,7 +3248,13 @@ TEST_F(EndToEndTest, RespectsNetworkState) {
|
|||||||
WaitForPacketsOrSilence(true, false);
|
WaitForPacketsOrSilence(true, false);
|
||||||
|
|
||||||
// Receiver-side network down.
|
// Receiver-side network down.
|
||||||
receiver_call_->SignalNetworkState(kNetworkDown);
|
receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
|
||||||
|
WaitForPacketsOrSilence(true, true);
|
||||||
|
|
||||||
|
// Network up for audio for both sides; video is still not expected to
|
||||||
|
// start
|
||||||
|
sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
|
||||||
|
receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
|
||||||
WaitForPacketsOrSilence(true, true);
|
WaitForPacketsOrSilence(true, true);
|
||||||
|
|
||||||
// Network back up again for both.
|
// Network back up again for both.
|
||||||
@ -3214,9 +3264,13 @@ TEST_F(EndToEndTest, RespectsNetworkState) {
|
|||||||
// network.
|
// network.
|
||||||
sender_state_ = kNetworkUp;
|
sender_state_ = kNetworkUp;
|
||||||
}
|
}
|
||||||
sender_call_->SignalNetworkState(kNetworkUp);
|
sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
|
||||||
receiver_call_->SignalNetworkState(kNetworkUp);
|
receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
|
||||||
WaitForPacketsOrSilence(false, false);
|
WaitForPacketsOrSilence(false, false);
|
||||||
|
|
||||||
|
// TODO(skvlad): add tests to verify that the audio streams are stopped
|
||||||
|
// when the network goes down for audio once the workaround in
|
||||||
|
// paced_sender.cc is removed.
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Encode(const VideoFrame& input_image,
|
int32_t Encode(const VideoFrame& input_image,
|
||||||
@ -3267,7 +3321,7 @@ TEST_F(EndToEndTest, RespectsNetworkState) {
|
|||||||
sender_done = true;
|
sender_done = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sender_rtp_ > initial_sender_rtp)
|
if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
|
||||||
sender_done = true;
|
sender_done = true;
|
||||||
}
|
}
|
||||||
if (receiver_down) {
|
if (receiver_down) {
|
||||||
@ -3279,7 +3333,7 @@ TEST_F(EndToEndTest, RespectsNetworkState) {
|
|||||||
receiver_done = true;
|
receiver_done = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (receiver_rtcp_ > initial_receiver_rtcp)
|
if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
|
||||||
receiver_done = true;
|
receiver_done = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3338,26 +3392,15 @@ TEST_F(EndToEndTest, CallReportsRttForSender) {
|
|||||||
DestroyStreams();
|
DestroyStreams();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(EndToEndTest, NewSendStreamsRespectNetworkDown) {
|
void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
|
||||||
class UnusedEncoder : public test::FakeEncoder {
|
MediaType network_to_bring_down,
|
||||||
public:
|
VideoEncoder* encoder,
|
||||||
UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
|
Transport* transport) {
|
||||||
int32_t Encode(const VideoFrame& input_image,
|
|
||||||
const CodecSpecificInfo* codec_specific_info,
|
|
||||||
const std::vector<FrameType>* frame_types) override {
|
|
||||||
ADD_FAILURE() << "Unexpected frame encode.";
|
|
||||||
return test::FakeEncoder::Encode(
|
|
||||||
input_image, codec_specific_info, frame_types);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CreateSenderCall(Call::Config());
|
CreateSenderCall(Call::Config());
|
||||||
sender_call_->SignalNetworkState(kNetworkDown);
|
sender_call_->SignalChannelNetworkState(network_to_bring_down, kNetworkDown);
|
||||||
|
|
||||||
UnusedTransport transport;
|
CreateSendConfig(1, 0, transport);
|
||||||
CreateSendConfig(1, 0, &transport);
|
video_send_config_.encoder_settings.encoder = encoder;
|
||||||
UnusedEncoder unused_encoder;
|
|
||||||
video_send_config_.encoder_settings.encoder = &unused_encoder;
|
|
||||||
CreateVideoStreams();
|
CreateVideoStreams();
|
||||||
CreateFrameGeneratorCapturer();
|
CreateFrameGeneratorCapturer();
|
||||||
|
|
||||||
@ -3368,15 +3411,17 @@ TEST_F(EndToEndTest, NewSendStreamsRespectNetworkDown) {
|
|||||||
DestroyStreams();
|
DestroyStreams();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(EndToEndTest, NewReceiveStreamsRespectNetworkDown) {
|
void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
|
||||||
|
MediaType network_to_bring_down,
|
||||||
|
Transport* transport) {
|
||||||
CreateCalls(Call::Config(), Call::Config());
|
CreateCalls(Call::Config(), Call::Config());
|
||||||
receiver_call_->SignalNetworkState(kNetworkDown);
|
receiver_call_->SignalChannelNetworkState(network_to_bring_down,
|
||||||
|
kNetworkDown);
|
||||||
|
|
||||||
test::DirectTransport sender_transport(sender_call_.get());
|
test::DirectTransport sender_transport(sender_call_.get());
|
||||||
sender_transport.SetReceiver(receiver_call_->Receiver());
|
sender_transport.SetReceiver(receiver_call_->Receiver());
|
||||||
CreateSendConfig(1, 0, &sender_transport);
|
CreateSendConfig(1, 0, &sender_transport);
|
||||||
UnusedTransport transport;
|
CreateMatchingReceiveConfigs(transport);
|
||||||
CreateMatchingReceiveConfigs(&transport);
|
|
||||||
CreateVideoStreams();
|
CreateVideoStreams();
|
||||||
CreateFrameGeneratorCapturer();
|
CreateFrameGeneratorCapturer();
|
||||||
|
|
||||||
@ -3389,6 +3434,63 @@ TEST_F(EndToEndTest, NewReceiveStreamsRespectNetworkDown) {
|
|||||||
DestroyStreams();
|
DestroyStreams();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
|
||||||
|
class UnusedEncoder : public test::FakeEncoder {
|
||||||
|
public:
|
||||||
|
UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
|
||||||
|
int32_t Encode(const VideoFrame& input_image,
|
||||||
|
const CodecSpecificInfo* codec_specific_info,
|
||||||
|
const std::vector<FrameType>* frame_types) override {
|
||||||
|
ADD_FAILURE() << "Unexpected frame encode.";
|
||||||
|
return test::FakeEncoder::Encode(input_image, codec_specific_info,
|
||||||
|
frame_types);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
UnusedEncoder unused_encoder;
|
||||||
|
UnusedTransport unused_transport;
|
||||||
|
VerifyNewVideoSendStreamsRespectNetworkState(
|
||||||
|
MediaType::VIDEO, &unused_encoder, &unused_transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
|
||||||
|
class RequiredEncoder : public test::FakeEncoder {
|
||||||
|
public:
|
||||||
|
RequiredEncoder()
|
||||||
|
: FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
|
||||||
|
~RequiredEncoder() {
|
||||||
|
if (!encoded_frame_) {
|
||||||
|
ADD_FAILURE() << "Didn't encode an expected frame";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int32_t Encode(const VideoFrame& input_image,
|
||||||
|
const CodecSpecificInfo* codec_specific_info,
|
||||||
|
const std::vector<FrameType>* frame_types) override {
|
||||||
|
encoded_frame_ = true;
|
||||||
|
return test::FakeEncoder::Encode(input_image, codec_specific_info,
|
||||||
|
frame_types);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool encoded_frame_;
|
||||||
|
};
|
||||||
|
|
||||||
|
RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
|
||||||
|
RequiredEncoder required_encoder;
|
||||||
|
VerifyNewVideoSendStreamsRespectNetworkState(
|
||||||
|
MediaType::AUDIO, &required_encoder, &required_transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
|
||||||
|
UnusedTransport transport;
|
||||||
|
VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
|
||||||
|
RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
|
||||||
|
VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
|
||||||
|
}
|
||||||
|
|
||||||
void VerifyEmptyNackConfig(const NackConfig& config) {
|
void VerifyEmptyNackConfig(const NackConfig& config) {
|
||||||
EXPECT_EQ(0, config.rtp_history_ms)
|
EXPECT_EQ(0, config.rtp_history_ms)
|
||||||
<< "Enabling NACK requires rtcp-fb: nack negotiation.";
|
<< "Enabling NACK requires rtcp-fb: nack negotiation.";
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user