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:
parent
63b3095d2b
commit
e2b9fc6909
@ -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),
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user