/*
 *  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 "test/pc/e2e/analyzer/video/default_video_quality_analyzer.h"

#include <algorithm>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "api/array_view.h"
#include "api/numerics/samples_stats_counter.h"
#include "api/test/metrics/metric.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "api/video/video_frame.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_frame_in_flight.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_internal_shared_objects.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer_stream_state.h"
#include "test/pc/e2e/metric_metadata_keys.h"

namespace webrtc {
namespace {

using ::webrtc::test::ImprovementDirection;
using ::webrtc::test::Unit;
using ::webrtc::webrtc_pc_e2e::MetricMetadataKey;

constexpr int kBitsInByte = 8;
constexpr absl::string_view kSkipRenderedFrameReasonProcessed = "processed";
constexpr absl::string_view kSkipRenderedFrameReasonRendered = "rendered";
constexpr absl::string_view kSkipRenderedFrameReasonDropped =
    "considered dropped";

void LogFrameCounters(const std::string& name, const FrameCounters& counters) {
  RTC_LOG(LS_INFO) << "[" << name
                   << "] Captured         : " << counters.captured;
  RTC_LOG(LS_INFO) << "[" << name
                   << "] Pre encoded      : " << counters.pre_encoded;
  RTC_LOG(LS_INFO) << "[" << name
                   << "] Encoded          : " << counters.encoded;
  RTC_LOG(LS_INFO) << "[" << name
                   << "] Received         : " << counters.received;
  RTC_LOG(LS_INFO) << "[" << name
                   << "] Decoded          : " << counters.decoded;
  RTC_LOG(LS_INFO) << "[" << name
                   << "] Rendered         : " << counters.rendered;
  RTC_LOG(LS_INFO) << "[" << name
                   << "] Dropped          : " << counters.dropped;
  RTC_LOG(LS_INFO) << "[" << name
                   << "] Failed to decode : " << counters.failed_to_decode;
}

void LogStreamInternalStats(const std::string& name,
                            const StreamStats& stats,
                            Timestamp start_time) {
  for (const auto& entry : stats.dropped_by_phase) {
    RTC_LOG(LS_INFO) << "[" << name << "] Dropped at " << ToString(entry.first)
                     << ": " << entry.second;
  }
  Timestamp first_encoded_frame_time = Timestamp::PlusInfinity();
  for (const StreamCodecInfo& encoder : stats.encoders) {
    RTC_DCHECK(encoder.switched_on_at.IsFinite());
    RTC_DCHECK(encoder.switched_from_at.IsFinite());
    if (first_encoded_frame_time.IsInfinite()) {
      first_encoded_frame_time = encoder.switched_on_at;
    }
    RTC_LOG(LS_INFO)
        << "[" << name << "] Used encoder: \"" << encoder.codec_name
        << "\" used from (frame_id=" << encoder.first_frame_id
        << "; from_stream_start="
        << (encoder.switched_on_at - stats.stream_started_time).ms()
        << "ms, from_call_start=" << (encoder.switched_on_at - start_time).ms()
        << "ms) until (frame_id=" << encoder.last_frame_id
        << "; from_stream_start="
        << (encoder.switched_from_at - stats.stream_started_time).ms()
        << "ms, from_call_start="
        << (encoder.switched_from_at - start_time).ms() << "ms)";
  }
  for (const StreamCodecInfo& decoder : stats.decoders) {
    RTC_DCHECK(decoder.switched_on_at.IsFinite());
    RTC_DCHECK(decoder.switched_from_at.IsFinite());
    RTC_LOG(LS_INFO)
        << "[" << name << "] Used decoder: \"" << decoder.codec_name
        << "\" used from (frame_id=" << decoder.first_frame_id
        << "; from_stream_start="
        << (decoder.switched_on_at - stats.stream_started_time).ms()
        << "ms, from_call_start=" << (decoder.switched_on_at - start_time).ms()
        << "ms) until (frame_id=" << decoder.last_frame_id
        << "; from_stream_start="
        << (decoder.switched_from_at - stats.stream_started_time).ms()
        << "ms, from_call_start="
        << (decoder.switched_from_at - start_time).ms() << "ms)";
  }
}

template <typename T>
absl::optional<T> MaybeGetValue(const std::map<size_t, T>& map, size_t key) {
  auto it = map.find(key);
  if (it == map.end()) {
    return absl::nullopt;
  }
  return it->second;
}

SamplesStatsCounter::StatsSample StatsSample(double value,
                                             Timestamp sampling_time) {
  return SamplesStatsCounter::StatsSample{value, sampling_time};
}

}  // namespace

DefaultVideoQualityAnalyzer::DefaultVideoQualityAnalyzer(
    webrtc::Clock* clock,
    test::MetricsLogger* metrics_logger,
    DefaultVideoQualityAnalyzerOptions options)
    : options_(options),
      clock_(clock),
      metrics_logger_(metrics_logger),
      frames_comparator_(clock, cpu_measurer_, options) {
  RTC_CHECK(metrics_logger_);
}

DefaultVideoQualityAnalyzer::~DefaultVideoQualityAnalyzer() {
  Stop();
}

void DefaultVideoQualityAnalyzer::Start(
    std::string test_case_name,
    rtc::ArrayView<const std::string> peer_names,
    int max_threads_count) {
  test_label_ = std::move(test_case_name);
  frames_comparator_.Start(max_threads_count);
  {
    MutexLock lock(&mutex_);
    peers_ = std::make_unique<NamesCollection>(peer_names);
    RTC_CHECK(start_time_.IsMinusInfinity());

    RTC_CHECK_EQ(state_, State::kNew)
        << "DefaultVideoQualityAnalyzer is already started";
    state_ = State::kActive;
    start_time_ = Now();
  }
}

uint16_t DefaultVideoQualityAnalyzer::OnFrameCaptured(
    absl::string_view peer_name,
    const std::string& stream_label,
    const webrtc::VideoFrame& frame) {
  // `next_frame_id` is atomic, so we needn't lock here.
  Timestamp captured_time = Now();
  Timestamp start_time = Timestamp::MinusInfinity();
  size_t peer_index = -1;
  size_t peers_count = -1;
  size_t stream_index;
  uint16_t frame_id = VideoFrame::kNotSetId;
  {
    MutexLock lock(&mutex_);
    frame_id = GetNextFrameId();
    RTC_CHECK_EQ(state_, State::kActive)
        << "DefaultVideoQualityAnalyzer has to be started before use";
    // Create a local copy of `start_time_`, peer's index and total peers count
    // to access it without holding a `mutex_` during access to
    // `frames_comparator_`.
    start_time = start_time_;
    peer_index = peers_->index(peer_name);
    peers_count = peers_->size();
    stream_index = streams_.AddIfAbsent(stream_label);
  }
  // Ensure stats for this stream exists.
  frames_comparator_.EnsureStatsForStream(stream_index, peer_index, peers_count,
                                          captured_time, start_time);
  {
    MutexLock lock(&mutex_);
    stream_to_sender_[stream_index] = peer_index;
    frame_counters_.captured++;
    for (size_t i : peers_->GetAllIndexes()) {
      if (i != peer_index || options_.enable_receive_own_stream) {
        InternalStatsKey key(stream_index, peer_index, i);
        stream_frame_counters_[key].captured++;
      }
    }

    std::set<size_t> frame_receivers_indexes = peers_->GetPresentIndexes();
    if (!options_.enable_receive_own_stream) {
      frame_receivers_indexes.erase(peer_index);
    }

    auto state_it = stream_states_.find(stream_index);
    if (state_it == stream_states_.end()) {
      stream_states_.emplace(
          stream_index,
          StreamState(peer_index, frame_receivers_indexes, captured_time));
    }
    StreamState* state = &stream_states_.at(stream_index);
    state->PushBack(frame_id);
    // Update frames in flight info.
    auto it = captured_frames_in_flight_.find(frame_id);
    if (it != captured_frames_in_flight_.end()) {
      // If we overflow uint16_t and hit previous frame id and this frame is
      // still in flight, it means that this stream wasn't rendered for long
      // time and we need to process existing frame as dropped.
      for (size_t i : peers_->GetPresentIndexes()) {
        if (i == peer_index && !options_.enable_receive_own_stream) {
          continue;
        }

        uint16_t oldest_frame_id = state->PopFront(i);
        RTC_DCHECK_EQ(frame_id, oldest_frame_id);
        frame_counters_.dropped++;
        InternalStatsKey key(stream_index, peer_index, i);
        stream_frame_counters_.at(key).dropped++;

        analyzer_stats_.frames_in_flight_left_count.AddSample(
            StatsSample(captured_frames_in_flight_.size(), Now()));
        frames_comparator_.AddComparison(
            InternalStatsKey(stream_index, peer_index, i),
            /*captured=*/absl::nullopt,
            /*rendered=*/absl::nullopt, FrameComparisonType::kDroppedFrame,
            it->second.GetStatsForPeer(i));
      }

      captured_frames_in_flight_.erase(it);
    }
    captured_frames_in_flight_.emplace(
        frame_id, FrameInFlight(stream_index, frame, captured_time,
                                std::move(frame_receivers_indexes)));
    // Set frame id on local copy of the frame
    captured_frames_in_flight_.at(frame_id).SetFrameId(frame_id);

    // Update history stream<->frame mapping
    for (auto it = stream_to_frame_id_history_.begin();
         it != stream_to_frame_id_history_.end(); ++it) {
      it->second.erase(frame_id);
    }
    stream_to_frame_id_history_[stream_index].insert(frame_id);
    stream_to_frame_id_full_history_[stream_index].push_back(frame_id);

    // If state has too many frames that are in flight => remove the oldest
    // queued frame in order to avoid to use too much memory.
    if (state->GetAliveFramesCount() >
        options_.max_frames_in_flight_per_stream_count) {
      uint16_t frame_id_to_remove = state->MarkNextAliveFrameAsDead();
      auto it = captured_frames_in_flight_.find(frame_id_to_remove);
      RTC_CHECK(it != captured_frames_in_flight_.end())
          << "Frame with ID " << frame_id_to_remove
          << " is expected to be in flight, but hasn't been found in "
          << "|captured_frames_in_flight_|";
      bool is_removed = it->second.RemoveFrame();
      RTC_DCHECK(is_removed)
          << "Invalid stream state: alive frame is removed already";
    }
    if (options_.report_infra_metrics) {
      analyzer_stats_.on_frame_captured_processing_time_ms.AddSample(
          (Now() - captured_time).ms<double>());
    }
  }
  return frame_id;
}

