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

#include <algorithm>
#include <memory>
#include <set>
#include <utility>

#include "absl/strings/string_view.h"
#include "api/jsep.h"
#include "api/media_stream_interface.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_event_log/rtc_event_log.h"
#include "api/rtc_event_log_output_file.h"
#include "api/scoped_refptr.h"
#include "api/test/time_controller.h"
#include "api/test/video_quality_analyzer_interface.h"
#include "pc/sdp_utils.h"
#include "pc/test/mock_peer_connection_observers.h"
#include "rtc_base/gunit.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/strings/string_builder.h"
#include "system_wrappers/include/cpu_info.h"
#include "system_wrappers/include/field_trial.h"
#include "test/field_trial.h"
#include "test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer.h"
#include "test/pc/e2e/analyzer/video/video_quality_metrics_reporter.h"
#include "test/pc/e2e/cross_media_metrics_reporter.h"
#include "test/pc/e2e/stats_poller.h"
#include "test/pc/e2e/test_peer_factory.h"
#include "test/testsupport/file_utils.h"
#include "test/testsupport/perf_test.h"

namespace webrtc {
namespace webrtc_pc_e2e {
namespace {

using VideoConfig = PeerConnectionE2EQualityTestFixture::VideoConfig;
using VideoCodecConfig = PeerConnectionE2EQualityTestFixture::VideoCodecConfig;

constexpr TimeDelta kDefaultTimeout = TimeDelta::Seconds(10);
constexpr char kSignalThreadName[] = "signaling_thread";
// 1 signaling, 2 network, 2 worker and 2 extra for codecs etc.
constexpr int kPeerConnectionUsedThreads = 7;
// Framework has extra thread for network layer and extra thread for peer
// connection stats polling.
constexpr int kFrameworkUsedThreads = 2;
constexpr int kMaxVideoAnalyzerThreads = 8;

constexpr TimeDelta kStatsUpdateInterval = TimeDelta::Seconds(1);

constexpr TimeDelta kAliveMessageLogInterval = TimeDelta::Seconds(30);

constexpr TimeDelta kQuickTestModeRunDuration = TimeDelta::Millis(100);

// Field trials to enable Flex FEC advertising and receiving.
constexpr char kFlexFecEnabledFieldTrials[] =
    "WebRTC-FlexFEC-03-Advertised/Enabled/WebRTC-FlexFEC-03/Enabled/";
constexpr char kUseStandardsBytesStats[] =
    "WebRTC-UseStandardBytesStats/Enabled/";

class FixturePeerConnectionObserver : public MockPeerConnectionObserver {
 public:
  // `on_track_callback` will be called when any new track will be added to peer
  // connection.
  // `on_connected_callback` will be called when peer connection will come to
  // either connected or completed state. Client should notice that in the case
  // of reconnect this callback can be called again, so it should be tolerant
  // to such behavior.
  FixturePeerConnectionObserver(
      std::function<void(rtc::scoped_refptr<RtpTransceiverInterface>)>
          on_track_callback,
      std::function<void()> on_connected_callback)
      : on_track_callback_(std::move(on_track_callback)),
        on_connected_callback_(std::move(on_connected_callback)) {}

  void OnTrack(
      rtc::scoped_refptr<RtpTransceiverInterface> transceiver) override {
    MockPeerConnectionObserver::OnTrack(transceiver);
    on_track_callback_(transceiver);
  }

  void OnIceConnectionChange(
      PeerConnectionInterface::IceConnectionState new_state) override {
    MockPeerConnectionObserver::OnIceConnectionChange(new_state);
    if (ice_connected_) {
      on_connected_callback_();
    }
  }

