/*
 *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/rtp_rtcp/source/source_tracker.h"

#include <algorithm>
#include <utility>

namespace webrtc {

constexpr int64_t SourceTracker::kTimeoutMs;

SourceTracker::SourceTracker(Clock* clock) : clock_(clock) {}

void SourceTracker::OnFrameDelivered(const RtpPacketInfos& packet_infos) {
  if (packet_infos.empty()) {
    return;
  }

  int64_t now_ms = clock_->TimeInMilliseconds();
  rtc::CritScope lock_scope(&lock_);

  for (const auto& packet_info : packet_infos) {
    for (uint32_t csrc : packet_info.csrcs()) {
      SourceKey key(RtpSourceType::CSRC, csrc);
      SourceEntry& entry = UpdateEntry(key);

      entry.timestamp_ms = now_ms;
      entry.audio_level = packet_info.audio_level();
      entry.absolute_capture_time = packet_info.absolute_capture_time();
      entry.rtp_timestamp = packet_info.rtp_timestamp();
    }

    SourceKey key(RtpSourceType::SSRC, packet_info.ssrc());
    SourceEntry& entry = UpdateEntry(key);

    entry.timestamp_ms = now_ms;
    entry.audio_level = packet_info.audio_level();
    entry.absolute_capture_time = packet_info.absolute_capture_time();
    entry.rtp_timestamp = packet_info.rtp_timestamp();
  }

  PruneEntries(now_ms);
}

std::vector<RtpSource> SourceTracker::GetSources() const {
  std::vector<RtpSource> sources;

  int64_t now_ms = clock_->TimeInMilliseconds();
  rtc::CritScope lock_scope(&lock_);

  PruneEntries(now_ms);

  for (const auto& pair : list_) {
    const SourceKey& key = pair.first;
    const SourceEntry& entry = pair.second;

    sources.emplace_back(
        entry.timestamp_ms, key.source, key.source_type, entry.rtp_timestamp,
        RtpSource::Extensions{entry.audio_level, entry.absolute_capture_time});
  }

  return sources;
}

SourceTracker::SourceEntry& SourceTracker::UpdateEntry(const SourceKey& key) {
  // We intentionally do |find() + emplace()|, instead of checking the return
  // value of |emplace()|, for performance reasons. It's much more likely for
  // the key to already exist than for it not to.
  auto map_it = map_.find(key);
  if (map_it == map_.end()) {
    // Insert a new entry at the front of the list.
    list_.emplace_front(key, SourceEntry());
    map_.emplace(key, list_.begin());
  } else if (map_it->second != list_.begin()) {
    // Move the old entry to the front of the list.
    list_.splice(list_.begin(), list_, map_it->second);
  }

  return list_.front().second;
}

void SourceTracker::PruneEntries(int64_t now_ms) const {
  int64_t prune_ms = now_ms - kTimeoutMs;

  while (!list_.empty() && list_.back().second.timestamp_ms < prune_ms) {
    map_.erase(list_.back().first);
    list_.pop_back();
  }
}

}  // namespace webrtc
