/*
 *  Copyright 2016 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 "pc/rtc_stats_collector.h"

#include <stdint.h>
#include <stdio.h>

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

#include "absl/functional/bind_front.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/audio/audio_device.h"
#include "api/audio/audio_processing_statistics.h"
#include "api/candidate.h"
#include "api/data_channel_interface.h"
#include "api/dtls_transport_interface.h"
#include "api/environment/environment.h"
#include "api/make_ref_counted.h"
#include "api/media_stream_interface.h"
#include "api/media_types.h"
#include "api/rtp_parameters.h"
#include "api/rtp_transceiver_direction.h"
#include "api/scoped_refptr.h"
#include "api/sequence_checker.h"
#include "api/stats/rtc_stats.h"
#include "api/stats/rtc_stats_collector_callback.h"
#include "api/stats/rtc_stats_report.h"
#include "api/stats/rtcstats_objects.h"
#include "api/transport/enums.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "api/video/video_content_type.h"
#include "api/video_codecs/scalability_mode.h"
#include "common_video/include/quality_limitation_reason.h"
#include "media/base/media_channel.h"
#include "media/base/stream_params.h"
#include "modules/rtp_rtcp/include/report_block_data.h"
#include "p2p/base/connection_info.h"
#include "p2p/base/ice_transport_internal.h"
#include "p2p/base/p2p_constants.h"
#include "p2p/base/port.h"
#include "p2p/base/transport_description.h"
#include "pc/channel_interface.h"
#include "pc/data_channel_utils.h"
#include "pc/peer_connection_internal.h"
#include "pc/rtc_stats_traversal.h"
#include "pc/rtp_receiver_proxy.h"
#include "pc/rtp_sender_proxy.h"
#include "pc/rtp_transceiver.h"
#include "pc/transport_stats.h"
#include "pc/webrtc_sdp.h"
#include "rtc_base/checks.h"
#include "rtc_base/event.h"
#include "rtc_base/ip_address.h"
#include "rtc_base/logging.h"
#include "rtc_base/network_constants.h"
#include "rtc_base/rtc_certificate.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/ssl_certificate.h"
#include "rtc_base/ssl_stream_adapter.h"
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/thread.h"
#include "rtc_base/time_utils.h"
#include "rtc_base/trace_event.h"

namespace webrtc {

namespace {

const char kDirectionInbound = 'I';
const char kDirectionOutbound = 'O';

static constexpr char kAudioPlayoutSingletonId[] = "AP";

// TODO(https://crbug.com/webrtc/10656): Consider making IDs less predictable.
std::string RTCCertificateIDFromFingerprint(const std::string& fingerprint) {
  return "CF" + fingerprint;
}

// `direction` is either kDirectionInbound or kDirectionOutbound.
std::string RTCCodecStatsIDFromTransportAndCodecParameters(
    const char direction,
    const std::string& transport_id,
    const RtpCodecParameters& codec_params) {
  char buf[1024];
  SimpleStringBuilder sb(buf);
  sb << 'C' << direction << transport_id << '_' << codec_params.payload_type;
  // TODO(https://crbug.com/webrtc/14420): If we stop supporting different FMTP
  // lines for the same PT and transport, which should be illegal SDP, then we
  // wouldn't need `fmtp` to be part of the ID here.
  StringBuilder fmtp;
  if (WriteFmtpParameters(codec_params.parameters, &fmtp)) {
    sb << '_' << fmtp.Release();
  }
  return sb.str();
}

std::string RTCIceCandidatePairStatsIDFromConnectionInfo(
    const ConnectionInfo& info) {
  char buf[4096];
  SimpleStringBuilder sb(buf);
  sb << "CP" << info.local_candidate.id() << "_" << info.remote_candidate.id();
  return sb.str();
}

std::string RTCTransportStatsIDFromTransportChannel(
    const std::string& transport_name,
    int channel_component) {
  char buf[1024];
  SimpleStringBuilder sb(buf);
  sb << 'T' << transport_name << channel_component;
  return sb.str();
}

std::string RTCInboundRtpStreamStatsIDFromSSRC(const std::string& transport_id,
                                               MediaType media_type,
                                               uint32_t ssrc) {
  char buf[1024];
  SimpleStringBuilder sb(buf);
  sb << 'I' << transport_id << (media_type == MediaType::AUDIO ? 'A' : 'V')
     << ssrc;
  return sb.str();
}

std::string RTCOutboundRtpStreamStatsIDFromSSRC(const std::string& transport_id,
                                                MediaType media_type,
                                                uint32_t ssrc) {
  char buf[1024];
  SimpleStringBuilder sb(buf);
  sb << 'O' << transport_id << (media_type == MediaType::AUDIO ? 'A' : 'V')
     << ssrc;
  return sb.str();
}

std::string RTCRemoteInboundRtpStreamStatsIdFromSourceSsrc(
    MediaType media_type,
    uint32_t source_ssrc) {
  char buf[1024];
  SimpleStringBuilder sb(buf);
  sb << "RI" << (media_type == MediaType::AUDIO ? 'A' : 'V') << source_ssrc;
  return sb.str();
}

std::string RTCRemoteOutboundRTPStreamStatsIDFromSSRC(MediaType media_type,
                                                      uint32_t source_ssrc) {
  char buf[1024];
  SimpleStringBuilder sb(buf);
  sb << "RO" << (media_type == MediaType::AUDIO ? 'A' : 'V') << source_ssrc;
  return sb.str();
}

std::string RTCMediaSourceStatsIDFromKindAndAttachment(MediaType media_type,
                                                       int attachment_id) {
  char buf[1024];
  SimpleStringBuilder sb(buf);
  sb << 'S' << (media_type == MediaType::AUDIO ? 'A' : 'V') << attachment_id;
  return sb.str();
}

const char* DataStateToRTCDataChannelState(
    DataChannelInterface::DataState state) {
  switch (state) {
    case DataChannelInterface::kConnecting:
      return "connecting";
    case DataChannelInterface::kOpen:
      return "open";
    case DataChannelInterface::kClosing:
      return "closing";
    case DataChannelInterface::kClosed:
      return "closed";
    default:
      RTC_DCHECK_NOTREACHED();
      return nullptr;
  }
}

const char* IceCandidatePairStateToRTCStatsIceCandidatePairState(
    IceCandidatePairState state) {
  switch (state) {
    case IceCandidatePairState::WAITING:
      return "waiting";
    case IceCandidatePairState::IN_PROGRESS:
      return "in-progress";
    case IceCandidatePairState::SUCCEEDED:
      return "succeeded";
    case IceCandidatePairState::FAILED:
      return "failed";
    default:
      RTC_DCHECK_NOTREACHED();
      return nullptr;
  }
}

const char* IceRoleToRTCIceRole(IceRole role) {
  switch (role) {
    case IceRole::ICEROLE_UNKNOWN:
      return "unknown";
    case IceRole::ICEROLE_CONTROLLED:
      return "controlled";
    case IceRole::ICEROLE_CONTROLLING:
      return "controlling";
    default:
      RTC_DCHECK_NOTREACHED();
      return nullptr;
  }
}

const char* DtlsTransportStateToRTCDtlsTransportState(
    DtlsTransportState state) {
  switch (state) {
    case DtlsTransportState::kNew:
      return "new";
    case DtlsTransportState::kConnecting:
      return "connecting";
    case DtlsTransportState::kConnected:
      return "connected";
    case DtlsTransportState::kClosed:
      return "closed";
    case DtlsTransportState::kFailed:
      return "failed";
    default:
      RTC_CHECK_NOTREACHED();
      return nullptr;
  }
}

const char* IceTransportStateToRTCIceTransportState(IceTransportState state) {
  switch (state) {
    case IceTransportState::kNew:
      return "new";
    case IceTransportState::kChecking:
      return "checking";
    case IceTransportState::kConnected:
      return "connected";
    case IceTransportState::kCompleted:
      return "completed";
    case IceTransportState::kFailed:
      return "failed";
    case IceTransportState::kDisconnected:
      return "disconnected";
    case IceTransportState::kClosed:
      return "closed";
    default:
      RTC_CHECK_NOTREACHED();
      return nullptr;
  }
}

const char* NetworkTypeToStatsType(AdapterType type) {
  switch (type) {
    case ADAPTER_TYPE_CELLULAR:
    case ADAPTER_TYPE_CELLULAR_2G:
    case ADAPTER_TYPE_CELLULAR_3G:
    case ADAPTER_TYPE_CELLULAR_4G:
    case ADAPTER_TYPE_CELLULAR_5G:
      return "cellular";
    case ADAPTER_TYPE_ETHERNET:
      return "ethernet";
    case ADAPTER_TYPE_WIFI:
      return "wifi";
    case ADAPTER_TYPE_VPN:
      return "vpn";
    case ADAPTER_TYPE_UNKNOWN:
    case ADAPTER_TYPE_LOOPBACK:
    case ADAPTER_TYPE_ANY:
      return "unknown";
  }
  RTC_DCHECK_NOTREACHED();
  return nullptr;
}

absl::string_view NetworkTypeToStatsNetworkAdapterType(AdapterType type) {
  switch (type) {
    case ADAPTER_TYPE_CELLULAR:
      return "cellular";
    case ADAPTER_TYPE_CELLULAR_2G:
      return "cellular2g";
    case ADAPTER_TYPE_CELLULAR_3G:
      return "cellular3g";
    case ADAPTER_TYPE_CELLULAR_4G:
      return "cellular4g";
    case ADAPTER_TYPE_CELLULAR_5G:
      return "cellular5g";
    case ADAPTER_TYPE_ETHERNET:
      return "ethernet";
    case ADAPTER_TYPE_WIFI:
      return "wifi";
    case ADAPTER_TYPE_UNKNOWN:
      return "unknown";
    case ADAPTER_TYPE_LOOPBACK:
      return "loopback";
    case ADAPTER_TYPE_ANY:
      return "any";
    case ADAPTER_TYPE_VPN:
      /* should not be handled here. Vpn is modelled as a bool */
      break;
  }
  RTC_DCHECK_NOTREACHED();
  return {};
}

const char* QualityLimitationReasonToRTCQualityLimitationReason(
    QualityLimitationReason reason) {
  switch (reason) {
    case QualityLimitationReason::kNone:
      return "none";
    case QualityLimitationReason::kCpu:
      return "cpu";
    case QualityLimitationReason::kBandwidth:
      return "bandwidth";
    case QualityLimitationReason::kOther:
      return "other";
  }
  RTC_CHECK_NOTREACHED();
}

std::map<std::string, double>
QualityLimitationDurationToRTCQualityLimitationDuration(
    std::map<QualityLimitationReason, int64_t> durations_ms) {
  std::map<std::string, double> result;
  // The internal duration is defined in milliseconds while the spec defines
  // the value in seconds:
  // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationdurations
  for (const auto& elem : durations_ms) {
    result[QualityLimitationReasonToRTCQualityLimitationReason(elem.first)] =
        elem.second / static_cast<double>(kNumMillisecsPerSec);
  }
  return result;
}

double DoubleAudioLevelFromIntAudioLevel(int audio_level) {
  RTC_DCHECK_GE(audio_level, 0);
  RTC_DCHECK_LE(audio_level, 32767);
  return audio_level / 32767.0;
}

