From 28d13cb88693bd5a75baf8508aad1d79c5640988 Mon Sep 17 00:00:00 2001 From: Elad Alon Date: Sat, 6 Apr 2019 21:09:30 +0200 Subject: [PATCH] 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 Reviewed-by: Niels Moller Reviewed-by: Danil Chapovalov Cr-Commit-Position: refs/heads/master@{#27485} --- .../source/rtp_sequence_number_map.cc | 17 +++- .../rtp_rtcp/source/rtp_sequence_number_map.h | 5 +- .../rtp_sequence_number_map_unittest.cc | 77 +++++++++++++++---- 3 files changed, 81 insertions(+), 18 deletions(-) diff --git a/modules/rtp_rtcp/source/rtp_sequence_number_map.cc b/modules/rtp_rtcp/source/rtp_sequence_number_map.cc index 95eafce714..28ae9c8400 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 #include +#include #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::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(first_sequence_number + i), + Info(timestamp, is_first, is_last)); + } +} + absl::optional 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 1f6a3044f8..68fcc634fc 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 @@ 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 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 5cb9d735bd..e371a3e755 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 @@ 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 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(kFirstSequenceNumber + 0u)), + Info(kTimestamp, true, false)); + EXPECT_EQ(uut.Get(static_cast(kFirstSequenceNumber + 1u)), + Info(kTimestamp, false, false)); + EXPECT_EQ(uut.Get(static_cast(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(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|.