void DefaultVideoQualityAnalyzer::OnFramePreEncode(
    absl::string_view peer_name,
    const webrtc::VideoFrame& frame) {
  Timestamp processing_started = Now();
  MutexLock lock(&mutex_);
  RTC_CHECK_EQ(state_, State::kActive)
      << "DefaultVideoQualityAnalyzer has to be started before use";

  auto it = captured_frames_in_flight_.find(frame.id());
  RTC_CHECK(it != captured_frames_in_flight_.end())
      << "Frame id=" << frame.id() << " not found";
  FrameInFlight& frame_in_flight = it->second;
  frame_counters_.pre_encoded++;
  size_t peer_index = peers_->index(peer_name);
  for (size_t i : peers_->GetAllIndexes()) {
    if (i != peer_index || options_.enable_receive_own_stream) {
      InternalStatsKey key(frame_in_flight.stream(), peer_index, i);
      stream_frame_counters_.at(key).pre_encoded++;
    }
  }
  frame_in_flight.SetPreEncodeTime(Now());

  if (options_.report_infra_metrics) {
    analyzer_stats_.on_frame_pre_encode_processing_time_ms.AddSample(
        (Now() - processing_started).ms<double>());
  }
}

void DefaultVideoQualityAnalyzer::OnFrameEncoded(
    absl::string_view peer_name,
    uint16_t frame_id,
    const webrtc::EncodedImage& encoded_image,
    const EncoderStats& stats,
    bool discarded) {
  if (discarded)
    return;

  Timestamp processing_started = Now();
  MutexLock lock(&mutex_);
  RTC_CHECK_EQ(state_, State::kActive)
      << "DefaultVideoQualityAnalyzer has to be started before use";

  auto it = captured_frames_in_flight_.find(frame_id);
  if (it == captured_frames_in_flight_.end()) {
    RTC_LOG(LS_WARNING)
        << "The encoding of video frame with id [" << frame_id << "] for peer ["
        << peer_name << "] finished after all receivers rendered this frame or "
        << "were removed. It can be OK for simulcast/SVC if higher quality "
        << "stream is not required or the last receiver was unregistered "
        << "between encoding of different layers, but it may indicate an ERROR "
        << "for singlecast or if it happens often.";
    return;
  }
  FrameInFlight& frame_in_flight = it->second;
  // For SVC we can receive multiple encoded images for one frame, so to cover
  // all cases we have to pick the last encode time.
  if (!frame_in_flight.HasEncodedTime()) {
    // Increase counters only when we meet this frame first time.
    frame_counters_.encoded++;
    size_t peer_index = peers_->index(peer_name);
    for (size_t i : peers_->GetAllIndexes()) {
      if (i != peer_index || options_.enable_receive_own_stream) {
        InternalStatsKey key(frame_in_flight.stream(), peer_index, i);
        stream_frame_counters_.at(key).encoded++;
      }
    }
  }
  Timestamp now = Now();
  StreamCodecInfo used_encoder;
  used_encoder.codec_name = stats.encoder_name;
  used_encoder.first_frame_id = frame_id;
  used_encoder.last_frame_id = frame_id;
  used_encoder.switched_on_at = now;
  used_encoder.switched_from_at = now;
  frame_in_flight.OnFrameEncoded(
      now, encoded_image._frameType, DataSize::Bytes(encoded_image.size()),
      stats.target_encode_bitrate, encoded_image.SpatialIndex().value_or(0),
      stats.qp, used_encoder);

  if (options_.report_infra_metrics) {
    analyzer_stats_.on_frame_encoded_processing_time_ms.AddSample(
        (Now() - processing_started).ms<double>());
  }
}