// Gets the `codecId` identified by `transport_id` and `codec_params`. If no
// such `RTCCodecStats` exist yet, create it and add it to `report`.
std::string GetCodecIdAndMaybeCreateCodecStats(
    Timestamp timestamp,
    const char direction,
    const std::string& transport_id,
    const RtpCodecParameters& codec_params,
    RTCStatsReport* report) {
  RTC_DCHECK_GE(codec_params.payload_type, 0);
  RTC_DCHECK_LE(codec_params.payload_type, 127);
  RTC_DCHECK(codec_params.clock_rate);
  uint32_t payload_type = static_cast<uint32_t>(codec_params.payload_type);
  std::string codec_id = RTCCodecStatsIDFromTransportAndCodecParameters(
      direction, transport_id, codec_params);
  if (report->Get(codec_id) != nullptr) {
    // The `RTCCodecStats` already exists.
    return codec_id;
  }
  // Create the `RTCCodecStats` that we want to reference.
  auto codec_stats = std::make_unique<RTCCodecStats>(codec_id, timestamp);
  codec_stats->payload_type = payload_type;
  codec_stats->mime_type = codec_params.mime_type();
  if (codec_params.clock_rate.has_value()) {
    codec_stats->clock_rate = static_cast<uint32_t>(*codec_params.clock_rate);
  }
  if (codec_params.num_channels) {
    codec_stats->channels = *codec_params.num_channels;
  }

  StringBuilder fmtp;
  if (WriteFmtpParameters(codec_params.parameters, &fmtp)) {
    codec_stats->sdp_fmtp_line = fmtp.Release();
  }
  codec_stats->transport_id = transport_id;
  report->AddStats(std::move(codec_stats));
  return codec_id;
}

// Provides the media independent counters (both audio and video).
void SetInboundRTPStreamStatsFromMediaReceiverInfo(
    const MediaReceiverInfo& media_receiver_info,
    RTCInboundRtpStreamStats* inbound_stats) {
  RTC_DCHECK(inbound_stats);
  inbound_stats->ssrc = media_receiver_info.ssrc();
  inbound_stats->packets_received =
      static_cast<uint32_t>(media_receiver_info.packets_received);
  inbound_stats->bytes_received =
      static_cast<uint64_t>(media_receiver_info.payload_bytes_received);
  inbound_stats->header_bytes_received = static_cast<uint64_t>(
      media_receiver_info.header_and_padding_bytes_received);
  if (media_receiver_info.retransmitted_bytes_received.has_value()) {
    inbound_stats->retransmitted_bytes_received =
        *media_receiver_info.retransmitted_bytes_received;
  }
  if (media_receiver_info.retransmitted_packets_received.has_value()) {
    inbound_stats->retransmitted_packets_received =
        *media_receiver_info.retransmitted_packets_received;
  }
  inbound_stats->packets_lost =
      static_cast<int32_t>(media_receiver_info.packets_lost);
  inbound_stats->jitter_buffer_delay =
      media_receiver_info.jitter_buffer_delay_seconds;
  inbound_stats->jitter_buffer_target_delay =
      media_receiver_info.jitter_buffer_target_delay_seconds;
  inbound_stats->jitter_buffer_minimum_delay =
      media_receiver_info.jitter_buffer_minimum_delay_seconds;
  inbound_stats->jitter_buffer_emitted_count =
      media_receiver_info.jitter_buffer_emitted_count;
  if (media_receiver_info.nacks_sent.has_value()) {
    inbound_stats->nack_count = *media_receiver_info.nacks_sent;
  }
  if (media_receiver_info.fec_packets_received.has_value()) {
    inbound_stats->fec_packets_received =
        *media_receiver_info.fec_packets_received;
  }
  if (media_receiver_info.fec_packets_discarded.has_value()) {
    inbound_stats->fec_packets_discarded =
        *media_receiver_info.fec_packets_discarded;
  }
  if (media_receiver_info.fec_bytes_received.has_value()) {
    inbound_stats->fec_bytes_received = *media_receiver_info.fec_bytes_received;
  }
  inbound_stats->total_processing_delay =
      media_receiver_info.total_processing_delay_seconds;
}

std::unique_ptr<RTCInboundRtpStreamStats> CreateInboundAudioStreamStats(
    const VoiceMediaInfo& voice_media_info,
    const VoiceReceiverInfo& voice_receiver_info,
    const std::string& transport_id,
    const std::string& mid,
    Timestamp timestamp,
    RTCStatsReport* report) {
  auto inbound_audio = std::make_unique<RTCInboundRtpStreamStats>(
      /*id=*/RTCInboundRtpStreamStatsIDFromSSRC(transport_id, MediaType::AUDIO,
                                                voice_receiver_info.ssrc()),
      timestamp);
  SetInboundRTPStreamStatsFromMediaReceiverInfo(voice_receiver_info,
                                                inbound_audio.get());
  inbound_audio->transport_id = transport_id;
  inbound_audio->mid = mid;
  inbound_audio->kind = "audio";
  if (voice_receiver_info.codec_payload_type.has_value()) {
    auto codec_param_it = voice_media_info.receive_codecs.find(
        *voice_receiver_info.codec_payload_type);
    RTC_DCHECK(codec_param_it != voice_media_info.receive_codecs.end());
    if (codec_param_it != voice_media_info.receive_codecs.end()) {
      inbound_audio->codec_id = GetCodecIdAndMaybeCreateCodecStats(
          inbound_audio->timestamp(), kDirectionInbound, transport_id,
          codec_param_it->second, report);
    }
  }
  inbound_audio->jitter =
      static_cast<double>(voice_receiver_info.jitter_ms) / kNumMillisecsPerSec;
  inbound_audio->total_samples_received =
      voice_receiver_info.total_samples_received;
  inbound_audio->concealed_samples = voice_receiver_info.concealed_samples;
  inbound_audio->silent_concealed_samples =
      voice_receiver_info.silent_concealed_samples;
  inbound_audio->concealment_events = voice_receiver_info.concealment_events;
  inbound_audio->inserted_samples_for_deceleration =
      voice_receiver_info.inserted_samples_for_deceleration;
  inbound_audio->removed_samples_for_acceleration =
      voice_receiver_info.removed_samples_for_acceleration;
  if (voice_receiver_info.audio_level >= 0) {
    inbound_audio->audio_level =
        DoubleAudioLevelFromIntAudioLevel(voice_receiver_info.audio_level);
  }
  inbound_audio->total_audio_energy = voice_receiver_info.total_output_energy;
  inbound_audio->total_samples_duration =
      voice_receiver_info.total_output_duration;
  // `fir_count` and `pli_count` are only valid for video and are
  // purposefully left undefined for audio.
  if (voice_receiver_info.last_packet_received.has_value()) {
    inbound_audio->last_packet_received_timestamp =
        voice_receiver_info.last_packet_received->ms<double>();
  }
  if (voice_receiver_info.estimated_playout_ntp_timestamp_ms.has_value()) {
    // TODO(bugs.webrtc.org/10529): Fix time origin.
    inbound_audio->estimated_playout_timestamp = static_cast<double>(
        *voice_receiver_info.estimated_playout_ntp_timestamp_ms);
  }
  inbound_audio->packets_discarded = voice_receiver_info.packets_discarded;
  inbound_audio->jitter_buffer_flushes =
      voice_receiver_info.jitter_buffer_flushes;
  inbound_audio->delayed_packet_outage_samples =
      voice_receiver_info.delayed_packet_outage_samples;
  inbound_audio->relative_packet_arrival_delay =
      voice_receiver_info.relative_packet_arrival_delay_seconds;
  inbound_audio->interruption_count =
      voice_receiver_info.interruption_count >= 0
          ? voice_receiver_info.interruption_count
          : 0;
  inbound_audio->total_interruption_duration =
      static_cast<double>(voice_receiver_info.total_interruption_duration_ms) /
      kNumMillisecsPerSec;
  return inbound_audio;
}

std::unique_ptr<RTCAudioPlayoutStats> CreateAudioPlayoutStats(
    const AudioDeviceModule::Stats& audio_device_stats,
    Timestamp timestamp) {
  auto stats = std::make_unique<RTCAudioPlayoutStats>(
      /*id=*/kAudioPlayoutSingletonId, timestamp);
  stats->synthesized_samples_duration =
      audio_device_stats.synthesized_samples_duration_s;
  stats->synthesized_samples_events =
      audio_device_stats.synthesized_samples_events;
  stats->total_samples_count = audio_device_stats.total_samples_count;
  stats->total_samples_duration = audio_device_stats.total_samples_duration_s;
  stats->total_playout_delay = audio_device_stats.total_playout_delay_s;
  return stats;
}

std::unique_ptr<RTCRemoteOutboundRtpStreamStats>
CreateRemoteOutboundMediaStreamStats(
    const MediaReceiverInfo& media_receiver_info,
    const std::string& mid,
    MediaType media_type,
    const RTCInboundRtpStreamStats& inbound_audio_stats,
    const std::string& transport_id,
    const bool stats_timestamp_with_environment_clock) {
  std::optional<Timestamp> last_sender_report_timestamp =
      stats_timestamp_with_environment_clock
          ? media_receiver_info.last_sender_report_timestamp
          : media_receiver_info.last_sender_report_utc_timestamp;
  if (!last_sender_report_timestamp.has_value()) {
    // Cannot create `RTCRemoteOutboundRtpStreamStats` when the RTCP SR arrival
    // timestamp is not available - i.e., until the first sender report is
    // received.
    return nullptr;
  }
  RTC_DCHECK_GT(media_receiver_info.sender_reports_reports_count, 0);

  // Create.
  auto stats = std::make_unique<RTCRemoteOutboundRtpStreamStats>(
      /*id=*/RTCRemoteOutboundRTPStreamStatsIDFromSSRC(
          media_type, media_receiver_info.ssrc()),
      *last_sender_report_timestamp);

  // Populate.
  // - RTCRtpStreamStats.
  stats->ssrc = media_receiver_info.ssrc();
  stats->kind = MediaTypeToString(media_type);
  stats->transport_id = transport_id;
  if (inbound_audio_stats.codec_id.has_value()) {
    stats->codec_id = *inbound_audio_stats.codec_id;
  }
  // - RTCSentRtpStreamStats.
  stats->packets_sent = media_receiver_info.sender_reports_packets_sent;
  stats->bytes_sent = media_receiver_info.sender_reports_bytes_sent;
  // - RTCRemoteOutboundRtpStreamStats.
  stats->local_id = inbound_audio_stats.id();
  // last_sender_report_remote_utc_timestamp_ms is set together with
  // last_sender_report_utc_timestamp_ms.
  RTC_DCHECK(
      media_receiver_info.last_sender_report_remote_utc_timestamp.has_value());
  stats->remote_timestamp =
      media_receiver_info.last_sender_report_remote_utc_timestamp->ms<double>();
  stats->reports_sent = media_receiver_info.sender_reports_reports_count;
  if (media_receiver_info.round_trip_time.has_value()) {
    stats->round_trip_time =
        media_receiver_info.round_trip_time->seconds<double>();
  }
  stats->round_trip_time_measurements =
      media_receiver_info.round_trip_time_measurements;
  stats->total_round_trip_time =
      media_receiver_info.total_round_trip_time.seconds<double>();

  return stats;
}

