ChannelStatistics RTT test case around remote SSRC change.
Bug: webrtc:11989
Change-Id: I7211ffa83ad381b6367d78e553cd5943dca515f2
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/201880
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Tim Na <natim@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33039}
diff --git a/audio/voip/test/audio_channel_unittest.cc b/audio/voip/test/audio_channel_unittest.cc
index 1a79d84..e0244c7 100644
--- a/audio/voip/test/audio_channel_unittest.cc
+++ b/audio/voip/test/audio_channel_unittest.cc
@@ -28,6 +28,7 @@
using ::testing::Invoke;
using ::testing::NiceMock;
+using ::testing::Return;
using ::testing::Unused;
constexpr uint64_t kStartTime = 123456789;
@@ -53,23 +54,27 @@
Invoke([&](std::unique_ptr<QueuedTask> task) { task->Run(); }));
}
- void SetUp() override {
- audio_channel_ = new rtc::RefCountedObject<AudioChannel>(
- &transport_, kLocalSsrc, task_queue_factory_.get(),
- process_thread_.get(), audio_mixer_.get(), decoder_factory_);
+ void SetUp() override { audio_channel_ = CreateAudioChannel(kLocalSsrc); }
- audio_channel_->SetEncoder(kPcmuPayload, kPcmuFormat,
- encoder_factory_->MakeAudioEncoder(
- kPcmuPayload, kPcmuFormat, absl::nullopt));
- audio_channel_->SetReceiveCodecs({{kPcmuPayload, kPcmuFormat}});
- audio_channel_->StartSend();
- audio_channel_->StartPlay();
- }
+ void TearDown() override { audio_channel_ = nullptr; }
- void TearDown() override {
- audio_channel_->StopSend();
- audio_channel_->StopPlay();
- audio_channel_ = nullptr;
+ rtc::scoped_refptr<AudioChannel> CreateAudioChannel(uint32_t ssrc) {
+ // Use same audio mixer here for simplicity sake as we are not checking
+ // audio activity of RTP in our testcases. If we need to do test on audio
+ // signal activity then we need to assign audio mixer for each channel.
+ // Also this uses the same transport object for different audio channel to
+ // simplify network routing logic.
+ rtc::scoped_refptr<AudioChannel> audio_channel =
+ new rtc::RefCountedObject<AudioChannel>(
+ &transport_, ssrc, task_queue_factory_.get(), process_thread_.get(),
+ audio_mixer_.get(), decoder_factory_);
+ audio_channel->SetEncoder(kPcmuPayload, kPcmuFormat,
+ encoder_factory_->MakeAudioEncoder(
+ kPcmuPayload, kPcmuFormat, absl::nullopt));
+ audio_channel->SetReceiveCodecs({{kPcmuPayload, kPcmuFormat}});
+ audio_channel->StartSend();
+ audio_channel->StartPlay();
+ return audio_channel;
}
std::unique_ptr<AudioFrame> GetAudioFrame(int order) {
@@ -269,5 +274,85 @@
EXPECT_FALSE(channel_stats->remote_rtcp->round_trip_time.has_value());
}
+// Check ChannelStatistics RTT metric after processing RTP and RTCP packets
+// using three audio channels where each represents media endpoint.
+//
+// 1) AC1 <- RTP/RTCP -> AC2
+// 2) AC1 <- RTP/RTCP -> AC3
+//
+// During step 1), AC1 should be able to check RTT from AC2's SSRC.
+// During step 2), AC1 should be able to check RTT from AC3's SSRC.
+TEST_F(AudioChannelTest, RttIsAvailableAfterChangeOfRemoteSsrc) {
+ // Create AC2 and AC3.
+ constexpr uint32_t kAc2Ssrc = 0xdeadbeef;
+ constexpr uint32_t kAc3Ssrc = 0xdeafbeef;
+
+ auto ac_2 = CreateAudioChannel(kAc2Ssrc);
+ auto ac_3 = CreateAudioChannel(kAc3Ssrc);
+
+ auto send_recv_rtp = [&](rtc::scoped_refptr<AudioChannel> rtp_sender,
+ rtc::scoped_refptr<AudioChannel> rtp_receiver) {
+ // Setup routing logic via transport_.
+ auto route_rtp = [&](const uint8_t* packet, size_t length, Unused) {
+ rtp_receiver->ReceivedRTPPacket(rtc::MakeArrayView(packet, length));
+ return true;
+ };
+ ON_CALL(transport_, SendRtp).WillByDefault(route_rtp);
+
+ // This will trigger route_rtp callback via transport_.
+ rtp_sender->GetAudioSender()->SendAudioData(GetAudioFrame(0));
+ rtp_sender->GetAudioSender()->SendAudioData(GetAudioFrame(1));
+
+ // Process received RTP in receiver.
+ AudioFrame audio_frame;
+ audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame);
+ audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame);
+
+ // Revert to default to avoid using reference in route_rtp lambda.
+ ON_CALL(transport_, SendRtp).WillByDefault(Return(true));
+ };
+
+ auto send_recv_rtcp = [&](rtc::scoped_refptr<AudioChannel> rtcp_sender,
+ rtc::scoped_refptr<AudioChannel> rtcp_receiver) {
+ // Setup routing logic via transport_.
+ auto route_rtcp = [&](const uint8_t* packet, size_t length) {
+ rtcp_receiver->ReceivedRTCPPacket(rtc::MakeArrayView(packet, length));
+ return true;
+ };
+ ON_CALL(transport_, SendRtcp).WillByDefault(route_rtcp);
+
+ // This will trigger route_rtcp callback via transport_.
+ rtcp_sender->SendRTCPReportForTesting(kRtcpSr);
+
+ // Revert to default to avoid using reference in route_rtcp lambda.
+ ON_CALL(transport_, SendRtcp).WillByDefault(Return(true));
+ };
+
+ // AC1 <-- RTP/RTCP --> AC2
+ send_recv_rtp(audio_channel_, ac_2);
+ send_recv_rtp(ac_2, audio_channel_);
+ send_recv_rtcp(audio_channel_, ac_2);
+ send_recv_rtcp(ac_2, audio_channel_);
+
+ absl::optional<ChannelStatistics> channel_stats =
+ audio_channel_->GetChannelStatistics();
+ ASSERT_TRUE(channel_stats);
+ EXPECT_EQ(channel_stats->remote_ssrc, kAc2Ssrc);
+ ASSERT_TRUE(channel_stats->remote_rtcp);
+ EXPECT_GT(channel_stats->remote_rtcp->round_trip_time, 0.0);
+
+ // AC1 <-- RTP/RTCP --> AC3
+ send_recv_rtp(audio_channel_, ac_3);
+ send_recv_rtp(ac_3, audio_channel_);
+ send_recv_rtcp(audio_channel_, ac_3);
+ send_recv_rtcp(ac_3, audio_channel_);
+
+ channel_stats = audio_channel_->GetChannelStatistics();
+ ASSERT_TRUE(channel_stats);
+ EXPECT_EQ(channel_stats->remote_ssrc, kAc3Ssrc);
+ ASSERT_TRUE(channel_stats->remote_rtcp);
+ EXPECT_GT(channel_stats->remote_rtcp->round_trip_time, 0.0);
+}
+
} // namespace
} // namespace webrtc