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:
committed by
Commit Bot
parent
8d3d6cf908
commit
f204787478
@ -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);
|
||||
|
||||
Reference in New Issue
Block a user