tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

source_tracker.cc (3981B)


      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 <cstdint>
     14 #include <utility>
     15 #include <vector>
     16 
     17 #include "api/rtp_packet_info.h"
     18 #include "api/rtp_packet_infos.h"
     19 #include "api/transport/rtp/rtp_source.h"
     20 #include "api/units/timestamp.h"
     21 #include "rtc_base/checks.h"
     22 #include "rtc_base/trace_event.h"
     23 #include "system_wrappers/include/clock.h"
     24 
     25 namespace webrtc {
     26 
     27 SourceTracker::SourceTracker(Clock* clock) : clock_(clock) {
     28  RTC_DCHECK(clock_);
     29 }
     30 
     31 void SourceTracker::OnFrameDelivered(const RtpPacketInfos& packet_infos,
     32                                     Timestamp delivery_time) {
     33  TRACE_EVENT0("webrtc", "SourceTracker::OnFrameDelivered");
     34  if (packet_infos.empty()) {
     35    return;
     36  }
     37  if (delivery_time.IsInfinite()) {
     38    delivery_time = clock_->CurrentTime();
     39  }
     40 
     41  for (const RtpPacketInfo& packet_info : packet_infos) {
     42    for (uint32_t csrc : packet_info.csrcs()) {
     43      SourceKey key(RtpSourceType::CSRC, csrc);
     44      SourceEntry& entry = UpdateEntry(key);
     45 
     46      const auto packet_time = packet_info.receive_time();
     47      entry.timestamp = packet_time.ms() ? packet_time : delivery_time;
     48      entry.audio_level = packet_info.audio_level();
     49      entry.absolute_capture_time = packet_info.absolute_capture_time();
     50      entry.local_capture_clock_offset =
     51          packet_info.local_capture_clock_offset();
     52      entry.rtp_timestamp = packet_info.rtp_timestamp();
     53    }
     54 
     55    SourceKey key(RtpSourceType::SSRC, packet_info.ssrc());
     56    SourceEntry& entry = UpdateEntry(key);
     57 
     58    entry.timestamp = delivery_time;
     59    entry.audio_level = packet_info.audio_level();
     60    entry.absolute_capture_time = packet_info.absolute_capture_time();
     61    entry.local_capture_clock_offset = packet_info.local_capture_clock_offset();
     62    entry.rtp_timestamp = packet_info.rtp_timestamp();
     63  }
     64 
     65  PruneEntries(delivery_time);
     66 }
     67 
     68 std::vector<RtpSource> SourceTracker::GetSources() const {
     69  PruneEntries(clock_->CurrentTime());
     70 
     71  std::vector<RtpSource> sources;
     72  for (const auto& pair : list_) {
     73    const SourceKey& key = pair.first;
     74    const SourceEntry& entry = pair.second;
     75 
     76    sources.emplace_back(
     77        entry.timestamp, key.source, key.source_type, entry.rtp_timestamp,
     78        RtpSource::Extensions{
     79            .audio_level = entry.audio_level,
     80            .absolute_capture_time = entry.absolute_capture_time,
     81            .local_capture_clock_offset = entry.local_capture_clock_offset});
     82  }
     83 
     84  std::sort(sources.begin(), sources.end(), [](const auto &a, const auto &b){
     85    return a.timestamp().ms() > b.timestamp().ms();
     86  });
     87 
     88  return sources;
     89 }
     90 
     91 SourceTracker::SourceEntry& SourceTracker::UpdateEntry(const SourceKey& key) {
     92  // We intentionally do |find() + emplace()|, instead of checking the return
     93  // value of `emplace()`, for performance reasons. It's much more likely for
     94  // the key to already exist than for it not to.
     95  auto map_it = map_.find(key);
     96  if (map_it == map_.end()) {
     97    // Insert a new entry at the front of the list.
     98    list_.emplace_front(key, SourceEntry());
     99    map_.emplace(key, list_.begin());
    100  } else if (map_it->second != list_.begin()) {
    101    // Move the old entry to the front of the list.
    102    list_.splice(list_.begin(), list_, map_it->second);
    103  }
    104 
    105  return list_.front().second;
    106 }
    107 
    108 void SourceTracker::PruneEntries(Timestamp now) const {
    109  if (now < Timestamp::Zero() + kTimeout) {
    110    return;
    111  }
    112  Timestamp prune = now - kTimeout;
    113  while (!list_.empty() && list_.back().second.timestamp < prune) {
    114    map_.erase(list_.back().first);
    115    list_.pop_back();
    116  }
    117 }
    118 
    119 }  // namespace webrtc