void DefaultVideoQualityAnalyzer::OnFrameDropped(
    absl::string_view peer_name,
    webrtc::EncodedImageCallback::DropReason reason) {
  // Here we do nothing, because we will see this drop on renderer side.
}

void DefaultVideoQualityAnalyzer::OnFramePreDecode(
    absl::string_view peer_name,
    uint16_t frame_id,
    const webrtc::EncodedImage& input_image) {
  Timestamp processing_started = Now();
  MutexLock lock(&mutex_);
  RTC_CHECK_EQ(state_, State::kActive)
      << "DefaultVideoQualityAnalyzer has to be started before use";

  size_t peer_index = peers_->index(peer_name);

  if (frame_id == VideoFrame::kNotSetId) {
    frame_counters_.received++;
    unknown_sender_frame_counters_[std::string(peer_name)].received++;
    return;
  }

  auto it = captured_frames_in_flight_.find(frame_id);
  if (it == captured_frames_in_flight_.end() ||
      it->second.HasReceivedTime(peer_index)) {
    // It means this frame was predecoded before, so we can skip it. It may
    // happen when we have multiple simulcast streams in one track and received
    // the same picture from two different streams because SFU can't reliably
    // correlate two simulcast streams and started relaying the second stream
    // from the same frame it has relayed right before for the first stream.
    return;
  }

  frame_counters_.received++;
  InternalStatsKey key(it->second.stream(),
                       stream_to_sender_.at(it->second.stream()), peer_index);
  stream_frame_counters_.at(key).received++;
  // Determine the time of the last received packet of this video frame.
  RTC_DCHECK(!input_image.PacketInfos().empty());
  Timestamp last_receive_time =
      std::max_element(input_image.PacketInfos().cbegin(),
                       input_image.PacketInfos().cend(),
                       [](const RtpPacketInfo& a, const RtpPacketInfo& b) {
                         return a.receive_time() < b.receive_time();
                       })
          ->receive_time();
  it->second.OnFramePreDecode(peer_index,
                              /*received_time=*/last_receive_time,
                              /*decode_start_time=*/Now(),
                              input_image._frameType,
                              DataSize::Bytes(input_image.size()));

  if (options_.report_infra_metrics) {
    analyzer_stats_.on_frame_pre_decode_processing_time_ms.AddSample(
        (Now() - processing_started).ms<double>());
  }
}

void DefaultVideoQualityAnalyzer::OnFrameDecoded(
    absl::string_view peer_name,
    const webrtc::VideoFrame& frame,
    const DecoderStats& stats) {
  Timestamp processing_started = Now();
  MutexLock lock(&mutex_);
  RTC_CHECK_EQ(state_, State::kActive)
      << "DefaultVideoQualityAnalyzer has to be started before use";

  size_t peer_index = peers_->index(peer_name);

  if (frame.id() == VideoFrame::kNotSetId) {
    frame_counters_.decoded++;
    unknown_sender_frame_counters_[std::string(peer_name)].decoded++;
    return;
  }

  auto it = captured_frames_in_flight_.find(frame.id());
  if (it == captured_frames_in_flight_.end() ||
      it->second.HasDecodeEndTime(peer_index)) {
    // It means this frame was decoded before, so we can skip it. It may happen
    // when we have multiple simulcast streams in one track and received
    // the same frame from two different streams because SFU can't reliably
    // correlate two simulcast streams and started relaying the second stream
    // from the same frame it has relayed right before for the first stream.
    return;
  }
  frame_counters_.decoded++;
  InternalStatsKey key(it->second.stream(),
                       stream_to_sender_.at(it->second.stream()), peer_index);
  stream_frame_counters_.at(key).decoded++;
  Timestamp now = Now();
  StreamCodecInfo used_decoder;
  used_decoder.codec_name = stats.decoder_name;
  used_decoder.first_frame_id = frame.id();
  used_decoder.last_frame_id = frame.id();
  used_decoder.switched_on_at = now;
  used_decoder.switched_from_at = now;
  it->second.OnFrameDecoded(peer_index, now, frame.width(), frame.height(),
                            used_decoder);

  if (options_.report_infra_metrics) {
    analyzer_stats_.on_frame_decoded_processing_time_ms.AddSample(
        (Now() - processing_started).ms<double>());
  }
}

