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:
parent
8d3d6cf908
commit
f204787478
@ -11,6 +11,7 @@ import("../../webrtc.gni")
|
||||
rtc_source_set("rtp_rtcp_format") {
|
||||
visibility = [ "*" ]
|
||||
public = [
|
||||
"include/report_block_data.h",
|
||||
"include/rtcp_statistics.h",
|
||||
"include/rtp_cvo.h",
|
||||
"include/rtp_header_extension_map.h",
|
||||
@ -50,6 +51,7 @@ rtc_source_set("rtp_rtcp_format") {
|
||||
"source/rtp_packet_to_send.h",
|
||||
]
|
||||
sources = [
|
||||
"include/report_block_data.cc",
|
||||
"include/rtp_rtcp_defines.cc",
|
||||
"source/rtcp_packet.cc",
|
||||
"source/rtcp_packet/app.cc",
|
||||
@ -446,6 +448,7 @@ if (rtc_include_tests) {
|
||||
"../../api:scoped_refptr",
|
||||
"../../api:transport_api",
|
||||
"../../api/transport:field_trial_based_config",
|
||||
"../../api/units:timestamp",
|
||||
"../../api/video:video_bitrate_allocation",
|
||||
"../../api/video:video_bitrate_allocator",
|
||||
"../../api/video:video_codec_constants",
|
||||
|
||||
44
modules/rtp_rtcp/include/report_block_data.cc
Normal file
44
modules/rtp_rtcp/include/report_block_data.cc
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2019 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "modules/rtp_rtcp/include/report_block_data.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
ReportBlockData::ReportBlockData()
|
||||
: report_block_(),
|
||||
report_block_timestamp_utc_us_(0),
|
||||
last_rtt_ms_(0),
|
||||
min_rtt_ms_(0),
|
||||
max_rtt_ms_(0),
|
||||
sum_rtt_ms_(0),
|
||||
num_rtts_(0) {}
|
||||
|
||||
double ReportBlockData::AvgRttMs() const {
|
||||
return num_rtts_ ? static_cast<double>(sum_rtt_ms_) / num_rtts_ : 0.0;
|
||||
}
|
||||
|
||||
void ReportBlockData::SetReportBlock(RTCPReportBlock report_block,
|
||||
int64_t report_block_timestamp_utc_us) {
|
||||
report_block_ = report_block;
|
||||
report_block_timestamp_utc_us_ = report_block_timestamp_utc_us;
|
||||
}
|
||||
|
||||
void ReportBlockData::AddRoundTripTimeSample(int64_t rtt_ms) {
|
||||
if (rtt_ms > max_rtt_ms_)
|
||||
max_rtt_ms_ = rtt_ms;
|
||||
if (num_rtts_ == 0 || rtt_ms < min_rtt_ms_)
|
||||
min_rtt_ms_ = rtt_ms;
|
||||
last_rtt_ms_ = rtt_ms;
|
||||
sum_rtt_ms_ += rtt_ms;
|
||||
++num_rtts_;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
59
modules/rtp_rtcp/include/report_block_data.h
Normal file
59
modules/rtp_rtcp/include/report_block_data.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2019 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_RTP_RTCP_INCLUDE_REPORT_BLOCK_DATA_H_
|
||||
#define MODULES_RTP_RTCP_INCLUDE_REPORT_BLOCK_DATA_H_
|
||||
|
||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ReportBlockData {
|
||||
public:
|
||||
ReportBlockData();
|
||||
|
||||
const RTCPReportBlock& report_block() const { return report_block_; }
|
||||
int64_t report_block_timestamp_utc_us() const {
|
||||
return report_block_timestamp_utc_us_;
|
||||
}
|
||||
int64_t last_rtt_ms() const { return last_rtt_ms_; }
|
||||
int64_t min_rtt_ms() const { return min_rtt_ms_; }
|
||||
int64_t max_rtt_ms() const { return max_rtt_ms_; }
|
||||
int64_t sum_rtt_ms() const { return sum_rtt_ms_; }
|
||||
size_t num_rtts() const { return num_rtts_; }
|
||||
bool has_rtt() const { return num_rtts_ != 0; }
|
||||
|
||||
double AvgRttMs() const;
|
||||
|
||||
void SetReportBlock(RTCPReportBlock report_block,
|
||||
int64_t report_block_timestamp_utc_us);
|
||||
void AddRoundTripTimeSample(int64_t rtt_ms);
|
||||
|
||||
private:
|
||||
RTCPReportBlock report_block_;
|
||||
int64_t report_block_timestamp_utc_us_;
|
||||
|
||||
int64_t last_rtt_ms_;
|
||||
int64_t min_rtt_ms_;
|
||||
int64_t max_rtt_ms_;
|
||||
int64_t sum_rtt_ms_;
|
||||
size_t num_rtts_;
|
||||
};
|
||||
|
||||
class ReportBlockDataObserver {
|
||||
public:
|
||||
virtual ~ReportBlockDataObserver() = default;
|
||||
|
||||
virtual void OnReportBlockDataUpdated(ReportBlockData report_block_data) = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_RTP_RTCP_INCLUDE_REPORT_BLOCK_DATA_H_
|
||||
@ -42,6 +42,7 @@
|
||||
#include "modules/rtp_rtcp/source/tmmbr_help.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/time_utils.h"
|
||||
#include "rtc_base/trace_event.h"
|
||||
#include "system_wrappers/include/ntp_time.h"
|
||||
|
||||
@ -69,7 +70,9 @@ struct RTCPReceiver::PacketInformation {
|
||||
|
||||
uint32_t remote_ssrc = 0;
|
||||
std::vector<uint16_t> nack_sequence_numbers;
|
||||
// TODO(hbos): Remove |report_blocks| in favor of |report_block_datas|.
|
||||
ReportBlockList report_blocks;
|
||||
std::vector<ReportBlockData> report_block_datas;
|
||||
int64_t rtt_ms = 0;
|
||||
uint32_t receiver_estimated_max_bitrate_bps = 0;
|
||||
std::unique_ptr<rtcp::TransportFeedback> transport_feedback;
|
||||
@ -108,16 +111,6 @@ struct RTCPReceiver::RrtrInformation {
|
||||
uint32_t local_receive_mid_ntp_time;
|
||||
};
|
||||
|
||||
struct RTCPReceiver::ReportBlockWithRtt {
|
||||
RTCPReportBlock report_block;
|
||||
|
||||
int64_t last_rtt_ms = 0;
|
||||
int64_t min_rtt_ms = 0;
|
||||
int64_t max_rtt_ms = 0;
|
||||
int64_t sum_rtt_ms = 0;
|
||||
size_t num_rtts = 0;
|
||||
};
|
||||
|
||||
struct RTCPReceiver::LastFirStatus {
|
||||
LastFirStatus(int64_t now_ms, uint8_t sequence_number)
|
||||
: request_ms(now_ms), sequence_number(sequence_number) {}
|
||||
@ -154,6 +147,7 @@ RTCPReceiver::RTCPReceiver(
|
||||
last_received_rb_ms_(0),
|
||||
last_increased_sequence_number_ms_(0),
|
||||
stats_callback_(nullptr),
|
||||
report_block_data_observer_(nullptr),
|
||||
packet_type_counter_observer_(packet_type_counter_observer),
|
||||
num_skipped_packets_(0),
|
||||
last_skipped_packets_warning_ms_(clock->TimeInMilliseconds()) {
|
||||
@ -213,22 +207,24 @@ int32_t RTCPReceiver::RTT(uint32_t remote_ssrc,
|
||||
if (it_info == it->second.end())
|
||||
return -1;
|
||||
|
||||
const ReportBlockWithRtt* report_block = &it_info->second;
|
||||
const ReportBlockData* report_block_data = &it_info->second;
|
||||
|
||||
if (report_block->num_rtts == 0)
|
||||
if (report_block_data->num_rtts() == 0)
|
||||
return -1;
|
||||
|
||||
if (last_rtt_ms)
|
||||
*last_rtt_ms = report_block->last_rtt_ms;
|
||||
*last_rtt_ms = report_block_data->last_rtt_ms();
|
||||
|
||||
if (avg_rtt_ms)
|
||||
*avg_rtt_ms = report_block->sum_rtt_ms / report_block->num_rtts;
|
||||
if (avg_rtt_ms) {
|
||||
*avg_rtt_ms =
|
||||
report_block_data->sum_rtt_ms() / report_block_data->num_rtts();
|
||||
}
|
||||
|
||||
if (min_rtt_ms)
|
||||
*min_rtt_ms = report_block->min_rtt_ms;
|
||||
*min_rtt_ms = report_block_data->min_rtt_ms();
|
||||
|
||||
if (max_rtt_ms)
|
||||
*max_rtt_ms = report_block->max_rtt_ms;
|
||||
*max_rtt_ms = report_block_data->max_rtt_ms();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -307,10 +303,19 @@ int32_t RTCPReceiver::StatisticsReceived(
|
||||
rtc::CritScope lock(&rtcp_receiver_lock_);
|
||||
for (const auto& reports_per_receiver : received_report_blocks_)
|
||||
for (const auto& report : reports_per_receiver.second)
|
||||
receive_blocks->push_back(report.second.report_block);
|
||||
receive_blocks->push_back(report.second.report_block());
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<ReportBlockData> RTCPReceiver::GetLatestReportBlockData() const {
|
||||
std::vector<ReportBlockData> result;
|
||||
rtc::CritScope lock(&rtcp_receiver_lock_);
|
||||
for (const auto& reports_per_receiver : received_report_blocks_)
|
||||
for (const auto& report : reports_per_receiver.second)
|
||||
result.push_back(report.second);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool RTCPReceiver::ParseCompoundPacket(const uint8_t* packet_begin,
|
||||
const uint8_t* packet_end,
|
||||
PacketInformation* packet_information) {
|
||||
@ -483,26 +488,26 @@ void RTCPReceiver::HandleReportBlock(const ReportBlock& report_block,
|
||||
|
||||
last_received_rb_ms_ = clock_->TimeInMilliseconds();
|
||||
|
||||
ReportBlockWithRtt* report_block_info =
|
||||
ReportBlockData* report_block_data =
|
||||
&received_report_blocks_[report_block.source_ssrc()][remote_ssrc];
|
||||
report_block_info->report_block.sender_ssrc = remote_ssrc;
|
||||
report_block_info->report_block.source_ssrc = report_block.source_ssrc();
|
||||
report_block_info->report_block.fraction_lost = report_block.fraction_lost();
|
||||
report_block_info->report_block.packets_lost =
|
||||
report_block.cumulative_lost_signed();
|
||||
RTCPReportBlock rtcp_report_block;
|
||||
rtcp_report_block.sender_ssrc = remote_ssrc;
|
||||
rtcp_report_block.source_ssrc = report_block.source_ssrc();
|
||||
rtcp_report_block.fraction_lost = report_block.fraction_lost();
|
||||
rtcp_report_block.packets_lost = report_block.cumulative_lost_signed();
|
||||
if (report_block.extended_high_seq_num() >
|
||||
report_block_info->report_block.extended_highest_sequence_number) {
|
||||
report_block_data->report_block().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_ms_ = clock_->TimeInMilliseconds();
|
||||
}
|
||||
report_block_info->report_block.extended_highest_sequence_number =
|
||||
rtcp_report_block.extended_highest_sequence_number =
|
||||
report_block.extended_high_seq_num();
|
||||
report_block_info->report_block.jitter = report_block.jitter();
|
||||
report_block_info->report_block.delay_since_last_sender_report =
|
||||
rtcp_report_block.jitter = report_block.jitter();
|
||||
rtcp_report_block.delay_since_last_sender_report =
|
||||
report_block.delay_since_last_sr();
|
||||
report_block_info->report_block.last_sender_report_timestamp =
|
||||
report_block.last_sr();
|
||||
rtcp_report_block.last_sender_report_timestamp = report_block.last_sr();
|
||||
report_block_data->SetReportBlock(rtcp_report_block, rtc::TimeUTCMicros());
|
||||
|
||||
int64_t rtt_ms = 0;
|
||||
uint32_t send_time_ntp = report_block.last_sr();
|
||||
@ -527,21 +532,14 @@ void RTCPReceiver::HandleReportBlock(const ReportBlock& report_block,
|
||||
uint32_t rtt_ntp = receive_time_ntp - delay_ntp - send_time_ntp;
|
||||
// Convert to 1/1000 seconds (milliseconds).
|
||||
rtt_ms = CompactNtpRttToMs(rtt_ntp);
|
||||
if (rtt_ms > report_block_info->max_rtt_ms)
|
||||
report_block_info->max_rtt_ms = rtt_ms;
|
||||
|
||||
if (report_block_info->num_rtts == 0 ||
|
||||
rtt_ms < report_block_info->min_rtt_ms)
|
||||
report_block_info->min_rtt_ms = rtt_ms;
|
||||
|
||||
report_block_info->last_rtt_ms = rtt_ms;
|
||||
report_block_info->sum_rtt_ms += rtt_ms;
|
||||
++report_block_info->num_rtts;
|
||||
report_block_data->AddRoundTripTimeSample(rtt_ms);
|
||||
|
||||
packet_information->rtt_ms = rtt_ms;
|
||||
}
|
||||
|
||||
packet_information->report_blocks.push_back(report_block_info->report_block);
|
||||
packet_information->report_blocks.push_back(
|
||||
report_block_data->report_block());
|
||||
packet_information->report_block_datas.push_back(*report_block_data);
|
||||
}
|
||||
|
||||
RTCPReceiver::TmmbrInformation* RTCPReceiver::FindOrCreateTmmbrInfo(
|
||||
@ -975,6 +973,12 @@ RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
|
||||
return stats_callback_;
|
||||
}
|
||||
|
||||
void RTCPReceiver::SetReportBlockDataObserver(
|
||||
ReportBlockDataObserver* observer) {
|
||||
rtc::CritScope cs(&feedbacks_lock_);
|
||||
report_block_data_observer_ = observer;
|
||||
}
|
||||
|
||||
// Holding no Critical section.
|
||||
void RTCPReceiver::TriggerCallbacksFromRtcpPacket(
|
||||
const PacketInformation& packet_information) {
|
||||
@ -1085,6 +1089,13 @@ void RTCPReceiver::TriggerCallbacksFromRtcpPacket(
|
||||
stats_callback_->StatisticsUpdated(stats, report_block.source_ssrc);
|
||||
}
|
||||
}
|
||||
if (report_block_data_observer_) {
|
||||
for (const auto& report_block_data :
|
||||
packet_information.report_block_datas) {
|
||||
report_block_data_observer_->OnReportBlockDataUpdated(
|
||||
report_block_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "modules/rtp_rtcp/include/report_block_data.h"
|
||||
#include "modules/rtp_rtcp/include/rtcp_statistics.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
#include "modules/rtp_rtcp/source/rtcp_nack_stats.h"
|
||||
@ -94,6 +95,11 @@ class RTCPReceiver {
|
||||
|
||||
// Get statistics.
|
||||
int32_t StatisticsReceived(std::vector<RTCPReportBlock>* receiveBlocks) const;
|
||||
// A snapshot of Report Blocks with additional data of interest to statistics.
|
||||
// Within this list, the sender-source SSRC pair is unique and per-pair the
|
||||
// ReportBlockData represents the latest Report Block that was received for
|
||||
// that pair.
|
||||
std::vector<ReportBlockData> GetLatestReportBlockData() const;
|
||||
|
||||
// Returns true if we haven't received an RTCP RR for several RTCP
|
||||
// intervals, but only triggers true once.
|
||||
@ -114,17 +120,17 @@ class RTCPReceiver {
|
||||
|
||||
void RegisterRtcpStatisticsCallback(RtcpStatisticsCallback* callback);
|
||||
RtcpStatisticsCallback* GetRtcpStatisticsCallback();
|
||||
void SetReportBlockDataObserver(ReportBlockDataObserver* observer);
|
||||
|
||||
private:
|
||||
struct PacketInformation;
|
||||
struct TmmbrInformation;
|
||||
struct RrtrInformation;
|
||||
struct ReportBlockWithRtt;
|
||||
struct LastFirStatus;
|
||||
// RTCP report blocks mapped by remote SSRC.
|
||||
using ReportBlockInfoMap = std::map<uint32_t, ReportBlockWithRtt>;
|
||||
using ReportBlockDataMap = std::map<uint32_t, ReportBlockData>;
|
||||
// RTCP report blocks map mapped by source SSRC.
|
||||
using ReportBlockMap = std::map<uint32_t, ReportBlockInfoMap>;
|
||||
using ReportBlockMap = std::map<uint32_t, ReportBlockDataMap>;
|
||||
|
||||
bool ParseCompoundPacket(const uint8_t* packet_begin,
|
||||
const uint8_t* packet_end,
|
||||
@ -262,6 +268,11 @@ class RTCPReceiver {
|
||||
int64_t last_increased_sequence_number_ms_;
|
||||
|
||||
RtcpStatisticsCallback* stats_callback_ RTC_GUARDED_BY(feedbacks_lock_);
|
||||
// TODO(hbos): Remove RtcpStatisticsCallback in favor of
|
||||
// ReportBlockDataObserver; the ReportBlockData contains a superset of the
|
||||
// RtcpStatistics data.
|
||||
ReportBlockDataObserver* report_block_data_observer_
|
||||
RTC_GUARDED_BY(feedbacks_lock_);
|
||||
|
||||
RtcpPacketTypeCounterObserver* const packet_type_counter_observer_;
|
||||
RtcpPacketTypeCounter packet_type_counter_;
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user