• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <utility>
15 
16 #include "rtc_base/trace_event.h"
17 
18 namespace webrtc {
19 
20 constexpr int64_t SourceTracker::kTimeoutMs;
21 
SourceTracker(Clock * clock)22 SourceTracker::SourceTracker(Clock* clock) : clock_(clock) {}
23 
OnFrameDelivered(const RtpPacketInfos & packet_infos)24 void SourceTracker::OnFrameDelivered(const RtpPacketInfos& packet_infos) {
25   if (packet_infos.empty()) {
26     return;
27   }
28 
29   TRACE_EVENT0("webrtc", "SourceTracker::OnFrameDelivered");
30 
31   int64_t now_ms = clock_->TimeInMilliseconds();
32   MutexLock lock_scope(&lock_);
33 
34   for (const RtpPacketInfo& packet_info : packet_infos) {
35     for (uint32_t csrc : packet_info.csrcs()) {
36       SourceKey key(RtpSourceType::CSRC, csrc);
37       SourceEntry& entry = UpdateEntry(key);
38 
39       entry.timestamp_ms = now_ms;
40       entry.audio_level = packet_info.audio_level();
41       entry.absolute_capture_time = packet_info.absolute_capture_time();
42       entry.local_capture_clock_offset =
43           packet_info.local_capture_clock_offset();
44       entry.rtp_timestamp = packet_info.rtp_timestamp();
45     }
46 
47     SourceKey key(RtpSourceType::SSRC, packet_info.ssrc());
48     SourceEntry& entry = UpdateEntry(key);
49 
50     entry.timestamp_ms = now_ms;
51     entry.audio_level = packet_info.audio_level();
52     entry.absolute_capture_time = packet_info.absolute_capture_time();
53     entry.local_capture_clock_offset = packet_info.local_capture_clock_offset();
54     entry.rtp_timestamp = packet_info.rtp_timestamp();
55   }
56 
57   PruneEntries(now_ms);
58 }
59 
GetSources() const60 std::vector<RtpSource> SourceTracker::GetSources() const {
61   std::vector<RtpSource> sources;
62 
63   int64_t now_ms = clock_->TimeInMilliseconds();
64   MutexLock lock_scope(&lock_);
65 
66   PruneEntries(now_ms);
67 
68   for (const auto& pair : list_) {
69     const SourceKey& key = pair.first;
70     const SourceEntry& entry = pair.second;
71 
72     sources.emplace_back(
73         entry.timestamp_ms, key.source, key.source_type, entry.rtp_timestamp,
74         RtpSource::Extensions{
75             .audio_level = entry.audio_level,
76             .absolute_capture_time = entry.absolute_capture_time,
77             .local_capture_clock_offset = entry.local_capture_clock_offset});
78   }
79 
80   return sources;
81 }
82 
UpdateEntry(const SourceKey & key)83 SourceTracker::SourceEntry& SourceTracker::UpdateEntry(const SourceKey& key) {
84   // We intentionally do |find() + emplace()|, instead of checking the return
85   // value of `emplace()`, for performance reasons. It's much more likely for
86   // the key to already exist than for it not to.
87   auto map_it = map_.find(key);
88   if (map_it == map_.end()) {
89     // Insert a new entry at the front of the list.
90     list_.emplace_front(key, SourceEntry());
91     map_.emplace(key, list_.begin());
92   } else if (map_it->second != list_.begin()) {
93     // Move the old entry to the front of the list.
94     list_.splice(list_.begin(), list_, map_it->second);
95   }
96 
97   return list_.front().second;
98 }
99 
PruneEntries(int64_t now_ms) const100 void SourceTracker::PruneEntries(int64_t now_ms) const {
101   int64_t prune_ms = now_ms - kTimeoutMs;
102 
103   while (!list_.empty() && list_.back().second.timestamp_ms < prune_ms) {
104     map_.erase(list_.back().first);
105     list_.pop_back();
106   }
107 }
108 
109 }  // namespace webrtc
110