void DefaultVideoQualityAnalyzer::OnFrameRendered(
    absl::string_view peer_name,
    const webrtc::VideoFrame& frame) {
  Timestamp processing_started = Now();
  MutexLock lock(&mutex_);
  RTC_CHECK_EQ(state_, State::kActive)
      << "DefaultVideoQualityAnalyzer has to be started before use";

  size_t peer_index = peers_->index(peer_name);

  if (frame.id() == VideoFrame::kNotSetId) {
    frame_counters_.rendered++;
    unknown_sender_frame_counters_[std::string(peer_name)].rendered++;
    return;
  }

  auto frame_it = captured_frames_in_flight_.find(frame.id());
  if (frame_it == captured_frames_in_flight_.end() ||
      frame_it->second.HasRenderedTime(peer_index) ||
      frame_it->second.IsDropped(peer_index)) {
    // It means this frame was rendered or dropped before, so we can skip it.
    // It may happen when we have multiple simulcast streams in one track and
    // received the same frame from two different streams because SFU can't
    // reliably correlate two simulcast streams and started relaying the second
    // stream from the same frame it has relayed right before for the first
    // stream.
    absl::string_view reason = kSkipRenderedFrameReasonProcessed;
    if (frame_it != captured_frames_in_flight_.end()) {
      if (frame_it->second.HasRenderedTime(peer_index)) {
        reason = kSkipRenderedFrameReasonRendered;
      } else if (frame_it->second.IsDropped(peer_index)) {
        reason = kSkipRenderedFrameReasonDropped;
      }
    }
    RTC_LOG(LS_WARNING)
        << "Peer " << peer_name
        << "; Received frame out of order: received frame with id "
        << frame.id() << " which was " << reason << " before";
    return;
  }

  // Find corresponding captured frame.
  FrameInFlight* frame_in_flight = &frame_it->second;
  absl::optional<VideoFrame> captured_frame = frame_in_flight->frame();

  const size_t stream_index = frame_in_flight->stream();
  StreamState* state = &stream_states_.at(stream_index);
  const InternalStatsKey stats_key(stream_index, state->sender(), peer_index);

  // Update frames counters.
  frame_counters_.rendered++;
  stream_frame_counters_.at(stats_key).rendered++;

  // Update current frame stats.
  frame_in_flight->OnFrameRendered(peer_index, Now());

  // After we received frame here we need to check if there are any dropped
  // frames between this one and last one, that was rendered for this video
  // stream.
  int dropped_count = 0;
  while (!state->IsEmpty(peer_index) &&
         state->Front(peer_index) != frame.id()) {
    dropped_count++;
    uint16_t dropped_frame_id = state->PopFront(peer_index);
    // Frame with id `dropped_frame_id` was dropped. We need:
    // 1. Update global and stream frame counters
    // 2. Extract corresponding frame from `captured_frames_in_flight_`
    // 3. Send extracted frame to comparison with dropped=true
    // 4. Cleanup dropped frame
    frame_counters_.dropped++;
    stream_frame_counters_.at(stats_key).dropped++;

    auto dropped_frame_it = captured_frames_in_flight_.find(dropped_frame_id);
    RTC_DCHECK(dropped_frame_it != captured_frames_in_flight_.end());
    dropped_frame_it->second.MarkDropped(peer_index);

    analyzer_stats_.frames_in_flight_left_count.AddSample(
        StatsSample(captured_frames_in_flight_.size(), Now()));
    frames_comparator_.AddComparison(
        stats_key, /*captured=*/absl::nullopt, /*rendered=*/absl::nullopt,
        FrameComparisonType::kDroppedFrame,
        dropped_frame_it->second.GetStatsForPeer(peer_index));

    if (dropped_frame_it->second.HaveAllPeersReceived()) {
      captured_frames_in_flight_.erase(dropped_frame_it);
    }
  }
  RTC_DCHECK(!state->IsEmpty(peer_index));
  state->PopFront(peer_index);

  if (state->last_rendered_frame_time(peer_index)) {
    frame_in_flight->SetPrevFrameRenderedTime(
        peer_index, state->last_rendered_frame_time(peer_index).value());
  }
  state->SetLastRenderedFrameTime(peer_index,
                                  frame_in_flight->rendered_time(peer_index));
  analyzer_stats_.frames_in_flight_left_count.AddSample(
      StatsSample(captured_frames_in_flight_.size(), Now()));
  frames_comparator_.AddComparison(
      stats_key, dropped_count, captured_frame, /*rendered=*/frame,
      FrameComparisonType::kRegular,
      frame_in_flight->GetStatsForPeer(peer_index));

  if (frame_it->second.HaveAllPeersReceived()) {
    captured_frames_in_flight_.erase(frame_it);
  }

  if (options_.report_infra_metrics) {
    analyzer_stats_.on_frame_rendered_processing_time_ms.AddSample(
        (Now() - processing_started).ms<double>());
  }
}

void DefaultVideoQualityAnalyzer::OnEncoderError(
    absl::string_view peer_name,
    const webrtc::VideoFrame& frame,
    int32_t error_code) {
  RTC_LOG(LS_ERROR) << "Encoder error for frame.id=" << frame.id()
                    << ", code=" << error_code;
}

void DefaultVideoQualityAnalyzer::OnDecoderError(absl::string_view peer_name,
                                                 uint16_t frame_id,
                                                 int32_t error_code,
                                                 const DecoderStats& stats) {
  RTC_LOG(LS_ERROR) << "Decoder error for frame_id=" << frame_id
                    << ", code=" << error_code;

  Timestamp processing_started = Now();
  MutexLock lock(&mutex_);
  RTC_CHECK_EQ(state_, State::kActive)
      << "DefaultVideoQualityAnalyzer has to be started before use";

  size_t peer_index = peers_->index(peer_name);

  if (frame_id == VideoFrame::kNotSetId) {
    frame_counters_.failed_to_decode++;
    unknown_sender_frame_counters_[std::string(peer_name)].failed_to_decode++;
    return;
  }

  auto it = captured_frames_in_flight_.find(frame_id);
  if (it == captured_frames_in_flight_.end() ||
      it->second.HasDecodeEndTime(peer_index)) {
    // It means this frame was decoded before, so we can skip it. It may happen
    // when we have multiple simulcast streams in one track and received
    // the same frame from two different streams because SFU can't reliably
    // correlate two simulcast streams and started relaying the second stream
    // from the same frame it has relayed right before for the first stream.
    return;
  }
  frame_counters_.failed_to_decode++;
  InternalStatsKey key(it->second.stream(),
                       stream_to_sender_.at(it->second.stream()), peer_index);
  stream_frame_counters_.at(key).failed_to_decode++;
  Timestamp now = Now();
  StreamCodecInfo used_decoder;
  used_decoder.codec_name = stats.decoder_name;
  used_decoder.first_frame_id = frame_id;
  used_decoder.last_frame_id = frame_id;
  used_decoder.switched_on_at = now;
  used_decoder.switched_from_at = now;
  it->second.OnDecoderError(peer_index, used_decoder);

  if (options_.report_infra_metrics) {
    analyzer_stats_.on_decoder_error_processing_time_ms.AddSample(
        (Now() - processing_started).ms<double>());
  }
}

void DefaultVideoQualityAnalyzer::RegisterParticipantInCall(
    absl::string_view peer_name) {
  MutexLock lock(&mutex_);
  RTC_CHECK(!peers_->HasName(peer_name));
  size_t new_peer_index = peers_->AddIfAbsent(peer_name);

  // Ensure stats for receiving (for frames from other peers to this one)
  // streams exists. Since in flight frames will be sent to the new peer
  // as well. Sending stats (from this peer to others) will be added by
  // DefaultVideoQualityAnalyzer::OnFrameCaptured.
  std::vector<std::pair<InternalStatsKey, Timestamp>> stream_started_time;
  for (auto [stream_index, sender_peer_index] : stream_to_sender_) {
    InternalStatsKey key(stream_index, sender_peer_index, new_peer_index);

    // To initiate `FrameCounters` for the stream we should pick frame
    // counters with the same stream index and the same sender's peer index
    // and any receiver's peer index and copy from its sender side
    // counters.
    FrameCounters counters;
    for (size_t i : peers_->GetPresentIndexes()) {
      InternalStatsKey prototype_key(stream_index, sender_peer_index, i);
      auto it = stream_frame_counters_.find(prototype_key);
      if (it != stream_frame_counters_.end()) {
        counters.captured = it->second.captured;
        counters.pre_encoded = it->second.pre_encoded;
        counters.encoded = it->second.encoded;
        break;
      }
    }
    // It may happen if we had only one peer before this method was invoked,
    // then `counters` will be empty. In such case empty `counters` are ok.
    stream_frame_counters_.insert({key, std::move(counters)});

    stream_started_time.push_back(
        {key, stream_states_.at(stream_index).stream_started_time()});
  }
  frames_comparator_.RegisterParticipantInCall(stream_started_time,
                                               start_time_);
  // Ensure, that frames states are handled correctly
  // (e.g. dropped frames tracking).
  for (auto& [stream_index, stream_state] : stream_states_) {
    stream_state.AddPeer(new_peer_index);
  }
  // Register new peer for every frame in flight.
  // It is guaranteed, that no garbage FrameInFlight objects will stay in
  // memory because of adding new peer. Even if the new peer won't receive the
  // frame, the frame will be removed by OnFrameRendered after next frame comes
  // for the new peer. It is important because FrameInFlight is a large object.
  for (auto& [frame_id, frame_in_flight] : captured_frames_in_flight_) {
    frame_in_flight.AddExpectedReceiver(new_peer_index);
  }
}

