blob: 2878b11d4186e2f889da7187911947ff11fb59f3 [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();
37 entry.rtp_timestamp = packet_info.rtp_timestamp();
38 }
39
40 SourceKey key(RtpSourceType::SSRC, packet_info.ssrc());
41 SourceEntry& entry = UpdateEntry(key);
42
43 entry.timestamp_ms = now_ms;
44 entry.audio_level = packet_info.audio_level();
45 entry.rtp_timestamp = packet_info.rtp_timestamp();
46 }
47
48 PruneEntries(now_ms);
49}
50
51std::vector<RtpSource> SourceTracker::GetSources() const {
52 std::vector<RtpSource> sources;
53
54 int64_t now_ms = clock_->TimeInMilliseconds();
55 rtc::CritScope lock_scope(&lock_);
56
57 PruneEntries(now_ms);
58
59 for (const auto& pair : list_) {
60 const SourceKey& key = pair.first;
61 const SourceEntry& entry = pair.second;
62
63 sources.emplace_back(entry.timestamp_ms, key.source, key.source_type,
64 entry.audio_level, entry.rtp_timestamp);
65 }
66
67 return sources;
68}
69
70SourceTracker::SourceEntry& SourceTracker::UpdateEntry(const SourceKey& key) {
71 // We intentionally do |find() + emplace()|, instead of checking the return
72 // value of |emplace()|, for performance reasons. It's much more likely for
73 // the key to already exist than for it not to.
74 auto map_it = map_.find(key);
75 if (map_it == map_.end()) {
76 // Insert a new entry at the front of the list.
77 list_.emplace_front(key, SourceEntry());
78 map_.emplace(key, list_.begin());
79 } else if (map_it->second != list_.begin()) {
80 // Move the old entry to the front of the list.
81 list_.splice(list_.begin(), list_, map_it->second);
82 }
83
84 return list_.front().second;
85}
86
87void SourceTracker::PruneEntries(int64_t now_ms) const {
88 int64_t prune_ms = now_ms - kTimeoutMs;
89
90 while (!list_.empty() && list_.back().second.timestamp_ms < prune_ms) {
91 map_.erase(list_.back().first);
92 list_.pop_back();
93 }
94}
95
96} // namespace webrtc