std::unique_ptr<RTCInboundRtpStreamStats>
CreateInboundRTPStreamStatsFromVideoReceiverInfo(
    const std::string& transport_id,
    const std::string& mid,
    const VideoMediaInfo& video_media_info,
    const VideoReceiverInfo& video_receiver_info,
    Timestamp timestamp,
    RTCStatsReport* report) {
  auto inbound_video = std::make_unique<RTCInboundRtpStreamStats>(
      RTCInboundRtpStreamStatsIDFromSSRC(transport_id, MediaType::VIDEO,
                                         video_receiver_info.ssrc()),
      timestamp);
  SetInboundRTPStreamStatsFromMediaReceiverInfo(video_receiver_info,
                                                inbound_video.get());
  inbound_video->transport_id = transport_id;
  inbound_video->mid = mid;
  inbound_video->kind = "video";
  if (video_receiver_info.codec_payload_type.has_value()) {
    auto codec_param_it = video_media_info.receive_codecs.find(
        *video_receiver_info.codec_payload_type);
    RTC_DCHECK(codec_param_it != video_media_info.receive_codecs.end());
    if (codec_param_it != video_media_info.receive_codecs.end()) {
      inbound_video->codec_id = GetCodecIdAndMaybeCreateCodecStats(
          inbound_video->timestamp(), kDirectionInbound, transport_id,
          codec_param_it->second, report);
    }
  }
  inbound_video->jitter =
      static_cast<double>(video_receiver_info.jitter_ms) / kNumMillisecsPerSec;
  inbound_video->fir_count =
      static_cast<uint32_t>(video_receiver_info.firs_sent);
  inbound_video->pli_count =
      static_cast<uint32_t>(video_receiver_info.plis_sent);
  inbound_video->frames_received = video_receiver_info.frames_received;
  inbound_video->frames_decoded = video_receiver_info.frames_decoded;
  inbound_video->frames_dropped = video_receiver_info.frames_dropped;
  inbound_video->key_frames_decoded = video_receiver_info.key_frames_decoded;
  if (video_receiver_info.frame_width > 0) {
    inbound_video->frame_width =
        static_cast<uint32_t>(video_receiver_info.frame_width);
  }
  if (video_receiver_info.frame_height > 0) {
    inbound_video->frame_height =
        static_cast<uint32_t>(video_receiver_info.frame_height);
  }
  if (video_receiver_info.framerate_decoded > 0) {
    inbound_video->frames_per_second = video_receiver_info.framerate_decoded;
  }
  if (video_receiver_info.qp_sum.has_value()) {
    inbound_video->qp_sum = *video_receiver_info.qp_sum;
  }
  if (video_receiver_info.corruption_score_sum.has_value()) {
    RTC_CHECK(video_receiver_info.corruption_score_squared_sum.has_value());
    RTC_CHECK_GT(video_receiver_info.corruption_score_count, 0);
    inbound_video->total_corruption_probability =
        *video_receiver_info.corruption_score_sum;
    inbound_video->total_squared_corruption_probability =
        *video_receiver_info.corruption_score_squared_sum;
    inbound_video->corruption_measurements =
        video_receiver_info.corruption_score_count;
  }
  if (video_receiver_info.timing_frame_info.has_value()) {
    inbound_video->goog_timing_frame_info =
        video_receiver_info.timing_frame_info->ToString();
  }
  inbound_video->total_decode_time =
      video_receiver_info.total_decode_time.seconds<double>();
  inbound_video->total_processing_delay =
      video_receiver_info.total_processing_delay.seconds<double>();
  inbound_video->total_assembly_time =
      video_receiver_info.total_assembly_time.seconds<double>();
  inbound_video->frames_assembled_from_multiple_packets =
      video_receiver_info.frames_assembled_from_multiple_packets;
  inbound_video->total_inter_frame_delay =
      video_receiver_info.total_inter_frame_delay;
  inbound_video->total_squared_inter_frame_delay =
      video_receiver_info.total_squared_inter_frame_delay;
  inbound_video->pause_count = video_receiver_info.pause_count;
  inbound_video->total_pauses_duration =
      static_cast<double>(video_receiver_info.total_pauses_duration_ms) /
      kNumMillisecsPerSec;
  inbound_video->freeze_count = video_receiver_info.freeze_count;
  inbound_video->total_freezes_duration =
      static_cast<double>(video_receiver_info.total_freezes_duration_ms) /
      kNumMillisecsPerSec;
  inbound_video->min_playout_delay =
      static_cast<double>(video_receiver_info.min_playout_delay_ms) /
      kNumMillisecsPerSec;
  if (video_receiver_info.last_packet_received.has_value()) {
    inbound_video->last_packet_received_timestamp =
        video_receiver_info.last_packet_received->ms<double>();
  }
  if (video_receiver_info.estimated_playout_ntp_timestamp_ms.has_value()) {
    // TODO(bugs.webrtc.org/10529): Fix time origin if needed.
    inbound_video->estimated_playout_timestamp = static_cast<double>(
        *video_receiver_info.estimated_playout_ntp_timestamp_ms);
  }
  // TODO(bugs.webrtc.org/10529): When info's `content_info` is optional
  // support the "unspecified" value.
  if (videocontenttypehelpers::IsScreenshare(video_receiver_info.content_type))
    inbound_video->content_type = "screenshare";
  if (video_receiver_info.decoder_implementation_name.has_value()) {
    inbound_video->decoder_implementation =
        *video_receiver_info.decoder_implementation_name;
  }
  if (video_receiver_info.power_efficient_decoder.has_value()) {
    inbound_video->power_efficient_decoder =
        *video_receiver_info.power_efficient_decoder;
  }
  for (const auto& ssrc_group : video_receiver_info.ssrc_groups) {
    if (ssrc_group.semantics == kFidSsrcGroupSemantics &&
        ssrc_group.ssrcs.size() == 2) {
      inbound_video->rtx_ssrc = ssrc_group.ssrcs[1];
    } else if (ssrc_group.semantics == kFecFrSsrcGroupSemantics &&
               ssrc_group.ssrcs.size() == 2) {
      // TODO(bugs.webrtc.org/15002): the ssrc-group might be >= 2 with
      // multistream support.
      inbound_video->fec_ssrc = ssrc_group.ssrcs[1];
    }
  }

  return inbound_video;
}

// Provides the media independent counters and information (both audio and
// video).
void SetOutboundRTPStreamStatsFromMediaSenderInfo(
    const MediaSenderInfo& media_sender_info,
    RTCOutboundRtpStreamStats* outbound_stats) {
  RTC_DCHECK(outbound_stats);
  outbound_stats->ssrc = media_sender_info.ssrc();
  outbound_stats->packets_sent =
      static_cast<uint32_t>(media_sender_info.packets_sent);
  outbound_stats->total_packet_send_delay =
      media_sender_info.total_packet_send_delay.seconds<double>();
  outbound_stats->retransmitted_packets_sent =
      media_sender_info.retransmitted_packets_sent;
  outbound_stats->bytes_sent =
      static_cast<uint64_t>(media_sender_info.payload_bytes_sent);
  outbound_stats->header_bytes_sent =
      static_cast<uint64_t>(media_sender_info.header_and_padding_bytes_sent);
  outbound_stats->retransmitted_bytes_sent =
      media_sender_info.retransmitted_bytes_sent;
  outbound_stats->nack_count = media_sender_info.nacks_received;
  if (media_sender_info.active.has_value()) {
    outbound_stats->active = *media_sender_info.active;
  }
}

std::unique_ptr<RTCOutboundRtpStreamStats>
CreateOutboundRTPStreamStatsFromVoiceSenderInfo(
    const std::string& transport_id,
    const std::string& mid,
    const VoiceMediaInfo& voice_media_info,
    const VoiceSenderInfo& voice_sender_info,
    Timestamp timestamp,
    RTCStatsReport* report) {
  auto outbound_audio = std::make_unique<RTCOutboundRtpStreamStats>(
      RTCOutboundRtpStreamStatsIDFromSSRC(transport_id, MediaType::AUDIO,
                                          voice_sender_info.ssrc()),
      timestamp);
  SetOutboundRTPStreamStatsFromMediaSenderInfo(voice_sender_info,
                                               outbound_audio.get());
  outbound_audio->transport_id = transport_id;
  outbound_audio->mid = mid;
  outbound_audio->kind = "audio";
  if (voice_sender_info.target_bitrate.has_value()) {
    outbound_audio->target_bitrate = voice_sender_info.target_bitrate->bps();
  }
  if (voice_sender_info.codec_payload_type.has_value()) {
    auto codec_param_it = voice_media_info.send_codecs.find(
        *voice_sender_info.codec_payload_type);
    RTC_DCHECK(codec_param_it != voice_media_info.send_codecs.end());
    if (codec_param_it != voice_media_info.send_codecs.end()) {
      outbound_audio->codec_id = GetCodecIdAndMaybeCreateCodecStats(
          outbound_audio->timestamp(), kDirectionOutbound, transport_id,
          codec_param_it->second, report);
    }
  }
  // `fir_count` and `pli_count` are only valid for video and are
  // purposefully left undefined for audio.
  return outbound_audio;
}

std::unique_ptr<RTCOutboundRtpStreamStats>
CreateOutboundRTPStreamStatsFromVideoSenderInfo(
    const std::string& transport_id,
    const std::string& mid,
    const VideoMediaInfo& video_media_info,
    const VideoSenderInfo& video_sender_info,
    Timestamp timestamp,
    RTCStatsReport* report) {
  auto outbound_video = std::make_unique<RTCOutboundRtpStreamStats>(
      RTCOutboundRtpStreamStatsIDFromSSRC(transport_id, MediaType::VIDEO,
                                          video_sender_info.ssrc()),
      timestamp);
  SetOutboundRTPStreamStatsFromMediaSenderInfo(video_sender_info,
                                               outbound_video.get());
  outbound_video->transport_id = transport_id;
  outbound_video->mid = mid;
  outbound_video->kind = "video";
  if (video_sender_info.codec_payload_type.has_value()) {
    auto codec_param_it = video_media_info.send_codecs.find(
        *video_sender_info.codec_payload_type);
    RTC_DCHECK(codec_param_it != video_media_info.send_codecs.end());
    if (codec_param_it != video_media_info.send_codecs.end()) {
      outbound_video->codec_id = GetCodecIdAndMaybeCreateCodecStats(
          outbound_video->timestamp(), kDirectionOutbound, transport_id,
          codec_param_it->second, report);
    }
  }
  outbound_video->fir_count =
      static_cast<uint32_t>(video_sender_info.firs_received);
  outbound_video->pli_count =
      static_cast<uint32_t>(video_sender_info.plis_received);
  if (video_sender_info.qp_sum.has_value())
    outbound_video->qp_sum = *video_sender_info.qp_sum;
  if (video_sender_info.target_bitrate.has_value()) {
    outbound_video->target_bitrate = video_sender_info.target_bitrate->bps();
  }
  outbound_video->frames_encoded = video_sender_info.frames_encoded;
  outbound_video->key_frames_encoded = video_sender_info.key_frames_encoded;
  outbound_video->total_encode_time =
      static_cast<double>(video_sender_info.total_encode_time_ms) /
      kNumMillisecsPerSec;
  outbound_video->total_encoded_bytes_target =
      video_sender_info.total_encoded_bytes_target;
  if (video_sender_info.send_frame_width > 0) {
    outbound_video->frame_width =
        static_cast<uint32_t>(video_sender_info.send_frame_width);
  }
  if (video_sender_info.send_frame_height > 0) {
    outbound_video->frame_height =
        static_cast<uint32_t>(video_sender_info.send_frame_height);
  }
  if (video_sender_info.framerate_sent > 0) {
    outbound_video->frames_per_second = video_sender_info.framerate_sent;
  }
  outbound_video->frames_sent = video_sender_info.frames_sent;
  outbound_video->huge_frames_sent = video_sender_info.huge_frames_sent;
  outbound_video->quality_limitation_reason =
      QualityLimitationReasonToRTCQualityLimitationReason(
          video_sender_info.quality_limitation_reason);
  outbound_video->quality_limitation_durations =
      QualityLimitationDurationToRTCQualityLimitationDuration(
          video_sender_info.quality_limitation_durations_ms);
  outbound_video->quality_limitation_resolution_changes =
      video_sender_info.quality_limitation_resolution_changes;
  // TODO(https://crbug.com/webrtc/10529): When info's `content_info` is
  // optional, support the "unspecified" value.
  if (videocontenttypehelpers::IsScreenshare(video_sender_info.content_type))
    outbound_video->content_type = "screenshare";
  if (video_sender_info.encoder_implementation_name.has_value()) {
    outbound_video->encoder_implementation =
        *video_sender_info.encoder_implementation_name;
  }
  if (video_sender_info.rid.has_value()) {
    outbound_video->rid = *video_sender_info.rid;
  }
  if (video_sender_info.encoding_index.has_value()) {
    outbound_video->encoding_index = *video_sender_info.encoding_index;
  }
  if (video_sender_info.power_efficient_encoder.has_value()) {
    outbound_video->power_efficient_encoder =
        *video_sender_info.power_efficient_encoder;
  }
  if (video_sender_info.scalability_mode) {
    outbound_video->scalability_mode = std::string(
        ScalabilityModeToString(*video_sender_info.scalability_mode));
  }
  for (const auto& ssrc_group : video_sender_info.ssrc_groups) {
    if (ssrc_group.semantics == kFidSsrcGroupSemantics &&
        ssrc_group.ssrcs.size() == 2 &&
        video_sender_info.ssrc() == ssrc_group.ssrcs[0]) {
      outbound_video->rtx_ssrc = ssrc_group.ssrcs[1];
    }
  }
  return outbound_video;
}

