Move media configuration classes out of  PeerConnectionE2EQualityTestFixture.

The goal is to remove the dependency between PeerConfigurerImpl and PeerConnectionE2EQualityTestFixture so that PeerConfigurerImpl can be used in PeerConnectionE2EQualityTestFixture API.

Change-Id: I29ae44b9d0e39075d0c395ff9d9f8d313be12176
Bug: webrtc:14627
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/281740
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Commit-Queue: Jeremy Leconte <jleconte@google.com>
Cr-Commit-Position: refs/heads/main@{#38560}
diff --git a/api/BUILD.gn b/api/BUILD.gn
index ce3271c..9768c6d 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -507,10 +507,7 @@
 rtc_source_set("peer_connection_quality_test_fixture_api") {
   visibility = [ "*" ]
   testonly = true
-  sources = [
-    "test/peerconnection_quality_test_fixture.cc",
-    "test/peerconnection_quality_test_fixture.h",
-  ]
+  sources = [ "test/peerconnection_quality_test_fixture.h" ]
 
   deps = [
     ":array_view",
@@ -540,6 +537,8 @@
     "audio:audio_mixer_api",
     "rtc_event_log",
     "task_queue",
+    "test/pclf:media_configuration",
+    "test/pclf:media_quality_test_params",
     "test/video:video_frame_writer",
     "transport:network_control",
     "units:time_delta",
@@ -1325,6 +1324,7 @@
       "../test:rtc_expect_death",
       "../test:test_support",
       "task_queue:task_queue_default_factory_unittests",
+      "test/pclf:media_configuration",
       "test/video:video_frame_writer",
       "transport:field_trial_based_config",
       "units:time_delta",
diff --git a/api/test/pclf/BUILD.gn b/api/test/pclf/BUILD.gn
index 1d6b995..6375e45 100644
--- a/api/test/pclf/BUILD.gn
+++ b/api/test/pclf/BUILD.gn
@@ -8,18 +8,66 @@
 
 import("../../../webrtc.gni")
 
+rtc_source_set("media_configuration") {
+  visibility = [ "*" ]
+  testonly = true
+  sources = [
+    "media_configuration.cc",
+    "media_configuration.h",
+  ]
+
+  deps = [
+    "../..:array_view",
+    "../..:audio_options_api",
+    "../..:audio_quality_analyzer_api",
+    "../..:callfactory_api",
+    "../..:fec_controller_api",
+    "../..:frame_generator_api",
+    "../..:function_view",
+    "../..:libjingle_peerconnection_api",
+    "../..:media_stream_interface",
+    "../..:packet_socket_factory",
+    "../..:peer_network_dependencies",
+    "../..:rtp_parameters",
+    "../..:simulated_network_api",
+    "../..:stats_observer_interface",
+    "../..:track_id_stream_info_map",
+    "../..:video_quality_analyzer_api",
+    "../../../modules/audio_processing:api",
+    "../../../rtc_base:checks",
+    "../../../rtc_base:rtc_base",
+    "../../../rtc_base:stringutils",
+    "../../../rtc_base:threading",
+    "../../../test:fileutils",
+    "../../../test:video_test_support",
+    "../../../test/pc/e2e:video_dumping",
+    "../../audio:audio_mixer_api",
+    "../../rtc_event_log",
+    "../../task_queue",
+    "../../transport:network_control",
+    "../../units:time_delta",
+    "../../video_codecs:video_codecs_api",
+    "../video:video_frame_writer",
+  ]
+  absl_deps = [
+    "//third_party/abseil-cpp/absl/memory",
+    "//third_party/abseil-cpp/absl/strings",
+    "//third_party/abseil-cpp/absl/types:optional",
+  ]
+}
+
 rtc_library("media_quality_test_params") {
   visibility = [ "*" ]
   testonly = true
   sources = [ "media_quality_test_params.h" ]
 
   deps = [
+    ":media_configuration",
     "../../../api:callfactory_api",
     "../../../api:fec_controller_api",
     "../../../api:field_trials_view",
     "../../../api:libjingle_peerconnection_api",
     "../../../api:packet_socket_factory",
-    "../../../api:peer_connection_quality_test_fixture_api",
     "../../../api/audio:audio_mixer_api",
     "../../../api/rtc_event_log",
     "../../../api/task_queue",
diff --git a/api/test/pclf/media_configuration.cc b/api/test/pclf/media_configuration.cc
new file mode 100644
index 0000000..b1694df
--- /dev/null
+++ b/api/test/pclf/media_configuration.cc
@@ -0,0 +1,322 @@
+/*
+ *  Copyright 2022 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 "api/test/pclf/media_configuration.h"
+
+#include <string>
+#include <utility>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/test/video/video_frame_writer.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/strings/string_builder.h"
+#include "test/pc/e2e/analyzer/video/video_dumping.h"
+#include "test/testsupport/file_utils.h"
+#include "test/testsupport/video_frame_writer.h"
+
+namespace webrtc {
+namespace webrtc_pc_e2e {
+namespace {
+
+std::string SpecToString(VideoResolution::Spec spec) {
+  switch (spec) {
+    case VideoResolution::Spec::kNone:
+      return "None";
+    case VideoResolution::Spec::kMaxFromSender:
+      return "MaxFromSender";
+  }
+}
+
+void AppendResolution(const VideoResolution& resolution,
+                      rtc::StringBuilder& builder) {
+  builder << "_" << resolution.width() << "x" << resolution.height() << "_"
+          << resolution.fps();
+}
+
+}  // namespace
+
+ScrollingParams::ScrollingParams(TimeDelta duration,
+                                 size_t source_width,
+                                 size_t source_height)
+    : duration(duration),
+      source_width(source_width),
+      source_height(source_height) {
+  RTC_CHECK_GT(duration.ms(), 0);
+}
+ScreenShareConfig::ScreenShareConfig(TimeDelta slide_change_interval)
+    : slide_change_interval(slide_change_interval) {
+  RTC_CHECK_GT(slide_change_interval.ms(), 0);
+}
+VideoSimulcastConfig::VideoSimulcastConfig(int simulcast_streams_count)
+    : simulcast_streams_count(simulcast_streams_count) {
+  RTC_CHECK_GT(simulcast_streams_count, 1);
+}
+EmulatedSFUConfig::EmulatedSFUConfig(int target_layer_index)
+    : target_layer_index(target_layer_index) {
+  RTC_CHECK_GE(target_layer_index, 0);
+}
+
+EmulatedSFUConfig::EmulatedSFUConfig(absl::optional<int> target_layer_index,
+                                     absl::optional<int> target_temporal_index)
+    : target_layer_index(target_layer_index),
+      target_temporal_index(target_temporal_index) {
+  RTC_CHECK_GE(target_temporal_index.value_or(0), 0);
+  if (target_temporal_index)
+    RTC_CHECK_GE(*target_temporal_index, 0);
+}
+
+VideoResolution::VideoResolution(size_t width, size_t height, int32_t fps)
+    : width_(width), height_(height), fps_(fps), spec_(Spec::kNone) {}
+VideoResolution::VideoResolution(Spec spec)
+    : width_(0), height_(0), fps_(0), spec_(spec) {}
+
+bool VideoResolution::operator==(const VideoResolution& other) const {
+  if (spec_ != Spec::kNone && spec_ == other.spec_) {
+    // If there is some particular spec set, then it doesn't matter what
+    // values we have in other fields.
+    return true;
+  }
+  return width_ == other.width_ && height_ == other.height_ &&
+         fps_ == other.fps_ && spec_ == other.spec_;
+}
+bool VideoResolution::operator!=(const VideoResolution& other) const {
+  return !(*this == other);
+}
+
+bool VideoResolution::IsRegular() const {
+  return spec_ == Spec::kNone;
+}
+std::string VideoResolution::ToString() const {
+  rtc::StringBuilder out;
+  out << "{ width=" << width_ << ", height=" << height_ << ", fps=" << fps_
+      << ", spec=" << SpecToString(spec_) << " }";
+  return out.Release();
+}
+
+VideoDumpOptions::VideoDumpOptions(
+    absl::string_view output_directory,
+    int sampling_modulo,
+    bool export_frame_ids,
+    std::function<std::unique_ptr<test::VideoFrameWriter>(
+        absl::string_view file_name_prefix,
+        const VideoResolution& resolution)> video_frame_writer_factory)
+    : output_directory_(output_directory),
+      sampling_modulo_(sampling_modulo),
+      export_frame_ids_(export_frame_ids),
+      video_frame_writer_factory_(video_frame_writer_factory) {
+  RTC_CHECK_GT(sampling_modulo, 0);
+}
+
+VideoDumpOptions::VideoDumpOptions(absl::string_view output_directory,
+                                   bool export_frame_ids)
+    : VideoDumpOptions(output_directory,
+                       kDefaultSamplingModulo,
+                       export_frame_ids) {}
+
+std::unique_ptr<test::VideoFrameWriter>
+VideoDumpOptions::CreateInputDumpVideoFrameWriter(
+    absl::string_view stream_label,
+    const VideoResolution& resolution) const {
+  std::unique_ptr<test::VideoFrameWriter> writer = video_frame_writer_factory_(
+      GetInputDumpFileName(stream_label, resolution), resolution);
+  absl::optional<std::string> frame_ids_file =
+      GetInputFrameIdsDumpFileName(stream_label, resolution);
+  if (frame_ids_file.has_value()) {
+    writer = CreateVideoFrameWithIdsWriter(std::move(writer), *frame_ids_file);
+  }
+  return writer;
+}
+
+std::unique_ptr<test::VideoFrameWriter>
+VideoDumpOptions::CreateOutputDumpVideoFrameWriter(
+    absl::string_view stream_label,
+    absl::string_view receiver,
+    const VideoResolution& resolution) const {
+  std::unique_ptr<test::VideoFrameWriter> writer = video_frame_writer_factory_(
+      GetOutputDumpFileName(stream_label, receiver, resolution), resolution);
+  absl::optional<std::string> frame_ids_file =
+      GetOutputFrameIdsDumpFileName(stream_label, receiver, resolution);
+  if (frame_ids_file.has_value()) {
+    writer = CreateVideoFrameWithIdsWriter(std::move(writer), *frame_ids_file);
+  }
+  return writer;
+}
+
+std::unique_ptr<test::VideoFrameWriter>
+VideoDumpOptions::Y4mVideoFrameWriterFactory(
+    absl::string_view file_name_prefix,
+    const VideoResolution& resolution) {
+  return std::make_unique<test::Y4mVideoFrameWriterImpl>(
+      std::string(file_name_prefix) + ".y4m", resolution.width(),
+      resolution.height(), resolution.fps());
+}
+
+std::string VideoDumpOptions::GetInputDumpFileName(
+    absl::string_view stream_label,
+    const VideoResolution& resolution) const {
+  rtc::StringBuilder file_name;
+  file_name << stream_label;
+  AppendResolution(resolution, file_name);
+  return test::JoinFilename(output_directory_, file_name.Release());
+}
+
+absl::optional<std::string> VideoDumpOptions::GetInputFrameIdsDumpFileName(
+    absl::string_view stream_label,
+    const VideoResolution& resolution) const {
+  if (!export_frame_ids_) {
+    return absl::nullopt;
+  }
+  return GetInputDumpFileName(stream_label, resolution) + ".frame_ids.txt";
+}
+
+std::string VideoDumpOptions::GetOutputDumpFileName(
+    absl::string_view stream_label,
+    absl::string_view receiver,
+    const VideoResolution& resolution) const {
+  rtc::StringBuilder file_name;
+  file_name << stream_label << "_" << receiver;
+  AppendResolution(resolution, file_name);
+  return test::JoinFilename(output_directory_, file_name.Release());
+}
+
+absl::optional<std::string> VideoDumpOptions::GetOutputFrameIdsDumpFileName(
+    absl::string_view stream_label,
+    absl::string_view receiver,
+    const VideoResolution& resolution) const {
+  if (!export_frame_ids_) {
+    return absl::nullopt;
+  }
+  return GetOutputDumpFileName(stream_label, receiver, resolution) +
+         ".frame_ids.txt";
+}
+
+std::string VideoDumpOptions::ToString() const {
+  rtc::StringBuilder out;
+  out << "{ output_directory_=" << output_directory_
+      << ", sampling_modulo_=" << sampling_modulo_
+      << ", export_frame_ids_=" << export_frame_ids_ << " }";
+  return out.Release();
+}
+
+VideoConfig::VideoConfig(const VideoResolution& resolution)
+    : width(resolution.width()),
+      height(resolution.height()),
+      fps(resolution.fps()) {
+  RTC_CHECK(resolution.IsRegular());
+}
+VideoConfig::VideoConfig(size_t width, size_t height, int32_t fps)
+    : width(width), height(height), fps(fps) {}
+VideoConfig::VideoConfig(std::string stream_label,
+                         size_t width,
+                         size_t height,
+                         int32_t fps)
+    : width(width),
+      height(height),
+      fps(fps),
+      stream_label(std::move(stream_label)) {}
+
+AudioConfig::AudioConfig(std::string stream_label)
+    : stream_label(std::move(stream_label)) {}
+
+VideoCodecConfig::VideoCodecConfig(std::string name)
+    : name(std::move(name)), required_params() {}
+VideoCodecConfig::VideoCodecConfig(
+    std::string name,
+    std::map<std::string, std::string> required_params)
+    : name(std::move(name)), required_params(std::move(required_params)) {}
+
+absl::optional<VideoResolution> VideoSubscription::GetMaxResolution(
+    rtc::ArrayView<const VideoConfig> video_configs) {
+  std::vector<VideoResolution> resolutions;
+  for (const auto& video_config : video_configs) {
+    resolutions.push_back(video_config.GetResolution());
+  }
+  return GetMaxResolution(resolutions);
+}
+
+absl::optional<VideoResolution> VideoSubscription::GetMaxResolution(
+    rtc::ArrayView<const VideoResolution> resolutions) {
+  if (resolutions.empty()) {
+    return absl::nullopt;
+  }
+
+  VideoResolution max_resolution;
+  for (const VideoResolution& resolution : resolutions) {
+    if (max_resolution.width() < resolution.width()) {
+      max_resolution.set_width(resolution.width());
+    }
+    if (max_resolution.height() < resolution.height()) {
+      max_resolution.set_height(resolution.height());
+    }
+    if (max_resolution.fps() < resolution.fps()) {
+      max_resolution.set_fps(resolution.fps());
+    }
+  }
+  return max_resolution;
+}
+
+bool VideoSubscription::operator==(const VideoSubscription& other) const {
+  return default_resolution_ == other.default_resolution_ &&
+         peers_resolution_ == other.peers_resolution_;
+}
+bool VideoSubscription::operator!=(const VideoSubscription& other) const {
+  return !(*this == other);
+}
+
+VideoSubscription& VideoSubscription::SubscribeToPeer(
+    absl::string_view peer_name,
+    VideoResolution resolution) {
+  peers_resolution_[std::string(peer_name)] = resolution;
+  return *this;
+}
+
+VideoSubscription& VideoSubscription::SubscribeToAllPeers(
+    VideoResolution resolution) {
+  default_resolution_ = resolution;
+  return *this;
+}
+
+absl::optional<VideoResolution> VideoSubscription::GetResolutionForPeer(
+    absl::string_view peer_name) const {
+  auto it = peers_resolution_.find(std::string(peer_name));
+  if (it == peers_resolution_.end()) {
+    return default_resolution_;
+  }
+  return it->second;
+}
+
+std::vector<std::string> VideoSubscription::GetSubscribedPeers() const {
+  std::vector<std::string> subscribed_streams;
+  subscribed_streams.reserve(peers_resolution_.size());
+  for (const auto& entry : peers_resolution_) {
+    subscribed_streams.push_back(entry.first);
+  }
+  return subscribed_streams;
+}
+
+std::string VideoSubscription::ToString() const {
+  rtc::StringBuilder out;
+  out << "{ default_resolution_=[";
+  if (default_resolution_.has_value()) {
+    out << default_resolution_->ToString();
+  } else {
+    out << "undefined";
+  }
+  out << "], {";
+  for (const auto& [peer_name, resolution] : peers_resolution_) {
+    out << "[" << peer_name << ": " << resolution.ToString() << "], ";
+  }
+  out << "} }";
+  return out.Release();
+}
+}  // namespace webrtc_pc_e2e
+}  // namespace webrtc
diff --git a/api/test/pclf/media_configuration.h b/api/test/pclf/media_configuration.h
new file mode 100644
index 0000000..c6ce1607
--- /dev/null
+++ b/api/test/pclf/media_configuration.h
@@ -0,0 +1,485 @@
+/*
+ *  Copyright (c) 2022 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.
+ */
+#ifndef API_TEST_PCLF_MEDIA_CONFIGURATION_H_
+#define API_TEST_PCLF_MEDIA_CONFIGURATION_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/async_resolver_factory.h"
+#include "api/audio/audio_mixer.h"
+#include "api/audio_options.h"
+#include "api/call/call_factory_interface.h"
+#include "api/fec_controller.h"
+#include "api/function_view.h"
+#include "api/media_stream_interface.h"
+#include "api/peer_connection_interface.h"
+#include "api/rtc_event_log/rtc_event_log_factory_interface.h"
+#include "api/rtp_parameters.h"
+#include "api/task_queue/task_queue_factory.h"
+#include "api/test/audio_quality_analyzer_interface.h"
+#include "api/test/frame_generator_interface.h"
+#include "api/test/peer_network_dependencies.h"
+#include "api/test/simulated_network.h"
+#include "api/test/stats_observer_interface.h"
+#include "api/test/track_id_stream_info_map.h"
+#include "api/test/video/video_frame_writer.h"
+#include "api/test/video_quality_analyzer_interface.h"
+#include "api/transport/network_control.h"
+#include "api/units/time_delta.h"
+#include "api/video_codecs/video_decoder_factory.h"
+#include "api/video_codecs/video_encoder.h"
+#include "api/video_codecs/video_encoder_factory.h"
+#include "modules/audio_processing/include/audio_processing.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/network.h"
+#include "rtc_base/rtc_certificate_generator.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/thread.h"
+
+namespace webrtc {
+namespace webrtc_pc_e2e {
+
+// The index of required capturing device in OS provided list of video
+// devices. On Linux and Windows the list will be obtained via
+// webrtc::VideoCaptureModule::DeviceInfo, on Mac OS via
+// [RTCCameraVideoCapturer captureDevices].
+enum class CapturingDeviceIndex : size_t {};
+
+// Contains parameters for screen share scrolling.
+//
+// If scrolling is enabled, then it will be done by putting sliding window
+// on source video and moving this window from top left corner to the
+// bottom right corner of the picture.
+//
+// In such case source dimensions must be greater or equal to the sliding
+// window dimensions. So `source_width` and `source_height` are the dimensions
+// of the source frame, while `VideoConfig::width` and `VideoConfig::height`
+// are the dimensions of the sliding window.
+//
+// Because `source_width` and `source_height` are dimensions of the source
+// frame, they have to be width and height of videos from
+// `ScreenShareConfig::slides_yuv_file_names`.
+//
+// Because scrolling have to be done on single slide it also requires, that
+// `duration` must be less or equal to
+// `ScreenShareConfig::slide_change_interval`.
+struct ScrollingParams {
+  ScrollingParams(TimeDelta duration,
+                  size_t source_width,
+                  size_t source_height);
+
+  // Duration of scrolling.
+  TimeDelta duration;
+  // Width of source slides video.
+  size_t source_width;
+  // Height of source slides video.
+  size_t source_height;
+};
+
+// Contains screen share video stream properties.
+struct ScreenShareConfig {
+  explicit ScreenShareConfig(TimeDelta slide_change_interval);
+
+  // Shows how long one slide should be presented on the screen during
+  // slide generation.
+  TimeDelta slide_change_interval;
+  // If true, slides will be generated programmatically. No scrolling params
+  // will be applied in such case.
+  bool generate_slides = false;
+  // If present scrolling will be applied. Please read extra requirement on
+  // `slides_yuv_file_names` for scrolling.
+  absl::optional<ScrollingParams> scrolling_params;
+  // Contains list of yuv files with slides.
+  //
+  // If empty, default set of slides will be used. In such case
+  // `VideoConfig::width` must be equal to `kDefaultSlidesWidth` and
+  // `VideoConfig::height` must be equal to `kDefaultSlidesHeight` or if
+  // `scrolling_params` are specified, then `ScrollingParams::source_width`
+  // must be equal to `kDefaultSlidesWidth` and
+  // `ScrollingParams::source_height` must be equal to `kDefaultSlidesHeight`.
+  std::vector<std::string> slides_yuv_file_names;
+};
+
+// Config for Vp8 simulcast or non-standard Vp9 SVC testing.
+//
+// To configure standard SVC setting, use `scalability_mode` in the
+// `encoding_params` array.
+// This configures Vp9 SVC by requesting simulcast layers, the request is
+// internally converted to a request for SVC layers.
+//
+// SVC support is limited:
+// During SVC testing there is no SFU, so framework will try to emulate SFU
+// behavior in regular p2p call. Because of it there are such limitations:
+//  * if `target_spatial_index` is not equal to the highest spatial layer
+//    then no packet/frame drops are allowed.
+//
+//    If there will be any drops, that will affect requested layer, then
+//    WebRTC SVC implementation will continue decoding only the highest
+//    available layer and won't restore lower layers, so analyzer won't
+//    receive required data which will cause wrong results or test failures.
+struct VideoSimulcastConfig {
+  explicit VideoSimulcastConfig(int simulcast_streams_count);
+
+  // Specified amount of simulcast streams/SVC layers, depending on which
+  // encoder is used.
+  int simulcast_streams_count;
+};
+
+// Configuration for the emulated Selective Forward Unit (SFU)
+//
+// The framework can optionally filter out frames that are decoded
+// using an emulated SFU.
+// When using simulcast or SVC, it's not always desirable to receive
+// all frames. In a real world call, a SFU will only forward a subset
+// of the frames.
+// The emulated SFU is not able to change its configuration dynamically,
+// if adaptation happens during the call, layers may be dropped and the
+// analyzer won't receive the required data which will cause wrong results or
+// test failures.
+struct EmulatedSFUConfig {
+  EmulatedSFUConfig() = default;
+  explicit EmulatedSFUConfig(int target_layer_index);
+  EmulatedSFUConfig(absl::optional<int> target_layer_index,
+                    absl::optional<int> target_temporal_index);
+
+  // Specifies simulcast or spatial index of the video stream to analyze.
+  // There are 2 cases:
+  // 1. simulcast encoding is used:
+  //    in such case `target_layer_index` will specify the index of
+  //    simulcast stream, that should be analyzed. Other streams will be
+  //    dropped.
+  // 2. SVC encoding is used:
+  //    in such case `target_layer_index` will specify the top interesting
+  //    spatial layer and all layers below, including target one will be
+  //    processed. All layers above target one will be dropped.
+  // If not specified then all streams will be received and analyzed.
+  // When set, it instructs the framework to create an emulated Selective
+  // Forwarding Unit (SFU) that will propagate only the requested layers.
+  absl::optional<int> target_layer_index;
+  // Specifies the index of the maximum temporal unit to keep.
+  // If not specified then all temporal layers will be received and analyzed.
+  // When set, it instructs the framework to create an emulated Selective
+  // Forwarding Unit (SFU) that will propagate only up to the requested layer.
+  absl::optional<int> target_temporal_index;
+};
+
+class VideoResolution {
+ public:
+  // Determines special resolutions, which can't be expressed in terms of
+  // width, height and fps.
+  enum class Spec {
+    // No extra spec set. It describes a regular resolution described by
+    // width, height and fps.
+    kNone,
+    // Describes resolution which contains max value among all sender's
+    // video streams in each dimension (width, height, fps).
+    kMaxFromSender
+  };
+
+  VideoResolution(size_t width, size_t height, int32_t fps);
+  explicit VideoResolution(Spec spec = Spec::kNone);
+
+  bool operator==(const VideoResolution& other) const;
+  bool operator!=(const VideoResolution& other) const;
+
+  size_t width() const { return width_; }
+  void set_width(size_t width) { width_ = width; }
+  size_t height() const { return height_; }
+  void set_height(size_t height) { height_ = height; }
+  int32_t fps() const { return fps_; }
+  void set_fps(int32_t fps) { fps_ = fps; }
+
+  // Returns if it is a regular resolution or not. The resolution is regular
+  // if it's spec is `Spec::kNone`.
+  bool IsRegular() const;
+
+  std::string ToString() const;
+
+ private:
+  size_t width_ = 0;
+  size_t height_ = 0;
+  int32_t fps_ = 0;
+  Spec spec_ = Spec::kNone;
+};
+
+class VideoDumpOptions {
+ public:
+  static constexpr int kDefaultSamplingModulo = 1;
+
+  // output_directory - the output directory where stream will be dumped. The
+  // output files' names will be constructed as
+  // <stream_name>_<receiver_name>_<resolution>.<extension> for output dumps
+  // and <stream_name>_<resolution>.<extension> for input dumps.
+  // By default <extension> is "y4m". Resolution is in the format
+  // <width>x<height>_<fps>.
+  // sampling_modulo - the module for the video frames to be dumped. Modulo
+  // equals X means every Xth frame will be written to the dump file. The
+  // value must be greater than 0. (Default: 1)
+  // export_frame_ids - specifies if frame ids should be exported together
+  // with content of the stream. If true, an output file with the same name as
+  // video dump and suffix ".frame_ids.txt" will be created. It will contain
+  // the frame ids in the same order as original frames in the output
+  // file with stream content. File will contain one frame id per line.
+  // (Default: false)
+  // `video_frame_writer_factory` - factory function to create a video frame
+  // writer for input and output video files. (Default: Y4M video writer
+  // factory).
+  explicit VideoDumpOptions(
+      absl::string_view output_directory,
+      int sampling_modulo = kDefaultSamplingModulo,
+      bool export_frame_ids = false,
+      std::function<std::unique_ptr<test::VideoFrameWriter>(
+          absl::string_view file_name_prefix,
+          const VideoResolution& resolution)> video_frame_writer_factory =
+          Y4mVideoFrameWriterFactory);
+  VideoDumpOptions(absl::string_view output_directory, bool export_frame_ids);
+
+  VideoDumpOptions(const VideoDumpOptions&) = default;
+  VideoDumpOptions& operator=(const VideoDumpOptions&) = default;
+  VideoDumpOptions(VideoDumpOptions&&) = default;
+  VideoDumpOptions& operator=(VideoDumpOptions&&) = default;
+
+  std::string output_directory() const { return output_directory_; }
+  int sampling_modulo() const { return sampling_modulo_; }
+  bool export_frame_ids() const { return export_frame_ids_; }
+
+  std::unique_ptr<test::VideoFrameWriter> CreateInputDumpVideoFrameWriter(
+      absl::string_view stream_label,
+      const VideoResolution& resolution) const;
+
+  std::unique_ptr<test::VideoFrameWriter> CreateOutputDumpVideoFrameWriter(
+      absl::string_view stream_label,
+      absl::string_view receiver,
+      const VideoResolution& resolution) const;
+
+  std::string ToString() const;
+
+ private:
+  static std::unique_ptr<test::VideoFrameWriter> Y4mVideoFrameWriterFactory(
+      absl::string_view file_name_prefix,
+      const VideoResolution& resolution);
+  std::string GetInputDumpFileName(absl::string_view stream_label,
+                                   const VideoResolution& resolution) const;
+  // Returns file name for input frame ids dump if `export_frame_ids()` is
+  // true, absl::nullopt otherwise.
+  absl::optional<std::string> GetInputFrameIdsDumpFileName(
+      absl::string_view stream_label,
+      const VideoResolution& resolution) const;
+  std::string GetOutputDumpFileName(absl::string_view stream_label,
+                                    absl::string_view receiver,
+                                    const VideoResolution& resolution) const;
+  // Returns file name for output frame ids dump if `export_frame_ids()` is
+  // true, absl::nullopt otherwise.
+  absl::optional<std::string> GetOutputFrameIdsDumpFileName(
+      absl::string_view stream_label,
+      absl::string_view receiver,
+      const VideoResolution& resolution) const;
+
+  std::string output_directory_;
+  int sampling_modulo_ = 1;
+  bool export_frame_ids_ = false;
+  std::function<std::unique_ptr<test::VideoFrameWriter>(
+      absl::string_view file_name_prefix,
+      const VideoResolution& resolution)>
+      video_frame_writer_factory_;
+};
+
+// Contains properties of single video stream.
+struct VideoConfig {
+  explicit VideoConfig(const VideoResolution& resolution);
+  VideoConfig(size_t width, size_t height, int32_t fps);
+  VideoConfig(std::string stream_label,
+              size_t width,
+              size_t height,
+              int32_t fps);
+
+  // Video stream width.
+  size_t width;
+  // Video stream height.
+  size_t height;
+  int32_t fps;
+  VideoResolution GetResolution() const {
+    return VideoResolution(width, height, fps);
+  }
+
+  // Have to be unique among all specified configs for all peers in the call.
+  // Will be auto generated if omitted.
+  absl::optional<std::string> stream_label;
+  // Will be set for current video track. If equals to kText or kDetailed -
+  // screencast in on.
+  absl::optional<VideoTrackInterface::ContentHint> content_hint;
+  // If presented video will be transfered in simulcast/SVC mode depending on
+  // which encoder is used.
+  //
+  // Simulcast is supported only from 1st added peer. For VP8 simulcast only
+  // without RTX is supported so it will be automatically disabled for all
+  // simulcast tracks. For VP9 simulcast enables VP9 SVC mode and support RTX,
+  // but only on non-lossy networks. See more in documentation to
+  // VideoSimulcastConfig.
+  absl::optional<VideoSimulcastConfig> simulcast_config;
+  // Configuration for the emulated Selective Forward Unit (SFU).
+  absl::optional<EmulatedSFUConfig> emulated_sfu_config;
+  // Encoding parameters for both singlecast and per simulcast layer.
+  // If singlecast is used, if not empty, a single value can be provided.
+  // If simulcast is used, if not empty, `encoding_params` size have to be
+  // equal to `simulcast_config.simulcast_streams_count`. Will be used to set
+  // transceiver send encoding params for each layer.
+  // RtpEncodingParameters::rid may be changed by fixture implementation to
+  // ensure signaling correctness.
+  std::vector<RtpEncodingParameters> encoding_params;
+  // Count of temporal layers for video stream. This value will be set into
+  // each RtpEncodingParameters of RtpParameters of corresponding
+  // RtpSenderInterface for this video stream.
+  absl::optional<int> temporal_layers_count;
+  // If specified defines how input should be dumped. It is actually one of
+  // the test's output file, which contains copy of what was captured during
+  // the test for this video stream on sender side. It is useful when
+  // generator is used as input.
+  absl::optional<VideoDumpOptions> input_dump_options;
+  // If specified defines how output should be dumped on the receiver side for
+  // this stream. The produced files contain what was rendered for this video
+  // stream on receiver side per each receiver.
+  absl::optional<VideoDumpOptions> output_dump_options;
+  // If set to true uses fixed frame rate while dumping output video to the
+  // file. Requested `VideoSubscription::fps()` will be used as frame rate.
+  bool output_dump_use_fixed_framerate = false;
+  // If true will display input and output video on the user's screen.
+  bool show_on_screen = false;
+  // If specified, determines a sync group to which this video stream belongs.
+  // According to bugs.webrtc.org/4762 WebRTC supports synchronization only
+  // for pair of single audio and single video stream.
+  absl::optional<std::string> sync_group;
+  // If specified, it will be set into RtpParameters of corresponding
+  // RtpSenderInterface for this video stream.
+  // Note that this setting takes precedence over `content_hint`.
+  absl::optional<DegradationPreference> degradation_preference;
+};
+
+// Contains properties for audio in the call.
+struct AudioConfig {
+  enum Mode {
+    kGenerated,
+    kFile,
+  };
+
+  AudioConfig() = default;
+  explicit AudioConfig(std::string stream_label);
+
+  // Have to be unique among all specified configs for all peers in the call.
+  // Will be auto generated if omitted.
+  absl::optional<std::string> stream_label;
+  Mode mode = kGenerated;
+  // Have to be specified only if mode = kFile
+  absl::optional<std::string> input_file_name;
+  // If specified the input stream will be also copied to specified file.
+  absl::optional<std::string> input_dump_file_name;
+  // If specified the output stream will be copied to specified file.
+  absl::optional<std::string> output_dump_file_name;
+
+  // Audio options to use.
+  cricket::AudioOptions audio_options;
+  // Sampling frequency of input audio data (from file or generated).
+  int sampling_frequency_in_hz = 48000;
+  // If specified, determines a sync group to which this audio stream belongs.
+  // According to bugs.webrtc.org/4762 WebRTC supports synchronization only
+  // for pair of single audio and single video stream.
+  absl::optional<std::string> sync_group;
+};
+
+struct VideoCodecConfig {
+  explicit VideoCodecConfig(std::string name);
+  VideoCodecConfig(std::string name,
+                   std::map<std::string, std::string> required_params);
+  // Next two fields are used to specify concrete video codec, that should be
+  // used in the test. Video code will be negotiated in SDP during offer/
+  // answer exchange.
+  // Video codec name. You can find valid names in
+  // media/base/media_constants.h
+  std::string name;
+  // Map of parameters, that have to be specified on SDP codec. Each parameter
+  // is described by key and value. Codec parameters will match the specified
+  // map if and only if for each key from `required_params` there will be
+  // a parameter with name equal to this key and parameter value will be equal
+  // to the value from `required_params` for this key.
+  // If empty then only name will be used to match the codec.
+  std::map<std::string, std::string> required_params;
+};
+
+// Subscription to the remote video streams. It declares which remote stream
+// peer should receive and in which resolution (width x height x fps).
+class VideoSubscription {
+ public:
+  // Returns the resolution constructed as maximum from all resolution
+  // dimensions: width, height and fps.
+  static absl::optional<VideoResolution> GetMaxResolution(
+      rtc::ArrayView<const VideoConfig> video_configs);
+  static absl::optional<VideoResolution> GetMaxResolution(
+      rtc::ArrayView<const VideoResolution> resolutions);
+
+  bool operator==(const VideoSubscription& other) const;
+  bool operator!=(const VideoSubscription& other) const;
+
+  // Subscribes receiver to all streams sent by the specified peer with
+  // specified resolution. It will override any resolution that was used in
+  // `SubscribeToAll` independently from methods call order.
+  VideoSubscription& SubscribeToPeer(
+      absl::string_view peer_name,
+      VideoResolution resolution =
+          VideoResolution(VideoResolution::Spec::kMaxFromSender));
+
+  // Subscribes receiver to the all sent streams with specified resolution.
+  // If any stream was subscribed to with `SubscribeTo` method that will
+  // override resolution passed to this function independently from methods
+  // call order.
+  VideoSubscription& SubscribeToAllPeers(
+      VideoResolution resolution =
+          VideoResolution(VideoResolution::Spec::kMaxFromSender));
+
+  // Returns resolution for specific sender. If no specific resolution was
+  // set for this sender, then will return resolution used for all streams.
+  // If subscription doesn't subscribe to all streams, `absl::nullopt` will be
+  // returned.
+  absl::optional<VideoResolution> GetResolutionForPeer(
+      absl::string_view peer_name) const;
+
+  // Returns a maybe empty list of senders for which peer explicitly
+  // subscribed to with specific resolution.
+  std::vector<std::string> GetSubscribedPeers() const;
+
+  std::string ToString() const;
+
+ private:
+  absl::optional<VideoResolution> default_resolution_ = absl::nullopt;
+  std::map<std::string, VideoResolution> peers_resolution_;
+};
+
+// Contains configuration for echo emulator.
+struct EchoEmulationConfig {
+  // Delay which represents the echo path delay, i.e. how soon rendered signal
+  // should reach capturer.
+  TimeDelta echo_delay = TimeDelta::Millis(50);
+};
+
+}  // namespace webrtc_pc_e2e
+}  // namespace webrtc
+
+#endif  // API_TEST_PCLF_MEDIA_CONFIGURATION_H_
diff --git a/api/test/pclf/media_quality_test_params.h b/api/test/pclf/media_quality_test_params.h
index 0f8bec1..65ca1c5 100644
--- a/api/test/pclf/media_quality_test_params.h
+++ b/api/test/pclf/media_quality_test_params.h
@@ -22,7 +22,7 @@
 #include "api/field_trials_view.h"
 #include "api/rtc_event_log/rtc_event_log_factory_interface.h"
 #include "api/task_queue/task_queue_factory.h"
-#include "api/test/peerconnection_quality_test_fixture.h"
+#include "api/test/pclf/media_configuration.h"
 #include "api/transport/network_control.h"
 #include "api/video_codecs/video_decoder_factory.h"
 #include "api/video_codecs/video_encoder_factory.h"
@@ -118,7 +118,7 @@
   // Peer name. If empty - default one will be set by the fixture.
   absl::optional<std::string> name;
   // If `audio_config` is set audio stream will be configured
-  absl::optional<PeerConnectionE2EQualityTestFixture::AudioConfig> audio_config;
+  absl::optional<AudioConfig> audio_config;
   // Flags to set on `cricket::PortAllocator`. These flags will be added
   // to the default ones that are presented on the port allocator.
   uint32_t port_allocator_extra_flags = cricket::kDefaultPortAllocatorFlags;
@@ -142,18 +142,38 @@
   PeerConnectionInterface::RTCConfiguration rtc_configuration;
   PeerConnectionInterface::RTCOfferAnswerOptions rtc_offer_answer_options;
   BitrateSettings bitrate_settings;
-  std::vector<PeerConnectionE2EQualityTestFixture::VideoCodecConfig>
-      video_codecs;
+  std::vector<VideoCodecConfig> video_codecs;
 };
 
 // Contains parameters that maybe changed by test writer during the test call.
 struct ConfigurableParams {
   // If `video_configs` is empty - no video should be added to the test call.
-  std::vector<PeerConnectionE2EQualityTestFixture::VideoConfig> video_configs;
+  std::vector<VideoConfig> video_configs;
 
-  PeerConnectionE2EQualityTestFixture::VideoSubscription video_subscription =
-      PeerConnectionE2EQualityTestFixture::VideoSubscription()
-          .SubscribeToAllPeers();
+  VideoSubscription video_subscription =
+      VideoSubscription().SubscribeToAllPeers();
+};
+
+// Contains parameters, that describe how long framework should run quality
+// test.
+struct RunParams {
+  explicit RunParams(TimeDelta run_duration) : run_duration(run_duration) {}
+
+  // Specifies how long the test should be run. This time shows how long
+  // the media should flow after connection was established and before
+  // it will be shut downed.
+  TimeDelta run_duration;
+
+  // If set to true peers will be able to use Flex FEC, otherwise they won't
+  // be able to negotiate it even if it's enabled on per peer level.
+  bool enable_flex_fec_support = false;
+  // If true will set conference mode in SDP media section for all video
+  // tracks for all peers.
+  bool use_conference_mode = false;
+  // If specified echo emulation will be done, by mixing the render audio into
+  // the capture signal. In such case input signal will be reduced by half to
+  // avoid saturation or compression in the echo path simulation.
+  absl::optional<EchoEmulationConfig> echo_emulation_config;
 };
 
 }  // namespace webrtc_pc_e2e
diff --git a/api/test/peerconnection_quality_test_fixture.cc b/api/test/peerconnection_quality_test_fixture.cc
deleted file mode 100644
index 89ac366..0000000
--- a/api/test/peerconnection_quality_test_fixture.cc
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- *  Copyright 2022 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 "api/test/peerconnection_quality_test_fixture.h"
-
-#include <string>
-
-#include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
-#include "api/array_view.h"
-#include "api/test/video/video_frame_writer.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/strings/string_builder.h"
-#include "test/pc/e2e/analyzer/video/video_dumping.h"
-#include "test/testsupport/file_utils.h"
-
-namespace webrtc {
-namespace webrtc_pc_e2e {
-namespace {
-
-using VideoCodecConfig = ::webrtc::webrtc_pc_e2e::
-    PeerConnectionE2EQualityTestFixture::VideoCodecConfig;
-using VideoSubscription = ::webrtc::webrtc_pc_e2e::
-    PeerConnectionE2EQualityTestFixture::VideoSubscription;
-using VideoResolution = ::webrtc::webrtc_pc_e2e::
-    PeerConnectionE2EQualityTestFixture::VideoResolution;
-
-std::string SpecToString(
-    PeerConnectionE2EQualityTestFixture::VideoResolution::VideoResolution::Spec
-        spec) {
-  switch (spec) {
-    case PeerConnectionE2EQualityTestFixture::VideoResolution::Spec::kNone:
-      return "None";
-    case PeerConnectionE2EQualityTestFixture::VideoResolution::Spec::
-        kMaxFromSender:
-      return "MaxFromSender";
-  }
-}
-
-void AppendResolution(const VideoResolution& resolution,
-                      rtc::StringBuilder& builder) {
-  builder << "_" << resolution.width() << "x" << resolution.height() << "_"
-          << resolution.fps();
-}
-
-}  // namespace
-
-PeerConnectionE2EQualityTestFixture::VideoResolution::VideoResolution(
-    size_t width,
-    size_t height,
-    int32_t fps)
-    : width_(width), height_(height), fps_(fps), spec_(Spec::kNone) {}
-PeerConnectionE2EQualityTestFixture::VideoResolution::VideoResolution(Spec spec)
-    : width_(0), height_(0), fps_(0), spec_(spec) {}
-
-bool PeerConnectionE2EQualityTestFixture::VideoResolution::operator==(
-    const VideoResolution& other) const {
-  if (spec_ != Spec::kNone && spec_ == other.spec_) {
-    // If there is some particular spec set, then it doesn't matter what
-    // values we have in other fields.
-    return true;
-  }
-  return width_ == other.width_ && height_ == other.height_ &&
-         fps_ == other.fps_ && spec_ == other.spec_;
-}
-
-std::string PeerConnectionE2EQualityTestFixture::VideoResolution::ToString()
-    const {
-  rtc::StringBuilder out;
-  out << "{ width=" << width_ << ", height=" << height_ << ", fps=" << fps_
-      << ", spec=" << SpecToString(spec_) << " }";
-  return out.Release();
-}
-
-bool PeerConnectionE2EQualityTestFixture::VideoSubscription::operator==(
-    const VideoSubscription& other) const {
-  return default_resolution_ == other.default_resolution_ &&
-         peers_resolution_ == other.peers_resolution_;
-}
-
-absl::optional<PeerConnectionE2EQualityTestFixture::VideoResolution>
-PeerConnectionE2EQualityTestFixture::VideoSubscription::GetMaxResolution(
-    rtc::ArrayView<const VideoConfig> video_configs) {
-  std::vector<VideoResolution> resolutions;
-  for (const auto& video_config : video_configs) {
-    resolutions.push_back(video_config.GetResolution());
-  }
-  return GetMaxResolution(resolutions);
-}
-
-absl::optional<PeerConnectionE2EQualityTestFixture::VideoResolution>
-PeerConnectionE2EQualityTestFixture::VideoSubscription::GetMaxResolution(
-    rtc::ArrayView<const VideoResolution> resolutions) {
-  if (resolutions.empty()) {
-    return absl::nullopt;
-  }
-
-  VideoResolution max_resolution;
-  for (const VideoResolution& resolution : resolutions) {
-    if (max_resolution.width() < resolution.width()) {
-      max_resolution.set_width(resolution.width());
-    }
-    if (max_resolution.height() < resolution.height()) {
-      max_resolution.set_height(resolution.height());
-    }
-    if (max_resolution.fps() < resolution.fps()) {
-      max_resolution.set_fps(resolution.fps());
-    }
-  }
-  return max_resolution;
-}
-
-std::string PeerConnectionE2EQualityTestFixture::VideoSubscription::ToString()
-    const {
-  rtc::StringBuilder out;
-  out << "{ default_resolution_=[";
-  if (default_resolution_.has_value()) {
-    out << default_resolution_->ToString();
-  } else {
-    out << "undefined";
-  }
-  out << "], {";
-  for (const auto& [peer_name, resolution] : peers_resolution_) {
-    out << "[" << peer_name << ": " << resolution.ToString() << "], ";
-  }
-  out << "} }";
-  return out.Release();
-}
-
-PeerConnectionE2EQualityTestFixture::VideoDumpOptions::VideoDumpOptions(
-    absl::string_view output_directory,
-    int sampling_modulo,
-    bool export_frame_ids,
-    std::function<std::unique_ptr<test::VideoFrameWriter>(
-        absl::string_view file_name_prefix,
-        const VideoResolution& resolution)> video_frame_writer_factory)
-    : output_directory_(output_directory),
-      sampling_modulo_(sampling_modulo),
-      export_frame_ids_(export_frame_ids),
-      video_frame_writer_factory_(video_frame_writer_factory) {
-  RTC_CHECK_GT(sampling_modulo, 0);
-}
-
-PeerConnectionE2EQualityTestFixture::VideoDumpOptions::VideoDumpOptions(
-    absl::string_view output_directory,
-    bool export_frame_ids)
-    : VideoDumpOptions(output_directory,
-                       kDefaultSamplingModulo,
-                       export_frame_ids) {}
-
-std::unique_ptr<test::VideoFrameWriter> PeerConnectionE2EQualityTestFixture::
-    VideoDumpOptions::CreateInputDumpVideoFrameWriter(
-        absl::string_view stream_label,
-        const VideoResolution& resolution) const {
-  std::unique_ptr<test::VideoFrameWriter> writer = video_frame_writer_factory_(
-      GetInputDumpFileName(stream_label, resolution), resolution);
-  absl::optional<std::string> frame_ids_file =
-      GetInputFrameIdsDumpFileName(stream_label, resolution);
-  if (frame_ids_file.has_value()) {
-    writer = CreateVideoFrameWithIdsWriter(std::move(writer), *frame_ids_file);
-  }
-  return writer;
-}
-
-std::unique_ptr<test::VideoFrameWriter> PeerConnectionE2EQualityTestFixture::
-    VideoDumpOptions::CreateOutputDumpVideoFrameWriter(
-        absl::string_view stream_label,
-        absl::string_view receiver,
-        const VideoResolution& resolution) const {
-  std::unique_ptr<test::VideoFrameWriter> writer = video_frame_writer_factory_(
-      GetOutputDumpFileName(stream_label, receiver, resolution), resolution);
-  absl::optional<std::string> frame_ids_file =
-      GetOutputFrameIdsDumpFileName(stream_label, receiver, resolution);
-  if (frame_ids_file.has_value()) {
-    writer = CreateVideoFrameWithIdsWriter(std::move(writer), *frame_ids_file);
-  }
-  return writer;
-}
-
-std::unique_ptr<test::VideoFrameWriter> PeerConnectionE2EQualityTestFixture::
-    VideoDumpOptions::Y4mVideoFrameWriterFactory(
-        absl::string_view file_name_prefix,
-        const VideoResolution& resolution) {
-  return std::make_unique<test::Y4mVideoFrameWriterImpl>(
-      std::string(file_name_prefix) + ".y4m", resolution.width(),
-      resolution.height(), resolution.fps());
-}
-
-std::string
-PeerConnectionE2EQualityTestFixture::VideoDumpOptions::GetInputDumpFileName(
-    absl::string_view stream_label,
-    const VideoResolution& resolution) const {
-  rtc::StringBuilder file_name;
-  file_name << stream_label;
-  AppendResolution(resolution, file_name);
-  return test::JoinFilename(output_directory_, file_name.Release());
-}
-
-absl::optional<std::string> PeerConnectionE2EQualityTestFixture::
-    VideoDumpOptions::GetInputFrameIdsDumpFileName(
-        absl::string_view stream_label,
-        const VideoResolution& resolution) const {
-  if (!export_frame_ids_) {
-    return absl::nullopt;
-  }
-  return GetInputDumpFileName(stream_label, resolution) + ".frame_ids.txt";
-}
-
-std::string
-PeerConnectionE2EQualityTestFixture::VideoDumpOptions::GetOutputDumpFileName(
-    absl::string_view stream_label,
-    absl::string_view receiver,
-    const VideoResolution& resolution) const {
-  rtc::StringBuilder file_name;
-  file_name << stream_label << "_" << receiver;
-  AppendResolution(resolution, file_name);
-  return test::JoinFilename(output_directory_, file_name.Release());
-}
-
-absl::optional<std::string> PeerConnectionE2EQualityTestFixture::
-    VideoDumpOptions::GetOutputFrameIdsDumpFileName(
-        absl::string_view stream_label,
-        absl::string_view receiver,
-        const VideoResolution& resolution) const {
-  if (!export_frame_ids_) {
-    return absl::nullopt;
-  }
-  return GetOutputDumpFileName(stream_label, receiver, resolution) +
-         ".frame_ids.txt";
-}
-
-std::string PeerConnectionE2EQualityTestFixture::VideoDumpOptions::ToString()
-    const {
-  rtc::StringBuilder out;
-  out << "{ output_directory_=" << output_directory_
-      << ", sampling_modulo_=" << sampling_modulo_
-      << ", export_frame_ids_=" << export_frame_ids_ << " }";
-  return out.Release();
-}
-
-PeerConnectionE2EQualityTestFixture::VideoConfig::VideoConfig(
-    const VideoResolution& resolution)
-    : width(resolution.width()),
-      height(resolution.height()),
-      fps(resolution.fps()) {
-  RTC_CHECK(resolution.IsRegular());
-}
-
-}  // namespace webrtc_pc_e2e
-}  // namespace webrtc
diff --git a/api/test/peerconnection_quality_test_fixture.h b/api/test/peerconnection_quality_test_fixture.h
index 21b21b4..167170c 100644
--- a/api/test/peerconnection_quality_test_fixture.h
+++ b/api/test/peerconnection_quality_test_fixture.h
@@ -10,6 +10,10 @@
 #ifndef API_TEST_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_
 #define API_TEST_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
+#include <functional>
 #include <map>
 #include <memory>
 #include <string>
@@ -32,6 +36,8 @@
 #include "api/task_queue/task_queue_factory.h"
 #include "api/test/audio_quality_analyzer_interface.h"
 #include "api/test/frame_generator_interface.h"
+#include "api/test/pclf/media_configuration.h"
+#include "api/test/pclf/media_quality_test_params.h"
 #include "api/test/peer_network_dependencies.h"
 #include "api/test/simulated_network.h"
 #include "api/test/stats_observer_interface.h"
@@ -45,6 +51,7 @@
 #include "api/video_codecs/video_encoder_factory.h"
 #include "media/base/media_constants.h"
 #include "modules/audio_processing/include/audio_processing.h"
+#include "rtc_base/checks.h"
 #include "rtc_base/network.h"
 #include "rtc_base/rtc_certificate_generator.h"
 #include "rtc_base/ssl_certificate.h"
@@ -59,471 +66,19 @@
 // API is in development. Can be changed/removed without notice.
 class PeerConnectionE2EQualityTestFixture {
  public:
-  // The index of required capturing device in OS provided list of video
-  // devices. On Linux and Windows the list will be obtained via
-  // webrtc::VideoCaptureModule::DeviceInfo, on Mac OS via
-  // [RTCCameraVideoCapturer captureDevices].
-  enum class CapturingDeviceIndex : size_t {};
-
-  // Contains parameters for screen share scrolling.
-  //
-  // If scrolling is enabled, then it will be done by putting sliding window
-  // on source video and moving this window from top left corner to the
-  // bottom right corner of the picture.
-  //
-  // In such case source dimensions must be greater or equal to the sliding
-  // window dimensions. So `source_width` and `source_height` are the dimensions
-  // of the source frame, while `VideoConfig::width` and `VideoConfig::height`
-  // are the dimensions of the sliding window.
-  //
-  // Because `source_width` and `source_height` are dimensions of the source
-  // frame, they have to be width and height of videos from
-  // `ScreenShareConfig::slides_yuv_file_names`.
-  //
-  // Because scrolling have to be done on single slide it also requires, that
-  // `duration` must be less or equal to
-  // `ScreenShareConfig::slide_change_interval`.
-  struct ScrollingParams {
-    ScrollingParams(TimeDelta duration,
-                    size_t source_width,
-                    size_t source_height)
-        : duration(duration),
-          source_width(source_width),
-          source_height(source_height) {
-      RTC_CHECK_GT(duration.ms(), 0);
-    }
-
-    // Duration of scrolling.
-    TimeDelta duration;
-    // Width of source slides video.
-    size_t source_width;
-    // Height of source slides video.
-    size_t source_height;
-  };
-
-  // Contains screen share video stream properties.
-  struct ScreenShareConfig {
-    explicit ScreenShareConfig(TimeDelta slide_change_interval)
-        : slide_change_interval(slide_change_interval) {
-      RTC_CHECK_GT(slide_change_interval.ms(), 0);
-    }
-
-    // Shows how long one slide should be presented on the screen during
-    // slide generation.
-    TimeDelta slide_change_interval;
-    // If true, slides will be generated programmatically. No scrolling params
-    // will be applied in such case.
-    bool generate_slides = false;
-    // If present scrolling will be applied. Please read extra requirement on
-    // `slides_yuv_file_names` for scrolling.
-    absl::optional<ScrollingParams> scrolling_params;
-    // Contains list of yuv files with slides.
-    //
-    // If empty, default set of slides will be used. In such case
-    // `VideoConfig::width` must be equal to `kDefaultSlidesWidth` and
-    // `VideoConfig::height` must be equal to `kDefaultSlidesHeight` or if
-    // `scrolling_params` are specified, then `ScrollingParams::source_width`
-    // must be equal to `kDefaultSlidesWidth` and
-    // `ScrollingParams::source_height` must be equal to `kDefaultSlidesHeight`.
-    std::vector<std::string> slides_yuv_file_names;
-  };
-
-  // Config for Vp8 simulcast or non-standard Vp9 SVC testing.
-  //
-  // To configure standard SVC setting, use `scalability_mode` in the
-  // `encoding_params` array.
-  // This configures Vp9 SVC by requesting simulcast layers, the request is
-  // internally converted to a request for SVC layers.
-  //
-  // SVC support is limited:
-  // During SVC testing there is no SFU, so framework will try to emulate SFU
-  // behavior in regular p2p call. Because of it there are such limitations:
-  //  * if `target_spatial_index` is not equal to the highest spatial layer
-  //    then no packet/frame drops are allowed.
-  //
-  //    If there will be any drops, that will affect requested layer, then
-  //    WebRTC SVC implementation will continue decoding only the highest
-  //    available layer and won't restore lower layers, so analyzer won't
-  //    receive required data which will cause wrong results or test failures.
-  struct VideoSimulcastConfig {
-    explicit VideoSimulcastConfig(int simulcast_streams_count)
-        : simulcast_streams_count(simulcast_streams_count) {
-      RTC_CHECK_GT(simulcast_streams_count, 1);
-    }
-
-    // Specified amount of simulcast streams/SVC layers, depending on which
-    // encoder is used.
-    int simulcast_streams_count;
-  };
-
-  // Configuration for the emulated Selective Forward Unit (SFU)
-  //
-  // The framework can optionally filter out frames that are decoded
-  // using an emulated SFU.
-  // When using simulcast or SVC, it's not always desirable to receive
-  // all frames. In a real world call, a SFU will only forward a subset
-  // of the frames.
-  // The emulated SFU is not able to change its configuration dynamically,
-  // if adaptation happens during the call, layers may be dropped and the
-  // analyzer won't receive the required data which will cause wrong results or
-  // test failures.
-  struct EmulatedSFUConfig {
-    EmulatedSFUConfig() {}
-    explicit EmulatedSFUConfig(int target_layer_index)
-        : target_layer_index(target_layer_index) {
-      RTC_CHECK_GE(target_layer_index, 0);
-    }
-
-    EmulatedSFUConfig(absl::optional<int> target_layer_index,
-                      absl::optional<int> target_temporal_index)
-        : target_layer_index(target_layer_index),
-          target_temporal_index(target_temporal_index) {
-      RTC_CHECK_GE(target_temporal_index.value_or(0), 0);
-      if (target_temporal_index)
-        RTC_CHECK_GE(*target_temporal_index, 0);
-    }
-
-    // Specifies simulcast or spatial index of the video stream to analyze.
-    // There are 2 cases:
-    // 1. simulcast encoding is used:
-    //    in such case `target_layer_index` will specify the index of
-    //    simulcast stream, that should be analyzed. Other streams will be
-    //    dropped.
-    // 2. SVC encoding is used:
-    //    in such case `target_layer_index` will specify the top interesting
-    //    spatial layer and all layers below, including target one will be
-    //    processed. All layers above target one will be dropped.
-    // If not specified then all streams will be received and analyzed.
-    // When set, it instructs the framework to create an emulated Selective
-    // Forwarding Unit (SFU) that will propagate only the requested layers.
-    absl::optional<int> target_layer_index;
-    // Specifies the index of the maximum temporal unit to keep.
-    // If not specified then all temporal layers will be received and analyzed.
-    // When set, it instructs the framework to create an emulated Selective
-    // Forwarding Unit (SFU) that will propagate only up to the requested layer.
-    absl::optional<int> target_temporal_index;
-  };
-
-  class VideoResolution {
-   public:
-    // Determines special resolutions, which can't be expressed in terms of
-    // width, height and fps.
-    enum class Spec {
-      // No extra spec set. It describes a regular resolution described by
-      // width, height and fps.
-      kNone,
-      // Describes resolution which contains max value among all sender's
-      // video streams in each dimension (width, height, fps).
-      kMaxFromSender
-    };
-
-    VideoResolution(size_t width, size_t height, int32_t fps);
-    explicit VideoResolution(Spec spec = Spec::kNone);
-
-    bool operator==(const VideoResolution& other) const;
-    bool operator!=(const VideoResolution& other) const {
-      return !(*this == other);
-    }
-
-    size_t width() const { return width_; }
-    void set_width(size_t width) { width_ = width; }
-    size_t height() const { return height_; }
-    void set_height(size_t height) { height_ = height; }
-    int32_t fps() const { return fps_; }
-    void set_fps(int32_t fps) { fps_ = fps; }
-
-    // Returns if it is a regular resolution or not. The resolution is regular
-    // if it's spec is `Spec::kNone`.
-    bool IsRegular() const { return spec_ == Spec::kNone; }
-
-    std::string ToString() const;
-
-   private:
-    size_t width_ = 0;
-    size_t height_ = 0;
-    int32_t fps_ = 0;
-    Spec spec_ = Spec::kNone;
-  };
-
-  class VideoDumpOptions {
-   public:
-    static constexpr int kDefaultSamplingModulo = 1;
-
-    // output_directory - the output directory where stream will be dumped. The
-    // output files' names will be constructed as
-    // <stream_name>_<receiver_name>_<resolution>.<extension> for output dumps
-    // and <stream_name>_<resolution>.<extension> for input dumps.
-    // By default <extension> is "y4m". Resolution is in the format
-    // <width>x<height>_<fps>.
-    // sampling_modulo - the module for the video frames to be dumped. Modulo
-    // equals X means every Xth frame will be written to the dump file. The
-    // value must be greater than 0. (Default: 1)
-    // export_frame_ids - specifies if frame ids should be exported together
-    // with content of the stream. If true, an output file with the same name as
-    // video dump and suffix ".frame_ids.txt" will be created. It will contain
-    // the frame ids in the same order as original frames in the output
-    // file with stream content. File will contain one frame id per line.
-    // (Default: false)
-    // `video_frame_writer_factory` - factory function to create a video frame
-    // writer for input and output video files. (Default: Y4M video writer
-    // factory).
-    explicit VideoDumpOptions(
-        absl::string_view output_directory,
-        int sampling_modulo = kDefaultSamplingModulo,
-        bool export_frame_ids = false,
-        std::function<std::unique_ptr<test::VideoFrameWriter>(
-            absl::string_view file_name_prefix,
-            const VideoResolution& resolution)> video_frame_writer_factory =
-            Y4mVideoFrameWriterFactory);
-    VideoDumpOptions(absl::string_view output_directory, bool export_frame_ids);
-
-    VideoDumpOptions(const VideoDumpOptions&) = default;
-    VideoDumpOptions& operator=(const VideoDumpOptions&) = default;
-    VideoDumpOptions(VideoDumpOptions&&) = default;
-    VideoDumpOptions& operator=(VideoDumpOptions&&) = default;
-
-    std::string output_directory() const { return output_directory_; }
-    int sampling_modulo() const { return sampling_modulo_; }
-    bool export_frame_ids() const { return export_frame_ids_; }
-
-    std::unique_ptr<test::VideoFrameWriter> CreateInputDumpVideoFrameWriter(
-        absl::string_view stream_label,
-        const VideoResolution& resolution) const;
-
-    std::unique_ptr<test::VideoFrameWriter> CreateOutputDumpVideoFrameWriter(
-        absl::string_view stream_label,
-        absl::string_view receiver,
-        const VideoResolution& resolution) const;
-
-    std::string ToString() const;
-
-   private:
-    static std::unique_ptr<test::VideoFrameWriter> Y4mVideoFrameWriterFactory(
-        absl::string_view file_name_prefix,
-        const VideoResolution& resolution);
-    std::string GetInputDumpFileName(absl::string_view stream_label,
-                                     const VideoResolution& resolution) const;
-    // Returns file name for input frame ids dump if `export_frame_ids()` is
-    // true, absl::nullopt otherwise.
-    absl::optional<std::string> GetInputFrameIdsDumpFileName(
-        absl::string_view stream_label,
-        const VideoResolution& resolution) const;
-    std::string GetOutputDumpFileName(absl::string_view stream_label,
-                                      absl::string_view receiver,
-                                      const VideoResolution& resolution) const;
-    // Returns file name for output frame ids dump if `export_frame_ids()` is
-    // true, absl::nullopt otherwise.
-    absl::optional<std::string> GetOutputFrameIdsDumpFileName(
-        absl::string_view stream_label,
-        absl::string_view receiver,
-        const VideoResolution& resolution) const;
-
-    std::string output_directory_;
-    int sampling_modulo_ = 1;
-    bool export_frame_ids_ = false;
-    std::function<std::unique_ptr<test::VideoFrameWriter>(
-        absl::string_view file_name_prefix,
-        const VideoResolution& resolution)>
-        video_frame_writer_factory_;
-  };
-
-  // Contains properties of single video stream.
-  struct VideoConfig {
-    explicit VideoConfig(const VideoResolution& resolution);
-    VideoConfig(size_t width, size_t height, int32_t fps)
-        : width(width), height(height), fps(fps) {}
-    VideoConfig(std::string stream_label,
-                size_t width,
-                size_t height,
-                int32_t fps)
-        : width(width),
-          height(height),
-          fps(fps),
-          stream_label(std::move(stream_label)) {}
-
-    // Video stream width.
-    size_t width;
-    // Video stream height.
-    size_t height;
-    int32_t fps;
-    VideoResolution GetResolution() const {
-      return VideoResolution(width, height, fps);
-    }
-
-    // Have to be unique among all specified configs for all peers in the call.
-    // Will be auto generated if omitted.
-    absl::optional<std::string> stream_label;
-    // Will be set for current video track. If equals to kText or kDetailed -
-    // screencast in on.
-    absl::optional<VideoTrackInterface::ContentHint> content_hint;
-    // If presented video will be transfered in simulcast/SVC mode depending on
-    // which encoder is used.
-    //
-    // Simulcast is supported only from 1st added peer. For VP8 simulcast only
-    // without RTX is supported so it will be automatically disabled for all
-    // simulcast tracks. For VP9 simulcast enables VP9 SVC mode and support RTX,
-    // but only on non-lossy networks. See more in documentation to
-    // VideoSimulcastConfig.
-    absl::optional<VideoSimulcastConfig> simulcast_config;
-    // Configuration for the emulated Selective Forward Unit (SFU).
-    absl::optional<EmulatedSFUConfig> emulated_sfu_config;
-    // Encoding parameters for both singlecast and per simulcast layer.
-    // If singlecast is used, if not empty, a single value can be provided.
-    // If simulcast is used, if not empty, `encoding_params` size have to be
-    // equal to `simulcast_config.simulcast_streams_count`. Will be used to set
-    // transceiver send encoding params for each layer.
-    // RtpEncodingParameters::rid may be changed by fixture implementation to
-    // ensure signaling correctness.
-    std::vector<RtpEncodingParameters> encoding_params;
-    // Count of temporal layers for video stream. This value will be set into
-    // each RtpEncodingParameters of RtpParameters of corresponding
-    // RtpSenderInterface for this video stream.
-    absl::optional<int> temporal_layers_count;
-    // If specified defines how input should be dumped. It is actually one of
-    // the test's output file, which contains copy of what was captured during
-    // the test for this video stream on sender side. It is useful when
-    // generator is used as input.
-    absl::optional<VideoDumpOptions> input_dump_options;
-    // If specified defines how output should be dumped on the receiver side for
-    // this stream. The produced files contain what was rendered for this video
-    // stream on receiver side per each receiver.
-    absl::optional<VideoDumpOptions> output_dump_options;
-    // If set to true uses fixed frame rate while dumping output video to the
-    // file. Requested `VideoSubscription::fps()` will be used as frame rate.
-    bool output_dump_use_fixed_framerate = false;
-    // If true will display input and output video on the user's screen.
-    bool show_on_screen = false;
-    // If specified, determines a sync group to which this video stream belongs.
-    // According to bugs.webrtc.org/4762 WebRTC supports synchronization only
-    // for pair of single audio and single video stream.
-    absl::optional<std::string> sync_group;
-    // If specified, it will be set into RtpParameters of corresponding
-    // RtpSenderInterface for this video stream.
-    // Note that this setting takes precedence over `content_hint`.
-    absl::optional<DegradationPreference> degradation_preference;
-  };
-
-  // Contains properties for audio in the call.
-  struct AudioConfig {
-    enum Mode {
-      kGenerated,
-      kFile,
-    };
-
-    AudioConfig() = default;
-    explicit AudioConfig(std::string stream_label)
-        : stream_label(std::move(stream_label)) {}
-
-    // Have to be unique among all specified configs for all peers in the call.
-    // Will be auto generated if omitted.
-    absl::optional<std::string> stream_label;
-    Mode mode = kGenerated;
-    // Have to be specified only if mode = kFile
-    absl::optional<std::string> input_file_name;
-    // If specified the input stream will be also copied to specified file.
-    absl::optional<std::string> input_dump_file_name;
-    // If specified the output stream will be copied to specified file.
-    absl::optional<std::string> output_dump_file_name;
-
-    // Audio options to use.
-    cricket::AudioOptions audio_options;
-    // Sampling frequency of input audio data (from file or generated).
-    int sampling_frequency_in_hz = 48000;
-    // If specified, determines a sync group to which this audio stream belongs.
-    // According to bugs.webrtc.org/4762 WebRTC supports synchronization only
-    // for pair of single audio and single video stream.
-    absl::optional<std::string> sync_group;
-  };
-
-  struct VideoCodecConfig {
-    explicit VideoCodecConfig(std::string name)
-        : name(std::move(name)), required_params() {}
-    VideoCodecConfig(std::string name,
-                     std::map<std::string, std::string> required_params)
-        : name(std::move(name)), required_params(std::move(required_params)) {}
-    // Next two fields are used to specify concrete video codec, that should be
-    // used in the test. Video code will be negotiated in SDP during offer/
-    // answer exchange.
-    // Video codec name. You can find valid names in
-    // media/base/media_constants.h
-    std::string name = cricket::kVp8CodecName;
-    // Map of parameters, that have to be specified on SDP codec. Each parameter
-    // is described by key and value. Codec parameters will match the specified
-    // map if and only if for each key from `required_params` there will be
-    // a parameter with name equal to this key and parameter value will be equal
-    // to the value from `required_params` for this key.
-    // If empty then only name will be used to match the codec.
-    std::map<std::string, std::string> required_params;
-  };
-
-  // Subscription to the remote video streams. It declares which remote stream
-  // peer should receive and in which resolution (width x height x fps).
-  class VideoSubscription {
-   public:
-    // Returns the resolution constructed as maximum from all resolution
-    // dimensions: width, height and fps.
-    static absl::optional<VideoResolution> GetMaxResolution(
-        rtc::ArrayView<const VideoConfig> video_configs);
-    static absl::optional<VideoResolution> GetMaxResolution(
-        rtc::ArrayView<const VideoResolution> resolutions);
-
-    bool operator==(const VideoSubscription& other) const;
-    bool operator!=(const VideoSubscription& other) const {
-      return !(*this == other);
-    }
-
-    // Subscribes receiver to all streams sent by the specified peer with
-    // specified resolution. It will override any resolution that was used in
-    // `SubscribeToAll` independently from methods call order.
-    VideoSubscription& SubscribeToPeer(
-        absl::string_view peer_name,
-        VideoResolution resolution =
-            VideoResolution(VideoResolution::Spec::kMaxFromSender)) {
-      peers_resolution_[std::string(peer_name)] = resolution;
-      return *this;
-    }
-
-    // Subscribes receiver to the all sent streams with specified resolution.
-    // If any stream was subscribed to with `SubscribeTo` method that will
-    // override resolution passed to this function independently from methods
-    // call order.
-    VideoSubscription& SubscribeToAllPeers(
-        VideoResolution resolution =
-            VideoResolution(VideoResolution::Spec::kMaxFromSender)) {
-      default_resolution_ = resolution;
-      return *this;
-    }
-
-    // Returns resolution for specific sender. If no specific resolution was
-    // set for this sender, then will return resolution used for all streams.
-    // If subscription doesn't subscribe to all streams, `absl::nullopt` will be
-    // returned.
-    absl::optional<VideoResolution> GetResolutionForPeer(
-        absl::string_view peer_name) const {
-      auto it = peers_resolution_.find(std::string(peer_name));
-      if (it == peers_resolution_.end()) {
-        return default_resolution_;
-      }
-      return it->second;
-    }
-
-    // Returns a maybe empty list of senders for which peer explicitly
-    // subscribed to with specific resolution.
-    std::vector<std::string> GetSubscribedPeers() const {
-      std::vector<std::string> subscribed_streams;
-      subscribed_streams.reserve(peers_resolution_.size());
-      for (const auto& entry : peers_resolution_) {
-        subscribed_streams.push_back(entry.first);
-      }
-      return subscribed_streams;
-    }
-
-    std::string ToString() const;
-
-   private:
-    absl::optional<VideoResolution> default_resolution_ = absl::nullopt;
-    std::map<std::string, VideoResolution> peers_resolution_;
-  };
+  using CapturingDeviceIndex = ::webrtc::webrtc_pc_e2e::CapturingDeviceIndex;
+  using ScrollingParams = ::webrtc::webrtc_pc_e2e::ScrollingParams;
+  using ScreenShareConfig = ::webrtc::webrtc_pc_e2e::ScreenShareConfig;
+  using VideoSimulcastConfig = ::webrtc::webrtc_pc_e2e::VideoSimulcastConfig;
+  using EmulatedSFUConfig = ::webrtc::webrtc_pc_e2e::EmulatedSFUConfig;
+  using VideoResolution = ::webrtc::webrtc_pc_e2e::VideoResolution;
+  using VideoDumpOptions = ::webrtc::webrtc_pc_e2e::VideoDumpOptions;
+  using VideoConfig = ::webrtc::webrtc_pc_e2e::VideoConfig;
+  using AudioConfig = ::webrtc::webrtc_pc_e2e::AudioConfig;
+  using VideoCodecConfig = ::webrtc::webrtc_pc_e2e::VideoCodecConfig;
+  using VideoSubscription = ::webrtc::webrtc_pc_e2e::VideoSubscription;
+  using EchoEmulationConfig = ::webrtc::webrtc_pc_e2e::EchoEmulationConfig;
+  using RunParams = ::webrtc::webrtc_pc_e2e::RunParams;
 
   // This class is used to fully configure one peer inside the call.
   class PeerConfigurer {
@@ -646,35 +201,6 @@
         BitrateSettings bitrate_settings) = 0;
   };
 
-  // Contains configuration for echo emulator.
-  struct EchoEmulationConfig {
-    // Delay which represents the echo path delay, i.e. how soon rendered signal
-    // should reach capturer.
-    TimeDelta echo_delay = TimeDelta::Millis(50);
-  };
-
-  // Contains parameters, that describe how long framework should run quality
-  // test.
-  struct RunParams {
-    explicit RunParams(TimeDelta run_duration) : run_duration(run_duration) {}
-
-    // Specifies how long the test should be run. This time shows how long
-    // the media should flow after connection was established and before
-    // it will be shut downed.
-    TimeDelta run_duration;
-
-    // If set to true peers will be able to use Flex FEC, otherwise they won't
-    // be able to negotiate it even if it's enabled on per peer level.
-    bool enable_flex_fec_support = false;
-    // If true will set conference mode in SDP media section for all video
-    // tracks for all peers.
-    bool use_conference_mode = false;
-    // If specified echo emulation will be done, by mixing the render audio into
-    // the capture signal. In such case input signal will be reduced by half to
-    // avoid saturation or compression in the echo path simulation.
-    absl::optional<EchoEmulationConfig> echo_emulation_config;
-  };
-
   // Represent an entity that will report quality metrics after test.
   class QualityMetricsReporter : public StatsObserverInterface {
    public:
diff --git a/api/test/peerconnection_quality_test_fixture_unittest.cc b/api/test/peerconnection_quality_test_fixture_unittest.cc
index 8da480b8..26ae8cf 100644
--- a/api/test/peerconnection_quality_test_fixture_unittest.cc
+++ b/api/test/peerconnection_quality_test_fixture_unittest.cc
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "absl/types/optional.h"
+#include "api/test/pclf/media_configuration.h"
 #include "api/test/video/video_frame_writer.h"
 #include "rtc_base/gunit.h"
 #include "test/gmock.h"
@@ -24,15 +25,6 @@
 
 using ::testing::Eq;
 
-using VideoResolution = ::webrtc::webrtc_pc_e2e::
-    PeerConnectionE2EQualityTestFixture::VideoResolution;
-using VideoConfig =
-    ::webrtc::webrtc_pc_e2e::PeerConnectionE2EQualityTestFixture::VideoConfig;
-using VideoSubscription = ::webrtc::webrtc_pc_e2e::
-    PeerConnectionE2EQualityTestFixture::VideoSubscription;
-using VideoDumpOptions = ::webrtc::webrtc_pc_e2e::
-    PeerConnectionE2EQualityTestFixture::VideoDumpOptions;
-
 TEST(PclfVideoSubscriptionTest,
      MaxFromSenderSpecEqualIndependentOfOtherFields) {
   VideoResolution r1(VideoResolution::Spec::kMaxFromSender);