xref: /aosp_15_r20/external/webrtc/modules/rtp_rtcp/source/source_tracker_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/rtp_rtcp/source/source_tracker.h"
12 
13 #include <algorithm>
14 #include <list>
15 #include <random>
16 #include <set>
17 #include <tuple>
18 #include <utility>
19 #include <vector>
20 
21 #include "absl/types/optional.h"
22 #include "api/rtp_headers.h"
23 #include "api/rtp_packet_info.h"
24 #include "api/rtp_packet_infos.h"
25 #include "system_wrappers/include/ntp_time.h"
26 #include "test/gmock.h"
27 #include "test/gtest.h"
28 
29 namespace webrtc {
30 namespace {
31 
32 using ::testing::Combine;
33 using ::testing::ElementsAre;
34 using ::testing::ElementsAreArray;
35 using ::testing::IsEmpty;
36 using ::testing::TestWithParam;
37 using ::testing::Values;
38 
39 constexpr size_t kPacketInfosCountMax = 5;
40 
41 // Simple "guaranteed to be correct" re-implementation of `SourceTracker` for
42 // dual-implementation testing purposes.
43 class ExpectedSourceTracker {
44  public:
ExpectedSourceTracker(Clock * clock)45   explicit ExpectedSourceTracker(Clock* clock) : clock_(clock) {}
46 
OnFrameDelivered(const RtpPacketInfos & packet_infos)47   void OnFrameDelivered(const RtpPacketInfos& packet_infos) {
48     const int64_t now_ms = clock_->TimeInMilliseconds();
49 
50     for (const auto& packet_info : packet_infos) {
51       RtpSource::Extensions extensions = {
52           packet_info.audio_level(), packet_info.absolute_capture_time(),
53           packet_info.local_capture_clock_offset()};
54 
55       for (const auto& csrc : packet_info.csrcs()) {
56         entries_.emplace_front(now_ms, csrc, RtpSourceType::CSRC,
57                                packet_info.rtp_timestamp(), extensions);
58       }
59 
60       entries_.emplace_front(now_ms, packet_info.ssrc(), RtpSourceType::SSRC,
61                              packet_info.rtp_timestamp(), extensions);
62     }
63 
64     PruneEntries(now_ms);
65   }
66 
GetSources() const67   std::vector<RtpSource> GetSources() const {
68     PruneEntries(clock_->TimeInMilliseconds());
69 
70     return std::vector<RtpSource>(entries_.begin(), entries_.end());
71   }
72 
73  private:
PruneEntries(int64_t now_ms) const74   void PruneEntries(int64_t now_ms) const {
75     const int64_t prune_ms = now_ms - 10000;  // 10 seconds
76 
77     std::set<std::pair<RtpSourceType, uint32_t>> seen;
78 
79     auto it = entries_.begin();
80     auto end = entries_.end();
81     while (it != end) {
82       auto next = it;
83       ++next;
84 
85       auto key = std::make_pair(it->source_type(), it->source_id());
86       if (!seen.insert(key).second || it->timestamp_ms() < prune_ms) {
87         entries_.erase(it);
88       }
89 
90       it = next;
91     }
92   }
93 
94   Clock* const clock_;
95 
96   mutable std::list<RtpSource> entries_;
97 };
98 
99 class SourceTrackerRandomTest
100     : public TestWithParam<std::tuple<uint32_t, uint32_t>> {
101  protected:
SourceTrackerRandomTest()102   SourceTrackerRandomTest()
103       : ssrcs_count_(std::get<0>(GetParam())),
104         csrcs_count_(std::get<1>(GetParam())),
105         generator_(42) {}
106 
GeneratePacketInfos()107   RtpPacketInfos GeneratePacketInfos() {
108     size_t count = std::uniform_int_distribution<size_t>(
109         1, kPacketInfosCountMax)(generator_);
110 
111     RtpPacketInfos::vector_type packet_infos;
112     for (size_t i = 0; i < count; ++i) {
113       packet_infos
114           .emplace_back(GenerateSsrc(), GenerateCsrcs(), GenerateRtpTimestamp(),
115                         GenerateReceiveTime())
116           .set_audio_level(GenerateAudioLevel())
117           .set_absolute_capture_time(GenerateAbsoluteCaptureTime())
118           .set_local_capture_clock_offset(GenerateLocalCaptureClockOffset());
119     }
120 
121     return RtpPacketInfos(std::move(packet_infos));
122   }
123 
GenerateClockAdvanceTimeMilliseconds()124   int64_t GenerateClockAdvanceTimeMilliseconds() {
125     double roll = std::uniform_real_distribution<double>(0.0, 1.0)(generator_);
126 
127     if (roll < 0.05) {
128       return 0;
129     }
130 
131     if (roll < 0.08) {
132       return SourceTracker::kTimeoutMs - 1;
133     }
134 
135     if (roll < 0.11) {
136       return SourceTracker::kTimeoutMs;
137     }
138 
139     if (roll < 0.19) {
140       return std::uniform_int_distribution<int64_t>(
141           SourceTracker::kTimeoutMs,
142           SourceTracker::kTimeoutMs * 1000)(generator_);
143     }
144 
145     return std::uniform_int_distribution<int64_t>(
146         1, SourceTracker::kTimeoutMs - 1)(generator_);
147   }
148 
149  private:
GenerateSsrc()150   uint32_t GenerateSsrc() {
151     return std::uniform_int_distribution<uint32_t>(1, ssrcs_count_)(generator_);
152   }
153 
GenerateCsrcs()154   std::vector<uint32_t> GenerateCsrcs() {
155     std::vector<uint32_t> csrcs;
156     for (size_t i = 1; i <= csrcs_count_ && csrcs.size() < kRtpCsrcSize; ++i) {
157       if (std::bernoulli_distribution(0.5)(generator_)) {
158         csrcs.push_back(i);
159       }
160     }
161 
162     return csrcs;
163   }
164 
GenerateRtpTimestamp()165   uint32_t GenerateRtpTimestamp() {
166     return std::uniform_int_distribution<uint32_t>()(generator_);
167   }
168 
GenerateAudioLevel()169   absl::optional<uint8_t> GenerateAudioLevel() {
170     if (std::bernoulli_distribution(0.25)(generator_)) {
171       return absl::nullopt;
172     }
173 
174     // Workaround for std::uniform_int_distribution<uint8_t> not being allowed.
175     return static_cast<uint8_t>(
176         std::uniform_int_distribution<uint16_t>()(generator_));
177   }
178 
GenerateAbsoluteCaptureTime()179   absl::optional<AbsoluteCaptureTime> GenerateAbsoluteCaptureTime() {
180     if (std::bernoulli_distribution(0.25)(generator_)) {
181       return absl::nullopt;
182     }
183 
184     AbsoluteCaptureTime value;
185 
186     value.absolute_capture_timestamp =
187         std::uniform_int_distribution<uint64_t>()(generator_);
188 
189     if (std::bernoulli_distribution(0.5)(generator_)) {
190       value.estimated_capture_clock_offset = absl::nullopt;
191     } else {
192       value.estimated_capture_clock_offset =
193           std::uniform_int_distribution<int64_t>()(generator_);
194     }
195 
196     return value;
197   }
198 
GenerateLocalCaptureClockOffset()199   absl::optional<TimeDelta> GenerateLocalCaptureClockOffset() {
200     if (std::bernoulli_distribution(0.5)(generator_)) {
201       return absl::nullopt;
202     }
203     return TimeDelta::Millis(
204         UQ32x32ToInt64Ms(std::uniform_int_distribution<int64_t>()(generator_)));
205   }
206 
GenerateReceiveTime()207   Timestamp GenerateReceiveTime() {
208     return Timestamp::Micros(
209         std::uniform_int_distribution<int64_t>()(generator_));
210   }
211 
212   const uint32_t ssrcs_count_;
213   const uint32_t csrcs_count_;
214 
215   std::mt19937 generator_;
216 };
217 
218 }  // namespace
219 
TEST_P(SourceTrackerRandomTest,RandomOperations)220 TEST_P(SourceTrackerRandomTest, RandomOperations) {
221   constexpr size_t kIterationsCount = 200;
222 
223   SimulatedClock clock(1000000000000ULL);
224   SourceTracker actual_tracker(&clock);
225   ExpectedSourceTracker expected_tracker(&clock);
226 
227   ASSERT_THAT(actual_tracker.GetSources(), IsEmpty());
228   ASSERT_THAT(expected_tracker.GetSources(), IsEmpty());
229 
230   for (size_t i = 0; i < kIterationsCount; ++i) {
231     RtpPacketInfos packet_infos = GeneratePacketInfos();
232 
233     actual_tracker.OnFrameDelivered(packet_infos);
234     expected_tracker.OnFrameDelivered(packet_infos);
235 
236     clock.AdvanceTimeMilliseconds(GenerateClockAdvanceTimeMilliseconds());
237 
238     ASSERT_THAT(actual_tracker.GetSources(),
239                 ElementsAreArray(expected_tracker.GetSources()));
240   }
241 }
242 
243 INSTANTIATE_TEST_SUITE_P(All,
244                          SourceTrackerRandomTest,
245                          Combine(/*ssrcs_count_=*/Values(1, 2, 4),
246                                  /*csrcs_count_=*/Values(0, 1, 3, 7)));
247 
TEST(SourceTrackerTest,StartEmpty)248 TEST(SourceTrackerTest, StartEmpty) {
249   SimulatedClock clock(1000000000000ULL);
250   SourceTracker tracker(&clock);
251 
252   EXPECT_THAT(tracker.GetSources(), IsEmpty());
253 }
254 
TEST(SourceTrackerTest,OnFrameDeliveredRecordsSourcesDistinctSsrcs)255 TEST(SourceTrackerTest, OnFrameDeliveredRecordsSourcesDistinctSsrcs) {
256   constexpr uint32_t kSsrc1 = 10;
257   constexpr uint32_t kSsrc2 = 11;
258   constexpr uint32_t kCsrcs0 = 20;
259   constexpr uint32_t kCsrcs1 = 21;
260   constexpr uint32_t kCsrcs2 = 22;
261   constexpr uint32_t kRtpTimestamp0 = 40;
262   constexpr uint32_t kRtpTimestamp1 = 50;
263   constexpr absl::optional<uint8_t> kAudioLevel0 = 50;
264   constexpr absl::optional<uint8_t> kAudioLevel1 = 20;
265   constexpr absl::optional<AbsoluteCaptureTime> kAbsoluteCaptureTime =
266       AbsoluteCaptureTime{/*absolute_capture_timestamp=*/12,
267                           /*estimated_capture_clock_offset=*/absl::nullopt};
268   constexpr absl::optional<TimeDelta> kLocalCaptureClockOffset = absl::nullopt;
269   constexpr Timestamp kReceiveTime0 = Timestamp::Millis(60);
270   constexpr Timestamp kReceiveTime1 = Timestamp::Millis(70);
271 
272   SimulatedClock clock(1000000000000ULL);
273   SourceTracker tracker(&clock);
274 
275   tracker.OnFrameDelivered(RtpPacketInfos(
276       {RtpPacketInfo(kSsrc1, {kCsrcs0, kCsrcs1}, kRtpTimestamp0, kReceiveTime0)
277            .set_audio_level(kAudioLevel0)
278            .set_absolute_capture_time(kAbsoluteCaptureTime)
279            .set_local_capture_clock_offset(kLocalCaptureClockOffset),
280        RtpPacketInfo(kSsrc2, {kCsrcs2}, kRtpTimestamp1, kReceiveTime1)
281            .set_audio_level(kAudioLevel1)
282            .set_absolute_capture_time(kAbsoluteCaptureTime)
283            .set_local_capture_clock_offset(kLocalCaptureClockOffset)}));
284 
285   int64_t timestamp_ms = clock.TimeInMilliseconds();
286   constexpr RtpSource::Extensions extensions0 = {
287       .audio_level = kAudioLevel0,
288       .absolute_capture_time = kAbsoluteCaptureTime,
289       .local_capture_clock_offset = kLocalCaptureClockOffset};
290   constexpr RtpSource::Extensions extensions1 = {
291       .audio_level = kAudioLevel1,
292       .absolute_capture_time = kAbsoluteCaptureTime,
293       .local_capture_clock_offset = kLocalCaptureClockOffset};
294 
295   EXPECT_THAT(tracker.GetSources(),
296               ElementsAre(RtpSource(timestamp_ms, kSsrc2, RtpSourceType::SSRC,
297                                     kRtpTimestamp1, extensions1),
298                           RtpSource(timestamp_ms, kCsrcs2, RtpSourceType::CSRC,
299                                     kRtpTimestamp1, extensions1),
300                           RtpSource(timestamp_ms, kSsrc1, RtpSourceType::SSRC,
301                                     kRtpTimestamp0, extensions0),
302                           RtpSource(timestamp_ms, kCsrcs1, RtpSourceType::CSRC,
303                                     kRtpTimestamp0, extensions0),
304                           RtpSource(timestamp_ms, kCsrcs0, RtpSourceType::CSRC,
305                                     kRtpTimestamp0, extensions0)));
306 }
307 
TEST(SourceTrackerTest,OnFrameDeliveredRecordsSourcesSameSsrc)308 TEST(SourceTrackerTest, OnFrameDeliveredRecordsSourcesSameSsrc) {
309   constexpr uint32_t kSsrc = 10;
310   constexpr uint32_t kCsrcs0 = 20;
311   constexpr uint32_t kCsrcs1 = 21;
312   constexpr uint32_t kCsrcs2 = 22;
313   constexpr uint32_t kRtpTimestamp0 = 40;
314   constexpr uint32_t kRtpTimestamp1 = 45;
315   constexpr uint32_t kRtpTimestamp2 = 50;
316   constexpr absl::optional<uint8_t> kAudioLevel0 = 50;
317   constexpr absl::optional<uint8_t> kAudioLevel1 = 20;
318   constexpr absl::optional<uint8_t> kAudioLevel2 = 10;
319   constexpr absl::optional<AbsoluteCaptureTime> kAbsoluteCaptureTime =
320       AbsoluteCaptureTime{/*absolute_capture_timestamp=*/12,
321                           /*estimated_capture_clock_offset=*/absl::nullopt};
322   constexpr absl::optional<TimeDelta> kLocalCaptureClockOffset = absl::nullopt;
323   constexpr Timestamp kReceiveTime0 = Timestamp::Millis(60);
324   constexpr Timestamp kReceiveTime1 = Timestamp::Millis(70);
325   constexpr Timestamp kReceiveTime2 = Timestamp::Millis(80);
326 
327   SimulatedClock clock(1000000000000ULL);
328   SourceTracker tracker(&clock);
329 
330   tracker.OnFrameDelivered(RtpPacketInfos({
331       RtpPacketInfo(kSsrc, {kCsrcs0, kCsrcs1}, kRtpTimestamp0, kReceiveTime0)
332           .set_audio_level(kAudioLevel0)
333           .set_absolute_capture_time(kAbsoluteCaptureTime)
334           .set_local_capture_clock_offset(kLocalCaptureClockOffset),
335       RtpPacketInfo(kSsrc, {kCsrcs2}, kRtpTimestamp1, kReceiveTime1)
336           .set_audio_level(kAudioLevel1)
337           .set_absolute_capture_time(kAbsoluteCaptureTime)
338           .set_local_capture_clock_offset(kLocalCaptureClockOffset),
339       RtpPacketInfo(kSsrc, {kCsrcs0}, kRtpTimestamp2, kReceiveTime2)
340           .set_audio_level(kAudioLevel2)
341           .set_absolute_capture_time(kAbsoluteCaptureTime)
342           .set_local_capture_clock_offset(kLocalCaptureClockOffset),
343   }));
344 
345   int64_t timestamp_ms = clock.TimeInMilliseconds();
346   constexpr RtpSource::Extensions extensions0 = {
347       .audio_level = kAudioLevel0,
348       .absolute_capture_time = kAbsoluteCaptureTime,
349       .local_capture_clock_offset = kLocalCaptureClockOffset};
350   constexpr RtpSource::Extensions extensions1 = {
351       .audio_level = kAudioLevel1,
352       .absolute_capture_time = kAbsoluteCaptureTime,
353       .local_capture_clock_offset = kLocalCaptureClockOffset};
354   constexpr RtpSource::Extensions extensions2 = {
355       .audio_level = kAudioLevel2,
356       .absolute_capture_time = kAbsoluteCaptureTime,
357       .local_capture_clock_offset = kLocalCaptureClockOffset};
358 
359   EXPECT_THAT(tracker.GetSources(),
360               ElementsAre(RtpSource(timestamp_ms, kSsrc, RtpSourceType::SSRC,
361                                     kRtpTimestamp2, extensions2),
362                           RtpSource(timestamp_ms, kCsrcs0, RtpSourceType::CSRC,
363                                     kRtpTimestamp2, extensions2),
364                           RtpSource(timestamp_ms, kCsrcs2, RtpSourceType::CSRC,
365                                     kRtpTimestamp1, extensions1),
366                           RtpSource(timestamp_ms, kCsrcs1, RtpSourceType::CSRC,
367                                     kRtpTimestamp0, extensions0)));
368 }
369 
TEST(SourceTrackerTest,OnFrameDeliveredUpdatesSources)370 TEST(SourceTrackerTest, OnFrameDeliveredUpdatesSources) {
371   constexpr uint32_t kSsrc1 = 10;
372   constexpr uint32_t kSsrc2 = 11;
373   constexpr uint32_t kCsrcs0 = 20;
374   constexpr uint32_t kCsrcs1 = 21;
375   constexpr uint32_t kCsrcs2 = 22;
376   constexpr uint32_t kRtpTimestamp0 = 40;
377   constexpr uint32_t kRtpTimestamp1 = 41;
378   constexpr uint32_t kRtpTimestamp2 = 42;
379   constexpr absl::optional<uint8_t> kAudioLevel0 = 50;
380   constexpr absl::optional<uint8_t> kAudioLevel1 = absl::nullopt;
381   constexpr absl::optional<uint8_t> kAudioLevel2 = 10;
382   constexpr absl::optional<AbsoluteCaptureTime> kAbsoluteCaptureTime0 =
383       AbsoluteCaptureTime{12, 34};
384   constexpr absl::optional<AbsoluteCaptureTime> kAbsoluteCaptureTime1 =
385       AbsoluteCaptureTime{56, 78};
386   constexpr absl::optional<AbsoluteCaptureTime> kAbsoluteCaptureTime2 =
387       AbsoluteCaptureTime{89, 90};
388   constexpr absl::optional<TimeDelta> kLocalCaptureClockOffset0 =
389       TimeDelta::Millis(123);
390   constexpr absl::optional<TimeDelta> kLocalCaptureClockOffset1 =
391       TimeDelta::Millis(456);
392   constexpr absl::optional<TimeDelta> kLocalCaptureClockOffset2 =
393       TimeDelta::Millis(789);
394   constexpr Timestamp kReceiveTime0 = Timestamp::Millis(60);
395   constexpr Timestamp kReceiveTime1 = Timestamp::Millis(61);
396   constexpr Timestamp kReceiveTime2 = Timestamp::Millis(62);
397 
398   constexpr RtpSource::Extensions extensions0 = {
399       .audio_level = kAudioLevel0,
400       .absolute_capture_time = kAbsoluteCaptureTime0,
401       .local_capture_clock_offset = kLocalCaptureClockOffset0};
402   constexpr RtpSource::Extensions extensions1 = {
403       .audio_level = kAudioLevel1,
404       .absolute_capture_time = kAbsoluteCaptureTime1,
405       .local_capture_clock_offset = kLocalCaptureClockOffset1};
406   constexpr RtpSource::Extensions extensions2 = {
407       .audio_level = kAudioLevel2,
408       .absolute_capture_time = kAbsoluteCaptureTime2,
409       .local_capture_clock_offset = kLocalCaptureClockOffset2};
410 
411   SimulatedClock clock(1000000000000ULL);
412   SourceTracker tracker(&clock);
413 
414   tracker.OnFrameDelivered(RtpPacketInfos(
415       {RtpPacketInfo(kSsrc1, {kCsrcs0, kCsrcs1}, kRtpTimestamp0, kReceiveTime0)
416            .set_audio_level(kAudioLevel0)
417            .set_absolute_capture_time(kAbsoluteCaptureTime0)
418            .set_local_capture_clock_offset(kLocalCaptureClockOffset0)}));
419 
420   int64_t timestamp_ms_0 = clock.TimeInMilliseconds();
421   EXPECT_THAT(
422       tracker.GetSources(),
423       ElementsAre(RtpSource(timestamp_ms_0, kSsrc1, RtpSourceType::SSRC,
424                             kRtpTimestamp0, extensions0),
425                   RtpSource(timestamp_ms_0, kCsrcs1, RtpSourceType::CSRC,
426                             kRtpTimestamp0, extensions0),
427                   RtpSource(timestamp_ms_0, kCsrcs0, RtpSourceType::CSRC,
428                             kRtpTimestamp0, extensions0)));
429 
430   // Deliver packets with updated sources.
431 
432   clock.AdvanceTimeMilliseconds(17);
433   tracker.OnFrameDelivered(RtpPacketInfos(
434       {RtpPacketInfo(kSsrc1, {kCsrcs0, kCsrcs2}, kRtpTimestamp1, kReceiveTime1)
435            .set_audio_level(kAudioLevel1)
436            .set_absolute_capture_time(kAbsoluteCaptureTime1)
437            .set_local_capture_clock_offset(kLocalCaptureClockOffset1)}));
438 
439   int64_t timestamp_ms_1 = clock.TimeInMilliseconds();
440 
441   EXPECT_THAT(
442       tracker.GetSources(),
443       ElementsAre(RtpSource(timestamp_ms_1, kSsrc1, RtpSourceType::SSRC,
444                             kRtpTimestamp1, extensions1),
445                   RtpSource(timestamp_ms_1, kCsrcs2, RtpSourceType::CSRC,
446                             kRtpTimestamp1, extensions1),
447                   RtpSource(timestamp_ms_1, kCsrcs0, RtpSourceType::CSRC,
448                             kRtpTimestamp1, extensions1),
449                   RtpSource(timestamp_ms_0, kCsrcs1, RtpSourceType::CSRC,
450                             kRtpTimestamp0, extensions0)));
451 
452   // Deliver more packets with update csrcs and a new ssrc.
453   clock.AdvanceTimeMilliseconds(17);
454 
455   tracker.OnFrameDelivered(RtpPacketInfos(
456       {RtpPacketInfo(kSsrc2, {kCsrcs0}, kRtpTimestamp2, kReceiveTime2)
457            .set_audio_level(kAudioLevel2)
458            .set_absolute_capture_time(kAbsoluteCaptureTime2)
459            .set_local_capture_clock_offset(kLocalCaptureClockOffset2)}));
460 
461   int64_t timestamp_ms_2 = clock.TimeInMilliseconds();
462 
463   EXPECT_THAT(
464       tracker.GetSources(),
465       ElementsAre(RtpSource(timestamp_ms_2, kSsrc2, RtpSourceType::SSRC,
466                             kRtpTimestamp2, extensions2),
467                   RtpSource(timestamp_ms_2, kCsrcs0, RtpSourceType::CSRC,
468                             kRtpTimestamp2, extensions2),
469                   RtpSource(timestamp_ms_1, kSsrc1, RtpSourceType::SSRC,
470                             kRtpTimestamp1, extensions1),
471                   RtpSource(timestamp_ms_1, kCsrcs2, RtpSourceType::CSRC,
472                             kRtpTimestamp1, extensions1),
473                   RtpSource(timestamp_ms_0, kCsrcs1, RtpSourceType::CSRC,
474                             kRtpTimestamp0, extensions0)));
475 }
476 
TEST(SourceTrackerTest,TimedOutSourcesAreRemoved)477 TEST(SourceTrackerTest, TimedOutSourcesAreRemoved) {
478   constexpr uint32_t kSsrc = 10;
479   constexpr uint32_t kCsrcs0 = 20;
480   constexpr uint32_t kCsrcs1 = 21;
481   constexpr uint32_t kCsrcs2 = 22;
482   constexpr uint32_t kRtpTimestamp0 = 40;
483   constexpr uint32_t kRtpTimestamp1 = 41;
484   constexpr absl::optional<uint8_t> kAudioLevel0 = 50;
485   constexpr absl::optional<uint8_t> kAudioLevel1 = absl::nullopt;
486   constexpr absl::optional<AbsoluteCaptureTime> kAbsoluteCaptureTime0 =
487       AbsoluteCaptureTime{12, 34};
488   constexpr absl::optional<AbsoluteCaptureTime> kAbsoluteCaptureTime1 =
489       AbsoluteCaptureTime{56, 78};
490   constexpr absl::optional<TimeDelta> kLocalCaptureClockOffset0 =
491       TimeDelta::Millis(123);
492   constexpr absl::optional<TimeDelta> kLocalCaptureClockOffset1 =
493       TimeDelta::Millis(456);
494   constexpr Timestamp kReceiveTime0 = Timestamp::Millis(60);
495   constexpr Timestamp kReceiveTime1 = Timestamp::Millis(61);
496 
497   SimulatedClock clock(1000000000000ULL);
498   SourceTracker tracker(&clock);
499 
500   tracker.OnFrameDelivered(RtpPacketInfos(
501       {RtpPacketInfo(kSsrc, {kCsrcs0, kCsrcs1}, kRtpTimestamp0, kReceiveTime0)
502            .set_audio_level(kAudioLevel0)
503            .set_absolute_capture_time(kAbsoluteCaptureTime0)
504            .set_local_capture_clock_offset(kLocalCaptureClockOffset0)}));
505 
506   clock.AdvanceTimeMilliseconds(17);
507 
508   tracker.OnFrameDelivered(RtpPacketInfos(
509       {RtpPacketInfo(kSsrc, {kCsrcs0, kCsrcs2}, kRtpTimestamp1, kReceiveTime1)
510            .set_audio_level(kAudioLevel1)
511            .set_absolute_capture_time(kAbsoluteCaptureTime1)
512            .set_local_capture_clock_offset(kLocalCaptureClockOffset1)}));
513 
514   int64_t timestamp_ms_1 = clock.TimeInMilliseconds();
515 
516   clock.AdvanceTimeMilliseconds(SourceTracker::kTimeoutMs);
517 
518   constexpr RtpSource::Extensions extensions1 = {
519       .audio_level = kAudioLevel1,
520       .absolute_capture_time = kAbsoluteCaptureTime1,
521       .local_capture_clock_offset = kLocalCaptureClockOffset1};
522 
523   EXPECT_THAT(
524       tracker.GetSources(),
525       ElementsAre(RtpSource(timestamp_ms_1, kSsrc, RtpSourceType::SSRC,
526                             kRtpTimestamp1, extensions1),
527                   RtpSource(timestamp_ms_1, kCsrcs2, RtpSourceType::CSRC,
528                             kRtpTimestamp1, extensions1),
529                   RtpSource(timestamp_ms_1, kCsrcs0, RtpSourceType::CSRC,
530                             kRtpTimestamp1, extensions1)));
531 }
532 
533 }  // namespace webrtc
534