Add a mutex free implementation of webrtc::ReceiveStatistics

The mutex is removed from the old existing implementation and instead a wrapper is implemented that ensure thread-safety.
Both the thread-safe and unsafe version share the same implementation of the logic.

There are two ways of construction:
webrtc::ReceiveStatistics::Create - thread-safe version.
webrtc::ReceiveStatistics::CreateUnLocked -thread-unsafe

Bug: none
Change-Id: Ica375919fda70180335c8f9ea666497811daf866
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211240
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33419}
This commit is contained in:
Per Kjellander 2021-03-10 12:31:38 +01:00 committed by Commit Bot
parent bb22066e60
commit ee8cd20ec5
4 changed files with 225 additions and 115 deletions

View File

@ -55,7 +55,12 @@ class ReceiveStatistics : public ReceiveStatisticsProvider,
public:
~ReceiveStatistics() override = default;
// Returns a thread-safe instance of ReceiveStatistics.
// https://chromium.googlesource.com/chromium/src/+/lkgr/docs/threading_and_tasks.md#threading-lexicon
static std::unique_ptr<ReceiveStatistics> Create(Clock* clock);
// Returns a thread-compatible instance of ReceiveStatistics.
static std::unique_ptr<ReceiveStatistics> CreateThreadCompatible(
Clock* clock);
// Returns a pointer to the statistician of an ssrc.
virtual StreamStatistician* GetStatistician(uint32_t ssrc) const = 0;

View File

