/*
 *  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, {{*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