void DefaultVideoQualityAnalyzer::UnregisterParticipantInCall(
    absl::string_view peer_name) {
  MutexLock lock(&mutex_);
  RTC_CHECK(peers_->HasName(peer_name));
  absl::optional<size_t> peer_index = peers_->RemoveIfPresent(peer_name);
  RTC_CHECK(peer_index.has_value());

  for (auto& [stream_index, stream_state] : stream_states_) {
    if (!options_.enable_receive_own_stream &&
        peer_index == stream_state.sender()) {
      continue;
    }

    AddExistingFramesInFlightForStreamToComparator(stream_index, stream_state,
                                                   *peer_index);

    stream_state.RemovePeer(*peer_index);
  }

  // Remove peer from every frame in flight. If we removed that last expected
  // receiver for the frame, then we should removed this frame if it was
  // already encoded. If frame wasn't encoded, it still will be used by sender
  // side pipeline, so we can't delete it yet.
  for (auto it = captured_frames_in_flight_.begin();
       it != captured_frames_in_flight_.end();) {
    FrameInFlight& frame_in_flight = it->second;
    frame_in_flight.RemoveExpectedReceiver(*peer_index);
    // If frame was fully sent and all receivers received it, then erase it.
    // It may happen that when we remove FrameInFlight only some Simulcast/SVC
    // layers were encoded and frame has encoded time, but more layers might be
    // encoded after removal. In such case it's safe to still remove a frame,
    // because OnFrameEncoded method will correctly handle the case when there
    // is no FrameInFlight for the received encoded image.
    if (frame_in_flight.HasEncodedTime() &&
        frame_in_flight.HaveAllPeersReceived()) {
      it = captured_frames_in_flight_.erase(it);
    } else {
      it++;
    }
  }
}

void DefaultVideoQualityAnalyzer::Stop() {
  std::map<InternalStatsKey, Timestamp> last_rendered_frame_times;
  {
    MutexLock lock(&mutex_);
    if (state_ == State::kStopped) {
      return;
    }
    RTC_CHECK_EQ(state_, State::kActive)
        << "DefaultVideoQualityAnalyzer has to be started before use";

    state_ = State::kStopped;

    // Add the amount of frames in flight to the analyzer stats before all left
    // frames in flight will be sent to the `frames_compartor_`.
    analyzer_stats_.frames_in_flight_left_count.AddSample(
        StatsSample(captured_frames_in_flight_.size(), Now()));

    for (auto& state_entry : stream_states_) {
      const size_t stream_index = state_entry.first;
      StreamState& stream_state = state_entry.second;

      // Populate `last_rendered_frame_times` map for all peers that were met in
      // call, not only for the currently presented ones.
      for (size_t peer_index : peers_->GetAllIndexes()) {
        if (peer_index == stream_state.sender() &&
            !options_.enable_receive_own_stream) {
          continue;
        }

        InternalStatsKey stats_key(stream_index, stream_state.sender(),
                                   peer_index);

        // If there are no freezes in the call we have to report
        // time_between_freezes_ms as call duration and in such case
        // `stream_last_freeze_end_time` for this stream will be `start_time_`.
        // If there is freeze, then we need add time from last rendered frame
        // to last freeze end as time between freezes.
        if (stream_state.last_rendered_frame_time(peer_index)) {
          last_rendered_frame_times.emplace(
              stats_key,
              stream_state.last_rendered_frame_time(peer_index).value());
        }
      }

      // Push left frame in flight for analysis for the peers that are still in
      // the call.
      for (size_t peer_index : peers_->GetPresentIndexes()) {
        if (peer_index == stream_state.sender() &&
            !options_.enable_receive_own_stream) {
          continue;
        }

        AddExistingFramesInFlightForStreamToComparator(
            stream_index, stream_state, peer_index);
      }
    }
  }
  frames_comparator_.Stop(last_rendered_frame_times);

  // Perform final Metrics update. On this place analyzer is stopped and no one
  // holds any locks.
  {
    MutexLock lock(&mutex_);
    FramesComparatorStats frames_comparator_stats =
        frames_comparator_.frames_comparator_stats();
    analyzer_stats_.comparisons_queue_size =
        std::move(frames_comparator_stats.comparisons_queue_size);
    analyzer_stats_.comparisons_done = frames_comparator_stats.comparisons_done;
    analyzer_stats_.cpu_overloaded_comparisons_done =
        frames_comparator_stats.cpu_overloaded_comparisons_done;
    analyzer_stats_.memory_overloaded_comparisons_done =
        frames_comparator_stats.memory_overloaded_comparisons_done;
  }
  ReportResults();
}

std::string DefaultVideoQualityAnalyzer::GetStreamLabel(uint16_t frame_id) {
  MutexLock lock1(&mutex_);
  auto it = captured_frames_in_flight_.find(frame_id);
  if (it != captured_frames_in_flight_.end()) {
    return streams_.name(it->second.stream());
  }
  for (auto hist_it = stream_to_frame_id_history_.begin();
       hist_it != stream_to_frame_id_history_.end(); ++hist_it) {
    auto hist_set_it = hist_it->second.find(frame_id);
    if (hist_set_it != hist_it->second.end()) {
      return streams_.name(hist_it->first);
    }
  }
  RTC_CHECK(false) << "Unknown frame_id=" << frame_id;
}

std::set<StatsKey> DefaultVideoQualityAnalyzer::GetKnownVideoStreams() const {
  MutexLock lock(&mutex_);
  std::set<StatsKey> out;
  for (auto& item : frames_comparator_.stream_stats()) {
    RTC_LOG(LS_INFO) << item.first.ToString() << " ==> "
                     << ToStatsKey(item.first).ToString();
    out.insert(ToStatsKey(item.first));
  }
  return out;
}

