Added Error Checking in Ingress/Egress and Extra Unit Tests
Added error checking in AudioIngress and AudioEgress to detect situations where codecs have not been set; added additional unit tests for VoipCore
Bug: webrtc:11251
Change-Id: Ibd57e518892c76e2865b844ba866e380a565dd6b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/180229
Commit-Queue: Tim Na <natim@webrtc.org>
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Reviewed-by: Tim Na <natim@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31874}
diff --git a/audio/voip/audio_channel.cc b/audio/voip/audio_channel.cc
index d9c89fc..43d4d0f 100644
--- a/audio/voip/audio_channel.cc
+++ b/audio/voip/audio_channel.cc
@@ -82,44 +82,50 @@
process_thread_->DeRegisterModule(rtp_rtcp_.get());
}
-void AudioChannel::StartSend() {
- egress_->StartSend();
+bool AudioChannel::StartSend() {
+ // If encoder has not been set, return false.
+ if (!egress_->StartSend()) {
+ return false;
+ }
// Start sending with RTP stack if it has not been sending yet.
- if (!rtp_rtcp_->Sending() && rtp_rtcp_->SetSendingStatus(true) != 0) {
- RTC_DLOG(LS_ERROR) << "StartSend() RTP/RTCP failed to start sending";
+ if (!rtp_rtcp_->Sending()) {
+ rtp_rtcp_->SetSendingStatus(true);
}
+ return true;
}
void AudioChannel::StopSend() {
egress_->StopSend();
- // If the channel is not playing and RTP stack is active then deactivate RTP
- // stack. SetSendingStatus(false) triggers the transmission of RTCP BYE
+ // Deactivate RTP stack when both sending and receiving are stopped.
+ // SetSendingStatus(false) triggers the transmission of RTCP BYE
// message to remote endpoint.
- if (!IsPlaying() && rtp_rtcp_->Sending() &&
- rtp_rtcp_->SetSendingStatus(false) != 0) {
- RTC_DLOG(LS_ERROR) << "StopSend() RTP/RTCP failed to stop sending";
+ if (!ingress_->IsPlaying() && rtp_rtcp_->Sending()) {
+ rtp_rtcp_->SetSendingStatus(false);
}
}
-void AudioChannel::StartPlay() {
- ingress_->StartPlay();
+bool AudioChannel::StartPlay() {
+ // If decoders have not been set, return false.
+ if (!ingress_->StartPlay()) {
+ return false;
+ }
// If RTP stack is not sending then start sending as in recv-only mode, RTCP
// receiver report is expected.
- if (!rtp_rtcp_->Sending() && rtp_rtcp_->SetSendingStatus(true) != 0) {
- RTC_DLOG(LS_ERROR) << "StartPlay() RTP/RTCP failed to start sending";
+ if (!rtp_rtcp_->Sending()) {
+ rtp_rtcp_->SetSendingStatus(true);
}
+ return true;
}
void AudioChannel::StopPlay() {
ingress_->StopPlay();
// Deactivate RTP stack only when both sending and receiving are stopped.
- if (!IsSendingMedia() && rtp_rtcp_->Sending() &&
- rtp_rtcp_->SetSendingStatus(false) != 0) {
- RTC_DLOG(LS_ERROR) << "StopPlay() RTP/RTCP failed to stop sending";
+ if (!rtp_rtcp_->SendingMedia() && rtp_rtcp_->Sending()) {
+ rtp_rtcp_->SetSendingStatus(false);
}
}
diff --git a/audio/voip/audio_channel.h b/audio/voip/audio_channel.h
index 659e990..12138ee 100644
--- a/audio/voip/audio_channel.h
+++ b/audio/voip/audio_channel.h
@@ -45,9 +45,11 @@
ChannelId GetId() const { return id_; }
// APIs to start/stop audio channel on each direction.
- void StartSend();
+ // StartSend/StartPlay returns false if encoder/decoders
+ // have not been set, respectively.
+ bool StartSend();
void StopSend();
- void StartPlay();
+ bool StartPlay();
void StopPlay();
// APIs relayed to AudioEgress.
diff --git a/audio/voip/audio_egress.cc b/audio/voip/audio_egress.cc
index 305f712..90e069e 100644
--- a/audio/voip/audio_egress.cc
+++ b/audio/voip/audio_egress.cc
@@ -56,8 +56,13 @@
audio_coding_->SetEncoder(std::move(encoder));
}
-void AudioEgress::StartSend() {
+bool AudioEgress::StartSend() {
+ if (!GetEncoderFormat()) {
+ RTC_DLOG(LS_WARNING) << "Send codec has not been set yet";
+ return false;
+ }
rtp_rtcp_->SetSendingMediaStatus(true);
+ return true;
}
void AudioEgress::StopSend() {
diff --git a/audio/voip/audio_egress.h b/audio/voip/audio_egress.h
index 8ec048f..6b2d374 100644
--- a/audio/voip/audio_egress.h
+++ b/audio/voip/audio_egress.h
@@ -59,8 +59,9 @@
// Start or stop sending operation of AudioEgress. This will start/stop
// the RTP stack also causes encoder queue thread to start/stop
- // processing input audio samples.
- void StartSend();
+ // processing input audio samples. StartSend will return false if
+ // a send codec has not been set.
+ bool StartSend();
void StopSend();
// Query the state of the RTP stack. This returns true if StartSend()
diff --git a/audio/voip/audio_ingress.cc b/audio/voip/audio_ingress.cc
index 560055d..0bddb42 100644
--- a/audio/voip/audio_ingress.cc
+++ b/audio/voip/audio_ingress.cc
@@ -103,6 +103,18 @@
: AudioMixer::Source::AudioFrameInfo::kNormal;
}
+bool AudioIngress::StartPlay() {
+ {
+ MutexLock lock(&lock_);
+ if (receive_codec_info_.empty()) {
+ RTC_DLOG(LS_WARNING) << "Receive codecs have not been set yet";
+ return false;
+ }
+ }
+ playing_ = true;
+ return true;
+}
+
void AudioIngress::SetReceiveCodecs(
const std::map<int, SdpAudioFormat>& codecs) {
{
diff --git a/audio/voip/audio_ingress.h b/audio/voip/audio_ingress.h
index 5a8df21..d09de60 100644
--- a/audio/voip/audio_ingress.h
+++ b/audio/voip/audio_ingress.h
@@ -51,7 +51,7 @@
~AudioIngress() override;
// Start or stop receiving operation of AudioIngress.
- void StartPlay() { playing_ = true; }
+ bool StartPlay();
void StopPlay() {
playing_ = false;
output_audio_level_.ResetLevelFullRange();
diff --git a/audio/voip/test/voip_core_unittest.cc b/audio/voip/test/voip_core_unittest.cc
index c1969d6..b97b637 100644
--- a/audio/voip/test/voip_core_unittest.cc
+++ b/audio/voip/test/voip_core_unittest.cc
@@ -96,5 +96,33 @@
EXPECT_FALSE(voip_core_->StartPlayout(*channel));
}
+TEST_F(VoipCoreTest, StartSendAndPlayoutWithoutSettingCodec) {
+ auto channel = voip_core_->CreateChannel(&transport_, 0xdeadc0de);
+ EXPECT_TRUE(channel);
+
+ // Call StartSend and StartPlayout without setting send/receive
+ // codec. Code should see that codecs aren't set and return false.
+ EXPECT_FALSE(voip_core_->StartSend(*channel));
+ EXPECT_FALSE(voip_core_->StartPlayout(*channel));
+
+ voip_core_->ReleaseChannel(*channel);
+}
+
+TEST_F(VoipCoreTest, StopSendAndPlayoutWithoutStarting) {
+ auto channel = voip_core_->CreateChannel(&transport_, 0xdeadc0de);
+ EXPECT_TRUE(channel);
+
+ voip_core_->SetSendCodec(*channel, kPcmuPayload, kPcmuFormat);
+ voip_core_->SetReceiveCodecs(*channel, {{kPcmuPayload, kPcmuFormat}});
+
+ // Call StopSend and StopPlayout without starting them in
+ // the first place. Should see that it is already in the
+ // stopped state and return true.
+ EXPECT_TRUE(voip_core_->StopSend(*channel));
+ EXPECT_TRUE(voip_core_->StopPlayout(*channel));
+
+ voip_core_->ReleaseChannel(*channel);
+}
+
} // namespace
} // namespace webrtc
diff --git a/audio/voip/voip_core.cc b/audio/voip/voip_core.cc
index 7292644..6390223 100644
--- a/audio/voip/voip_core.cc
+++ b/audio/voip/voip_core.cc
@@ -238,12 +238,10 @@
bool VoipCore::StartSend(ChannelId channel) {
auto audio_channel = GetChannel(channel);
- if (!audio_channel) {
+ if (!audio_channel || !audio_channel->StartSend()) {
return false;
}
- audio_channel->StartSend();
-
return UpdateAudioTransportWithSenders();
}
@@ -260,12 +258,10 @@
bool VoipCore::StartPlayout(ChannelId channel) {
auto audio_channel = GetChannel(channel);
- if (!audio_channel) {
+ if (!audio_channel || !audio_channel->StartPlay()) {
return false;
}
- audio_channel->StartPlay();
-
if (!audio_device_module_->Playing()) {
if (audio_device_module_->InitPlayout() != 0) {
RTC_LOG(LS_ERROR) << "InitPlayout failed";