 private:
  std::function<void(rtc::scoped_refptr<RtpTransceiverInterface>)>
      on_track_callback_;
  std::function<void()> on_connected_callback_;
};

void ValidateP2PSimulcastParams(
    const std::vector<std::unique_ptr<PeerConfigurerImpl>>& peers) {
  for (size_t i = 0; i < peers.size(); ++i) {
    Params* params = peers[i]->params();
    ConfigurableParams* configurable_params = peers[i]->configurable_params();
    for (const VideoConfig& video_config : configurable_params->video_configs) {
      if (video_config.simulcast_config) {
        // When we simulate SFU we support only one video codec.
        RTC_CHECK_EQ(params->video_codecs.size(), 1)
            << "Only 1 video codec is supported when simulcast is enabled in "
            << "at least 1 video config";
      }
    }
  }
}

}  // namespace

PeerConnectionE2EQualityTest::PeerConnectionE2EQualityTest(
    std::string test_case_name,
    TimeController& time_controller,
    std::unique_ptr<AudioQualityAnalyzerInterface> audio_quality_analyzer,
    std::unique_ptr<VideoQualityAnalyzerInterface> video_quality_analyzer)
    : time_controller_(time_controller),
      task_queue_factory_(time_controller_.CreateTaskQueueFactory()),
      test_case_name_(std::move(test_case_name)),
      executor_(std::make_unique<TestActivitiesExecutor>(
          time_controller_.GetClock())) {
  // Create default video quality analyzer. We will always create an analyzer,
  // even if there are no video streams, because it will be installed into video
  // encoder/decoder factories.
  if (video_quality_analyzer == nullptr) {
    video_quality_analyzer = std::make_unique<DefaultVideoQualityAnalyzer>(
        time_controller_.GetClock());
  }
  encoded_image_data_propagator_ =
      std::make_unique<SingleProcessEncodedImageDataInjector>();
  video_quality_analyzer_injection_helper_ =
      std::make_unique<VideoQualityAnalyzerInjectionHelper>(
          std::move(video_quality_analyzer),
          encoded_image_data_propagator_.get(),
          encoded_image_data_propagator_.get());

  if (audio_quality_analyzer == nullptr) {
    audio_quality_analyzer = std::make_unique<DefaultAudioQualityAnalyzer>();
  }
  audio_quality_analyzer_.swap(audio_quality_analyzer);
}

void PeerConnectionE2EQualityTest::ExecuteAt(
    TimeDelta target_time_since_start,
    std::function<void(TimeDelta)> func) {
  executor_->ScheduleActivity(target_time_since_start, absl::nullopt, func);
}

void PeerConnectionE2EQualityTest::ExecuteEvery(
    TimeDelta initial_delay_since_start,
    TimeDelta interval,
    std::function<void(TimeDelta)> func) {
  executor_->ScheduleActivity(initial_delay_since_start, interval, func);
}

void PeerConnectionE2EQualityTest::AddQualityMetricsReporter(
    std::unique_ptr<QualityMetricsReporter> quality_metrics_reporter) {
  quality_metrics_reporters_.push_back(std::move(quality_metrics_reporter));
}

PeerConnectionE2EQualityTest::PeerHandle* PeerConnectionE2EQualityTest::AddPeer(
    const PeerNetworkDependencies& network_dependencies,
    rtc::FunctionView<void(PeerConfigurer*)> configurer) {
  peer_configurations_.push_back(std::make_unique<PeerConfigurerImpl>(
      network_dependencies.network_thread, network_dependencies.network_manager,
      network_dependencies.packet_socket_factory));
  configurer(peer_configurations_.back().get());
  peer_handles_.push_back(PeerHandleImpl());
  return &peer_handles_.back();
}

void PeerConnectionE2EQualityTest::Run(RunParams run_params) {
  webrtc::webrtc_pc_e2e::PeerParamsPreprocessor params_preprocessor;
  for (auto& peer_configuration : peer_configurations_) {
    params_preprocessor.SetDefaultValuesForMissingParams(*peer_configuration);
    params_preprocessor.ValidateParams(*peer_configuration);
  }
  ValidateP2PSimulcastParams(peer_configurations_);
  RTC_CHECK_EQ(peer_configurations_.size(), 2)
      << "Only peer to peer calls are allowed, please add 2 peers";

  std::unique_ptr<PeerConfigurerImpl> alice_configurer =
      std::move(peer_configurations_[0]);
  std::unique_ptr<PeerConfigurerImpl> bob_configurer =
      std::move(peer_configurations_[1]);
  peer_configurations_.clear();

  for (size_t i = 0;
       i < bob_configurer->configurable_params()->video_configs.size(); ++i) {
    // We support simulcast only from caller.
    RTC_CHECK(!bob_configurer->configurable_params()
                   ->video_configs[i]
                   .simulcast_config)
        << "Only simulcast stream from first peer is supported";
  }

  test::ScopedFieldTrials field_trials(GetFieldTrials(run_params));

  // Print test summary
  RTC_LOG(LS_INFO)
      << "Media quality test: " << *alice_configurer->params()->name
      << " will make a call to " << *bob_configurer->params()->name
      << " with media video="
      << !alice_configurer->configurable_params()->video_configs.empty()
      << "; audio=" << alice_configurer->params()->audio_config.has_value()
      << ". " << *bob_configurer->params()->name
      << " will respond with media video="
      << !bob_configurer->configurable_params()->video_configs.empty()
      << "; audio=" << bob_configurer->params()->audio_config.has_value();

  const std::unique_ptr<rtc::Thread> signaling_thread =
      time_controller_.CreateThread(kSignalThreadName);
  media_helper_ = std::make_unique<MediaHelper>(
      video_quality_analyzer_injection_helper_.get(), task_queue_factory_.get(),
      time_controller_.GetClock());

  // Create a `task_queue_`.
  task_queue_ = std::make_unique<webrtc::TaskQueueForTest>(
      time_controller_.GetTaskQueueFactory()->CreateTaskQueue(
          "pc_e2e_quality_test", webrtc::TaskQueueFactory::Priority::NORMAL));

  // Create call participants: Alice and Bob.
  // Audio streams are intercepted in AudioDeviceModule, so if it is required to
  // catch output of Alice's stream, Alice's output_dump_file_name should be
  // passed to Bob's TestPeer setup as audio output file name.
  absl::optional<RemotePeerAudioConfig> alice_remote_audio_config =
      RemotePeerAudioConfig::Create(bob_configurer->params()->audio_config);
  absl::optional<RemotePeerAudioConfig> bob_remote_audio_config =
      RemotePeerAudioConfig::Create(alice_configurer->params()->audio_config);
  // Copy Alice and Bob video configs and names to correctly pass them into
  // lambdas.
  std::vector<VideoConfig> alice_video_configs =
      alice_configurer->configurable_params()->video_configs;
  std::string alice_name = alice_configurer->params()->name.value();
  std::vector<VideoConfig> bob_video_configs =
      bob_configurer->configurable_params()->video_configs;
  std::string bob_name = bob_configurer->params()->name.value();

  TestPeerFactory test_peer_factory(
      signaling_thread.get(), time_controller_,
      video_quality_analyzer_injection_helper_.get(), task_queue_.get());
  alice_ = test_peer_factory.CreateTestPeer(
      std::move(alice_configurer),
      std::make_unique<FixturePeerConnectionObserver>(
          [this, bob_video_configs, alice_name](
              rtc::scoped_refptr<RtpTransceiverInterface> transceiver) {
            OnTrackCallback(alice_name, transceiver, bob_video_configs);
          },
          [this]() { StartVideo(alice_video_sources_); }),
      alice_remote_audio_config, run_params.echo_emulation_config);
  bob_ = test_peer_factory.CreateTestPeer(
      std::move(bob_configurer),
      std::make_unique<FixturePeerConnectionObserver>(
          [this, alice_video_configs,
           bob_name](rtc::scoped_refptr<RtpTransceiverInterface> transceiver) {
            OnTrackCallback(bob_name, transceiver, alice_video_configs);
          },
          [this]() { StartVideo(bob_video_sources_); }),
      bob_remote_audio_config, run_params.echo_emulation_config);

  int num_cores = CpuInfo::DetectNumberOfCores();
  RTC_DCHECK_GE(num_cores, 1);

  int video_analyzer_threads =
      num_cores - kPeerConnectionUsedThreads - kFrameworkUsedThreads;
  if (video_analyzer_threads <= 0) {
    video_analyzer_threads = 1;
  }
  video_analyzer_threads =
      std::min(video_analyzer_threads, kMaxVideoAnalyzerThreads);
  RTC_LOG(LS_INFO) << "video_analyzer_threads=" << video_analyzer_threads;
  quality_metrics_reporters_.push_back(
      std::make_unique<VideoQualityMetricsReporter>(
          time_controller_.GetClock()));
  quality_metrics_reporters_.push_back(
      std::make_unique<CrossMediaMetricsReporter>());

  video_quality_analyzer_injection_helper_->Start(
      test_case_name_,
      std::vector<std::string>{alice_->params().name.value(),
                               bob_->params().name.value()},
      video_analyzer_threads);
  audio_quality_analyzer_->Start(test_case_name_, &analyzer_helper_);
  for (auto& reporter : quality_metrics_reporters_) {
    reporter->Start(test_case_name_, &analyzer_helper_);
  }

  // Start RTCEventLog recording if requested.
  if (alice_->params().rtc_event_log_path) {
    auto alice_rtc_event_log = std::make_unique<webrtc::RtcEventLogOutputFile>(
        alice_->params().rtc_event_log_path.value());
    alice_->pc()->StartRtcEventLog(std::move(alice_rtc_event_log),
                                   webrtc::RtcEventLog::kImmediateOutput);
  }
  if (bob_->params().rtc_event_log_path) {
    auto bob_rtc_event_log = std::make_unique<webrtc::RtcEventLogOutputFile>(
        bob_->params().rtc_event_log_path.value());
    bob_->pc()->StartRtcEventLog(std::move(bob_rtc_event_log),
                                 webrtc::RtcEventLog::kImmediateOutput);
  }

  // Setup alive logging. It is done to prevent test infra to think that test is
  // dead.
  RepeatingTaskHandle::DelayedStart(task_queue_->Get(),
                                    kAliveMessageLogInterval, []() {
                                      std::printf("Test is still running...\n");
                                      return kAliveMessageLogInterval;
                                    });

  RTC_LOG(LS_INFO) << "Configuration is done. Now " << *alice_->params().name
                   << " is calling to " << *bob_->params().name << "...";

  // Setup stats poller.
  std::vector<StatsObserverInterface*> observers = {
      audio_quality_analyzer_.get(),
      video_quality_analyzer_injection_helper_.get()};
  for (auto& reporter : quality_metrics_reporters_) {
    observers.push_back(reporter.get());
  }
  StatsPoller stats_poller(observers,
                           std::map<std::string, StatsProvider*>{
                               {*alice_->params().name, alice_.get()},
                               {*bob_->params().name, bob_.get()}});
  executor_->ScheduleActivity(TimeDelta::Zero(), kStatsUpdateInterval,
                              [&stats_poller](TimeDelta) {
                                stats_poller.PollStatsAndNotifyObservers();
                              });

  // Setup call.
  signaling_thread->Invoke<void>(RTC_FROM_HERE, [this, &run_params] {
    SetupCallOnSignalingThread(run_params);
  });
  std::unique_ptr<SignalingInterceptor> signaling_interceptor =
      CreateSignalingInterceptor(run_params);
  // Connect peers.
  signaling_thread->Invoke<void>(RTC_FROM_HERE, [this, &signaling_interceptor] {
    ExchangeOfferAnswer(signaling_interceptor.get());
  });
  WaitUntilIceCandidatesGathered(signaling_thread.get());

  signaling_thread->Invoke<void>(RTC_FROM_HERE, [this, &signaling_interceptor] {
    ExchangeIceCandidates(signaling_interceptor.get());
  });
  WaitUntilPeersAreConnected(signaling_thread.get());

  executor_->Start(task_queue_.get());
  Timestamp start_time = Now();

  bool is_quick_test_enabled = field_trial::IsEnabled("WebRTC-QuickPerfTest");
  if (is_quick_test_enabled) {
    time_controller_.AdvanceTime(kQuickTestModeRunDuration);
  } else {
    time_controller_.AdvanceTime(run_params.run_duration);
  }

  RTC_LOG(LS_INFO) << "Test is done, initiating disconnect sequence.";

  // Stop all client started tasks to prevent their access to any call related
  // objects after these objects will be destroyed during call tear down.
  executor_->Stop();
  // There is no guarantee, that last stats collection will happen at the end
  // of the call, so we force it after executor, which is among others is doing
  // stats collection, was stopped.
  task_queue_->SendTask(
      [&stats_poller]() {
        // Get final end-of-call stats.
        stats_poller.PollStatsAndNotifyObservers();
      },
      RTC_FROM_HERE);
  // We need to detach AEC dumping from peers, because dump uses `task_queue_`
  // inside.
  alice_->DetachAecDump();
  bob_->DetachAecDump();
  // Tear down the call.
  signaling_thread->Invoke<void>(RTC_FROM_HERE,
                                 [this] { TearDownCallOnSignalingThread(); });

  Timestamp end_time = Now();
  RTC_LOG(LS_INFO) << "All peers are disconnected.";
  {
    MutexLock lock(&lock_);
    real_test_duration_ = end_time - start_time;
  }

  ReportGeneralTestResults();
  audio_quality_analyzer_->Stop();
  video_quality_analyzer_injection_helper_->Stop();
  for (auto& reporter : quality_metrics_reporters_) {
    reporter->StopAndReportResults();
  }

  // Reset `task_queue_` after test to cleanup.
  task_queue_.reset();

  alice_ = nullptr;
  bob_ = nullptr;
  // Ensuring that TestVideoCapturerVideoTrackSource are destroyed on the right
  // thread.
  RTC_CHECK(alice_video_sources_.empty());
  RTC_CHECK(bob_video_sources_.empty());
}

std::string PeerConnectionE2EQualityTest::GetFieldTrials(
    const RunParams& run_params) {
  std::vector<absl::string_view> default_field_trials = {
      kUseStandardsBytesStats};
  if (run_params.enable_flex_fec_support) {
    default_field_trials.push_back(kFlexFecEnabledFieldTrials);
  }
  rtc::StringBuilder sb;
  sb << field_trial::GetFieldTrialString();
  for (const absl::string_view& field_trial : default_field_trials) {
    sb << field_trial;
  }
  return sb.Release();
}

void PeerConnectionE2EQualityTest::OnTrackCallback(
    absl::string_view peer_name,
    rtc::scoped_refptr<RtpTransceiverInterface> transceiver,
    std::vector<VideoConfig> remote_video_configs) {
  const rtc::scoped_refptr<MediaStreamTrackInterface>& track =
      transceiver->receiver()->track();
  RTC_CHECK_EQ(transceiver->receiver()->stream_ids().size(), 2)
      << "Expected 2 stream ids: 1st - sync group, 2nd - unique stream label";
  std::string sync_group = transceiver->receiver()->stream_ids()[0];
  std::string stream_label = transceiver->receiver()->stream_ids()[1];
  analyzer_helper_.AddTrackToStreamMapping(track->id(), stream_label,
                                           sync_group);
  if (track->kind() != MediaStreamTrackInterface::kVideoKind) {
    return;
  }

  // It is safe to cast here, because it is checked above that
  // track->kind() is kVideoKind.
  auto* video_track = static_cast<VideoTrackInterface*>(track.get());
  std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>> video_sink =
      video_quality_analyzer_injection_helper_->CreateVideoSink(peer_name);
  video_track->AddOrUpdateSink(video_sink.get(), rtc::VideoSinkWants());
  output_video_sinks_.push_back(std::move(video_sink));
}

void PeerConnectionE2EQualityTest::SetupCallOnSignalingThread(
    const RunParams& run_params) {
  // We need receive-only transceivers for Bob's media stream, so there will
  // be media section in SDP for that streams in Alice's offer, because it is
  // forbidden to add new media sections in answer in Unified Plan.
  RtpTransceiverInit receive_only_transceiver_init;
  receive_only_transceiver_init.direction = RtpTransceiverDirection::kRecvOnly;
  int alice_transceivers_counter = 0;
  if (bob_->params().audio_config) {
    // Setup receive audio transceiver if Bob has audio to send. If we'll need
    // multiple audio streams, then we need transceiver for each Bob's audio
    // stream.
    RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
        alice_->AddTransceiver(cricket::MediaType::MEDIA_TYPE_AUDIO,
                               receive_only_transceiver_init);
    RTC_CHECK(result.ok());
    alice_transceivers_counter++;
  }

  size_t alice_video_transceivers_non_simulcast_counter = 0;
  for (auto& video_config : alice_->configurable_params().video_configs) {
    RtpTransceiverInit transceiver_params;
    if (video_config.simulcast_config) {
      transceiver_params.direction = RtpTransceiverDirection::kSendOnly;
      // Because simulcast enabled `alice_->params().video_codecs` has only 1
      // element.
      if (alice_->params().video_codecs[0].name == cricket::kVp8CodecName) {
        // For Vp8 simulcast we need to add as many RtpEncodingParameters to the
        // track as many simulcast streams requested. If they specified in
        // `video_config.simulcast_config` it should be copied from there.
        for (int i = 0;
             i < video_config.simulcast_config->simulcast_streams_count; ++i) {
          RtpEncodingParameters enc_params;
          if (!video_config.encoding_params.empty()) {
            enc_params = video_config.encoding_params[i];
          }
          // We need to be sure, that all rids will be unique with all mids.
          enc_params.rid = std::to_string(alice_transceivers_counter) + "000" +
                           std::to_string(i);
          transceiver_params.send_encodings.push_back(enc_params);
        }
      }
    } else {
      transceiver_params.direction = RtpTransceiverDirection::kSendRecv;
      RtpEncodingParameters enc_params;
      if (video_config.encoding_params.size() == 1) {
        enc_params = video_config.encoding_params[0];
      }
      transceiver_params.send_encodings.push_back(enc_params);

      alice_video_transceivers_non_simulcast_counter++;
    }
    RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
        alice_->AddTransceiver(cricket::MediaType::MEDIA_TYPE_VIDEO,
                               transceiver_params);
    RTC_CHECK(result.ok());

    alice_transceivers_counter++;
  }

  // Add receive only transceivers in case Bob has more video_configs than
  // Alice.
  for (size_t i = alice_video_transceivers_non_simulcast_counter;
       i < bob_->configurable_params().video_configs.size(); ++i) {
    RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
        alice_->AddTransceiver(cricket::MediaType::MEDIA_TYPE_VIDEO,
                               receive_only_transceiver_init);
    RTC_CHECK(result.ok());
    alice_transceivers_counter++;
  }

  // Then add media for Alice and Bob
  media_helper_->MaybeAddAudio(alice_.get());
  alice_video_sources_ = media_helper_->MaybeAddVideo(alice_.get());
  media_helper_->MaybeAddAudio(bob_.get());
  bob_video_sources_ = media_helper_->MaybeAddVideo(bob_.get());

  SetPeerCodecPreferences(alice_.get());
  SetPeerCodecPreferences(bob_.get());
}

void PeerConnectionE2EQualityTest::TearDownCallOnSignalingThread() {
  TearDownCall();
}

void PeerConnectionE2EQualityTest::SetPeerCodecPreferences(TestPeer* peer) {
  std::vector<RtpCodecCapability> with_rtx_video_capabilities =
      FilterVideoCodecCapabilities(
          peer->params().video_codecs, true, peer->params().use_ulp_fec,
          peer->params().use_flex_fec,
          peer->pc_factory()
              ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_VIDEO)
              .codecs);
  std::vector<RtpCodecCapability> without_rtx_video_capabilities =
      FilterVideoCodecCapabilities(
          peer->params().video_codecs, false, peer->params().use_ulp_fec,
          peer->params().use_flex_fec,
          peer->pc_factory()
              ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_VIDEO)
              .codecs);

