blob: 22b887c5d2986ce7ca68738275f61e25c11494bf [file] [log] [blame]
Chen Xing9c16af72019-06-12 12:13:22 +02001/*
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 <utility>
15
16namespace webrtc {
17
18constexpr int64_t SourceTracker::kTimeoutMs;
19
20SourceTracker::SourceTracker(Clock* clock) : clock_(clock) {}
21
22void SourceTracker::OnFrameDelivered(const RtpPacketInfos& packet_infos) {
23 if (packet_infos.empty()) {
24 return;
25 }
26
27 int64_t now_ms = clock_->TimeInMilliseconds();
28 rtc::CritScope lock_scope(&lock_);
29
30 for (const auto& packet_info : packet_infos) {
31 for (uint32_t csrc : packet_info.csrcs()) {
32 SourceKey key(RtpSourceType::CSRC, csrc);
33 SourceEntry& entry = UpdateEntry(key);
34
35 entry.timestamp_ms = now_ms;
36 entry.audio_level = packet_info.audio_level();
Ruslan Burakovd51cc7b2019-11-20 16:48:34 +010037 entry.absolute_capture_time = packet_info.absolute_capture_time();
Chen Xing9c16af72019-06-12 12:13:22 +020038 entry.rtp_timestamp = packet_info.rtp_timestamp();
39 }
40
41 SourceKey key(RtpSourceType::SSRC, packet_info.ssrc());
42 SourceEntry& entry = UpdateEntry(key);
43
44 entry.timestamp_ms = now_ms;
45 entry.audio_level = packet_info.audio_level();
Ruslan Burakovd51cc7b2019-11-20 16:48:34 +010046 entry.absolute_capture_time = packet_info.absolute_capture_time();
Chen Xing9c16af72019-06-12 12:13:22 +020047 entry.rtp_timestamp = packet_info.rtp_timestamp();
48 }
49
50 PruneEntries(now_ms);
51}
52
53std::vector<RtpSource> SourceTracker::GetSources() const {
54 std::vector<RtpSource> sources;
55
56 int64_t now_ms = clock_->TimeInMilliseconds();
57 rtc::CritScope lock_scope(&lock_);
58
59 PruneEntries(now_ms);
60
61 for (const auto& pair : list_) {
62 const SourceKey& key = pair.first;
63 const SourceEntry& entry = pair.second;
64
Ruslan Burakovd51cc7b2019-11-20 16:48:34 +010065 sources.emplace_back(
66 entry.timestamp_ms, key.source, key.source_type, entry.rtp_timestamp,
67 RtpSource::Extensions{entry.audio_level, entry.absolute_capture_time});
Chen Xing9c16af72019-06-12 12:13:22 +020068 }
69
70 return sources;
71}
72
73SourceTracker::SourceEntry& SourceTracker::UpdateEntry(const SourceKey& key) {
74 // We intentionally do |find() + emplace()|, instead of checking the return
75 // value of |emplace()|, for performance reasons. It's much more likely for
76 // the key to already exist than for it not to.
77 auto map_it = map_.find(key);
78 if (map_it == map_.end()) {
79 // Insert a new entry at the front of the list.
80 list_.emplace_front(key, SourceEntry());
81 map_.emplace(key, list_.begin());
82 } else if (map_it->second != list_.begin()) {
83 // Move the old entry to the front of the list.
84 list_.splice(list_.begin(), list_, map_it->second);
85 }
86
87 return list_.front().second;
88}
89
90void SourceTracker::PruneEntries(int64_t now_ms) const {
91 int64_t prune_ms = now_ms - kTimeoutMs;
92
93 while (!list_.empty() && list_.back().second.timestamp_ms < prune_ms) {
94 map_.erase(list_.back().first);
95 list_.pop_back();
96 }
97}
98
99} // namespace webrtc