Add RtpSequenceNumberMap::InsertFrame()
This will make code using RtpSequenceNumberMap simpler. Bug: webrtc:10501 Change-Id: I74b11f3562d5962efb42b5bb7662489d7d411388 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/131386 Commit-Queue: Elad Alon <eladalon@webrtc.org> Reviewed-by: Niels Moller <nisse@webrtc.org> Reviewed-by: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/master@{#27485}
This commit is contained in:
@ -12,6 +12,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "rtc_base/checks.h"
|
||||
@ -28,7 +29,7 @@ RtpSequenceNumberMap::RtpSequenceNumberMap(size_t max_entries)
|
||||
|
||||
RtpSequenceNumberMap::~RtpSequenceNumberMap() = default;
|
||||
|
||||
void RtpSequenceNumberMap::Insert(uint16_t sequence_number, Info info) {
|
||||
void RtpSequenceNumberMap::InsertPacket(uint16_t sequence_number, Info info) {
|
||||
RTC_DCHECK(associations_.size() < 2 ||
|
||||
AheadOf(associations_.back().sequence_number,
|
||||
associations_.front().sequence_number));
|
||||
@ -79,6 +80,20 @@ void RtpSequenceNumberMap::Insert(uint16_t sequence_number, Info info) {
|
||||
associations_.front().sequence_number));
|
||||
}
|
||||
|
||||
void RtpSequenceNumberMap::InsertFrame(uint16_t first_sequence_number,
|
||||
size_t packet_count,
|
||||
uint32_t timestamp) {
|
||||
RTC_DCHECK_GT(packet_count, 0);
|
||||
RTC_DCHECK_LE(packet_count, std::numeric_limits<size_t>::max());
|
||||
|
||||
for (size_t i = 0; i < packet_count; ++i) {
|
||||
const bool is_first = (i == 0);
|
||||
const bool is_last = (i == packet_count - 1);
|
||||
InsertPacket(static_cast<uint16_t>(first_sequence_number + i),
|
||||
Info(timestamp, is_first, is_last));
|
||||
}
|
||||
}
|
||||
|
||||
absl::optional<RtpSequenceNumberMap::Info> RtpSequenceNumberMap::Get(
|
||||
uint16_t sequence_number) const {
|
||||
// To make the binary search easier to understand, we use the fact that
|
||||
|
||||
@ -53,7 +53,10 @@ class RtpSequenceNumberMap final {
|
||||
RtpSequenceNumberMap& operator=(const RtpSequenceNumberMap& other) = delete;
|
||||
~RtpSequenceNumberMap();
|
||||
|
||||
void Insert(uint16_t sequence_number, Info info);
|
||||
void InsertPacket(uint16_t sequence_number, Info info);
|
||||
void InsertFrame(uint16_t first_sequence_number,
|
||||
size_t packet_count,
|
||||
uint32_t timestamp);
|
||||
|
||||
absl::optional<Info> Get(uint16_t sequence_number) const;
|
||||
|
||||
|
||||
@ -147,7 +147,7 @@ TEST_F(RtpSequenceNumberMapTest, GetUnknownSequenceNumberReturnsNullOpt1) {
|
||||
|
||||
constexpr uint16_t kKnownSequenceNumber = 10;
|
||||
constexpr uint32_t kArbitrary = 987;
|
||||
uut.Insert(kKnownSequenceNumber, {kArbitrary, false, false});
|
||||
uut.InsertPacket(kKnownSequenceNumber, {kArbitrary, false, false});
|
||||
|
||||
constexpr uint16_t kUnknownSequenceNumber = kKnownSequenceNumber + 1;
|
||||
EXPECT_FALSE(uut.Get(kUnknownSequenceNumber));
|
||||
@ -161,7 +161,7 @@ TEST_F(RtpSequenceNumberMapTest, GetUnknownSequenceNumberReturnsNullOpt2) {
|
||||
const std::vector<Association> setup = {CreateAssociation(1000, 500), //
|
||||
CreateAssociation(1020, 501)};
|
||||
for (const Association& association : setup) {
|
||||
uut.Insert(association.sequence_number, association.info);
|
||||
uut.InsertPacket(association.sequence_number, association.info);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(uut.Get(1001));
|
||||
@ -179,12 +179,57 @@ TEST_P(RtpSequenceNumberMapTestWithParams,
|
||||
/*allow_obsoletion=*/false);
|
||||
|
||||
for (const Association& association : associations) {
|
||||
uut.Insert(association.sequence_number, association.info);
|
||||
uut.InsertPacket(association.sequence_number, association.info);
|
||||
}
|
||||
|
||||
VerifyAssociations(uut, associations);
|
||||
}
|
||||
|
||||
TEST_F(RtpSequenceNumberMapTest, InsertFrameOnSinglePacketFrame) {
|
||||
RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
|
||||
|
||||
constexpr uint16_t kSequenceNumber = 888;
|
||||
constexpr uint32_t kTimestamp = 98765;
|
||||
uut.InsertFrame(kSequenceNumber, 1, kTimestamp);
|
||||
|
||||
EXPECT_EQ(uut.Get(kSequenceNumber), Info(kTimestamp, true, true));
|
||||
}
|
||||
|
||||
TEST_F(RtpSequenceNumberMapTest, InsertFrameOnMultiPacketFrameNoWrapAround) {
|
||||
RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
|
||||
|
||||
constexpr uint16_t kFirstSequenceNumber = 0;
|
||||
constexpr uint32_t kTimestamp = 98765;
|
||||
uut.InsertFrame(kFirstSequenceNumber, 3, kTimestamp);
|
||||
|
||||
EXPECT_EQ(uut.Get(kFirstSequenceNumber + 0), Info(kTimestamp, true, false));
|
||||
EXPECT_EQ(uut.Get(kFirstSequenceNumber + 1), Info(kTimestamp, false, false));
|
||||
EXPECT_EQ(uut.Get(kFirstSequenceNumber + 2), Info(kTimestamp, false, true));
|
||||
}
|
||||
|
||||
TEST_F(RtpSequenceNumberMapTest, InsertFrameOnMultiPacketFrameWithWrapAround) {
|
||||
RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
|
||||
|
||||
constexpr uint16_t kFirstSequenceNumber = kUint16Max;
|
||||
constexpr uint32_t kTimestamp = 98765;
|
||||
uut.InsertFrame(kFirstSequenceNumber, 3, kTimestamp);
|
||||
|
||||
// Suppress "truncation of constant value" warning; wrap-around is intended.
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4309)
|
||||
#endif
|
||||
EXPECT_EQ(uut.Get(static_cast<uint16_t>(kFirstSequenceNumber + 0u)),
|
||||
Info(kTimestamp, true, false));
|
||||
EXPECT_EQ(uut.Get(static_cast<uint16_t>(kFirstSequenceNumber + 1u)),
|
||||
Info(kTimestamp, false, false));
|
||||
EXPECT_EQ(uut.Get(static_cast<uint16_t>(kFirstSequenceNumber + 2u)),
|
||||
Info(kTimestamp, false, true));
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F(RtpSequenceNumberMapTest,
|
||||
GetObsoleteSequenceNumberReturnsNullOptSingleValueObsoleted) {
|
||||
RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
|
||||
@ -194,18 +239,18 @@ TEST_F(RtpSequenceNumberMapTest,
|
||||
CreateAssociation(0x8000, 20), //
|
||||
CreateAssociation(0x8001u, 30)};
|
||||
|
||||
uut.Insert(associations[0].sequence_number, associations[0].info);
|
||||
uut.InsertPacket(associations[0].sequence_number, associations[0].info);
|
||||
|
||||
// First association not yet obsolete, and therefore remembered.
|
||||
RTC_DCHECK(AheadOf(associations[1].sequence_number,
|
||||
associations[0].sequence_number));
|
||||
uut.Insert(associations[1].sequence_number, associations[1].info);
|
||||
uut.InsertPacket(associations[1].sequence_number, associations[1].info);
|
||||
VerifyAssociations(uut, {associations[0], associations[1]});
|
||||
|
||||
// Test focus - new entry obsoletes first entry.
|
||||
RTC_DCHECK(!AheadOf(associations[2].sequence_number,
|
||||
associations[0].sequence_number));
|
||||
uut.Insert(associations[2].sequence_number, associations[2].info);
|
||||
uut.InsertPacket(associations[2].sequence_number, associations[2].info);
|
||||
VerifyAssociations(uut, {associations[1], associations[2]});
|
||||
}
|
||||
|
||||
@ -231,7 +276,7 @@ void RtpSequenceNumberMapTest::
|
||||
}
|
||||
|
||||
for (auto association : associations) {
|
||||
uut.Insert(association.sequence_number, association.info);
|
||||
uut.InsertPacket(association.sequence_number, association.info);
|
||||
}
|
||||
VerifyAssociations(uut, associations);
|
||||
|
||||
@ -261,7 +306,7 @@ void RtpSequenceNumberMapTest::
|
||||
// Record the new association.
|
||||
const Association new_association =
|
||||
CreateAssociation(new_sequence_number, 60);
|
||||
uut.Insert(new_association.sequence_number, new_association.info);
|
||||
uut.InsertPacket(new_association.sequence_number, new_association.info);
|
||||
|
||||
// Make sure all obsoleted elements were removed.
|
||||
const size_t obsoleted_count =
|
||||
@ -320,12 +365,12 @@ void RtpSequenceNumberMapTest::RepeatedSequenceNumberInvalidatesAll(
|
||||
CreateAssociation(102, 502)};
|
||||
RTC_DCHECK_LT(index_of_repeated, setup.size());
|
||||
for (const Association& association : setup) {
|
||||
uut.Insert(association.sequence_number, association.info);
|
||||
uut.InsertPacket(association.sequence_number, association.info);
|
||||
}
|
||||
|
||||
const Association new_association =
|
||||
CreateAssociation(setup[index_of_repeated].sequence_number, 503);
|
||||
uut.Insert(new_association.sequence_number, new_association.info);
|
||||
uut.InsertPacket(new_association.sequence_number, new_association.info);
|
||||
|
||||
// All entries from setup invalidated.
|
||||
// New entry valid and mapped to new value.
|
||||
@ -361,11 +406,11 @@ TEST_F(RtpSequenceNumberMapTest,
|
||||
CreateAssociation(1020, 501), //
|
||||
CreateAssociation(1030, 502)};
|
||||
for (const Association& association : setup) {
|
||||
uut.Insert(association.sequence_number, association.info);
|
||||
uut.InsertPacket(association.sequence_number, association.info);
|
||||
}
|
||||
|
||||
const Association new_association = CreateAssociation(1010, 503);
|
||||
uut.Insert(new_association.sequence_number, new_association.info);
|
||||
uut.InsertPacket(new_association.sequence_number, new_association.info);
|
||||
|
||||
// All entries from setup invalidated.
|
||||
// New entry valid and mapped to new value.
|
||||
@ -384,13 +429,13 @@ TEST_F(RtpSequenceNumberMapTest, MaxEntriesObserved) {
|
||||
uint32_t timestamp = 789;
|
||||
for (size_t i = 0; i < kMaxEntries; ++i) {
|
||||
associations.push_back(CreateAssociation(i, ++timestamp));
|
||||
uut.Insert(associations[i].sequence_number, associations[i].info);
|
||||
uut.InsertPacket(associations[i].sequence_number, associations[i].info);
|
||||
}
|
||||
VerifyAssociations(uut, associations); // Sanity.
|
||||
|
||||
const Association new_association =
|
||||
CreateAssociation(kMaxEntries, ++timestamp);
|
||||
uut.Insert(new_association.sequence_number, new_association.info);
|
||||
uut.InsertPacket(new_association.sequence_number, new_association.info);
|
||||
associations.push_back(new_association);
|
||||
|
||||
// The +1 is for |new_association|.
|
||||
@ -410,7 +455,7 @@ void RtpSequenceNumberMapTest::MaxEntriesReachedAtSameTimeAsObsoletionOfItem(
|
||||
uint32_t timestamp = 789;
|
||||
for (size_t i = 0; i < max_entries; ++i) {
|
||||
associations.push_back(CreateAssociation(i, ++timestamp));
|
||||
uut.Insert(associations[i].sequence_number, associations[i].info);
|
||||
uut.InsertPacket(associations[i].sequence_number, associations[i].info);
|
||||
}
|
||||
VerifyAssociations(uut, associations); // Sanity.
|
||||
|
||||
@ -418,7 +463,7 @@ void RtpSequenceNumberMapTest::MaxEntriesReachedAtSameTimeAsObsoletionOfItem(
|
||||
static_cast<uint16_t>(obsoleted_count) + (1 << 15);
|
||||
const Association new_association =
|
||||
CreateAssociation(new_association_sequence_number, ++timestamp);
|
||||
uut.Insert(new_association.sequence_number, new_association.info);
|
||||
uut.InsertPacket(new_association.sequence_number, new_association.info);
|
||||
associations.push_back(new_association);
|
||||
|
||||
// The +1 is for |new_association|.
|
||||
|
||||
Reference in New Issue
Block a user