@ -13,6 +13,7 @@
#include <cmath>
#include <cstdlib>
#include <memory>
#include <utility>
#include <vector>
#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
@ -100,7 +101,6 @@ bool StreamStatisticianImpl::UpdateOutOfOrder(const RtpPacketReceived& packet,
}
void StreamStatisticianImpl::UpdateCounters(const RtpPacketReceived& packet) {
MutexLock lock(&stream_lock_);
RTC_DCHECK_EQ(ssrc_, packet.Ssrc());
int64_t now_ms = clock_->TimeInMilliseconds();
@ -159,17 +159,14 @@ void StreamStatisticianImpl::UpdateJitter(const RtpPacketReceived& packet,
void StreamStatisticianImpl::SetMaxReorderingThreshold(
int max_reordering_threshold) {
MutexLock lock(&stream_lock_);
max_reordering_threshold_ = max_reordering_threshold;
}
void StreamStatisticianImpl::EnableRetransmitDetection(bool enable) {
MutexLock lock(&stream_lock_);
enable_retransmit_detection_ = enable;
}
RtpReceiveStats StreamStatisticianImpl::GetStats() const {
MutexLock lock(&stream_lock_);
RtpReceiveStats stats;
stats.packets_lost = cumulative_loss_;
// TODO(nisse): Can we return a float instead?
@ -183,7 +180,6 @@ RtpReceiveStats StreamStatisticianImpl::GetStats() const {
bool StreamStatisticianImpl::GetActiveStatisticsAndReset(
RtcpStatistics* statistics) {
MutexLock lock(&stream_lock_);
if (clock_->TimeInMilliseconds() - last_receive_time_ms_ >=
kStatisticsTimeoutMs) {
// Not active.
@ -192,9 +188,7 @@ bool StreamStatisticianImpl::GetActiveStatisticsAndReset(
if (!ReceivedRtpPacket()) {
return false;
}
*statistics = CalculateRtcpStatistics();
return true;
}
@ -241,7 +235,6 @@ RtcpStatistics StreamStatisticianImpl::CalculateRtcpStatistics() {
}
absl::optional<int> StreamStatisticianImpl::GetFractionLostInPercent() const {
MutexLock lock(&stream_lock_);
if (!ReceivedRtpPacket()) {
return absl::nullopt;
}
@ -257,12 +250,10 @@ absl::optional<int> StreamStatisticianImpl::GetFractionLostInPercent() const {
StreamDataCounters StreamStatisticianImpl::GetReceiveStreamDataCounters()
const {
MutexLock lock(&stream_lock_);
return receive_counters_;
}
uint32_t StreamStatisticianImpl::BitrateReceived() const {
MutexLock lock(&stream_lock_);
return incoming_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
}
@ -295,21 +286,33 @@ bool StreamStatisticianImpl::IsRetransmitOfOldPacket(
}
std::unique_ptr<ReceiveStatistics> ReceiveStatistics::Create(Clock* clock) {
return std::make_unique<ReceiveStatisticsImpl>(clock);
return std::make_unique<ReceiveStatisticsLocked>(
clock, [](uint32_t ssrc, Clock* clock, int max_reordering_threshold) {
return std::make_unique<StreamStatisticianLocked>(
ssrc, clock, max_reordering_threshold);
});
}
ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock)
std::unique_ptr<ReceiveStatistics> ReceiveStatistics::CreateThreadCompatible(
Clock* clock) {
return std::make_unique<ReceiveStatisticsImpl>(
clock, [](uint32_t ssrc, Clock* clock, int max_reordering_threshold) {
return std::make_unique<StreamStatisticianImpl>(
ssrc, clock, max_reordering_threshold);
});
}
ReceiveStatisticsImpl::ReceiveStatisticsImpl(
Clock* clock,
std::function<std::unique_ptr<StreamStatisticianImplInterface>(
uint32_t ssrc,
Clock* clock,
int max_reordering_threshold)> stream_statistician_factory)
: clock_(clock),
stream_statistician_factory_(std::move(stream_statistician_factory)),
last_returned_ssrc_(0),
max_reordering_threshold_(kDefaultMaxReorderingThreshold) {}
ReceiveStatisticsImpl::~ReceiveStatisticsImpl() {
while (!statisticians_.empty()) {
delete statisticians_.begin()->second;
statisticians_.erase(statisticians_.begin());
}
}
void ReceiveStatisticsImpl::OnRtpPacket(const RtpPacketReceived& packet) {
// StreamStatisticianImpl instance is created once and only destroyed when
// this whole ReceiveStatisticsImpl is destroyed. StreamStatisticianImpl has
@ -318,34 +321,28 @@ void ReceiveStatisticsImpl::OnRtpPacket(const RtpPacketReceived& packet) {
GetOrCreateStatistician(packet.Ssrc())->UpdateCounters(packet);
}
StreamStatisticianImpl* ReceiveStatisticsImpl::GetStatistician(
StreamStatistician* ReceiveStatisticsImpl::GetStatistician(
uint32_t ssrc) const {
MutexLock lock(&receive_statistics_lock_);
const auto& it = statisticians_.find(ssrc);
if (it == statisticians_.end())
return NULL;
return it->second;
return nullptr;
return it->second.get();
}
StreamStatisticianImpl* ReceiveStatisticsImpl::GetOrCreateStatistician(
StreamStatisticianImplInterface* ReceiveStatisticsImpl::GetOrCreateStatistician(
uint32_t ssrc) {
MutexLock lock(&receive_statistics_lock_);
StreamStatisticianImpl*& impl = statisticians_[ssrc];
std::unique_ptr<StreamStatisticianImplInterface>& impl = statisticians_[ssrc];
if (impl == nullptr) { // new element
impl = new StreamStatisticianImpl(ssrc, clock_, max_reordering_threshold_);
impl =
stream_statistician_factory_(ssrc, clock_, max_reordering_threshold_);
}
return impl;
return impl.get();
}
void ReceiveStatisticsImpl::SetMaxReorderingThreshold(
int max_reordering_threshold) {
std::map<uint32_t, StreamStatisticianImpl*> statisticians;
{
MutexLock lock(&receive_statistics_lock_);
max_reordering_threshold_ = max_reordering_threshold;
statisticians = statisticians_;
}
for (auto& statistician : statisticians) {
max_reordering_threshold_ = max_reordering_threshold;
for (auto& statistician : statisticians_) {
statistician.second->SetMaxReorderingThreshold(max_reordering_threshold);
}
}
@ -364,15 +361,11 @@ void ReceiveStatisticsImpl::EnableRetransmitDetection(uint32_t ssrc,
std::vector<rtcp::ReportBlock> ReceiveStatisticsImpl::RtcpReportBlocks(
size_t max_blocks) {
std::map<uint32_t, StreamStatisticianImpl*> statisticians;
{
MutexLock lock(&receive_statistics_lock_);
statisticians = statisticians_;
}
std::vector<rtcp::ReportBlock> result;
result.reserve(std::min(max_blocks, statisticians.size()));
auto add_report_block = [&result](uint32_t media_ssrc,
StreamStatisticianImpl* statistician) {
result.reserve(std::min(max_blocks, statisticians_.size()));
auto add_report_block = [&result](
uint32_t media_ssrc,
StreamStatisticianImplInterface* statistician) {
// Do we have receive statistics to send?
RtcpStatistics stats;
if (!statistician->GetActiveStatisticsAndReset(&stats))
@ -390,13 +383,13 @@ std::vector<rtcp::ReportBlock> ReceiveStatisticsImpl::RtcpReportBlocks(
block.SetJitter(stats.jitter);
};
const auto start_it = statisticians.upper_bound(last_returned_ssrc_);
const auto start_it = statisticians_.upper_bound(last_returned_ssrc_);
for (auto it = start_it;
result.size() < max_blocks && it != statisticians.end(); ++it)
add_report_block(it->first, it->second);
for (auto it = statisticians.begin();
result.size() < max_blocks && it != statisticians_.end(); ++it)
add_report_block(it->first, it->second.get());
for (auto it = statisticians_.begin();
result.size() < max_blocks && it != start_it; ++it)
add_report_block(it->first, it->second);
add_report_block(it->first, it->second.get());
if (!result.empty())
last_returned_ssrc_ = result.back().source_ssrc();

View File

@ -12,7 +12,10 @@
#define MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_
#include <algorithm>
#include <functional>
#include <map>
#include <memory>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
@ -24,86 +27,141 @@
namespace webrtc {
class StreamStatisticianImpl : public StreamStatistician {
// Extends StreamStatistician with methods needed by the implementation.
class StreamStatisticianImplInterface : public StreamStatistician {
public:
virtual ~StreamStatisticianImplInterface() = default;
virtual bool GetActiveStatisticsAndReset(RtcpStatistics* statistics) = 0;
virtual void SetMaxReorderingThreshold(int max_reordering_threshold) = 0;
virtual void EnableRetransmitDetection(bool enable) = 0;
virtual void UpdateCounters(const RtpPacketReceived& packet) = 0;
};
// Thread-compatible implementation of StreamStatisticianImplInterface.
class StreamStatisticianImpl : public StreamStatisticianImplInterface {
public:
StreamStatisticianImpl(uint32_t ssrc,
Clock* clock,
int max_reordering_threshold);
~StreamStatisticianImpl() override;
// Implements StreamStatistician
RtpReceiveStats GetStats() const override;
bool GetActiveStatisticsAndReset(RtcpStatistics* statistics);
absl::optional<int> GetFractionLostInPercent() const override;
StreamDataCounters GetReceiveStreamDataCounters() const override;
uint32_t BitrateReceived() const override;
void SetMaxReorderingThreshold(int max_reordering_threshold);
void EnableRetransmitDetection(bool enable);
// Implements StreamStatisticianImplInterface
bool GetActiveStatisticsAndReset(RtcpStatistics* statistics) override;
void SetMaxReorderingThreshold(int max_reordering_threshold) override;
void EnableRetransmitDetection(bool enable) override;
// Updates StreamStatistician for incoming packets.
void UpdateCounters(const RtpPacketReceived& packet);
void UpdateCounters(const RtpPacketReceived& packet) override;
private:
bool IsRetransmitOfOldPacket(const RtpPacketReceived& packet,
int64_t now_ms) const
RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
RtcpStatistics CalculateRtcpStatistics()
RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
void UpdateJitter(const RtpPacketReceived& packet, int64_t receive_time_ms)
RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
int64_t now_ms) const;
RtcpStatistics CalculateRtcpStatistics();
void UpdateJitter(const RtpPacketReceived& packet, int64_t receive_time_ms);
// Updates StreamStatistician for out of order packets.
// Returns true if packet considered to be out of order.
bool UpdateOutOfOrder(const RtpPacketReceived& packet,
int64_t sequence_number,
int64_t now_ms)
RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
int64_t now_ms);
// Checks if this StreamStatistician received any rtp packets.
bool ReceivedRtpPacket() const RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_) {
return received_seq_first_ >= 0;
}
bool ReceivedRtpPacket() const { return received_seq_first_ >= 0; }
const uint32_t ssrc_;
Clock* const clock_;
mutable Mutex stream_lock_;
RateStatistics incoming_bitrate_ RTC_GUARDED_BY(&stream_lock_);
RateStatistics incoming_bitrate_;
// In number of packets or sequence numbers.
int max_reordering_threshold_ RTC_GUARDED_BY(&stream_lock_);
bool enable_retransmit_detection_ RTC_GUARDED_BY(&stream_lock_);
int max_reordering_threshold_;
bool enable_retransmit_detection_;
// Stats on received RTP packets.
uint32_t jitter_q4_ RTC_GUARDED_BY(&stream_lock_);
uint32_t jitter_q4_;
// Cumulative loss according to RFC 3550, which may be negative (and often is,
// if packets are reordered and there are non-RTX retransmissions).
int32_t cumulative_loss_ RTC_GUARDED_BY(&stream_lock_);
int32_t cumulative_loss_;
// Offset added to outgoing rtcp reports, to make ensure that the reported
// cumulative loss is non-negative. Reports with negative values confuse some
// senders, in particular, our own loss-based bandwidth estimator.
int32_t cumulative_loss_rtcp_offset_ RTC_GUARDED_BY(&stream_lock_);
int32_t cumulative_loss_rtcp_offset_;
int64_t last_receive_time_ms_ RTC_GUARDED_BY(&stream_lock_);
uint32_t last_received_timestamp_ RTC_GUARDED_BY(&stream_lock_);
SequenceNumberUnwrapper seq_unwrapper_ RTC_GUARDED_BY(&stream_lock_);
int64_t received_seq_first_ RTC_GUARDED_BY(&stream_lock_);
int64_t received_seq_max_ RTC_GUARDED_BY(&stream_lock_);
int64_t last_receive_time_ms_;
uint32_t last_received_timestamp_;
SequenceNumberUnwrapper seq_unwrapper_;
int64_t received_seq_first_;
int64_t received_seq_max_;
// Assume that the other side restarted when there are two sequential packets
// with large jump from received_seq_max_.
absl::optional<uint16_t> received_seq_out_of_order_
RTC_GUARDED_BY(&stream_lock_);
absl::optional<uint16_t> received_seq_out_of_order_;
// Current counter values.
StreamDataCounters receive_counters_ RTC_GUARDED_BY(&stream_lock_);
StreamDataCounters receive_counters_;
// Counter values when we sent the last report.
int32_t last_report_cumulative_loss_ RTC_GUARDED_BY(&stream_lock_);
int64_t last_report_seq_max_ RTC_GUARDED_BY(&stream_lock_);
int32_t last_report_cumulative_loss_;
int64_t last_report_seq_max_;
};
// Thread-safe implementation of StreamStatisticianImplInterface.
class StreamStatisticianLocked : public StreamStatisticianImplInterface {
public:
StreamStatisticianLocked(uint32_t ssrc,
Clock* clock,
int max_reordering_threshold)
: impl_(ssrc, clock, max_reordering_threshold) {}
~StreamStatisticianLocked() override = default;
RtpReceiveStats GetStats() const override {
MutexLock lock(&stream_lock_);
return impl_.GetStats();
}
absl::optional<int> GetFractionLostInPercent() const override {
MutexLock lock(&stream_lock_);
return impl_.GetFractionLostInPercent();
}
StreamDataCounters GetReceiveStreamDataCounters() const override {
MutexLock lock(&stream_lock_);
return impl_.GetReceiveStreamDataCounters();
}
uint32_t BitrateReceived() const override {
MutexLock lock(&stream_lock_);
return impl_.BitrateReceived();
}
bool GetActiveStatisticsAndReset(RtcpStatistics* statistics) override {
MutexLock lock(&stream_lock_);
return impl_.GetActiveStatisticsAndReset(statistics);
}
void SetMaxReorderingThreshold(int max_reordering_threshold) override {
MutexLock lock(&stream_lock_);
return impl_.SetMaxReorderingThreshold(max_reordering_threshold);
}
void EnableRetransmitDetection(bool enable) override {
MutexLock lock(&stream_lock_);
return impl_.EnableRetransmitDetection(enable);
}
void UpdateCounters(const RtpPacketReceived& packet) override {
MutexLock lock(&stream_lock_);
return impl_.UpdateCounters(packet);
}
private:
mutable Mutex stream_lock_;
StreamStatisticianImpl impl_ RTC_GUARDED_BY(&stream_lock_);
};
// Thread-compatible implementation.
class ReceiveStatisticsImpl : public ReceiveStatistics {
public:
explicit ReceiveStatisticsImpl(Clock* clock);
~ReceiveStatisticsImpl() override;
ReceiveStatisticsImpl(
Clock* clock,
std::function<std::unique_ptr<StreamStatisticianImplInterface>(
uint32_t ssrc,
Clock* clock,
int max_reordering_threshold)> stream_statistician_factory);
~ReceiveStatisticsImpl() override = default;
// Implements ReceiveStatisticsProvider.
std::vector<rtcp::ReportBlock> RtcpReportBlocks(size_t max_blocks) override;
@ -112,22 +170,69 @@ class ReceiveStatisticsImpl : public ReceiveStatistics {
void OnRtpPacket(const RtpPacketReceived& packet) override;
// Implements ReceiveStatistics.
// Note: More specific return type for use in the implementation.
StreamStatisticianImpl* GetStatistician(uint32_t ssrc) const override;
StreamStatistician* GetStatistician(uint32_t ssrc) const override;
void SetMaxReorderingThreshold(int max_reordering_threshold) override;
void SetMaxReorderingThreshold(uint32_t ssrc,
int max_reordering_threshold) override;
void EnableRetransmitDetection(uint32_t ssrc, bool enable) override;
private:
StreamStatisticianImpl* GetOrCreateStatistician(uint32_t ssrc);
StreamStatisticianImplInterface* GetOrCreateStatistician(uint32_t ssrc);
Clock* const clock_;
mutable Mutex receive_statistics_lock_;
std::function<std::unique_ptr<StreamStatisticianImplInterface>(
uint32_t ssrc,
Clock* clock,
int max_reordering_threshold)>
stream_statistician_factory_;
uint32_t last_returned_ssrc_;
int max_reordering_threshold_ RTC_GUARDED_BY(receive_statistics_lock_);
std::map<uint32_t, StreamStatisticianImpl*> statisticians_
RTC_GUARDED_BY(receive_statistics_lock_);
int max_reordering_threshold_;
std::map<uint32_t, std::unique_ptr<StreamStatisticianImplInterface>>
statisticians_;
};
// Thread-safe implementation wrapping access to ReceiveStatisticsImpl with a
// mutex.
class ReceiveStatisticsLocked : public ReceiveStatistics {
public:
explicit ReceiveStatisticsLocked(
Clock* clock,
std::function<std::unique_ptr<StreamStatisticianImplInterface>(
uint32_t ssrc,
Clock* clock,
int max_reordering_threshold)> stream_statitician_factory)
: impl_(clock, std::move(stream_statitician_factory)) {}
~ReceiveStatisticsLocked() override = default;
std::vector<rtcp::ReportBlock> RtcpReportBlocks(size_t max_blocks) override {
MutexLock lock(&receive_statistics_lock_);
return impl_.RtcpReportBlocks(max_blocks);
}
void OnRtpPacket(const RtpPacketReceived& packet) override {
MutexLock lock(&receive_statistics_lock_);
return impl_.OnRtpPacket(packet);
}
StreamStatistician* GetStatistician(uint32_t ssrc) const override {
MutexLock lock(&receive_statistics_lock_);
return impl_.GetStatistician(ssrc);
}
void SetMaxReorderingThreshold(int max_reordering_threshold) override {
MutexLock lock(&receive_statistics_lock_);
return impl_.SetMaxReorderingThreshold(max_reordering_threshold);
}
void SetMaxReorderingThreshold(uint32_t ssrc,
int max_reordering_threshold) override {
MutexLock lock(&receive_statistics_lock_);
return impl_.SetMaxReorderingThreshold(ssrc, max_reordering_threshold);
}
void EnableRetransmitDetection(uint32_t ssrc, bool enable) override {
MutexLock lock(&receive_statistics_lock_);
return impl_.EnableRetransmitDetection(ssrc, enable);
}
private:
mutable Mutex receive_statistics_lock_;
ReceiveStatisticsImpl impl_ RTC_GUARDED_BY(&receive_statistics_lock_);
};
} // namespace webrtc
#endif // MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_

View File

@ -65,10 +65,13 @@ void IncrementSequenceNumber(RtpPacketReceived* packet) {
IncrementSequenceNumber(packet, 1);
}
class ReceiveStatisticsTest : public ::testing::Test {
class ReceiveStatisticsTest : public ::testing::TestWithParam<bool> {
public:
ReceiveStatisticsTest()
: clock_(0), receive_statistics_(ReceiveStatistics::Create(&clock_)) {
: clock_(0),
receive_statistics_(
GetParam() ? ReceiveStatistics::Create(&clock_)
: ReceiveStatistics::CreateThreadCompatible(&clock_)) {
packet1_ = CreateRtpPacket(kSsrc1, kPacketSize1);
packet2_ = CreateRtpPacket(kSsrc2, kPacketSize2);
}
@ -80,7 +83,14 @@ class ReceiveStatisticsTest : public ::testing::Test {
RtpPacketReceived packet2_;
};
TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) {
INSTANTIATE_TEST_SUITE_P(All,
ReceiveStatisticsTest,
::testing::Bool(),
[](::testing::TestParamInfo<bool> info) {
return info.param ? "WithMutex" : "WithoutMutex";
});
TEST_P(ReceiveStatisticsTest, TwoIncomingSsrcs) {
receive_statistics_->OnRtpPacket(packet1_);
IncrementSequenceNumber(&packet1_);
receive_statistics_->OnRtpPacket(packet2_);
@ -133,7 +143,7 @@ TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) {
EXPECT_EQ(3u, counters.transmitted.packets);
}
TEST_F(ReceiveStatisticsTest,
TEST_P(ReceiveStatisticsTest,
RtcpReportBlocksReturnsMaxBlocksWhenThereAreMoreStatisticians) {
RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kPacketSize1);
RtpPacketReceived packet2 = CreateRtpPacket(kSsrc2, kPacketSize1);
@ -147,7 +157,7 @@ TEST_F(ReceiveStatisticsTest,
EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
}
TEST_F(ReceiveStatisticsTest,
TEST_P(ReceiveStatisticsTest,
RtcpReportBlocksReturnsAllObservedSsrcsWithMultipleCalls) {
RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kPacketSize1);
RtpPacketReceived packet2 = CreateRtpPacket(kSsrc2, kPacketSize1);
@ -174,7 +184,7 @@ TEST_F(ReceiveStatisticsTest,
UnorderedElementsAre(kSsrc1, kSsrc2, kSsrc3, kSsrc4));
}
TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
TEST_P(ReceiveStatisticsTest, ActiveStatisticians) {
receive_statistics_->OnRtpPacket(packet1_);
IncrementSequenceNumber(&packet1_);
clock_.AdvanceTimeMilliseconds(1000);
@ -206,7 +216,7 @@ TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
EXPECT_EQ(2u, counters.transmitted.packets);
}
TEST_F(ReceiveStatisticsTest,
TEST_P(ReceiveStatisticsTest,
DoesntCreateRtcpReportBlockUntilFirstReceivedPacketForSsrc) {
// Creates a statistician object for the ssrc.
receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
@ -217,7 +227,7 @@ TEST_F(ReceiveStatisticsTest,
EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
}
TEST_F(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
TEST_P(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
receive_statistics_->OnRtpPacket(packet1_);
StreamStatistician* statistician =
receive_statistics_->GetStatistician(kSsrc1);
@ -233,7 +243,7 @@ TEST_F(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
EXPECT_EQ(2u, counters.transmitted.packets);
}
TEST_F(ReceiveStatisticsTest, SimpleLossComputation) {
TEST_P(ReceiveStatisticsTest, SimpleLossComputation) {
packet1_.SetSequenceNumber(1);
receive_statistics_->OnRtpPacket(packet1_);
packet1_.SetSequenceNumber(3);
@ -256,7 +266,7 @@ TEST_F(ReceiveStatisticsTest, SimpleLossComputation) {
EXPECT_EQ(20, statistician->GetFractionLostInPercent());
}
TEST_F(ReceiveStatisticsTest, LossComputationWithReordering) {
TEST_P(ReceiveStatisticsTest, LossComputationWithReordering) {
packet1_.SetSequenceNumber(1);
receive_statistics_->OnRtpPacket(packet1_);
packet1_.SetSequenceNumber(3);
@ -279,7 +289,7 @@ TEST_F(ReceiveStatisticsTest, LossComputationWithReordering) {
EXPECT_EQ(20, statistician->GetFractionLostInPercent());
}
TEST_F(ReceiveStatisticsTest, LossComputationWithDuplicates) {
TEST_P(ReceiveStatisticsTest, LossComputationWithDuplicates) {
// Lose 2 packets, but also receive 1 duplicate. Should actually count as
// only 1 packet being lost.
packet1_.SetSequenceNumber(1);
@ -304,7 +314,7 @@ TEST_F(ReceiveStatisticsTest, LossComputationWithDuplicates) {
EXPECT_EQ(20, statistician->GetFractionLostInPercent());
}
TEST_F(ReceiveStatisticsTest, LossComputationWithSequenceNumberWrapping) {
TEST_P(ReceiveStatisticsTest, LossComputationWithSequenceNumberWrapping) {
// First, test loss computation over a period that included a sequence number
// rollover.
packet1_.SetSequenceNumber(0xfffd);
@ -344,7 +354,7 @@ TEST_F(ReceiveStatisticsTest, LossComputationWithSequenceNumberWrapping) {
EXPECT_EQ(28, statistician->GetFractionLostInPercent());
}
TEST_F(ReceiveStatisticsTest, StreamRestartDoesntCountAsLoss) {
TEST_P(ReceiveStatisticsTest, StreamRestartDoesntCountAsLoss) {
receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
packet1_.SetSequenceNumber(0);
@ -377,7 +387,7 @@ TEST_F(ReceiveStatisticsTest, StreamRestartDoesntCountAsLoss) {
EXPECT_EQ(0, statistician->GetFractionLostInPercent());
}
TEST_F(ReceiveStatisticsTest, CountsLossAfterStreamRestart) {
TEST_P(ReceiveStatisticsTest, CountsLossAfterStreamRestart) {
receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
packet1_.SetSequenceNumber(0);
@ -405,7 +415,7 @@ TEST_F(ReceiveStatisticsTest, CountsLossAfterStreamRestart) {
EXPECT_EQ(0, statistician->GetFractionLostInPercent());
}
TEST_F(ReceiveStatisticsTest, StreamCanRestartAtSequenceNumberWrapAround) {
TEST_P(ReceiveStatisticsTest, StreamCanRestartAtSequenceNumberWrapAround) {
receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
packet1_.SetSequenceNumber(0xffff - 401);
@ -428,7 +438,7 @@ TEST_F(ReceiveStatisticsTest, StreamCanRestartAtSequenceNumberWrapAround) {
EXPECT_EQ(1, report_blocks[0].cumulative_lost_signed());
}
TEST_F(ReceiveStatisticsTest, StreamRestartNeedsTwoConsecutivePackets) {
TEST_P(ReceiveStatisticsTest, StreamRestartNeedsTwoConsecutivePackets) {
receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
packet1_.SetSequenceNumber(400);
@ -458,7 +468,7 @@ TEST_F(ReceiveStatisticsTest, StreamRestartNeedsTwoConsecutivePackets) {
EXPECT_EQ(4u, report_blocks[0].extended_high_seq_num());
}
TEST_F(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) {
TEST_P(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) {
packet1_.SetSequenceNumber(0xffff);
receive_statistics_->OnRtpPacket(packet1_);
@ -503,8 +513,7 @@ TEST_F(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) {
EXPECT_EQ(0x20001u, report_blocks[0].extended_high_seq_num());
}
TEST_F(ReceiveStatisticsTest, StreamDataCounters) {
receive_statistics_ = ReceiveStatistics::Create(&clock_);
TEST_P(ReceiveStatisticsTest, StreamDataCounters) {
receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
const size_t kHeaderLength = 20;
@ -554,9 +563,7 @@ TEST_F(ReceiveStatisticsTest, StreamDataCounters) {
EXPECT_EQ(counters.retransmitted.packets, 1u);
}
TEST_F(ReceiveStatisticsTest, LastPacketReceivedTimestamp) {
receive_statistics_ = ReceiveStatistics::Create(&clock_);
TEST_P(ReceiveStatisticsTest, LastPacketReceivedTimestamp) {
clock_.AdvanceTimeMilliseconds(42);
receive_statistics_->OnRtpPacket(packet1_);
StreamDataCounters counters = receive_statistics_->GetStatistician(kSsrc1)