VideoStreamsInfo DefaultVideoQualityAnalyzer::GetKnownStreams() const {
  MutexLock lock(&mutex_);
  std::map<std::string, std::string> stream_to_sender;
  std::map<std::string, std::set<std::string>> sender_to_streams;
  std::map<std::string, std::set<std::string>> stream_to_receivers;

  for (auto& item : frames_comparator_.stream_stats()) {
    const std::string& stream_label = streams_.name(item.first.stream);
    const std::string& sender = peers_->name(item.first.sender);
    const std::string& receiver = peers_->name(item.first.receiver);
    RTC_LOG(LS_INFO) << item.first.ToString() << " ==> "
                     << "stream=" << stream_label << "; sender=" << sender
                     << "; receiver=" << receiver;
    stream_to_sender.emplace(stream_label, sender);
    auto streams_it = sender_to_streams.find(sender);
    if (streams_it != sender_to_streams.end()) {
      streams_it->second.emplace(stream_label);
    } else {
      sender_to_streams.emplace(sender, std::set<std::string>{stream_label});
    }
    auto receivers_it = stream_to_receivers.find(stream_label);
    if (receivers_it != stream_to_receivers.end()) {
      receivers_it->second.emplace(receiver);
    } else {
      stream_to_receivers.emplace(stream_label,
                                  std::set<std::string>{receiver});
    }
  }

  return VideoStreamsInfo(std::move(stream_to_sender),
                          std::move(sender_to_streams),
                          std::move(stream_to_receivers));
}

FrameCounters DefaultVideoQualityAnalyzer::GetGlobalCounters() const {
  MutexLock lock(&mutex_);
  return frame_counters_;
}

std::map<std::string, FrameCounters>
DefaultVideoQualityAnalyzer::GetUnknownSenderFrameCounters() const {
  MutexLock lock(&mutex_);
  return unknown_sender_frame_counters_;
}

std::map<StatsKey, FrameCounters>
DefaultVideoQualityAnalyzer::GetPerStreamCounters() const {
  MutexLock lock(&mutex_);
  std::map<StatsKey, FrameCounters> out;
  for (auto& item : stream_frame_counters_) {
    out.emplace(ToStatsKey(item.first), item.second);
  }
  return out;
}

std::map<StatsKey, StreamStats> DefaultVideoQualityAnalyzer::GetStats() const {
  MutexLock lock1(&mutex_);
  std::map<StatsKey, StreamStats> out;
  for (auto& item : frames_comparator_.stream_stats()) {
    out.emplace(ToStatsKey(item.first), item.second);
  }
  return out;
}

AnalyzerStats DefaultVideoQualityAnalyzer::GetAnalyzerStats() const {
  MutexLock lock(&mutex_);
  return analyzer_stats_;
}

uint16_t DefaultVideoQualityAnalyzer::GetNextFrameId() {
  uint16_t frame_id = next_frame_id_++;
  if (next_frame_id_ == VideoFrame::kNotSetId) {
    next_frame_id_ = 1;
  }
  return frame_id;
}

void DefaultVideoQualityAnalyzer::
    AddExistingFramesInFlightForStreamToComparator(size_t stream_index,
                                                   StreamState& stream_state,
                                                   size_t peer_index) {
  InternalStatsKey stats_key(stream_index, stream_state.sender(), peer_index);

  // Add frames in flight for this stream into frames comparator.
  // Frames in flight were not rendered, so they won't affect stream's
  // last rendered frame time.
  while (!stream_state.IsEmpty(peer_index)) {
    uint16_t frame_id = stream_state.PopFront(peer_index);
    auto it = captured_frames_in_flight_.find(frame_id);
    RTC_DCHECK(it != captured_frames_in_flight_.end());
    FrameInFlight& frame = it->second;

    frames_comparator_.AddComparison(stats_key, /*captured=*/absl::nullopt,
                                     /*rendered=*/absl::nullopt,
                                     FrameComparisonType::kFrameInFlight,
                                     frame.GetStatsForPeer(peer_index));
  }
}