  // Set codecs for transceivers
  for (auto transceiver : peer->pc()->GetTransceivers()) {
    if (transceiver->media_type() == cricket::MediaType::MEDIA_TYPE_VIDEO) {
      if (transceiver->sender()->init_send_encodings().size() > 1) {
        // If transceiver's sender has more then 1 send encodings, it means it
        // has multiple simulcast streams, so we need disable RTX on it.
        RTCError result =
            transceiver->SetCodecPreferences(without_rtx_video_capabilities);
        RTC_CHECK(result.ok());
      } else {
        RTCError result =
            transceiver->SetCodecPreferences(with_rtx_video_capabilities);
        RTC_CHECK(result.ok());
      }
    }
  }
}

std::unique_ptr<SignalingInterceptor>
PeerConnectionE2EQualityTest::CreateSignalingInterceptor(
    const RunParams& run_params) {
  std::map<std::string, int> stream_label_to_simulcast_streams_count;
  // We add only Alice here, because simulcast/svc is supported only from the
  // first peer.
  for (auto& video_config : alice_->configurable_params().video_configs) {
    if (video_config.simulcast_config) {
      stream_label_to_simulcast_streams_count.insert(
          {*video_config.stream_label,
           video_config.simulcast_config->simulcast_streams_count});
    }
  }
  PatchingParams patching_params(run_params.use_conference_mode,
                                 stream_label_to_simulcast_streams_count);
  return std::make_unique<SignalingInterceptor>(patching_params);
}

