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