/* * Copyright (c) 2026 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/video_coding/utility/reference_buffer_tracker.h" #include #include "api/units/timestamp.h" #include "test/gmock.h" #include "test/gtest.h" namespace webrtc { namespace { using ::testing::ElementsAre; using ::testing::IsEmpty; TEST(ReferenceBufferTrackerTest, InitializesWithCustomBufferCount) { ReferenceBufferTracker tracker3(/*num_buffers=*/3); EXPECT_EQ(tracker3.num_buffers(), 3); for (int i = 0; i < 3; ++i) { EXPECT_EQ(tracker3.GetTimestamp(i), std::nullopt); } ReferenceBufferTracker tracker8(/*num_buffers=*/8); EXPECT_EQ(tracker8.num_buffers(), 8); for (int i = 0; i < 8; ++i) { EXPECT_EQ(tracker8.GetTimestamp(i), std::nullopt); } } TEST(ReferenceBufferTrackerTest, UpdateAndGetTimestamp) { ReferenceBufferTracker tracker(/*num_buffers=*/4); tracker.Update(/*buffer_id=*/1, Timestamp::Millis(100)); tracker.Update(/*buffer_id=*/3, Timestamp::Millis(250)); EXPECT_EQ(tracker.GetTimestamp(0), std::nullopt); EXPECT_EQ(tracker.GetTimestamp(1), Timestamp::Millis(100)); EXPECT_EQ(tracker.GetTimestamp(2), std::nullopt); EXPECT_EQ(tracker.GetTimestamp(3), Timestamp::Millis(250)); // Overwrite buffer 1. tracker.Update(/*buffer_id=*/1, Timestamp::Millis(300)); EXPECT_EQ(tracker.GetTimestamp(1), Timestamp::Millis(300)); } TEST(ReferenceBufferTrackerTest, ResetClearsAllTimestamps) { ReferenceBufferTracker tracker(/*num_buffers=*/4); tracker.Update(0, Timestamp::Millis(100)); tracker.Update(1, Timestamp::Millis(200)); tracker.Update(2, Timestamp::Millis(300)); tracker.Update(3, Timestamp::Millis(400)); tracker.Reset(); for (int i = 0; i < 4; ++i) { EXPECT_EQ(tracker.GetTimestamp(i), std::nullopt); } } TEST(ReferenceBufferTrackerTest, OrderByTimestampAllBuffersHaveTimestamps) { ReferenceBufferTracker tracker(/*num_buffers=*/4); tracker.Update(0, Timestamp::Millis(100)); tracker.Update(1, Timestamp::Millis(400)); tracker.Update(2, Timestamp::Millis(200)); tracker.Update(3, Timestamp::Millis(300)); // Full set, out of order. Most recent should be first: 1 (400ms), 3 (300ms), // 2 (200ms), 0 (100ms). const int buffers[] = {0, 1, 2, 3}; EXPECT_THAT(tracker.OrderByTimestamp(buffers), ElementsAre(1, 3, 2, 0)); // Subset of buffers. const int subset[] = {0, 2, 3}; EXPECT_THAT(tracker.OrderByTimestamp(subset), ElementsAre(3, 2, 0)); // Single buffer. const int single[] = {2}; EXPECT_THAT(tracker.OrderByTimestamp(single), ElementsAre(2)); // Empty list. EXPECT_THAT(tracker.OrderByTimestamp({}), IsEmpty()); } TEST(ReferenceBufferTrackerTest, OrderByTimestampWithUnsetBuffers) { ReferenceBufferTracker tracker(/*num_buffers=*/5); // Only buffers 0 and 2 have timestamps. tracker.Update(0, Timestamp::Millis(100)); tracker.Update(2, Timestamp::Millis(200)); // Buffers with timestamps should precede unset buffers. const int buffers[] = {0, 1, 2, 3, 4}; EXPECT_THAT(tracker.OrderByTimestamp(buffers), ElementsAre(2, 0, 1, 3, 4)); // When all requested buffers are unset, stable order is preserved. const int unset_buffers[] = {4, 3, 1}; EXPECT_THAT(tracker.OrderByTimestamp(unset_buffers), ElementsAre(4, 3, 1)); } TEST(ReferenceBufferTrackerTest, OrderByTimestampPreservesOrderForEqualTimestamps) { ReferenceBufferTracker tracker(/*num_buffers=*/4); tracker.Update(0, Timestamp::Millis(200)); tracker.Update(1, Timestamp::Millis(200)); tracker.Update(2, Timestamp::Millis(100)); tracker.Update(3, Timestamp::Millis(200)); const int buffers[] = {0, 1, 2, 3}; // Buffers 0, 1, 3 all have 200ms, buffer 2 has 100ms. // Stable sort must preserve 0, 1, 3 relative order. EXPECT_THAT(tracker.OrderByTimestamp(buffers), ElementsAre(0, 1, 3, 2)); const int reversed[] = {3, 1, 0, 2}; EXPECT_THAT(tracker.OrderByTimestamp(reversed), ElementsAre(3, 1, 0, 2)); } } // namespace } // namespace webrtc