void PeerConnectionE2EQualityTest::WaitUntilIceCandidatesGathered(
    rtc::Thread* signaling_thread) {
  ASSERT_TRUE(time_controller_.Wait(
      [&]() {
        return signaling_thread->Invoke<bool>(RTC_FROM_HERE, [&]() {
          return alice_->IsIceGatheringDone() && bob_->IsIceGatheringDone();
        });
      },
      2 * kDefaultTimeout));
}

void PeerConnectionE2EQualityTest::WaitUntilPeersAreConnected(
    rtc::Thread* signaling_thread) {
  // This means that ICE and DTLS are connected.
  alice_connected_ = time_controller_.Wait(
      [&]() {
        return signaling_thread->Invoke<bool>(
            RTC_FROM_HERE, [&]() { return alice_->IsIceConnected(); });
      },
      kDefaultTimeout);
  bob_connected_ = time_controller_.Wait(
      [&]() {
        return signaling_thread->Invoke<bool>(
            RTC_FROM_HERE, [&]() { return bob_->IsIceConnected(); });
      },
      kDefaultTimeout);
}

void PeerConnectionE2EQualityTest::ExchangeOfferAnswer(
    SignalingInterceptor* signaling_interceptor) {
  std::string log_output;

  auto offer = alice_->CreateOffer();
  RTC_CHECK(offer);
  offer->ToString(&log_output);
  RTC_LOG(LS_INFO) << "Original offer: " << log_output;
  LocalAndRemoteSdp patch_result = signaling_interceptor->PatchOffer(
      std::move(offer), alice_->params().video_codecs[0]);
  patch_result.local_sdp->ToString(&log_output);
  RTC_LOG(LS_INFO) << "Offer to set as local description: " << log_output;
  patch_result.remote_sdp->ToString(&log_output);
  RTC_LOG(LS_INFO) << "Offer to set as remote description: " << log_output;

  bool set_local_offer =
      alice_->SetLocalDescription(std::move(patch_result.local_sdp));
  RTC_CHECK(set_local_offer);
  bool set_remote_offer =
      bob_->SetRemoteDescription(std::move(patch_result.remote_sdp));
  RTC_CHECK(set_remote_offer);
  auto answer = bob_->CreateAnswer();
  RTC_CHECK(answer);
  answer->ToString(&log_output);
  RTC_LOG(LS_INFO) << "Original answer: " << log_output;
  patch_result = signaling_interceptor->PatchAnswer(
      std::move(answer), bob_->params().video_codecs[0]);
  patch_result.local_sdp->ToString(&log_output);
  RTC_LOG(LS_INFO) << "Answer to set as local description: " << log_output;
  patch_result.remote_sdp->ToString(&log_output);
  RTC_LOG(LS_INFO) << "Answer to set as remote description: " << log_output;

  bool set_local_answer =
      bob_->SetLocalDescription(std::move(patch_result.local_sdp));
  RTC_CHECK(set_local_answer);
  bool set_remote_answer =
      alice_->SetRemoteDescription(std::move(patch_result.remote_sdp));
  RTC_CHECK(set_remote_answer);
}