void DefaultVideoQualityAnalyzer::ReportResults() {
  MutexLock lock(&mutex_);
  for (auto& item : frames_comparator_.stream_stats()) {
    ReportResults(item.first, item.second,
                  stream_frame_counters_.at(item.first));
  }
  // TODO(bugs.webrtc.org/14757): Remove kExperimentalTestNameMetadataKey.
  metrics_logger_->LogSingleValueMetric(
      "cpu_usage_%", test_label_, GetCpuUsagePercent(), Unit::kUnitless,
      ImprovementDirection::kSmallerIsBetter,
      {{MetricMetadataKey::kExperimentalTestNameMetadataKey, test_label_}});
  LogFrameCounters("Global", frame_counters_);
  if (!unknown_sender_frame_counters_.empty()) {
    RTC_LOG(LS_INFO) << "Received frame counters with unknown frame id:";
    for (const auto& [peer_name, frame_counters] :
         unknown_sender_frame_counters_) {
      LogFrameCounters(peer_name, frame_counters);
    }
  }
  RTC_LOG(LS_INFO) << "Received frame counters per stream:";
  for (const auto& [stats_key, stream_stats] :
       frames_comparator_.stream_stats()) {
    LogFrameCounters(ToStatsKey(stats_key).ToString(),
                     stream_frame_counters_.at(stats_key));
    LogStreamInternalStats(ToStatsKey(stats_key).ToString(), stream_stats,
                           start_time_);
  }
  if (!analyzer_stats_.comparisons_queue_size.IsEmpty()) {
    RTC_LOG(LS_INFO) << "comparisons_queue_size min="
                     << analyzer_stats_.comparisons_queue_size.GetMin()
                     << "; max="
                     << analyzer_stats_.comparisons_queue_size.GetMax()
                     << "; 99%="
                     << analyzer_stats_.comparisons_queue_size.GetPercentile(
                            0.99);
  }
  RTC_LOG(LS_INFO) << "comparisons_done=" << analyzer_stats_.comparisons_done;
  RTC_LOG(LS_INFO) << "cpu_overloaded_comparisons_done="
                   << analyzer_stats_.cpu_overloaded_comparisons_done;
  RTC_LOG(LS_INFO) << "memory_overloaded_comparisons_done="
                   << analyzer_stats_.memory_overloaded_comparisons_done;
  if (options_.report_infra_metrics) {
    metrics_logger_->LogMetric("comparisons_queue_size", test_label_,
                               analyzer_stats_.comparisons_queue_size,
                               Unit::kCount,
                               ImprovementDirection::kSmallerIsBetter);
    metrics_logger_->LogMetric("frames_in_flight_left_count", test_label_,
                               analyzer_stats_.frames_in_flight_left_count,
                               Unit::kCount,
                               ImprovementDirection::kSmallerIsBetter);
    metrics_logger_->LogSingleValueMetric(
        "comparisons_done", test_label_, analyzer_stats_.comparisons_done,
        Unit::kCount, ImprovementDirection::kNeitherIsBetter);
    metrics_logger_->LogSingleValueMetric(
        "cpu_overloaded_comparisons_done", test_label_,
        analyzer_stats_.cpu_overloaded_comparisons_done, Unit::kCount,
        ImprovementDirection::kNeitherIsBetter);
    metrics_logger_->LogSingleValueMetric(
        "memory_overloaded_comparisons_done", test_label_,
        analyzer_stats_.memory_overloaded_comparisons_done, Unit::kCount,
        ImprovementDirection::kNeitherIsBetter);
    metrics_logger_->LogSingleValueMetric(
        "test_duration", test_label_, (Now() - start_time_).ms(),
        Unit::kMilliseconds, ImprovementDirection::kNeitherIsBetter);

    metrics_logger_->LogMetric(
        "on_frame_captured_processing_time_ms", test_label_,
        analyzer_stats_.on_frame_captured_processing_time_ms,
        Unit::kMilliseconds, ImprovementDirection::kSmallerIsBetter);
    metrics_logger_->LogMetric(
        "on_frame_pre_encode_processing_time_ms", test_label_,
        analyzer_stats_.on_frame_pre_encode_processing_time_ms,
        Unit::kMilliseconds, ImprovementDirection::kSmallerIsBetter);
    metrics_logger_->LogMetric(
        "on_frame_encoded_processing_time_ms", test_label_,
        analyzer_stats_.on_frame_encoded_processing_time_ms,
        Unit::kMilliseconds, ImprovementDirection::kSmallerIsBetter);
    metrics_logger_->LogMetric(
        "on_frame_pre_decode_processing_time_ms", test_label_,
        analyzer_stats_.on_frame_pre_decode_processing_time_ms,
        Unit::kMilliseconds, ImprovementDirection::kSmallerIsBetter);
    metrics_logger_->LogMetric(
        "on_frame_decoded_processing_time_ms", test_label_,
        analyzer_stats_.on_frame_decoded_processing_time_ms,
        Unit::kMilliseconds, ImprovementDirection::kSmallerIsBetter);
    metrics_logger_->LogMetric(
        "on_frame_rendered_processing_time_ms", test_label_,
        analyzer_stats_.on_frame_rendered_processing_time_ms,
        Unit::kMilliseconds, ImprovementDirection::kSmallerIsBetter);
    metrics_logger_->LogMetric(
        "on_decoder_error_processing_time_ms", test_label_,
        analyzer_stats_.on_decoder_error_processing_time_ms,
        Unit::kMilliseconds, ImprovementDirection::kSmallerIsBetter);
  }
}