std::unique_ptr<RTCRemoteInboundRtpStreamStats>
ProduceRemoteInboundRtpStreamStatsFromReportBlockData(
    const std::string& transport_id,
    const ReportBlockData& report_block,
    MediaType media_type,
    const std::map<std::string, RTCOutboundRtpStreamStats*>& outbound_rtps,
    const RTCStatsReport& report,
    const bool stats_timestamp_with_environment_clock) {
  // RTCStats' timestamp generally refers to when the metric was sampled, but
  // for "remote-[outbound/inbound]-rtp" it refers to the local time when the
  // Report Block was received.
  Timestamp arrival_timestamp = stats_timestamp_with_environment_clock
                                    ? report_block.report_block_timestamp()
                                    : report_block.report_block_timestamp_utc();
  auto remote_inbound = std::make_unique<RTCRemoteInboundRtpStreamStats>(
      RTCRemoteInboundRtpStreamStatsIdFromSourceSsrc(
          media_type, report_block.source_ssrc()),
      arrival_timestamp);
  remote_inbound->ssrc = report_block.source_ssrc();
  remote_inbound->kind = media_type == MediaType::AUDIO ? "audio" : "video";
  remote_inbound->packets_lost = report_block.cumulative_lost();
  remote_inbound->fraction_lost = report_block.fraction_lost();
  if (report_block.num_rtts() > 0) {
    remote_inbound->round_trip_time = report_block.last_rtt().seconds<double>();
  }
  remote_inbound->total_round_trip_time =
      report_block.sum_rtts().seconds<double>();
  remote_inbound->round_trip_time_measurements = report_block.num_rtts();

  std::string local_id = RTCOutboundRtpStreamStatsIDFromSSRC(
      transport_id, media_type, report_block.source_ssrc());
  // Look up local stat from `outbound_rtps` where the pointers are non-const.
  auto local_id_it = outbound_rtps.find(local_id);
  if (local_id_it != outbound_rtps.end()) {
    remote_inbound->local_id = local_id;
    auto& outbound_rtp = *local_id_it->second;
    outbound_rtp.remote_id = remote_inbound->id();
    // The RTP/RTCP transport is obtained from the
    // RTCOutboundRtpStreamStats's transport.
    const auto* transport_from_id = report.Get(transport_id);
    if (transport_from_id) {
      const auto& transport = transport_from_id->cast_to<RTCTransportStats>();
      // If RTP and RTCP are not multiplexed, there is a separate RTCP
      // transport paired with the RTP transport, otherwise the same
      // transport is used for RTCP and RTP.
      remote_inbound->transport_id =
          transport.rtcp_transport_stats_id.has_value()
              ? *transport.rtcp_transport_stats_id
              : *outbound_rtp.transport_id;
    }
    // We're assuming the same codec is used on both ends. However if the
    // codec is switched out on the fly we may have received a Report Block
    // based on the previous codec and there is no way to tell which point in
    // time the codec changed for the remote end.
    const auto* codec_from_id = outbound_rtp.codec_id.has_value()
                                    ? report.Get(*outbound_rtp.codec_id)
                                    : nullptr;
    if (codec_from_id) {
      remote_inbound->codec_id = *outbound_rtp.codec_id;
      const auto& codec = codec_from_id->cast_to<RTCCodecStats>();
      if (codec.clock_rate.has_value()) {
        remote_inbound->jitter =
            report_block.jitter(*codec.clock_rate).seconds<double>();
      }
    }
  }
  return remote_inbound;
}

void ProduceCertificateStatsFromSSLCertificateStats(
    Timestamp timestamp,
    const SSLCertificateStats& certificate_stats,
    RTCStatsReport* report) {
  RTCCertificateStats* prev_certificate_stats = nullptr;
  for (const SSLCertificateStats* s = &certificate_stats; s;
       s = s->issuer.get()) {
    std::string certificate_stats_id =
        RTCCertificateIDFromFingerprint(s->fingerprint);
    // It is possible for the same certificate to show up multiple times, e.g.
    // if local and remote side use the same certificate in a loopback call.
    // If the report already contains stats for this certificate, skip it.
    if (report->Get(certificate_stats_id)) {
      RTC_DCHECK_EQ(s, &certificate_stats);
      break;
    }
    RTCCertificateStats* current_certificate_stats =
        new RTCCertificateStats(certificate_stats_id, timestamp);
    current_certificate_stats->fingerprint = s->fingerprint;
    current_certificate_stats->fingerprint_algorithm = s->fingerprint_algorithm;
    current_certificate_stats->base64_certificate = s->base64_certificate;
    if (prev_certificate_stats)
      prev_certificate_stats->issuer_certificate_id =
          current_certificate_stats->id();
    report->AddStats(
        std::unique_ptr<RTCCertificateStats>(current_certificate_stats));
    prev_certificate_stats = current_certificate_stats;
  }
}

const std::string& ProduceIceCandidateStats(Timestamp timestamp,
                                            const Candidate& candidate,
                                            bool is_local,
                                            const std::string& transport_id,
                                            RTCStatsReport* report) {
  std::string id = "I" + candidate.id();
  const RTCStats* stats = report->Get(id);
  if (!stats) {
    std::unique_ptr<RTCIceCandidateStats> candidate_stats;
    if (is_local) {
      candidate_stats =
          std::make_unique<RTCLocalIceCandidateStats>(std::move(id), timestamp);
    } else {
      candidate_stats = std::make_unique<RTCRemoteIceCandidateStats>(
          std::move(id), timestamp);
    }
    candidate_stats->transport_id = transport_id;
    if (is_local) {
      candidate_stats->network_type =
          NetworkTypeToStatsType(candidate.network_type());
      const std::string& relay_protocol = candidate.relay_protocol();
      const std::string& url = candidate.url();
      if (candidate.is_relay() ||
          (candidate.is_prflx() && !relay_protocol.empty())) {
        RTC_DCHECK(relay_protocol.compare("udp") == 0 ||
                   relay_protocol.compare("tcp") == 0 ||
                   relay_protocol.compare("tls") == 0);
        candidate_stats->relay_protocol = relay_protocol;
        if (!url.empty()) {
          candidate_stats->url = url;
        }
      } else if (candidate.is_stun()) {
        if (!url.empty()) {
          candidate_stats->url = url;
        }
      }
      if (candidate.network_type() == ADAPTER_TYPE_VPN) {
        candidate_stats->vpn = true;
        candidate_stats->network_adapter_type =
            std::string(NetworkTypeToStatsNetworkAdapterType(
                candidate.underlying_type_for_vpn()));
      } else {
        candidate_stats->vpn = false;
        candidate_stats->network_adapter_type = std::string(
            NetworkTypeToStatsNetworkAdapterType(candidate.network_type()));
      }
    } else {
      // We don't expect to know the adapter type of remote candidates.
      RTC_DCHECK_EQ(ADAPTER_TYPE_UNKNOWN, candidate.network_type());
      RTC_DCHECK_EQ(0, candidate.relay_protocol().compare(""));
      RTC_DCHECK_EQ(ADAPTER_TYPE_UNKNOWN, candidate.underlying_type_for_vpn());
    }
    candidate_stats->ip = candidate.address().ipaddr().ToString();
    candidate_stats->address = candidate.address().ipaddr().ToString();
    candidate_stats->port = static_cast<int32_t>(candidate.address().port());
    candidate_stats->protocol = candidate.protocol();
    candidate_stats->candidate_type = candidate.type_name();
    candidate_stats->priority = static_cast<int32_t>(candidate.priority());
    candidate_stats->foundation = candidate.foundation();
    auto related_address = candidate.related_address();
    if (related_address.port() != 0) {
      candidate_stats->related_address = related_address.ipaddr().ToString();
      candidate_stats->related_port =
          static_cast<int32_t>(related_address.port());
    }
    const std::string& username = candidate.username();
    if (!username.empty()) {
      candidate_stats->username_fragment = username;
    }
    if (candidate.protocol() == "tcp") {
      candidate_stats->tcp_type = candidate.tcptype();
    }

    stats = candidate_stats.get();
    report->AddStats(std::move(candidate_stats));
  }
  RTC_DCHECK_EQ(stats->type(), is_local ? RTCLocalIceCandidateStats::kType
                                        : RTCRemoteIceCandidateStats::kType);
  return stats->id();
}

template <typename StatsType>
void SetAudioProcessingStats(StatsType* stats,
                             const AudioProcessingStats& apm_stats) {
  if (apm_stats.echo_return_loss.has_value()) {
    stats->echo_return_loss = *apm_stats.echo_return_loss;
  }
  if (apm_stats.echo_return_loss_enhancement.has_value()) {
    stats->echo_return_loss_enhancement =
        *apm_stats.echo_return_loss_enhancement;
  }
}

}  // namespace

scoped_refptr<RTCStatsReport> RTCStatsCollector::CreateReportFilteredBySelector(
    bool filter_by_sender_selector,
    scoped_refptr<const RTCStatsReport> report,
    scoped_refptr<RtpSenderInternal> sender_selector,
    scoped_refptr<RtpReceiverInternal> receiver_selector) {
  std::vector<std::string> rtpstream_ids;
  if (filter_by_sender_selector) {
    // Filter mode: RTCStatsCollector::RequestInfo::kSenderSelector
    if (sender_selector) {
      // Find outbound-rtp(s) of the sender using ssrc lookup.
      auto encodings = sender_selector->GetParametersInternal().encodings;
      for (const auto* outbound_rtp :
           report->GetStatsOfType<RTCOutboundRtpStreamStats>()) {
        RTC_DCHECK(outbound_rtp->ssrc.has_value());
        auto it = std::find_if(encodings.begin(), encodings.end(),
                               [ssrc = *outbound_rtp->ssrc](
                                   const RtpEncodingParameters& encoding) {
                                 return encoding.ssrc == ssrc;
                               });
        if (it != encodings.end()) {
          rtpstream_ids.push_back(outbound_rtp->id());
        }
      }
    }
  } else {
    // Filter mode: RTCStatsCollector::RequestInfo::kReceiverSelector
    if (receiver_selector) {
      // Find the inbound-rtp of the receiver using ssrc lookup.
      std::optional<uint32_t> ssrc;
      worker_thread_->BlockingCall([&] { ssrc = receiver_selector->ssrc(); });
      if (ssrc.has_value()) {
        for (const auto* inbound_rtp :
             report->GetStatsOfType<RTCInboundRtpStreamStats>()) {
          RTC_DCHECK(inbound_rtp->ssrc.has_value());
          if (*inbound_rtp->ssrc == *ssrc) {
            rtpstream_ids.push_back(inbound_rtp->id());
          }
        }
      }
    }
  }
  if (rtpstream_ids.empty())
    return RTCStatsReport::Create(report->timestamp());
  return TakeReferencedStats(report->Copy(), rtpstream_ids);
}

RTCStatsCollector::CertificateStatsPair
RTCStatsCollector::CertificateStatsPair::Copy() const {
  CertificateStatsPair copy;
  copy.local = local ? local->Copy() : nullptr;
  copy.remote = remote ? remote->Copy() : nullptr;
  return copy;
}

RTCStatsCollector::RequestInfo::RequestInfo(
    scoped_refptr<RTCStatsCollectorCallback> callback)
    : RequestInfo(FilterMode::kAll, std::move(callback), nullptr, nullptr) {}