void PeerConnectionE2EQualityTest::ExchangeIceCandidates(
    SignalingInterceptor* signaling_interceptor) {
  // Connect an ICE candidate pairs.
  std::vector<std::unique_ptr<IceCandidateInterface>> alice_candidates =
      signaling_interceptor->PatchOffererIceCandidates(
          alice_->observer()->GetAllCandidates());
  for (auto& candidate : alice_candidates) {
    std::string candidate_str;
    RTC_CHECK(candidate->ToString(&candidate_str));
    RTC_LOG(LS_INFO) << *alice_->params().name
                     << " ICE candidate(mid= " << candidate->sdp_mid()
                     << "): " << candidate_str;
  }
  ASSERT_TRUE(bob_->AddIceCandidates(std::move(alice_candidates)));
  std::vector<std::unique_ptr<IceCandidateInterface>> bob_candidates =
      signaling_interceptor->PatchAnswererIceCandidates(
          bob_->observer()->GetAllCandidates());
  for (auto& candidate : bob_candidates) {
    std::string candidate_str;
    RTC_CHECK(candidate->ToString(&candidate_str));
    RTC_LOG(LS_INFO) << *bob_->params().name
                     << " ICE candidate(mid= " << candidate->sdp_mid()
                     << "): " << candidate_str;
  }
  ASSERT_TRUE(alice_->AddIceCandidates(std::move(bob_candidates)));
}

