Move FecOverheadRate, BitrateCallbacks to rtp_sender_egress_unittest.

Bug: webrtc:11340
Change-Id: I33dcaea0146429de94d7610b46592b41e0c5549a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/219685
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34068}
This commit is contained in:
Erik Språng 2021-05-20 15:26:56 +02:00 committed by WebRTC LUCI CQ
parent 63b3095d2b
commit e2b9fc6909
2 changed files with 76 additions and 143 deletions

View File

@ -31,6 +31,7 @@
namespace webrtc {
namespace {
using ::testing::_;
using ::testing::Field;
using ::testing::NiceMock;
using ::testing::StrictMock;
@ -403,6 +404,80 @@ TEST_P(RtpSenderEgressTest, OnSendPacketNotUpdatedForRetransmits) {
sender->SendPacket(packet.get(), PacedPacketInfo());
}
TEST_P(RtpSenderEgressTest, ReportsFecRate) {
constexpr int kNumPackets = 10;
constexpr TimeDelta kTimeBetweenPackets = TimeDelta::Millis(33);
std::unique_ptr<RtpSenderEgress> sender = CreateRtpSenderEgress();
DataSize total_fec_data_sent = DataSize::Zero();
// Send some packets, alternating between media and FEC.
for (size_t i = 0; i < kNumPackets; ++i) {
std::unique_ptr<RtpPacketToSend> media_packet = BuildRtpPacket();
media_packet->set_packet_type(RtpPacketMediaType::kVideo);
media_packet->SetPayloadSize(500);
sender->SendPacket(media_packet.get(), PacedPacketInfo());
std::unique_ptr<RtpPacketToSend> fec_packet = BuildRtpPacket();
fec_packet->set_packet_type(RtpPacketMediaType::kForwardErrorCorrection);
fec_packet->SetPayloadSize(123);
sender->SendPacket(fec_packet.get(), PacedPacketInfo());
total_fec_data_sent += DataSize::Bytes(fec_packet->size());
time_controller_.AdvanceTime(kTimeBetweenPackets);
}
EXPECT_NEAR(
(sender->GetSendRates()[RtpPacketMediaType::kForwardErrorCorrection])
.bps(),
(total_fec_data_sent / (kTimeBetweenPackets * kNumPackets)).bps(), 500);
}
TEST_P(RtpSenderEgressTest, BitrateCallbacks) {
class MockBitrateStaticsObserver : public BitrateStatisticsObserver {
public:
MOCK_METHOD(void, Notify, (uint32_t, uint32_t, uint32_t), (override));
} observer;
RtpRtcpInterface::Configuration config = DefaultConfig();
config.send_bitrate_observer = &observer;
auto sender = std::make_unique<RtpSenderEgress>(config, &packet_history_);
// Simulate kNumPackets sent with kPacketInterval intervals, with the
// number of packets selected so that we fill (but don't overflow) the one
// second averaging window.
const TimeDelta kWindowSize = TimeDelta::Seconds(1);
const TimeDelta kPacketInterval = TimeDelta::Millis(20);
const int kNumPackets = (kWindowSize - kPacketInterval) / kPacketInterval;
DataSize total_data_sent = DataSize::Zero();
// Send all but on of the packets, expect a call for each packet but don't
// verify bitrate yet (noisy measurements in the beginning).
for (int i = 0; i < kNumPackets; ++i) {
std::unique_ptr<RtpPacketToSend> packet = BuildRtpPacket();
packet->SetPayloadSize(500);
// Mark all packets as retransmissions - will cause total and retransmission
// rates to be equal.
packet->set_packet_type(RtpPacketMediaType::kRetransmission);
total_data_sent += DataSize::Bytes(packet->size());
EXPECT_CALL(observer, Notify(_, _, kSsrc))
.WillOnce([&](uint32_t total_bitrate_bps,
uint32_t retransmission_bitrate_bps, uint32_t /*ssrc*/) {
TimeDelta window_size = i * kPacketInterval + TimeDelta::Millis(1);
// If there is just a single data point, there is no well defined
// averaging window so a bitrate of zero will be reported.
const double expected_bitrate_bps =
i == 0 ? 0.0 : (total_data_sent / window_size).bps();
EXPECT_NEAR(total_bitrate_bps, expected_bitrate_bps, 500);
EXPECT_NEAR(retransmission_bitrate_bps, expected_bitrate_bps, 500);
});
sender->SendPacket(packet.get(), PacedPacketInfo());
time_controller_.AdvanceTime(kPacketInterval);
}
}
INSTANTIATE_TEST_SUITE_P(WithAndWithoutOverhead,
RtpSenderEgressTest,
::testing::Values(TestConfig(false),

View File

@ -72,8 +72,6 @@ const uint64_t kStartTime = 123456789;
const size_t kMaxPaddingSize = 224u;
const uint8_t kPayloadData[] = {47, 11, 32, 93, 89};
const int64_t kDefaultExpectedRetransmissionTimeMs = 125;
const char kNoRid[] = "";
const char kNoMid[] = "";
const size_t kMaxPaddingLength = 224; // Value taken from rtp_sender.cc.
const uint32_t kTimestampTicksPerMs = 90; // 90kHz clock.
@ -775,6 +773,7 @@ TEST_P(RtpSenderTestWithoutPacer, RidIncludedOnSentPackets) {
TEST_P(RtpSenderTestWithoutPacer, RidIncludedOnRtxSentPackets) {
const char kRid[] = "f";
const char kNoRid[] = "";
EnableRtx();
EnableRidSending(kRid);
@ -1012,147 +1011,6 @@ TEST_P(RtpSenderTestWithoutPacer,
EXPECT_FALSE(rtx_packet.HasExtension<RepairedRtpStreamId>());
}
TEST_P(RtpSenderTest, FecOverheadRate) {
constexpr uint32_t kTimestamp = 1234;
constexpr int kMediaPayloadType = 127;
constexpr VideoCodecType kCodecType = VideoCodecType::kVideoCodecGeneric;
constexpr int kFlexfecPayloadType = 118;
const std::vector<RtpExtension> kNoRtpExtensions;
const std::vector<RtpExtensionSize> kNoRtpExtensionSizes;
FlexfecSender flexfec_sender(kFlexfecPayloadType, kFlexFecSsrc, kSsrc, kNoMid,
kNoRtpExtensions, kNoRtpExtensionSizes,
nullptr /* rtp_state */, clock_);
// Reset |rtp_sender_| to use this FlexFEC instance.
SetUpRtpSender(false, false, false, &flexfec_sender);
FieldTrialBasedConfig field_trials;
RTPSenderVideo::Config video_config;
video_config.clock = clock_;
video_config.rtp_sender = rtp_sender();
video_config.fec_type = flexfec_sender.GetFecType();
video_config.fec_overhead_bytes = flexfec_sender.MaxPacketOverhead();
video_config.field_trials = &field_trials;
RTPSenderVideo rtp_sender_video(video_config);
// Parameters selected to generate a single FEC packet per media packet.
FecProtectionParams params;
params.fec_rate = 15;
params.max_fec_frames = 1;
params.fec_mask_type = kFecMaskRandom;
rtp_egress()->SetFecProtectionParameters(params, params);
constexpr size_t kNumMediaPackets = 10;
constexpr size_t kNumFecPackets = kNumMediaPackets;
constexpr int64_t kTimeBetweenPacketsMs = 10;
for (size_t i = 0; i < kNumMediaPackets; ++i) {
RTPVideoHeader video_header;
video_header.frame_type = VideoFrameType::kVideoFrameKey;
EXPECT_TRUE(rtp_sender_video.SendVideo(
kMediaPayloadType, kCodecType, kTimestamp, clock_->TimeInMilliseconds(),
kPayloadData, video_header, kDefaultExpectedRetransmissionTimeMs));
time_controller_.AdvanceTime(TimeDelta::Millis(kTimeBetweenPacketsMs));
}
constexpr size_t kRtpHeaderLength = 12;
constexpr size_t kFlexfecHeaderLength = 20;
constexpr size_t kGenericCodecHeaderLength = 1;
constexpr size_t kPayloadLength = sizeof(kPayloadData);
constexpr size_t kPacketLength = kRtpHeaderLength + kFlexfecHeaderLength +
kGenericCodecHeaderLength + kPayloadLength;
EXPECT_NEAR(
kNumFecPackets * kPacketLength * 8 /
(kNumFecPackets * kTimeBetweenPacketsMs / 1000.0f),
rtp_egress()
->GetSendRates()[RtpPacketMediaType::kForwardErrorCorrection]
.bps<double>(),
500);
}
TEST_P(RtpSenderTest, BitrateCallbacks) {
class TestCallback : public BitrateStatisticsObserver {
public:
TestCallback()
: BitrateStatisticsObserver(),
num_calls_(0),
ssrc_(0),
total_bitrate_(0),
retransmit_bitrate_(0) {}
~TestCallback() override = default;
void Notify(uint32_t total_bitrate,
uint32_t retransmit_bitrate,
uint32_t ssrc) override {
++num_calls_;
ssrc_ = ssrc;
total_bitrate_ = total_bitrate;
retransmit_bitrate_ = retransmit_bitrate;
}
uint32_t num_calls_;
uint32_t ssrc_;
uint32_t total_bitrate_;
uint32_t retransmit_bitrate_;
} callback;
RtpRtcpInterface::Configuration config;
config.clock = clock_;
config.outgoing_transport = &transport_;
config.local_media_ssrc = kSsrc;
config.send_bitrate_observer = &callback;
config.retransmission_rate_limiter = &retransmission_rate_limiter_;
rtp_sender_context_ =
std::make_unique<RtpSenderContext>(config, &time_controller_);
FieldTrialBasedConfig field_trials;
RTPSenderVideo::Config video_config;
video_config.clock = clock_;
video_config.rtp_sender = rtp_sender();
video_config.field_trials = &field_trials;
RTPSenderVideo rtp_sender_video(video_config);
const VideoCodecType kCodecType = VideoCodecType::kVideoCodecGeneric;
const uint8_t kPayloadType = 127;
// Simulate kNumPackets sent with kPacketInterval ms intervals, with the
// number of packets selected so that we fill (but don't overflow) the one
// second averaging window.
const uint32_t kWindowSizeMs = 1000;
const uint32_t kPacketInterval = 20;
const uint32_t kNumPackets =
(kWindowSizeMs - kPacketInterval) / kPacketInterval;
// Overhead = 12 bytes RTP header + 1 byte generic header.
const uint32_t kPacketOverhead = 13;
uint8_t payload[] = {47, 11, 32, 93, 89};
rtp_sender_context_->packet_history_.SetStorePacketsStatus(
RtpPacketHistory::StorageMode::kStoreAndCull, 1);
uint32_t ssrc = rtp_sender()->SSRC();
// Send a few frames.
RTPVideoHeader video_header;
for (uint32_t i = 0; i < kNumPackets; ++i) {
video_header.frame_type = VideoFrameType::kVideoFrameKey;
ASSERT_TRUE(rtp_sender_video.SendVideo(
kPayloadType, kCodecType, 1234, 4321, payload, video_header,
kDefaultExpectedRetransmissionTimeMs));
time_controller_.AdvanceTime(TimeDelta::Millis(kPacketInterval));
}
// We get one call for every stats updated, thus two calls since both the
// stream stats and the retransmit stats are updated once.
EXPECT_EQ(kNumPackets, callback.num_calls_);
EXPECT_EQ(ssrc, callback.ssrc_);
const uint32_t kTotalPacketSize = kPacketOverhead + sizeof(payload);
// Bitrate measured over delta between last and first timestamp, plus one.
const uint32_t kExpectedWindowMs = (kNumPackets - 1) * kPacketInterval + 1;
const uint32_t kExpectedBitsAccumulated = kTotalPacketSize * kNumPackets * 8;
const uint32_t kExpectedRateBps =
(kExpectedBitsAccumulated * 1000 + (kExpectedWindowMs / 2)) /
kExpectedWindowMs;
EXPECT_EQ(kExpectedRateBps, callback.total_bitrate_);
}
TEST_P(RtpSenderTestWithoutPacer, StreamDataCountersCallbacks) {
const uint8_t kPayloadType = 127;
const VideoCodecType kCodecType = VideoCodecType::kVideoCodecGeneric;