RTCStatsCollector::RequestInfo::RequestInfo(
    scoped_refptr<RtpSenderInternal> selector,
    scoped_refptr<RTCStatsCollectorCallback> callback)
    : RequestInfo(FilterMode::kSenderSelector,
                  std::move(callback),
                  std::move(selector),
                  nullptr) {}

RTCStatsCollector::RequestInfo::RequestInfo(
    scoped_refptr<RtpReceiverInternal> selector,
    scoped_refptr<RTCStatsCollectorCallback> callback)
    : RequestInfo(FilterMode::kReceiverSelector,
                  std::move(callback),
                  nullptr,
                  std::move(selector)) {}

RTCStatsCollector::RequestInfo::RequestInfo(
    RTCStatsCollector::RequestInfo::FilterMode filter_mode,
    scoped_refptr<RTCStatsCollectorCallback> callback,
    scoped_refptr<RtpSenderInternal> sender_selector,
    scoped_refptr<RtpReceiverInternal> receiver_selector)
    : filter_mode_(filter_mode),
      callback_(std::move(callback)),
      sender_selector_(std::move(sender_selector)),
      receiver_selector_(std::move(receiver_selector)) {
  RTC_DCHECK(callback_);
  RTC_DCHECK(!sender_selector_ || !receiver_selector_);
}

scoped_refptr<RTCStatsCollector> RTCStatsCollector::Create(
    PeerConnectionInternal* pc,
    const Environment& env,
    int64_t cache_lifetime_us) {
  return make_ref_counted<RTCStatsCollector>(pc, env, cache_lifetime_us);
}

RTCStatsCollector::RTCStatsCollector(PeerConnectionInternal* pc,
                                     const Environment& env,
                                     int64_t cache_lifetime_us)
    : pc_(pc),
      env_(env),
      stats_timestamp_with_environment_clock_(
          pc->GetConfiguration().stats_timestamp_with_environment_clock()),
      signaling_thread_(pc->signaling_thread()),
      worker_thread_(pc->worker_thread()),
      network_thread_(pc->network_thread()),
      num_pending_partial_reports_(0),
      partial_report_timestamp_us_(0),
      network_report_event_(true /* manual_reset */,
                            true /* initially_signaled */),
      cache_timestamp_us_(0),
      cache_lifetime_us_(cache_lifetime_us) {
  RTC_DCHECK(pc_);
  RTC_DCHECK(signaling_thread_);
  RTC_DCHECK(worker_thread_);
  RTC_DCHECK(network_thread_);
  RTC_DCHECK_GE(cache_lifetime_us_, 0);
}

RTCStatsCollector::~RTCStatsCollector() {
  RTC_DCHECK_EQ(num_pending_partial_reports_, 0);
}

void RTCStatsCollector::GetStatsReport(
    scoped_refptr<RTCStatsCollectorCallback> callback) {
  GetStatsReportInternal(RequestInfo(std::move(callback)));
}

void RTCStatsCollector::GetStatsReport(
    scoped_refptr<RtpSenderInternal> selector,
    scoped_refptr<RTCStatsCollectorCallback> callback) {
  GetStatsReportInternal(RequestInfo(std::move(selector), std::move(callback)));
}

void RTCStatsCollector::GetStatsReport(
    scoped_refptr<RtpReceiverInternal> selector,
    scoped_refptr<RTCStatsCollectorCallback> callback) {
  GetStatsReportInternal(RequestInfo(std::move(selector), std::move(callback)));
}

void RTCStatsCollector::GetStatsReportInternal(
    RTCStatsCollector::RequestInfo request) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  requests_.push_back(std::move(request));

  // "Now" using a monotonically increasing timer.
  int64_t cache_now_us = TimeMicros();
  if (cached_report_ &&
      cache_now_us - cache_timestamp_us_ <= cache_lifetime_us_) {
    // We have a fresh cached report to deliver. Deliver asynchronously, since
    // the caller may not be expecting a synchronous callback, and it avoids
    // reentrancy problems.
    signaling_thread_->PostTask(
        absl::bind_front(&RTCStatsCollector::DeliverCachedReport,
                         scoped_refptr<RTCStatsCollector>(this), cached_report_,
                         std::move(requests_)));
  } else if (!num_pending_partial_reports_) {
    // Only start gathering stats if we're not already gathering stats. In the
    // case of already gathering stats, `callback_` will be invoked when there
    // are no more pending partial reports.

    Timestamp timestamp =
        stats_timestamp_with_environment_clock_
            ?
            // "Now" using a monotonically increasing timer.
            env_.clock().CurrentTime()
            :
            // "Now" using a system clock, relative to the UNIX epoch (Jan 1,
            // 1970, UTC), in microseconds. The system clock could be modified
            // and is not necessarily monotonically increasing.
            Timestamp::Micros(TimeUTCMicros());

    num_pending_partial_reports_ = 2;
    partial_report_timestamp_us_ = cache_now_us;

    // Prepare `transceiver_stats_infos_` and `call_stats_` for use in
    // `ProducePartialResultsOnNetworkThread` and
    // `ProducePartialResultsOnSignalingThread`.
    PrepareTransceiverStatsInfosAndCallStats_s_w_n();
    // Don't touch `network_report_` on the signaling thread until
    // ProducePartialResultsOnNetworkThread() has signaled the
    // `network_report_event_`.
    network_report_event_.Reset();
    scoped_refptr<RTCStatsCollector> collector(this);
    network_thread_->PostTask([collector,
                               sctp_transport_name = pc_->sctp_transport_name(),
                               timestamp]() mutable {
      collector->ProducePartialResultsOnNetworkThread(
          timestamp, std::move(sctp_transport_name));
    });
    ProducePartialResultsOnSignalingThread(timestamp);
  }
}

void RTCStatsCollector::ClearCachedStatsReport() {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  cached_report_ = nullptr;
  MutexLock lock(&cached_certificates_mutex_);
  cached_certificates_by_transport_.clear();
}

void RTCStatsCollector::WaitForPendingRequest() {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  // If a request is pending, blocks until the `network_report_event_` is
  // signaled and then delivers the result. Otherwise this is a NO-OP.
  MergeNetworkReport_s();
}

void RTCStatsCollector::ProducePartialResultsOnSignalingThread(
    Timestamp timestamp) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  partial_report_ = RTCStatsReport::Create(timestamp);

  ProducePartialResultsOnSignalingThreadImpl(timestamp, partial_report_.get());

  // ProducePartialResultsOnSignalingThread() is running synchronously on the
  // signaling thread, so it is always the first partial result delivered on the
  // signaling thread. The request is not complete until MergeNetworkReport_s()
  // happens; we don't have to do anything here.
  RTC_DCHECK_GT(num_pending_partial_reports_, 1);
  --num_pending_partial_reports_;
}

void RTCStatsCollector::ProducePartialResultsOnSignalingThreadImpl(
    Timestamp timestamp,
    RTCStatsReport* partial_report) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  ProduceMediaSourceStats_s(timestamp, partial_report);
  ProducePeerConnectionStats_s(timestamp, partial_report);
  ProduceAudioPlayoutStats_s(timestamp, partial_report);
}