void DefaultVideoQualityAnalyzer::ReportResults(
    const InternalStatsKey& key,
    const StreamStats& stats,
    const FrameCounters& frame_counters) {
  TimeDelta test_duration = Now() - start_time_;
  std::string test_case_name = GetTestCaseName(ToMetricName(key));
  // TODO(bugs.webrtc.org/14757): Remove kExperimentalTestNameMetadataKey.
  std::map<std::string, std::string> metric_metadata{
      {MetricMetadataKey::kPeerMetadataKey, peers_->name(key.sender)},
      {MetricMetadataKey::kVideoStreamMetadataKey, streams_.name(key.stream)},
      {MetricMetadataKey::kSenderMetadataKey, peers_->name(key.sender)},
      {MetricMetadataKey::kReceiverMetadataKey, peers_->name(key.receiver)},
      {MetricMetadataKey::kExperimentalTestNameMetadataKey, test_label_}};

  double sum_squared_interframe_delays_secs = 0;
  Timestamp video_start_time = Timestamp::PlusInfinity();
  Timestamp video_end_time = Timestamp::MinusInfinity();
  for (const SamplesStatsCounter::StatsSample& sample :
       stats.time_between_rendered_frames_ms.GetTimedSamples()) {
    double interframe_delay_ms = sample.value;
    const double interframe_delays_secs = interframe_delay_ms / 1000.0;
    // Sum of squared inter frame intervals is used to calculate the harmonic
    // frame rate metric. The metric aims to reflect overall experience related
    // to smoothness of video playback and includes both freezes and pauses.
    sum_squared_interframe_delays_secs +=
        interframe_delays_secs * interframe_delays_secs;
    if (sample.time < video_start_time) {
      video_start_time = sample.time;
    }
    if (sample.time > video_end_time) {
      video_end_time = sample.time;
    }
  }
  double harmonic_framerate_fps = 0;
  TimeDelta video_duration = video_end_time - video_start_time;
  if (sum_squared_interframe_delays_secs > 0.0 && video_duration.IsFinite()) {
    harmonic_framerate_fps =
        video_duration.seconds<double>() / sum_squared_interframe_delays_secs;
  }

  metrics_logger_->LogMetric(
      "psnr_dB", test_case_name, stats.psnr, Unit::kUnitless,
      ImprovementDirection::kBiggerIsBetter, metric_metadata);
  metrics_logger_->LogMetric(
      "ssim", test_case_name, stats.ssim, Unit::kUnitless,
      ImprovementDirection::kBiggerIsBetter, metric_metadata);
  metrics_logger_->LogMetric("transport_time", test_case_name,
                             stats.transport_time_ms, Unit::kMilliseconds,
                             ImprovementDirection::kSmallerIsBetter,
                             metric_metadata);
  metrics_logger_->LogMetric(
      "total_delay_incl_transport", test_case_name,
      stats.total_delay_incl_transport_ms, Unit::kMilliseconds,
      ImprovementDirection::kSmallerIsBetter, metric_metadata);
  metrics_logger_->LogMetric(
      "time_between_rendered_frames", test_case_name,
      stats.time_between_rendered_frames_ms, Unit::kMilliseconds,
      ImprovementDirection::kSmallerIsBetter, metric_metadata);
  metrics_logger_->LogSingleValueMetric(
      "harmonic_framerate", test_case_name, harmonic_framerate_fps,
      Unit::kHertz, ImprovementDirection::kBiggerIsBetter, metric_metadata);
  metrics_logger_->LogSingleValueMetric(
      "encode_frame_rate", test_case_name,
      stats.encode_frame_rate.IsEmpty()
          ? 0
          : stats.encode_frame_rate.GetEventsPerSecond(),
      Unit::kHertz, ImprovementDirection::kBiggerIsBetter, metric_metadata);
  metrics_logger_->LogMetric(
      "encode_time", test_case_name, stats.encode_time_ms, Unit::kMilliseconds,
      ImprovementDirection::kSmallerIsBetter, metric_metadata);
  metrics_logger_->LogMetric("time_between_freezes", test_case_name,
                             stats.time_between_freezes_ms, Unit::kMilliseconds,
                             ImprovementDirection::kBiggerIsBetter,
                             metric_metadata);
  metrics_logger_->LogMetric("freeze_time_ms", test_case_name,
                             stats.freeze_time_ms, Unit::kMilliseconds,
                             ImprovementDirection::kSmallerIsBetter,
                             metric_metadata);
  metrics_logger_->LogMetric(
      "pixels_per_frame", test_case_name, stats.resolution_of_decoded_frame,
      Unit::kCount, ImprovementDirection::kBiggerIsBetter, metric_metadata);
  metrics_logger_->LogSingleValueMetric(
      "min_psnr_dB", test_case_name,
      stats.psnr.IsEmpty() ? 0 : stats.psnr.GetMin(), Unit::kUnitless,
      ImprovementDirection::kBiggerIsBetter, metric_metadata);
  metrics_logger_->LogMetric(
      "decode_time", test_case_name, stats.decode_time_ms, Unit::kMilliseconds,
      ImprovementDirection::kSmallerIsBetter, metric_metadata);
  metrics_logger_->LogMetric(
      "receive_to_render_time", test_case_name, stats.receive_to_render_time_ms,
      Unit::kMilliseconds, ImprovementDirection::kSmallerIsBetter,
      metric_metadata);
  metrics_logger_->LogSingleValueMetric(
      "dropped_frames", test_case_name, frame_counters.dropped, Unit::kCount,
      ImprovementDirection::kSmallerIsBetter, metric_metadata);
  metrics_logger_->LogSingleValueMetric(
      "frames_in_flight", test_case_name,
      frame_counters.captured - frame_counters.rendered -
          frame_counters.dropped,
      Unit::kCount, ImprovementDirection::kSmallerIsBetter, metric_metadata);
  metrics_logger_->LogSingleValueMetric(
      "rendered_frames", test_case_name, frame_counters.rendered, Unit::kCount,
      ImprovementDirection::kBiggerIsBetter, metric_metadata);
  metrics_logger_->LogMetric(
      "max_skipped", test_case_name, stats.skipped_between_rendered,
      Unit::kCount, ImprovementDirection::kSmallerIsBetter, metric_metadata);
  metrics_logger_->LogMetric(
      "target_encode_bitrate", test_case_name,
      stats.target_encode_bitrate / 1000, Unit::kKilobitsPerSecond,
      ImprovementDirection::kNeitherIsBetter, metric_metadata);
  for (const auto& [spatial_layer, qp] : stats.spatial_layers_qp) {
    std::map<std::string, std::string> qp_metadata = metric_metadata;
    qp_metadata[MetricMetadataKey::kSpatialLayerMetadataKey] =
        std::to_string(spatial_layer);
    metrics_logger_->LogMetric("qp_sl" + std::to_string(spatial_layer),
                               test_case_name, qp, Unit::kUnitless,
                               ImprovementDirection::kSmallerIsBetter,
                               std::move(qp_metadata));
  }
  metrics_logger_->LogSingleValueMetric(
      "actual_encode_bitrate", test_case_name,
      static_cast<double>(stats.total_encoded_images_payload) /
          test_duration.seconds<double>() * kBitsInByte / 1000,
      Unit::kKilobitsPerSecond, ImprovementDirection::kNeitherIsBetter,
      metric_metadata);

  if (options_.report_detailed_frame_stats) {
    metrics_logger_->LogSingleValueMetric(
        "capture_frame_rate", test_case_name,
        stats.capture_frame_rate.IsEmpty()
            ? 0
            : stats.capture_frame_rate.GetEventsPerSecond(),
        Unit::kHertz, ImprovementDirection::kBiggerIsBetter, metric_metadata);
    metrics_logger_->LogSingleValueMetric(
        "num_encoded_frames", test_case_name, frame_counters.encoded,
        Unit::kCount, ImprovementDirection::kBiggerIsBetter, metric_metadata);
    metrics_logger_->LogSingleValueMetric(
        "num_decoded_frames", test_case_name, frame_counters.decoded,
        Unit::kCount, ImprovementDirection::kBiggerIsBetter, metric_metadata);
    metrics_logger_->LogSingleValueMetric(
        "num_send_key_frames", test_case_name, stats.num_send_key_frames,
        Unit::kCount, ImprovementDirection::kBiggerIsBetter, metric_metadata);
    metrics_logger_->LogSingleValueMetric(
        "num_recv_key_frames", test_case_name, stats.num_recv_key_frames,
        Unit::kCount, ImprovementDirection::kBiggerIsBetter, metric_metadata);

    metrics_logger_->LogMetric("recv_key_frame_size_bytes", test_case_name,
                               stats.recv_key_frame_size_bytes, Unit::kCount,
                               ImprovementDirection::kBiggerIsBetter,
                               metric_metadata);
    metrics_logger_->LogMetric("recv_delta_frame_size_bytes", test_case_name,
                               stats.recv_delta_frame_size_bytes, Unit::kCount,
                               ImprovementDirection::kBiggerIsBetter,
                               metric_metadata);
  }
}

std::string DefaultVideoQualityAnalyzer::GetTestCaseName(
    const std::string& stream_label) const {
  return test_label_ + "/" + stream_label;
}

Timestamp DefaultVideoQualityAnalyzer::Now() {
  return clock_->CurrentTime();
}

StatsKey DefaultVideoQualityAnalyzer::ToStatsKey(
    const InternalStatsKey& key) const {
  return StatsKey(streams_.name(key.stream), peers_->name(key.receiver));
}

std::string DefaultVideoQualityAnalyzer::ToMetricName(
    const InternalStatsKey& key) const {
  const std::string& stream_label = streams_.name(key.stream);
  if (peers_->GetKnownSize() <= 2 && key.sender != key.receiver) {
    // TODO(titovartem): remove this special case.
    return stream_label;
  }
  rtc::StringBuilder out;
  out << stream_label << "_" << peers_->name(key.sender) << "_"
      << peers_->name(key.receiver);
  return out.str();
}

double DefaultVideoQualityAnalyzer::GetCpuUsagePercent() {
  return cpu_measurer_.GetCpuUsagePercent();
}

std::map<std::string, std::vector<uint16_t>>
DefaultVideoQualityAnalyzer::GetStreamFrames() const {
  MutexLock lock(&mutex_);
  std::map<std::string, std::vector<uint16_t>> out;
  for (auto entry_it : stream_to_frame_id_full_history_) {
    out.insert({streams_.name(entry_it.first), entry_it.second});
  }
  return out;
}

}  // namespace webrtc
