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}
diff --git a/modules/rtp_rtcp/source/rtp_sequence_number_map.cc b/modules/rtp_rtcp/source/rtp_sequence_number_map.cc
index 95eafce..28ae9c8 100644
--- a/modules/rtp_rtcp/source/rtp_sequence_number_map.cc
+++ b/modules/rtp_rtcp/source/rtp_sequence_number_map.cc
@@ -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() = 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 @@
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
diff --git a/modules/rtp_rtcp/source/rtp_sequence_number_map.h b/modules/rtp_rtcp/source/rtp_sequence_number_map.h
index 1f6a304..68fcc63 100644
--- a/modules/rtp_rtcp/source/rtp_sequence_number_map.h
+++ b/modules/rtp_rtcp/source/rtp_sequence_number_map.h
@@ -53,7 +53,10 @@
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;
diff --git a/modules/rtp_rtcp/source/rtp_sequence_number_map_unittest.cc b/modules/rtp_rtcp/source/rtp_sequence_number_map_unittest.cc
index 5cb9d73..e371a3e75 100644
--- a/modules/rtp_rtcp/source/rtp_sequence_number_map_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sequence_number_map_unittest.cc
@@ -147,7 +147,7 @@
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 @@
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 @@
/*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 @@
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 @@
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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|.