void RTCStatsCollector::ProducePartialResultsOnNetworkThread(
    Timestamp timestamp,
    std::optional<std::string> sctp_transport_name) {
  TRACE_EVENT0("webrtc",
               "RTCStatsCollector::ProducePartialResultsOnNetworkThread");
  RTC_DCHECK_RUN_ON(network_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  // Touching `network_report_` on this thread is safe by this method because
  // `network_report_event_` is reset before this method is invoked.
  network_report_ = RTCStatsReport::Create(timestamp);

  ProduceDataChannelStats_n(timestamp, network_report_.get());

  std::set<std::string> transport_names;
  if (sctp_transport_name) {
    transport_names.emplace(std::move(*sctp_transport_name));
  }

  for (const auto& info : transceiver_stats_infos_) {
    if (info.transport_name)
      transport_names.insert(*info.transport_name);
  }

  std::map<std::string, TransportStats> transport_stats_by_name =
      pc_->GetTransportStatsByNames(transport_names);
  std::map<std::string, CertificateStatsPair> transport_cert_stats =
      PrepareTransportCertificateStats_n(transport_stats_by_name);

  ProducePartialResultsOnNetworkThreadImpl(timestamp, transport_stats_by_name,
                                           transport_cert_stats,
                                           network_report_.get());

  // Signal that it is now safe to touch `network_report_` on the signaling
  // thread, and post a task to merge it into the final results.
  network_report_event_.Set();
  scoped_refptr<RTCStatsCollector> collector(this);
  signaling_thread_->PostTask(
      [collector] { collector->MergeNetworkReport_s(); });
}

void RTCStatsCollector::ProducePartialResultsOnNetworkThreadImpl(
    Timestamp timestamp,
    const std::map<std::string, TransportStats>& transport_stats_by_name,
    const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
    RTCStatsReport* partial_report) {
  RTC_DCHECK_RUN_ON(network_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  ProduceCertificateStats_n(timestamp, transport_cert_stats, partial_report);
  ProduceIceCandidateAndPairStats_n(timestamp, transport_stats_by_name,
                                    call_stats_, partial_report);
  ProduceTransportStats_n(timestamp, transport_stats_by_name,
                          transport_cert_stats, partial_report);
  ProduceRTPStreamStats_n(timestamp, transceiver_stats_infos_, partial_report);
}

void RTCStatsCollector::MergeNetworkReport_s() {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  // The `network_report_event_` must be signaled for it to be safe to touch
  // `network_report_`. This is normally not blocking, but if
  // WaitForPendingRequest() is called while a request is pending, we might have
  // to wait until the network thread is done touching `network_report_`.
  network_report_event_.Wait(Event::kForever);
  if (!network_report_) {
    // Normally, MergeNetworkReport_s() is executed because it is posted from
    // the network thread. But if WaitForPendingRequest() is called while a
    // request is pending, an early call to MergeNetworkReport_s() is made,
    // merging the report and setting `network_report_` to null. If so, when the
    // previously posted MergeNetworkReport_s() is later executed, the report is
    // already null and nothing needs to be done here.
    return;
  }
  RTC_DCHECK_GT(num_pending_partial_reports_, 0);
  RTC_DCHECK(partial_report_);
  partial_report_->TakeMembersFrom(network_report_);
  network_report_ = nullptr;
  --num_pending_partial_reports_;
  // `network_report_` is currently the only partial report collected
  // asynchronously, so `num_pending_partial_reports_` must now be 0 and we are
  // ready to deliver the result.
  RTC_DCHECK_EQ(num_pending_partial_reports_, 0);
  cache_timestamp_us_ = partial_report_timestamp_us_;
  cached_report_ = partial_report_;
  partial_report_ = nullptr;
  transceiver_stats_infos_.clear();
  // Trace WebRTC Stats when getStats is called on Javascript.
  // This allows access to WebRTC stats from trace logs. To enable them,
  // select the "webrtc_stats" category when recording traces.
  TRACE_EVENT_INSTANT1("webrtc_stats", "webrtc_stats", TRACE_EVENT_SCOPE_GLOBAL,
                       "report", cached_report_->ToJson());

  // Deliver report and clear `requests_`.
  std::vector<RequestInfo> requests;
  requests.swap(requests_);
  DeliverCachedReport(cached_report_, std::move(requests));
}

void RTCStatsCollector::DeliverCachedReport(
    scoped_refptr<const RTCStatsReport> cached_report,
    std::vector<RTCStatsCollector::RequestInfo> requests) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  RTC_DCHECK(!requests.empty());
  RTC_DCHECK(cached_report);

  for (const RequestInfo& request : requests) {
    if (request.filter_mode() == RequestInfo::FilterMode::kAll) {
      request.callback()->OnStatsDelivered(cached_report);
    } else {
      bool filter_by_sender_selector;
      scoped_refptr<RtpSenderInternal> sender_selector;
      scoped_refptr<RtpReceiverInternal> receiver_selector;
      if (request.filter_mode() == RequestInfo::FilterMode::kSenderSelector) {
        filter_by_sender_selector = true;
        sender_selector = request.sender_selector();
      } else {
        RTC_DCHECK(request.filter_mode() ==
                   RequestInfo::FilterMode::kReceiverSelector);
        filter_by_sender_selector = false;
        receiver_selector = request.receiver_selector();
      }
      request.callback()->OnStatsDelivered(CreateReportFilteredBySelector(
          filter_by_sender_selector, cached_report, sender_selector,
          receiver_selector));
    }
  }
}

void RTCStatsCollector::ProduceCertificateStats_n(
    Timestamp timestamp,
    const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
    RTCStatsReport* report) const {
  RTC_DCHECK_RUN_ON(network_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  for (const auto& transport_cert_stats_pair : transport_cert_stats) {
    if (transport_cert_stats_pair.second.local) {
      ProduceCertificateStatsFromSSLCertificateStats(
          timestamp, *transport_cert_stats_pair.second.local.get(), report);
    }
    if (transport_cert_stats_pair.second.remote) {
      ProduceCertificateStatsFromSSLCertificateStats(
          timestamp, *transport_cert_stats_pair.second.remote.get(), report);
    }
  }
}

void RTCStatsCollector::ProduceDataChannelStats_n(
    Timestamp timestamp,
    RTCStatsReport* report) const {
  RTC_DCHECK_RUN_ON(network_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;
  std::vector<DataChannelStats> data_stats = pc_->GetDataChannelStats();
  for (const auto& stats : data_stats) {
    auto data_channel_stats = std::make_unique<RTCDataChannelStats>(
        "D" + absl::StrCat(stats.internal_id), timestamp);
    data_channel_stats->label = std::move(stats.label);
    data_channel_stats->protocol = std::move(stats.protocol);
    if (stats.id >= 0) {
      // Do not set this value before the DTLS handshake is finished
      // and filter out the magic value -1.
      data_channel_stats->data_channel_identifier = stats.id;
    }
    data_channel_stats->state = DataStateToRTCDataChannelState(stats.state);
    data_channel_stats->messages_sent = stats.messages_sent;
    data_channel_stats->bytes_sent = stats.bytes_sent;
    data_channel_stats->messages_received = stats.messages_received;
    data_channel_stats->bytes_received = stats.bytes_received;
    report->AddStats(std::move(data_channel_stats));
  }
}

void RTCStatsCollector::ProduceIceCandidateAndPairStats_n(
    Timestamp timestamp,
    const std::map<std::string, TransportStats>& transport_stats_by_name,
    const Call::Stats& call_stats,
    RTCStatsReport* report) const {
  RTC_DCHECK_RUN_ON(network_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  for (const auto& entry : transport_stats_by_name) {
    const std::string& transport_name = entry.first;
    const TransportStats& transport_stats = entry.second;
    for (const auto& channel_stats : transport_stats.channel_stats) {
      std::string transport_id = RTCTransportStatsIDFromTransportChannel(
          transport_name, channel_stats.component);
      for (const auto& info :
           channel_stats.ice_transport_stats.connection_infos) {
        auto candidate_pair_stats = std::make_unique<RTCIceCandidatePairStats>(
            RTCIceCandidatePairStatsIDFromConnectionInfo(info), timestamp);

        candidate_pair_stats->transport_id = transport_id;
        candidate_pair_stats->local_candidate_id = ProduceIceCandidateStats(
            timestamp, info.local_candidate, true, transport_id, report);
        candidate_pair_stats->remote_candidate_id = ProduceIceCandidateStats(
            timestamp, info.remote_candidate, false, transport_id, report);
        candidate_pair_stats->state =
            IceCandidatePairStateToRTCStatsIceCandidatePairState(info.state);
        candidate_pair_stats->priority = info.priority;
        candidate_pair_stats->nominated = info.nominated;
        // TODO(hbos): This writable is different than the spec. It goes to
        // false after a certain amount of time without a response passes.
        // https://crbug.com/633550
        candidate_pair_stats->writable = info.writable;
        // Note that sent_total_packets includes discarded packets but
        // sent_total_bytes does not.
        candidate_pair_stats->packets_sent = static_cast<uint64_t>(
            info.sent_total_packets - info.sent_discarded_packets);
        candidate_pair_stats->packets_discarded_on_send =
            static_cast<uint64_t>(info.sent_discarded_packets);
        candidate_pair_stats->packets_received =
            static_cast<uint64_t>(info.packets_received);
        candidate_pair_stats->bytes_sent =
            static_cast<uint64_t>(info.sent_total_bytes);
        candidate_pair_stats->bytes_discarded_on_send =
            static_cast<uint64_t>(info.sent_discarded_bytes);
        candidate_pair_stats->bytes_received =
            static_cast<uint64_t>(info.recv_total_bytes);
        candidate_pair_stats->total_round_trip_time =
            static_cast<double>(info.total_round_trip_time_ms) /
            kNumMillisecsPerSec;
        if (info.current_round_trip_time_ms.has_value()) {
          candidate_pair_stats->current_round_trip_time =
              static_cast<double>(*info.current_round_trip_time_ms) /
              kNumMillisecsPerSec;
        }
        if (info.best_connection) {
          // The bandwidth estimations we have are for the selected candidate
          // pair ("info.best_connection").
          RTC_DCHECK_GE(call_stats.send_bandwidth_bps, 0);
          RTC_DCHECK_GE(call_stats.recv_bandwidth_bps, 0);
          if (call_stats.send_bandwidth_bps > 0) {
            candidate_pair_stats->available_outgoing_bitrate =
                static_cast<double>(call_stats.send_bandwidth_bps);
          }
          if (call_stats.recv_bandwidth_bps > 0) {
            candidate_pair_stats->available_incoming_bitrate =
                static_cast<double>(call_stats.recv_bandwidth_bps);
          }
        }
        candidate_pair_stats->requests_received =
            static_cast<uint64_t>(info.recv_ping_requests);
        candidate_pair_stats->requests_sent =
            static_cast<uint64_t>(info.sent_ping_requests_total);
        candidate_pair_stats->responses_received =
            static_cast<uint64_t>(info.recv_ping_responses);
        candidate_pair_stats->responses_sent =
            static_cast<uint64_t>(info.sent_ping_responses);
        RTC_DCHECK_GE(info.sent_ping_requests_total,
                      info.sent_ping_requests_before_first_response);
        candidate_pair_stats->consent_requests_sent = static_cast<uint64_t>(
            info.sent_ping_requests_total -
            info.sent_ping_requests_before_first_response);

        if (info.last_data_received.has_value()) {
          candidate_pair_stats->last_packet_received_timestamp =
              static_cast<double>(info.last_data_received->ms());
        }
        if (info.last_data_sent) {
          candidate_pair_stats->last_packet_sent_timestamp =
              static_cast<double>(info.last_data_sent->ms());
        }

        report->AddStats(std::move(candidate_pair_stats));
      }

      // Produce local candidate stats. If a transport exists these will already
      // have been produced.
      for (const auto& candidate_stats :
           channel_stats.ice_transport_stats.candidate_stats_list) {
        const auto& candidate = candidate_stats.candidate();
        ProduceIceCandidateStats(timestamp, candidate, true, transport_id,
                                 report);
      }
    }
  }
}

void RTCStatsCollector::ProduceMediaSourceStats_s(
    Timestamp timestamp,
    RTCStatsReport* report) const {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  for (const RtpTransceiverStatsInfo& transceiver_stats_info :
       transceiver_stats_infos_) {
    const auto& track_media_info_map =
        transceiver_stats_info.track_media_info_map;
    for (const auto& sender : transceiver_stats_info.transceiver->senders()) {
      const auto& sender_internal = sender->internal();
      const auto& track = sender_internal->track();
      if (!track)
        continue;
      // TODO(https://crbug.com/webrtc/10771): The same track could be attached
      // to multiple senders which should result in multiple senders referencing
      // the same media-source stats. When all media source related metrics are
      // moved to the track's source (e.g. input frame rate is moved from
      // webrtc::VideoSenderInfo to VideoTrackSourceInterface::Stats and audio
      // levels are moved to the corresponding audio track/source object), don't
      // create separate media source stats objects on a per-attachment basis.
      std::unique_ptr<RTCMediaSourceStats> media_source_stats;
      if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
        AudioTrackInterface* audio_track =
            static_cast<AudioTrackInterface*>(track.get());
        auto audio_source_stats = std::make_unique<RTCAudioSourceStats>(
            RTCMediaSourceStatsIDFromKindAndAttachment(
                MediaType::AUDIO, sender_internal->AttachmentId()),
            timestamp);
        // TODO(https://crbug.com/webrtc/10771): We shouldn't need to have an
        // SSRC assigned (there shouldn't need to exist a send-stream, created
        // by an O/A exchange) in order to read audio media-source stats.
        // TODO(https://crbug.com/webrtc/8694): SSRC 0 shouldn't be a magic
        // value indicating no SSRC.
        if (sender_internal->ssrc() != 0) {
          auto* voice_sender_info =
              track_media_info_map.GetVoiceSenderInfoBySsrc(
                  sender_internal->ssrc());
          if (voice_sender_info) {
            audio_source_stats->audio_level = DoubleAudioLevelFromIntAudioLevel(
                voice_sender_info->audio_level);
            audio_source_stats->total_audio_energy =
                voice_sender_info->total_input_energy;
            audio_source_stats->total_samples_duration =
                voice_sender_info->total_input_duration;
            SetAudioProcessingStats(audio_source_stats.get(),
                                    voice_sender_info->apm_statistics);
          }
        }
        // Audio processor may be attached to either the track or the send
        // stream, so look in both places.
        auto audio_processor(audio_track->GetAudioProcessor());
        if (audio_processor.get()) {
          // The `has_remote_tracks` argument is obsolete; makes no difference
          // if it's set to true or false.
          AudioProcessorInterface::AudioProcessorStatistics ap_stats =
              audio_processor->GetStats(/*has_remote_tracks=*/false);
          SetAudioProcessingStats(audio_source_stats.get(),
                                  ap_stats.apm_statistics);
        }
        media_source_stats = std::move(audio_source_stats);
      } else {
        RTC_DCHECK_EQ(MediaStreamTrackInterface::kVideoKind, track->kind());
        auto video_source_stats = std::make_unique<RTCVideoSourceStats>(
            RTCMediaSourceStatsIDFromKindAndAttachment(
                MediaType::VIDEO, sender_internal->AttachmentId()),
            timestamp);
        auto* video_track = static_cast<VideoTrackInterface*>(track.get());
        auto* video_source = video_track->GetSource();
        VideoTrackSourceInterface::Stats source_stats;
        if (video_source && video_source->GetStats(&source_stats)) {
          video_source_stats->width = source_stats.input_width;
          video_source_stats->height = source_stats.input_height;
        }
        // TODO(https://crbug.com/webrtc/10771): We shouldn't need to have an
        // SSRC assigned (there shouldn't need to exist a send-stream, created
        // by an O/A exchange) in order to get framesPerSecond.
        // TODO(https://crbug.com/webrtc/8694): SSRC 0 shouldn't be a magic
        // value indicating no SSRC.
        if (sender_internal->ssrc() != 0) {
          auto* video_sender_info =
              track_media_info_map.GetVideoSenderInfoBySsrc(
                  sender_internal->ssrc());
          if (video_sender_info) {
            video_source_stats->frames_per_second =
                video_sender_info->framerate_input;
            video_source_stats->frames = video_sender_info->frames;
          }
        }
        media_source_stats = std::move(video_source_stats);
      }
      media_source_stats->track_identifier = track->id();
      media_source_stats->kind = track->kind();
      report->AddStats(std::move(media_source_stats));
    }
  }
}

void RTCStatsCollector::ProducePeerConnectionStats_s(
    Timestamp timestamp,
    RTCStatsReport* report) const {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  auto stats(std::make_unique<RTCPeerConnectionStats>("P", timestamp));
  stats->data_channels_opened = internal_record_.data_channels_opened;
  stats->data_channels_closed = internal_record_.data_channels_closed;
  report->AddStats(std::move(stats));
}

void RTCStatsCollector::ProduceAudioPlayoutStats_s(
    Timestamp timestamp,
    RTCStatsReport* report) const {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  if (audio_device_stats_) {
    report->AddStats(CreateAudioPlayoutStats(*audio_device_stats_, timestamp));
  }
}

void RTCStatsCollector::ProduceRTPStreamStats_n(
    Timestamp timestamp,
    const std::vector<RtpTransceiverStatsInfo>& transceiver_stats_infos,
    RTCStatsReport* report) const {
  RTC_DCHECK_RUN_ON(network_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  for (const RtpTransceiverStatsInfo& stats : transceiver_stats_infos) {
    if (stats.media_type == MediaType::AUDIO) {
      ProduceAudioRTPStreamStats_n(timestamp, stats, report);
    } else if (stats.media_type == MediaType::VIDEO) {
      ProduceVideoRTPStreamStats_n(timestamp, stats, report);
    } else {
      RTC_DCHECK_NOTREACHED();
    }
  }
}

void RTCStatsCollector::ProduceAudioRTPStreamStats_n(
    Timestamp timestamp,
    const RtpTransceiverStatsInfo& stats,
    RTCStatsReport* report) const {
  RTC_DCHECK_RUN_ON(network_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  if (!stats.mid || !stats.transport_name) {
    return;
  }
  RTC_DCHECK(stats.track_media_info_map.voice_media_info().has_value());
  std::string mid = *stats.mid;
  std::string transport_id = RTCTransportStatsIDFromTransportChannel(
      *stats.transport_name, ICE_CANDIDATE_COMPONENT_RTP);
  // Inbound and remote-outbound.
  // The remote-outbound stats are based on RTCP sender reports sent from the
  // remote endpoint providing metrics about the remote outbound streams.
  for (const VoiceReceiverInfo& voice_receiver_info :
       stats.track_media_info_map.voice_media_info()->receivers) {
    if (!voice_receiver_info.connected())
      continue;
    // Inbound.
    auto inbound_audio = CreateInboundAudioStreamStats(
        *stats.track_media_info_map.voice_media_info(), voice_receiver_info,
        transport_id, mid, timestamp, report);
    // TODO(hta): This lookup should look for the sender, not the track.
    scoped_refptr<AudioTrackInterface> audio_track =
        stats.track_media_info_map.GetAudioTrack(voice_receiver_info);
    if (audio_track) {
      inbound_audio->track_identifier = audio_track->id();
    }
    if (audio_device_stats_ && stats.media_type == MediaType::AUDIO &&
        stats.current_direction &&
        (*stats.current_direction == RtpTransceiverDirection::kSendRecv ||
         *stats.current_direction == RtpTransceiverDirection::kRecvOnly)) {
      inbound_audio->playout_id = kAudioPlayoutSingletonId;
    }
    auto* inbound_audio_ptr = report->TryAddStats(std::move(inbound_audio));
    if (!inbound_audio_ptr) {
      RTC_LOG(LS_ERROR)
          << "Unable to add audio 'inbound-rtp' to report, ID is not unique.";
      continue;
    }
    // Remote-outbound.
    auto remote_outbound_audio = CreateRemoteOutboundMediaStreamStats(
        voice_receiver_info, mid, MediaType::AUDIO, *inbound_audio_ptr,
        transport_id, stats_timestamp_with_environment_clock_);
    // Add stats.
    if (remote_outbound_audio) {
      // When the remote outbound stats are available, the remote ID for the
      // local inbound stats is set.
      auto* remote_outbound_audio_ptr =
          report->TryAddStats(std::move(remote_outbound_audio));
      if (remote_outbound_audio_ptr) {
        inbound_audio_ptr->remote_id = remote_outbound_audio_ptr->id();
      } else {
        RTC_LOG(LS_ERROR) << "Unable to add audio 'remote-outbound-rtp' to "
                          << "report, ID is not unique.";
      }
    }
  }
  // Outbound.
  std::map<std::string, RTCOutboundRtpStreamStats*> audio_outbound_rtps;
  for (const VoiceSenderInfo& voice_sender_info :
       stats.track_media_info_map.voice_media_info()->senders) {
    if (!voice_sender_info.connected())
      continue;
    auto outbound_audio = CreateOutboundRTPStreamStatsFromVoiceSenderInfo(
        transport_id, mid, *stats.track_media_info_map.voice_media_info(),
        voice_sender_info, timestamp, report);
    scoped_refptr<AudioTrackInterface> audio_track =
        stats.track_media_info_map.GetAudioTrack(voice_sender_info);
    if (audio_track) {
      int attachment_id =
          stats.track_media_info_map.GetAttachmentIdByTrack(audio_track.get())
              .value();
      outbound_audio->media_source_id =
          RTCMediaSourceStatsIDFromKindAndAttachment(MediaType::AUDIO,
                                                     attachment_id);
    }
    auto audio_outbound_pair =
        std::make_pair(outbound_audio->id(), outbound_audio.get());
    if (report->TryAddStats(std::move(outbound_audio))) {
      audio_outbound_rtps.insert(std::move(audio_outbound_pair));
    } else {
      RTC_LOG(LS_ERROR)
          << "Unable to add audio 'outbound-rtp' to report, ID is not unique.";
    }
  }
  // Remote-inbound.
  // These are Report Block-based, information sent from the remote endpoint,
  // providing metrics about our Outbound streams. We take advantage of the fact
  // that RTCOutboundRtpStreamStats, RTCCodecStats and RTCTransport have already
  // been added to the report.
  for (const VoiceSenderInfo& voice_sender_info :
       stats.track_media_info_map.voice_media_info()->senders) {
    for (const auto& report_block_data : voice_sender_info.report_block_datas) {
      report->AddStats(ProduceRemoteInboundRtpStreamStatsFromReportBlockData(
          transport_id, report_block_data, MediaType::AUDIO,
          audio_outbound_rtps, *report,
          stats_timestamp_with_environment_clock_));
    }
  }
}

void RTCStatsCollector::ProduceVideoRTPStreamStats_n(
    Timestamp timestamp,
    const RtpTransceiverStatsInfo& stats,
    RTCStatsReport* report) const {
  RTC_DCHECK_RUN_ON(network_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  if (!stats.mid || !stats.transport_name) {
    return;
  }
  RTC_DCHECK(stats.track_media_info_map.video_media_info().has_value());
  std::string mid = *stats.mid;
  std::string transport_id = RTCTransportStatsIDFromTransportChannel(
      *stats.transport_name, ICE_CANDIDATE_COMPONENT_RTP);
  // Inbound and remote-outbound.
  for (const VideoReceiverInfo& video_receiver_info :
       stats.track_media_info_map.video_media_info()->receivers) {
    if (!video_receiver_info.connected())
      continue;
    auto inbound_video = CreateInboundRTPStreamStatsFromVideoReceiverInfo(
        transport_id, mid, *stats.track_media_info_map.video_media_info(),
        video_receiver_info, timestamp, report);
    scoped_refptr<VideoTrackInterface> video_track =
        stats.track_media_info_map.GetVideoTrack(video_receiver_info);
    if (video_track) {
      inbound_video->track_identifier = video_track->id();
    }
    auto* inbound_video_ptr = report->TryAddStats(std::move(inbound_video));
    if (!inbound_video_ptr) {
      RTC_LOG(LS_ERROR)
          << "Unable to add video 'inbound-rtp' to report, ID is not unique.";
      continue;
    }
    // Remote-outbound.
    auto remote_outbound_video = CreateRemoteOutboundMediaStreamStats(
        video_receiver_info, mid, MediaType::VIDEO, *inbound_video_ptr,
        transport_id, stats_timestamp_with_environment_clock_);
    // Add stats.
    if (remote_outbound_video) {
      // When the remote outbound stats are available, the remote ID for the
      // local inbound stats is set.
      auto* remote_outbound_video_ptr =
          report->TryAddStats(std::move(remote_outbound_video));
      if (remote_outbound_video_ptr) {
        inbound_video_ptr->remote_id = remote_outbound_video_ptr->id();
      } else {
        RTC_LOG(LS_ERROR) << "Unable to add video 'remote-outbound-rtp' to "
                          << "report, ID is not unique.";
      }
    }
  }
  // Outbound
  std::map<std::string, RTCOutboundRtpStreamStats*> video_outbound_rtps;
  for (const VideoSenderInfo& video_sender_info :
       stats.track_media_info_map.video_media_info()->senders) {
    if (!video_sender_info.connected())
      continue;
    auto outbound_video = CreateOutboundRTPStreamStatsFromVideoSenderInfo(
        transport_id, mid, *stats.track_media_info_map.video_media_info(),
        video_sender_info, timestamp, report);
    scoped_refptr<VideoTrackInterface> video_track =
        stats.track_media_info_map.GetVideoTrack(video_sender_info);
    if (video_track) {
      int attachment_id =
          stats.track_media_info_map.GetAttachmentIdByTrack(video_track.get())
              .value();
      outbound_video->media_source_id =
          RTCMediaSourceStatsIDFromKindAndAttachment(MediaType::VIDEO,
                                                     attachment_id);
    }
    auto video_outbound_pair =
        std::make_pair(outbound_video->id(), outbound_video.get());
    if (report->TryAddStats(std::move(outbound_video))) {
      video_outbound_rtps.insert(std::move(video_outbound_pair));
    } else {
      RTC_LOG(LS_ERROR)
          << "Unable to add video 'outbound-rtp' to report, ID is not unique.";
    }
  }
  // Remote-inbound
  // These are Report Block-based, information sent from the remote endpoint,
  // providing metrics about our Outbound streams. We take advantage of the fact
  // that RTCOutboundRtpStreamStats, RTCCodecStats and RTCTransport have already
  // been added to the report.
  for (const VideoSenderInfo& video_sender_info :
       stats.track_media_info_map.video_media_info()->senders) {
    for (const auto& report_block_data : video_sender_info.report_block_datas) {
      report->AddStats(ProduceRemoteInboundRtpStreamStatsFromReportBlockData(
          transport_id, report_block_data, MediaType::VIDEO,
          video_outbound_rtps, *report,
          stats_timestamp_with_environment_clock_));
    }
  }
}

void RTCStatsCollector::ProduceTransportStats_n(
    Timestamp timestamp,
    const std::map<std::string, TransportStats>& transport_stats_by_name,
    const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
    RTCStatsReport* report) const {
  RTC_DCHECK_RUN_ON(network_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  for (const auto& entry : transport_stats_by_name) {
    const std::string& transport_name = entry.first;
    const TransportStats& transport_stats = entry.second;

    // Get reference to RTCP channel, if it exists.
    std::string rtcp_transport_stats_id;
    for (const TransportChannelStats& channel_stats :
         transport_stats.channel_stats) {
      if (channel_stats.component == ICE_CANDIDATE_COMPONENT_RTCP) {
        rtcp_transport_stats_id = RTCTransportStatsIDFromTransportChannel(
            transport_name, channel_stats.component);
        break;
      }
    }

    // Get reference to local and remote certificates of this transport, if they
    // exist.
    const auto& certificate_stats_it =
        transport_cert_stats.find(transport_name);
    std::string local_certificate_id, remote_certificate_id;
    RTC_DCHECK(certificate_stats_it != transport_cert_stats.cend());
    if (certificate_stats_it != transport_cert_stats.cend()) {
      if (certificate_stats_it->second.local) {
        local_certificate_id = RTCCertificateIDFromFingerprint(
            certificate_stats_it->second.local->fingerprint);
      }
      if (certificate_stats_it->second.remote) {
        remote_certificate_id = RTCCertificateIDFromFingerprint(
            certificate_stats_it->second.remote->fingerprint);
      }
    }

    // There is one transport stats for each channel.
    for (const TransportChannelStats& channel_stats :
         transport_stats.channel_stats) {
      auto channel_transport_stats = std::make_unique<RTCTransportStats>(
          RTCTransportStatsIDFromTransportChannel(transport_name,
                                                  channel_stats.component),
          timestamp);
      channel_transport_stats->packets_sent =
          channel_stats.ice_transport_stats.packets_sent;
      channel_transport_stats->packets_received =
          channel_stats.ice_transport_stats.packets_received;
      channel_transport_stats->bytes_sent =
          channel_stats.ice_transport_stats.bytes_sent;
      channel_transport_stats->bytes_received =
          channel_stats.ice_transport_stats.bytes_received;
      channel_transport_stats->dtls_state =
          DtlsTransportStateToRTCDtlsTransportState(channel_stats.dtls_state);
      channel_transport_stats->selected_candidate_pair_changes =
          channel_stats.ice_transport_stats.selected_candidate_pair_changes;
      channel_transport_stats->ice_role =
          IceRoleToRTCIceRole(channel_stats.ice_transport_stats.ice_role);
      channel_transport_stats->ice_local_username_fragment =
          channel_stats.ice_transport_stats.ice_local_username_fragment;
      channel_transport_stats->ice_state =
          IceTransportStateToRTCIceTransportState(
              channel_stats.ice_transport_stats.ice_state);
      for (const ConnectionInfo& info :
           channel_stats.ice_transport_stats.connection_infos) {
        if (info.best_connection) {
          channel_transport_stats->selected_candidate_pair_id =
              RTCIceCandidatePairStatsIDFromConnectionInfo(info);
        }
      }
      if (channel_stats.component != ICE_CANDIDATE_COMPONENT_RTCP &&
          !rtcp_transport_stats_id.empty()) {
        channel_transport_stats->rtcp_transport_stats_id =
            rtcp_transport_stats_id;
      }
      if (!local_certificate_id.empty())
        channel_transport_stats->local_certificate_id = local_certificate_id;
      if (!remote_certificate_id.empty())
        channel_transport_stats->remote_certificate_id = remote_certificate_id;
      // Crypto information
      if (channel_stats.ssl_version_bytes) {
        char bytes[5];
        snprintf(bytes, sizeof(bytes), "%04X", channel_stats.ssl_version_bytes);
        channel_transport_stats->tls_version = bytes;
      }

      if (channel_stats.dtls_role) {
        channel_transport_stats->dtls_role =
            *channel_stats.dtls_role == SSL_CLIENT ? "client" : "server";
      } else {
        channel_transport_stats->dtls_role = "unknown";
      }

      channel_transport_stats->dtls_cipher =
          channel_stats.tls_cipher_suite_name;
      if (channel_stats.srtp_crypto_suite != kSrtpInvalidCryptoSuite &&
          SrtpCryptoSuiteToName(channel_stats.srtp_crypto_suite).length()) {
        channel_transport_stats->srtp_cipher =
            SrtpCryptoSuiteToName(channel_stats.srtp_crypto_suite);
      }
      report->AddStats(std::move(channel_transport_stats));
    }
  }
}

std::map<std::string, RTCStatsCollector::CertificateStatsPair>
RTCStatsCollector::PrepareTransportCertificateStats_n(
    const std::map<std::string, TransportStats>& transport_stats_by_name) {
  RTC_DCHECK_RUN_ON(network_thread_);
  Thread::ScopedDisallowBlockingCalls no_blocking_calls;

  std::map<std::string, CertificateStatsPair> transport_cert_stats;
  {
    MutexLock lock(&cached_certificates_mutex_);
    // Copy the certificate info from the cache, avoiding expensive
    // webrtc::SSLCertChain::GetStats() calls.
    for (const auto& pair : cached_certificates_by_transport_) {
      transport_cert_stats.insert(
          std::make_pair(pair.first, pair.second.Copy()));
    }
  }
  if (transport_cert_stats.empty()) {
    // Collect certificate info.
    for (const auto& entry : transport_stats_by_name) {
      const std::string& transport_name = entry.first;

      CertificateStatsPair certificate_stats_pair;
      scoped_refptr<RTCCertificate> local_certificate;
      if (pc_->GetLocalCertificate(transport_name, &local_certificate)) {
        certificate_stats_pair.local =
            local_certificate->GetSSLCertificateChain().GetStats();
      }

      auto remote_cert_chain = pc_->GetRemoteSSLCertChain(transport_name);
      if (remote_cert_chain) {
        certificate_stats_pair.remote = remote_cert_chain->GetStats();
      }

      transport_cert_stats.insert(
          std::make_pair(transport_name, std::move(certificate_stats_pair)));
    }
    // Copy the result into the certificate cache for future reference.
    MutexLock lock(&cached_certificates_mutex_);
    for (const auto& pair : transport_cert_stats) {
      cached_certificates_by_transport_.insert(
          std::make_pair(pair.first, pair.second.Copy()));
    }
  }
  return transport_cert_stats;
}

void RTCStatsCollector::PrepareTransceiverStatsInfosAndCallStats_s_w_n() {
  RTC_DCHECK_RUN_ON(signaling_thread_);

  transceiver_stats_infos_.clear();
  // These are used to invoke GetStats for all the media channels together in
  // one worker thread hop.
  std::map<VoiceMediaSendChannelInterface*, VoiceMediaSendInfo>
      voice_send_stats;
  std::map<VideoMediaSendChannelInterface*, VideoMediaSendInfo>
      video_send_stats;
  std::map<VoiceMediaReceiveChannelInterface*, VoiceMediaReceiveInfo>
      voice_receive_stats;
  std::map<VideoMediaReceiveChannelInterface*, VideoMediaReceiveInfo>
      video_receive_stats;

  auto transceivers = pc_->GetTransceiversInternal();

  // TODO(tommi): See if we can avoid synchronously blocking the signaling
  // thread while we do this (or avoid the BlockingCall at all).
  network_thread_->BlockingCall([&] {
    Thread::ScopedDisallowBlockingCalls no_blocking_calls;

    for (const auto& transceiver_proxy : transceivers) {
      RtpTransceiver* transceiver = transceiver_proxy->internal();
      MediaType media_type = transceiver->media_type();

      // Prepare stats entry. The TrackMediaInfoMap will be filled in after the
      // stats have been fetched on the worker thread.
      transceiver_stats_infos_.emplace_back();
      RtpTransceiverStatsInfo& stats = transceiver_stats_infos_.back();
      stats.transceiver = transceiver;
      stats.media_type = media_type;

      ChannelInterface* channel = transceiver->channel();
      if (!channel) {
        // The remaining fields require a BaseChannel.
        continue;
      }

      stats.mid = channel->mid();
      stats.transport_name = std::string(channel->transport_name());

      if (media_type == MediaType::AUDIO) {
        auto voice_send_channel = channel->voice_media_send_channel();
        RTC_DCHECK(voice_send_stats.find(voice_send_channel) ==
                   voice_send_stats.end());
        voice_send_stats.insert(
            std::make_pair(voice_send_channel, VoiceMediaSendInfo()));

        auto voice_receive_channel = channel->voice_media_receive_channel();
        RTC_DCHECK(voice_receive_stats.find(voice_receive_channel) ==
                   voice_receive_stats.end());
        voice_receive_stats.insert(
            std::make_pair(voice_receive_channel, VoiceMediaReceiveInfo()));
      } else if (media_type == MediaType::VIDEO) {
        auto video_send_channel = channel->video_media_send_channel();
        RTC_DCHECK(video_send_stats.find(video_send_channel) ==
                   video_send_stats.end());
        video_send_stats.insert(
            std::make_pair(video_send_channel, VideoMediaSendInfo()));
        auto video_receive_channel = channel->video_media_receive_channel();
        RTC_DCHECK(video_receive_stats.find(video_receive_channel) ==
                   video_receive_stats.end());
        video_receive_stats.insert(
            std::make_pair(video_receive_channel, VideoMediaReceiveInfo()));
      } else {
        RTC_DCHECK_NOTREACHED();
      }
    }
  });

  // We jump to the worker thread and call GetStats() on each media channel as
  // well as GetCallStats(). At the same time we construct the
  // TrackMediaInfoMaps, which also needs info from the worker thread. This
  // minimizes the number of thread jumps.
  worker_thread_->BlockingCall([&] {
    Thread::ScopedDisallowBlockingCalls no_blocking_calls;

    for (auto& pair : voice_send_stats) {
      if (!pair.first->GetStats(&pair.second)) {
        RTC_LOG(LS_WARNING) << "Failed to get voice send stats.";
      }
    }
    for (auto& pair : voice_receive_stats) {
      if (!pair.first->GetStats(&pair.second,
                                /*get_and_clear_legacy_stats=*/false)) {
        RTC_LOG(LS_WARNING) << "Failed to get voice receive stats.";
      }
    }
    for (auto& pair : video_send_stats) {
      if (!pair.first->GetStats(&pair.second)) {
        RTC_LOG(LS_WARNING) << "Failed to get video send stats.";
      }
    }
    for (auto& pair : video_receive_stats) {
      if (!pair.first->GetStats(&pair.second)) {
        RTC_LOG(LS_WARNING) << "Failed to get video receive stats.";
      }
    }

    // Create the TrackMediaInfoMap for each transceiver stats object
    // and keep track of whether we have at least one audio receiver.
    bool has_audio_receiver = false;
    for (auto& stats : transceiver_stats_infos_) {
      auto transceiver = stats.transceiver;
      std::optional<VoiceMediaInfo> voice_media_info;
      std::optional<VideoMediaInfo> video_media_info;
      auto channel = transceiver->channel();
      if (channel) {
        MediaType media_type = transceiver->media_type();
        if (media_type == MediaType::AUDIO) {
          auto voice_send_channel = channel->voice_media_send_channel();
          auto voice_receive_channel = channel->voice_media_receive_channel();
          voice_media_info = VoiceMediaInfo(
              std::move(voice_send_stats[voice_send_channel]),
              std::move(voice_receive_stats[voice_receive_channel]));
        } else if (media_type == MediaType::VIDEO) {
          auto video_send_channel = channel->video_media_send_channel();
          auto video_receive_channel = channel->video_media_receive_channel();
          video_media_info = VideoMediaInfo(
              std::move(video_send_stats[video_send_channel]),
              std::move(video_receive_stats[video_receive_channel]));
        }
      }
      std::vector<scoped_refptr<RtpSenderInternal>> senders;
      for (const auto& sender : transceiver->senders()) {
        senders.push_back(scoped_refptr<RtpSenderInternal>(sender->internal()));
      }
      std::vector<scoped_refptr<RtpReceiverInternal>> receivers;
      for (const auto& receiver : transceiver->receivers()) {
        receivers.push_back(
            scoped_refptr<RtpReceiverInternal>(receiver->internal()));
      }
      stats.track_media_info_map.Initialize(std::move(voice_media_info),
                                            std::move(video_media_info),
                                            senders, receivers);
      if (transceiver->media_type() == MediaType::AUDIO) {
        has_audio_receiver |= !receivers.empty();
      }
    }

    call_stats_ = pc_->GetCallStats();
    audio_device_stats_ =
        has_audio_receiver ? pc_->GetAudioDeviceStats() : std::nullopt;
  });

  for (auto& stats : transceiver_stats_infos_) {
    stats.current_direction = stats.transceiver->current_direction();
  }
}

void RTCStatsCollector::OnSctpDataChannelStateChanged(
    int channel_id,
    DataChannelInterface::DataState state) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  if (state == DataChannelInterface::DataState::kOpen) {
    bool result =
        internal_record_.opened_data_channels.insert(channel_id).second;
    RTC_DCHECK(result);
    ++internal_record_.data_channels_opened;
  } else if (state == DataChannelInterface::DataState::kClosed) {
    // Only channels that have been fully opened (and have increased the
    // `data_channels_opened_` counter) increase the closed counter.
    if (internal_record_.opened_data_channels.erase(channel_id)) {
      ++internal_record_.data_channels_closed;
    }
  }
}

}  // namespace webrtc
