In ReportBlockData expose RTCP report block properties directly

These accessors would allow to deprecated report_block() accessor and
then would allow to remove redundant RTCPReportBlock and ReportBlock types converging on single
ReportBlockData type to pass that information across WebRTC components

helpers like fraction_lost() and jitter() would also allow to unify conversion of the rtp specific format into more common way of represent such information

Bug: None
Change-Id: I3c97f96affcf83b529095899bd63af007f8b4014
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/303880
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39975}
This commit is contained in:
Danil Chapovalov 2023-05-03 09:32:01 +02:00 committed by WebRTC LUCI CQ
parent b03c4a5437
commit d3eddff30c
4 changed files with 114 additions and 82 deletions

View File

@ -10,10 +10,15 @@
#include "modules/rtp_rtcp/include/report_block_data.h"
#include "rtc_base/checks.h"
namespace webrtc {
TimeDelta ReportBlockData::AvgRtt() const {
return num_rtts_ > 0 ? sum_rtt_ / num_rtts_ : TimeDelta::Zero();
TimeDelta ReportBlockData::jitter(int rtp_clock_rate_hz) const {
RTC_DCHECK_GT(rtp_clock_rate_hz, 0);
// Conversion to TimeDelta and division are swapped to avoid conversion
// to/from floating point types.
return TimeDelta::Seconds(jitter()) / rtp_clock_rate_hz;
}
void ReportBlockData::SetReportBlock(uint32_t sender_ssrc,

View File

@ -18,6 +18,9 @@
namespace webrtc {
// Represents fields and derived information received in RTCP report block
// attached to RTCP sender report or RTCP receiver report, as described in
// https://www.rfc-editor.org/rfc/rfc3550#section-6.4.1
class ReportBlockData {
public:
ReportBlockData() = default;
@ -25,6 +28,50 @@ class ReportBlockData {
ReportBlockData(const ReportBlockData&) = default;
ReportBlockData& operator=(const ReportBlockData&) = default;
// The SSRC identifier for the originator of this report block,
// i.e. remote receiver of the RTP stream.
uint32_t sender_ssrc() const { return report_block_.sender_ssrc; }
// The SSRC identifier of the source to which the information in this
// reception report block pertains, i.e. local sender of the RTP stream.
uint32_t source_ssrc() const { return report_block_.source_ssrc; }
// The fraction of RTP data packets from 'source_ssrc()' lost since the
// previous report block was sent.
// Fraction loss in range [0.0, 1.0].
float fraction_lost() const { return fraction_lost_raw() / 256.0; }
// Fraction loss as was written in the raw packet: range is [0, 255] where 0
// represents no loss, and 255 represents 99.6% loss (255/256 * 100%).
uint8_t fraction_lost_raw() const { return report_block_.fraction_lost; }
// The total number of RTP data packets from 'source_ssrc()' that have been
// lost since the beginning of reception. This number is defined to be the
// number of packets expected less the number of packets actually received,
// where the number of packets received includes any which are late or
// duplicates. Thus, packets that arrive late are not counted as lost, and the
// loss may be negative if there are duplicates.
int cumulative_lost() const { return report_block_.packets_lost; }
// The low 16 bits contain the highest sequence number received in an RTP data
// packet from 'source_ssrc()', and the most significant 16 bits extend that
// sequence number with the corresponding count of sequence number cycles.
uint32_t extended_highest_sequence_number() const {
return report_block_.extended_highest_sequence_number;
}
// An estimate of the statistical variance of the RTP data packet interarrival
// time, measured in RTP timestamp units. The interarrival jitter J is defined
// to be the mean deviation (smoothed absolute value) of the difference D in
// packet spacing at the receiver compared to the sender for a pair of
// packets.
uint32_t jitter() const { return report_block_.jitter; }
// Jitter converted to common time units.
TimeDelta jitter(int rtp_clock_rate_hz) const;
// TODO(danilchap): Deprecate in favor of using ReportBlockData accessors
// directly.
const RTCPReportBlock& report_block() const { return report_block_; }
[[deprecated]] int64_t report_block_timestamp_utc_us() const {
@ -34,11 +81,14 @@ class ReportBlockData {
[[deprecated]] int64_t min_rtt_ms() const { return min_rtt_.ms(); }
[[deprecated]] int64_t max_rtt_ms() const { return max_rtt_.ms(); }
[[deprecated]] int64_t sum_rtt_ms() const { return sum_rtt_.ms(); }
[[deprecated]] double AvgRttMs() const { return AvgRtt().ms<double>(); }
// Time in utc epoch (Jan 1st, 1970) the report block was received.
Timestamp report_block_timestamp_utc() const {
return report_block_timestamp_utc_;
}
// Round Trip Time measurments for given (sender_ssrc, source_ssrc) pair.
// Min, max, sum, number of measurements are since beginning of the call.
TimeDelta last_rtt() const { return last_rtt_; }
TimeDelta min_rtt() const { return min_rtt_; }
TimeDelta max_rtt() const { return max_rtt_; }
@ -46,11 +96,9 @@ class ReportBlockData {
size_t num_rtts() const { return num_rtts_; }
bool has_rtt() const { return num_rtts_ != 0; }
TimeDelta AvgRtt() const;
void SetReportBlock(uint32_t sender_ssrc,
const rtcp::ReportBlock& report_block,
Timestamp report_block_timestamp_utc_us);
Timestamp report_block_timestamp_utc);
void AddRoundTripTimeSample(TimeDelta rtt);
private:

View File

@ -612,7 +612,7 @@ void RTCPReceiver::HandleReportBlock(const ReportBlock& report_block,
ReportBlockData* report_block_data =
&received_report_blocks_[report_block.source_ssrc()];
if (report_block.extended_high_seq_num() >
report_block_data->report_block().extended_highest_sequence_number) {
report_block_data->extended_highest_sequence_number()) {
// We have successfully delivered new RTP packets to the remote side after
// the last RR was sent from the remote side.
last_increased_sequence_number_ = last_received_rb_;
@ -806,7 +806,7 @@ bool RTCPReceiver::HandleBye(const CommonHeader& rtcp_block) {
// Clear our lists.
rtts_.erase(bye.sender_ssrc());
EraseIf(received_report_blocks_, [&](const auto& elem) {
return elem.second.report_block().sender_ssrc == bye.sender_ssrc();
return elem.second.sender_ssrc() == bye.sender_ssrc();
});
TmmbrInformation* tmmbr_info = GetTmmbrInformation(bye.sender_ssrc());

View File

@ -441,12 +441,10 @@ TEST(RtcpReceiverTest, InjectRrPacketWithTwoReportBlocks) {
receiver.IncomingPacket(rr1.Build());
EXPECT_EQ(now, receiver.LastReceivedReportBlockMs());
EXPECT_THAT(receiver.GetLatestReportBlockData(),
UnorderedElementsAre(
Property(&ReportBlockData::report_block,
Field(&RTCPReportBlock::fraction_lost, 0)),
Property(&ReportBlockData::report_block,
Field(&RTCPReportBlock::fraction_lost, 10))));
EXPECT_THAT(
receiver.GetLatestReportBlockData(),
UnorderedElementsAre(Property(&ReportBlockData::fraction_lost_raw, 0),
Property(&ReportBlockData::fraction_lost_raw, 10)));
// Insert next receiver report with same ssrc but new values.
rtcp::ReportBlock rb3;
@ -478,20 +476,16 @@ TEST(RtcpReceiverTest, InjectRrPacketWithTwoReportBlocks) {
EXPECT_THAT(
receiver.GetLatestReportBlockData(),
UnorderedElementsAre(
Property(
&ReportBlockData::report_block,
AllOf(Field(&RTCPReportBlock::source_ssrc, kReceiverMainSsrc),
Field(&RTCPReportBlock::fraction_lost, kFracLost[0]),
Field(&RTCPReportBlock::packets_lost, kCumLost[0]),
Field(&RTCPReportBlock::extended_highest_sequence_number,
kSequenceNumbers[0]))),
Property(
&ReportBlockData::report_block,
AllOf(Field(&RTCPReportBlock::source_ssrc, kReceiverExtraSsrc),
Field(&RTCPReportBlock::fraction_lost, kFracLost[1]),
Field(&RTCPReportBlock::packets_lost, kCumLost[1]),
Field(&RTCPReportBlock::extended_highest_sequence_number,
kSequenceNumbers[1])))));
AllOf(Property(&ReportBlockData::source_ssrc, kReceiverMainSsrc),
Property(&ReportBlockData::fraction_lost_raw, kFracLost[0]),
Property(&ReportBlockData::cumulative_lost, kCumLost[0]),
Property(&ReportBlockData::extended_highest_sequence_number,
kSequenceNumbers[0])),
AllOf(Property(&ReportBlockData::source_ssrc, kReceiverExtraSsrc),
Property(&ReportBlockData::fraction_lost_raw, kFracLost[1]),
Property(&ReportBlockData::cumulative_lost, kCumLost[1]),
Property(&ReportBlockData::extended_highest_sequence_number,
kSequenceNumbers[1]))));
}
TEST(RtcpReceiverTest,
@ -522,16 +516,14 @@ TEST(RtcpReceiverTest,
EXPECT_EQ(now, receiver.LastReceivedReportBlockMs());
EXPECT_THAT(
receiver.GetLatestReportBlockData(),
ElementsAre(Property(
&ReportBlockData::report_block,
AllOf(Field(&RTCPReportBlock::source_ssrc, kReceiverMainSsrc),
Field(&RTCPReportBlock::sender_ssrc, kSenderSsrc),
Field(&RTCPReportBlock::fraction_lost, kFracLost[0]),
Field(&RTCPReportBlock::packets_lost, kCumLost[0]),
Field(&RTCPReportBlock::extended_highest_sequence_number,
kSequenceNumbers[0])))));
EXPECT_THAT(receiver.GetLatestReportBlockData(),
ElementsAre(AllOf(
Property(&ReportBlockData::source_ssrc, kReceiverMainSsrc),
Property(&ReportBlockData::sender_ssrc, kSenderSsrc),
Property(&ReportBlockData::fraction_lost_raw, kFracLost[0]),
Property(&ReportBlockData::cumulative_lost, kCumLost[0]),
Property(&ReportBlockData::extended_highest_sequence_number,
kSequenceNumbers[0]))));
rtcp::ReportBlock rb2;
rb2.SetMediaSsrc(kReceiverMainSsrc);
@ -547,16 +539,14 @@ TEST(RtcpReceiverTest,
OnReceivedRtcpReceiverReport(SizeIs(1), _, now));
receiver.IncomingPacket(rr2.Build());
EXPECT_THAT(
receiver.GetLatestReportBlockData(),
UnorderedElementsAre(Property(
&ReportBlockData::report_block,
AllOf(Field(&RTCPReportBlock::source_ssrc, kReceiverMainSsrc),
Field(&RTCPReportBlock::sender_ssrc, kSenderSsrc2),
Field(&RTCPReportBlock::fraction_lost, kFracLost[1]),
Field(&RTCPReportBlock::packets_lost, kCumLost[1]),
Field(&RTCPReportBlock::extended_highest_sequence_number,
kSequenceNumbers[1])))));
EXPECT_THAT(receiver.GetLatestReportBlockData(),
UnorderedElementsAre(AllOf(
Property(&ReportBlockData::source_ssrc, kReceiverMainSsrc),
Property(&ReportBlockData::sender_ssrc, kSenderSsrc2),
Property(&ReportBlockData::fraction_lost_raw, kFracLost[1]),
Property(&ReportBlockData::cumulative_lost, kCumLost[1]),
Property(&ReportBlockData::extended_highest_sequence_number,
kSequenceNumbers[1]))));
}
TEST(RtcpReceiverTest, GetRtt) {
@ -1573,19 +1563,18 @@ TEST(RtcpReceiverTest,
rtcp_report.SetSenderSsrc(kSenderSsrc);
rtcp_report.AddReportBlock(rtcp_block);
EXPECT_CALL(observer, OnReportBlockDataUpdated)
.WillOnce([&](ReportBlockData report_block_data) {
const auto& report_block = report_block_data.report_block();
EXPECT_EQ(rtcp_block.source_ssrc(), report_block.source_ssrc);
EXPECT_EQ(kSenderSsrc, report_block.sender_ssrc);
EXPECT_EQ(rtcp_block.fraction_lost(), report_block.fraction_lost);
EXPECT_EQ(rtcp_block.cumulative_lost(), report_block.packets_lost);
.WillOnce([&](ReportBlockData report_block) {
EXPECT_EQ(rtcp_block.source_ssrc(), report_block.source_ssrc());
EXPECT_EQ(kSenderSsrc, report_block.sender_ssrc());
EXPECT_EQ(rtcp_block.fraction_lost(), report_block.fraction_lost_raw());
EXPECT_EQ(rtcp_block.cumulative_lost(), report_block.cumulative_lost());
EXPECT_EQ(rtcp_block.extended_high_seq_num(),
report_block.extended_highest_sequence_number);
EXPECT_EQ(rtcp_block.jitter(), report_block.jitter);
EXPECT_EQ(report_block_data.report_block_timestamp_utc(),
report_block.extended_highest_sequence_number());
EXPECT_EQ(rtcp_block.jitter(), report_block.jitter());
EXPECT_EQ(report_block.report_block_timestamp_utc(),
Timestamp::Millis(kNtpNowMs));
// No RTT is calculated in this test.
EXPECT_EQ(0u, report_block_data.num_rtts());
EXPECT_EQ(0u, report_block.num_rtts());
});
EXPECT_CALL(mocks.rtp_rtcp_impl, OnReceivedRtcpReportBlocks);
EXPECT_CALL(mocks.bandwidth_observer, OnReceivedRtcpReceiverReport);
@ -1627,8 +1616,7 @@ TEST(RtcpReceiverTest, VerifyRttObtainedFromReportBlockDataObserver) {
InSequence sequence;
EXPECT_CALL(observer, OnReportBlockDataUpdated)
.WillOnce([&](ReportBlockData report_block_data) {
EXPECT_EQ(kReceiverMainSsrc,
report_block_data.report_block().source_ssrc);
EXPECT_EQ(kReceiverMainSsrc, report_block_data.source_ssrc());
EXPECT_EQ(1u, report_block_data.num_rtts());
EXPECT_EQ(kRtt, report_block_data.min_rtt());
EXPECT_EQ(kRtt, report_block_data.max_rtt());
@ -1637,8 +1625,7 @@ TEST(RtcpReceiverTest, VerifyRttObtainedFromReportBlockDataObserver) {
});
EXPECT_CALL(observer, OnReportBlockDataUpdated)
.WillOnce([](ReportBlockData report_block_data) {
EXPECT_EQ(kReceiverExtraSsrc,
report_block_data.report_block().source_ssrc);
EXPECT_EQ(kReceiverExtraSsrc, report_block_data.source_ssrc());
EXPECT_EQ(0u, report_block_data.num_rtts());
});
receiver.IncomingPacket(sr.Build());
@ -1664,11 +1651,9 @@ TEST(RtcpReceiverTest, GetReportBlockDataAfterOneReportBlock) {
auto report_block_datas = receiver.GetLatestReportBlockData();
ASSERT_THAT(report_block_datas, SizeIs(1));
EXPECT_EQ(kReceiverMainSsrc,
report_block_datas[0].report_block().source_ssrc);
EXPECT_EQ(
kSequenceNumber,
report_block_datas[0].report_block().extended_highest_sequence_number);
EXPECT_EQ(kReceiverMainSsrc, report_block_datas[0].source_ssrc());
EXPECT_EQ(kSequenceNumber,
report_block_datas[0].extended_highest_sequence_number());
}
TEST(RtcpReceiverTest, GetReportBlockDataAfterTwoReportBlocksOfSameSsrc) {
@ -1706,11 +1691,9 @@ TEST(RtcpReceiverTest, GetReportBlockDataAfterTwoReportBlocksOfSameSsrc) {
// Only the latest block should be returned.
auto report_block_datas = receiver.GetLatestReportBlockData();
ASSERT_THAT(report_block_datas, SizeIs(1));
EXPECT_EQ(kReceiverMainSsrc,
report_block_datas[0].report_block().source_ssrc);
EXPECT_EQ(
kSequenceNumber2,
report_block_datas[0].report_block().extended_highest_sequence_number);
EXPECT_EQ(kReceiverMainSsrc, report_block_datas[0].source_ssrc());
EXPECT_EQ(kSequenceNumber2,
report_block_datas[0].extended_highest_sequence_number());
}
TEST(RtcpReceiverTest, GetReportBlockDataAfterTwoReportBlocksOfDifferentSsrcs) {
@ -1747,16 +1730,12 @@ TEST(RtcpReceiverTest, GetReportBlockDataAfterTwoReportBlocksOfDifferentSsrcs) {
// Both report blocks should be returned.
auto report_block_datas = receiver.GetLatestReportBlockData();
ASSERT_THAT(report_block_datas, SizeIs(2));
EXPECT_EQ(kReceiverMainSsrc,
report_block_datas[0].report_block().source_ssrc);
EXPECT_EQ(
kSequenceNumber1,
report_block_datas[0].report_block().extended_highest_sequence_number);
EXPECT_EQ(kReceiverExtraSsrc,
report_block_datas[1].report_block().source_ssrc);
EXPECT_EQ(
kSequenceNumber2,
report_block_datas[1].report_block().extended_highest_sequence_number);
EXPECT_EQ(kReceiverMainSsrc, report_block_datas[0].source_ssrc());
EXPECT_EQ(kSequenceNumber1,
report_block_datas[0].extended_highest_sequence_number());
EXPECT_EQ(kReceiverExtraSsrc, report_block_datas[1].source_ssrc());
EXPECT_EQ(kSequenceNumber2,
report_block_datas[1].extended_highest_sequence_number());
}
TEST(RtcpReceiverTest, ReceivesTransportFeedback) {