void PeerConnectionE2EQualityTest::StartVideo(
    const std::vector<rtc::scoped_refptr<TestVideoCapturerVideoTrackSource>>&
        sources) {
  for (auto& source : sources) {
    if (source->state() != MediaSourceInterface::SourceState::kLive) {
      source->Start();
    }
  }
}

void PeerConnectionE2EQualityTest::TearDownCall() {
  for (const auto& video_source : alice_video_sources_) {
    video_source->Stop();
  }
  for (const auto& video_source : bob_video_sources_) {
    video_source->Stop();
  }

  alice_video_sources_.clear();
  bob_video_sources_.clear();

  alice_->Close();
  bob_->Close();

  media_helper_ = nullptr;
}

void PeerConnectionE2EQualityTest::ReportGeneralTestResults() {
  test::PrintResult(*alice_->params().name + "_connected", "", test_case_name_,
                    alice_connected_, "unitless",
                    /*important=*/false,
                    test::ImproveDirection::kBiggerIsBetter);
  test::PrintResult(*bob_->params().name + "_connected", "", test_case_name_,
                    bob_connected_, "unitless",
                    /*important=*/false,
                    test::ImproveDirection::kBiggerIsBetter);
}

Timestamp PeerConnectionE2EQualityTest::Now() const {
  return time_controller_.GetClock()->CurrentTime();
}

}  // namespace webrtc_pc_e2e
}  // namespace webrtc
