ReportBlockData and observer added, for stats collection in future CLs.

The ReportBlockData contains information about a ReportBlock and
additional data such as RTT. This will be used for the calculation of
RTCRemoteInboundRtpStreamStats, see full picture here:
https://webrtc-review.googlesource.com/c/src/+/134107

ReportBlockData is a class version of the previously internal struct
RTCPReceiver::ReportBlockWithRtt.
- The new name makes sense even if we add more info to it, which will
  be needed for future metrics.
- The new location is modules/rtp_rtcp/include/report_block_data.h.

The RTCPReceiver allows obtaining the ReportBlockData in two ways:
1. Using a ReportBlockDataObserver that is notified on receiving a
   report block.
2. Using the GetLatestReportBlockData().

Both codepaths will be needed; video stats uses observers and audio
stats uses polling.

Further plumbing will be done in follow-up CLs.

Bug: webrtc:10455, webrtc:10456
Change-Id: Ic9e5b4f451b5f4b203efcd6fa3bbf9736487e1f4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/136584
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27961}
This commit is contained in:
Henrik Boström
2019-05-16 13:32:20 +02:00
committed by Commit Bot
parent 8d3d6cf908
commit f204787478
6 changed files with 377 additions and 45 deletions

View File

@ -11,8 +11,10 @@
#include <memory>
#include "api/array_view.h"
#include "api/units/timestamp.h"
#include "api/video/video_bitrate_allocation.h"
#include "api/video/video_bitrate_allocator.h"
#include "modules/rtp_rtcp/include/report_block_data.h"
#include "modules/rtp_rtcp/mocks/mock_rtcp_bandwidth_observer.h"
#include "modules/rtp_rtcp/source/byte_io.h"
#include "modules/rtp_rtcp/source/rtcp_packet.h"
@ -34,6 +36,7 @@
#include "modules/rtp_rtcp/source/rtcp_receiver.h"
#include "modules/rtp_rtcp/source/time_util.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/fake_clock.h"
#include "rtc_base/random.h"
#include "system_wrappers/include/ntp_time.h"
#include "test/gmock.h"
@ -42,10 +45,12 @@
namespace webrtc {
namespace {
using rtcp::ReceiveTimeInfo;
using ::testing::_;
using ::testing::AllOf;
using ::testing::ElementsAreArray;
using ::testing::Field;
using ::testing::InSequence;
using ::testing::IsEmpty;
using ::testing::NiceMock;
using ::testing::Property;
@ -53,7 +58,6 @@ using ::testing::SizeIs;
using ::testing::StrEq;
using ::testing::StrictMock;
using ::testing::UnorderedElementsAre;
using rtcp::ReceiveTimeInfo;
class MockRtcpPacketTypeCounterObserver : public RtcpPacketTypeCounterObserver {
public:
@ -82,6 +86,11 @@ class MockRtcpCallbackImpl : public RtcpStatisticsCallback {
MOCK_METHOD2(CNameChanged, void(const char*, uint32_t));
};
class MockReportBlockDataObserverImpl : public ReportBlockDataObserver {
public:
MOCK_METHOD1(OnReportBlockDataUpdated, void(ReportBlockData));
};
class MockTransportFeedbackObserver : public TransportFeedbackObserver {
public:
MOCK_METHOD1(OnAddPacket, void(const RtpPacketSendInfo&));
@ -1176,6 +1185,201 @@ TEST_F(RtcpReceiverTest, Callbacks) {
InjectRtcpPacket(rr2);
}
TEST_F(RtcpReceiverTest,
VerifyBlockAndTimestampObtainedFromReportBlockDataObserver) {
MockReportBlockDataObserverImpl observer;
rtcp_receiver_.SetReportBlockDataObserver(&observer);
const uint8_t kFractionLoss = 3;
const uint32_t kCumulativeLoss = 7;
const uint32_t kJitter = 9;
const uint16_t kSequenceNumber = 1234;
const int64_t kUtcNowUs = 42;
// The "report_block_timestamp_utc_us" is obtained from the global UTC clock
// (not the simulcated |system_clock_|) and requires a scoped fake clock.
rtc::ScopedFakeClock fake_clock;
fake_clock.SetTime(Timestamp::us(kUtcNowUs));
rtcp::ReportBlock rtcp_block;
rtcp_block.SetMediaSsrc(kReceiverMainSsrc);
rtcp_block.SetExtHighestSeqNum(kSequenceNumber);
rtcp_block.SetFractionLost(kFractionLoss);
rtcp_block.SetCumulativeLost(kCumulativeLoss);
rtcp_block.SetJitter(kJitter);
rtcp::ReceiverReport rtcp_report;
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_signed(),
report_block.packets_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(kUtcNowUs, report_block_data.report_block_timestamp_utc_us());
// No RTT is calculated in this test.
EXPECT_EQ(0u, report_block_data.num_rtts());
});
EXPECT_CALL(rtp_rtcp_impl_, OnReceivedRtcpReportBlocks);
EXPECT_CALL(bandwidth_observer_, OnReceivedRtcpReceiverReport);
InjectRtcpPacket(rtcp_report);
}
TEST_F(RtcpReceiverTest, VerifyRttObtainedFromReportBlockDataObserver) {
MockReportBlockDataObserverImpl observer;
rtcp_receiver_.SetReportBlockDataObserver(&observer);
const int64_t kRttMs = 120;
const uint32_t kDelayNtp = 123000;
const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp);
uint32_t sent_ntp =
CompactNtp(TimeMicrosToNtp(system_clock_.TimeInMicroseconds()));
system_clock_.AdvanceTimeMilliseconds(kRttMs + kDelayMs);
rtcp::SenderReport sr;
sr.SetSenderSsrc(kSenderSsrc);
rtcp::ReportBlock block;
block.SetMediaSsrc(kReceiverMainSsrc);
block.SetLastSr(sent_ntp);
block.SetDelayLastSr(kDelayNtp);
sr.AddReportBlock(block);
block.SetMediaSsrc(kReceiverExtraSsrc);
block.SetLastSr(0);
sr.AddReportBlock(block);
EXPECT_CALL(rtp_rtcp_impl_, OnReceivedRtcpReportBlocks);
EXPECT_CALL(bandwidth_observer_, OnReceivedRtcpReceiverReport);
InSequence sequence;
EXPECT_CALL(observer, OnReportBlockDataUpdated)
.WillOnce([&](ReportBlockData report_block_data) {
EXPECT_EQ(kReceiverMainSsrc,
report_block_data.report_block().source_ssrc);
EXPECT_EQ(1u, report_block_data.num_rtts());
EXPECT_EQ(kRttMs, report_block_data.min_rtt_ms());
EXPECT_EQ(kRttMs, report_block_data.max_rtt_ms());
EXPECT_EQ(kRttMs, report_block_data.sum_rtt_ms());
EXPECT_EQ(kRttMs, report_block_data.last_rtt_ms());
});
EXPECT_CALL(observer, OnReportBlockDataUpdated)
.WillOnce([](ReportBlockData report_block_data) {
EXPECT_EQ(kReceiverExtraSsrc,
report_block_data.report_block().source_ssrc);
EXPECT_EQ(0u, report_block_data.num_rtts());
});
InjectRtcpPacket(sr);
}
TEST_F(RtcpReceiverTest, GetReportBlockDataAfterOneReportBlock) {
const uint16_t kSequenceNumber = 1234;
rtcp::ReportBlock rtcp_block;
rtcp_block.SetMediaSsrc(kReceiverMainSsrc);
rtcp_block.SetExtHighestSeqNum(kSequenceNumber);
rtcp::ReceiverReport rtcp_report;
rtcp_report.SetSenderSsrc(kSenderSsrc);
rtcp_report.AddReportBlock(rtcp_block);
EXPECT_CALL(rtp_rtcp_impl_, OnReceivedRtcpReportBlocks);
EXPECT_CALL(bandwidth_observer_, OnReceivedRtcpReceiverReport);
InjectRtcpPacket(rtcp_report);
auto report_block_datas = rtcp_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);
}
TEST_F(RtcpReceiverTest, GetReportBlockDataAfterTwoReportBlocksOfSameSsrc) {
const uint16_t kSequenceNumber1 = 1234;
const uint16_t kSequenceNumber2 = 1235;
rtcp::ReportBlock rtcp_block1;
rtcp_block1.SetMediaSsrc(kReceiverMainSsrc);
rtcp_block1.SetExtHighestSeqNum(kSequenceNumber1);
rtcp::ReceiverReport rtcp_report1;
rtcp_report1.SetSenderSsrc(kSenderSsrc);
rtcp_report1.AddReportBlock(rtcp_block1);
EXPECT_CALL(rtp_rtcp_impl_, OnReceivedRtcpReportBlocks);
EXPECT_CALL(bandwidth_observer_, OnReceivedRtcpReceiverReport);
InjectRtcpPacket(rtcp_report1);
// Inject a report block with an increased the sequence number for the same
// source SSRC.
rtcp::ReportBlock rtcp_block2;
rtcp_block2.SetMediaSsrc(kReceiverMainSsrc);
rtcp_block2.SetExtHighestSeqNum(kSequenceNumber2);
rtcp::ReceiverReport rtcp_report2;
rtcp_report2.SetSenderSsrc(kSenderSsrc);
rtcp_report2.AddReportBlock(rtcp_block2);
EXPECT_CALL(rtp_rtcp_impl_, OnReceivedRtcpReportBlocks);
EXPECT_CALL(bandwidth_observer_, OnReceivedRtcpReceiverReport);
InjectRtcpPacket(rtcp_report2);
// Only the latest block should be returned.
auto report_block_datas = rtcp_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);
}
TEST_F(RtcpReceiverTest,
GetReportBlockDataAfterTwoReportBlocksOfDifferentSsrcs) {
const uint16_t kSequenceNumber1 = 1234;
const uint16_t kSequenceNumber2 = 42;
rtcp::ReportBlock rtcp_block1;
rtcp_block1.SetMediaSsrc(kReceiverMainSsrc);
rtcp_block1.SetExtHighestSeqNum(kSequenceNumber1);
rtcp::ReceiverReport rtcp_report1;
rtcp_report1.SetSenderSsrc(kSenderSsrc);
rtcp_report1.AddReportBlock(rtcp_block1);
EXPECT_CALL(rtp_rtcp_impl_, OnReceivedRtcpReportBlocks);
EXPECT_CALL(bandwidth_observer_, OnReceivedRtcpReceiverReport);
InjectRtcpPacket(rtcp_report1);
// Inject a report block for a different source SSRC.
rtcp::ReportBlock rtcp_block2;
rtcp_block2.SetMediaSsrc(kReceiverExtraSsrc);
rtcp_block2.SetExtHighestSeqNum(kSequenceNumber2);
rtcp::ReceiverReport rtcp_report2;
rtcp_report2.SetSenderSsrc(kSenderSsrc);
rtcp_report2.AddReportBlock(rtcp_block2);
EXPECT_CALL(rtp_rtcp_impl_, OnReceivedRtcpReportBlocks);
EXPECT_CALL(bandwidth_observer_, OnReceivedRtcpReceiverReport);
InjectRtcpPacket(rtcp_report2);
// Both report blocks should be returned.
auto report_block_datas = rtcp_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);
}
TEST_F(RtcpReceiverTest, ReceivesTransportFeedback) {
rtcp::TransportFeedback packet;
packet.SetMediaSsrc(kReceiverMainSsrc);