/*
 *  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 "rtc_base/task_queue_for_test.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_frame_tracking_id_injector.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());
  }
  if (field_trial::IsEnabled("WebRTC-VideoFrameTrackingIdAdvertised")) {
    encoded_image_data_propagator_ =
        std::make_unique<VideoFrameTrackingIdInjector>();
  } else {
    encoded_image_data_propagator_ =
        std::make_unique<SingleProcessEncodedImageDataInjector>();
  }
  video_quality_analyzer_injection_helper_ =
      std::make_unique<VideoQualityAnalyzerInjectionHelper>(
          time_controller_.GetClock(), 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.
  SendTask(signaling_thread.get(),
           [this, &run_params] { SetupCallOnSignalingThread(run_params); });
  std::unique_ptr<SignalingInterceptor> signaling_interceptor =
      CreateSignalingInterceptor(run_params);
  // Connect peers.
  SendTask(signaling_thread.get(), [this, &signaling_interceptor] {
    ExchangeOfferAnswer(signaling_interceptor.get());
  });
  WaitUntilIceCandidatesGathered(signaling_thread.get());

  SendTask(signaling_thread.get(), [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();
  });
  // We need to detach AEC dumping from peers, because dump uses `task_queue_`
  // inside.
  alice_->DetachAecDump();
  bob_->DetachAecDump();
  // Tear down the call.
  SendTask(signaling_thread.get(), [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(
      [&]() {
        bool result;
        SendTask(signaling_thread, [&]() {
          result = alice_->IsIceGatheringDone() && bob_->IsIceGatheringDone();
        });
        return result;
      },
      2 * kDefaultTimeout));
}

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