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}
This commit is contained in:
Tim Na 2021-01-15 15:54:07 -08:00 committed by Commit Bot
parent a24d35eb09
commit 1cbf21e157

View file

@ -28,6 +28,7 @@ namespace {
using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::Unused;
constexpr uint64_t kStartTime = 123456789;
@ -53,23 +54,27 @@ class AudioChannelTest : public ::testing::Test {
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,
void TearDown() override { 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();
}
void TearDown() override {
audio_channel_->StopSend();
audio_channel_->StopPlay();
audio_channel_ = nullptr;
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 @@ TEST_F(AudioChannelTest, TestChannelStatistics) {
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