/*
 *  Copyright (c) 2015 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 "video/video_quality_test.h"

#include <stdio.h>
#include <algorithm>
#include <deque>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include "logging/rtc_event_log/output/rtc_event_log_output_file.h"
#include "media/engine/internalencoderfactory.h"
#include "media/engine/vp8_encoder_simulcast_proxy.h"
#include "media/engine/webrtcvideoengine.h"
#include "modules/audio_mixer/audio_mixer_impl.h"
#include "modules/video_coding/codecs/h264/include/h264.h"
#include "modules/video_coding/codecs/multiplex/include/multiplex_encoder_adapter.h"
#include "modules/video_coding/codecs/vp8/include/vp8.h"
#include "modules/video_coding/codecs/vp9/include/vp9.h"
#include "test/run_loop.h"
#include "test/testsupport/fileutils.h"
#include "test/video_renderer.h"
#include "video/video_analyzer.h"

namespace {
constexpr char kSyncGroup[] = "av_sync";
constexpr int kOpusMinBitrateBps = 6000;
constexpr int kOpusBitrateFbBps = 32000;
constexpr int kFramesSentInQuickTest = 1;
constexpr uint32_t kThumbnailSendSsrcStart = 0xE0000;
constexpr uint32_t kThumbnailRtxSsrcStart = 0xF0000;

constexpr int kDefaultMaxQp = cricket::WebRtcVideoChannel::kDefaultQpMax;

class VideoStreamFactory
    : public webrtc::VideoEncoderConfig::VideoStreamFactoryInterface {
 public:
  explicit VideoStreamFactory(const std::vector<webrtc::VideoStream>& streams)
      : streams_(streams) {}

 private:
  std::vector<webrtc::VideoStream> CreateEncoderStreams(
      int width,
      int height,
      const webrtc::VideoEncoderConfig& encoder_config) override {
    // The highest layer must match the incoming resolution.
    std::vector<webrtc::VideoStream> streams = streams_;
    streams[streams_.size() - 1].height = height;
    streams[streams_.size() - 1].width = width;

    streams[0].bitrate_priority = encoder_config.bitrate_priority;
    return streams;
  }

  std::vector<webrtc::VideoStream> streams_;
};
}  // namespace

namespace webrtc {

// Not used by these tests.
std::vector<SdpVideoFormat>
VideoQualityTest::TestVideoEncoderFactory::GetSupportedFormats() const {
  RTC_NOTREACHED();
  return {};
}

VideoEncoderFactory::CodecInfo
VideoQualityTest::TestVideoEncoderFactory::QueryVideoEncoder(
    const SdpVideoFormat& format) const {
  CodecInfo codec_info;
  codec_info.is_hardware_accelerated = false;
  codec_info.has_internal_source = false;
  return codec_info;
}

std::unique_ptr<VideoEncoder>
VideoQualityTest::TestVideoEncoderFactory::CreateVideoEncoder(
    const SdpVideoFormat& format) {
  if (format.name == "VP8") {
    return absl::make_unique<VP8EncoderSimulcastProxy>(
        &internal_encoder_factory_, format);
  } else if (format.name == "multiplex") {
    return absl::make_unique<MultiplexEncoderAdapter>(
        &internal_encoder_factory_, SdpVideoFormat(cricket::kVp9CodecName));
  } else {
    return internal_encoder_factory_.CreateVideoEncoder(format);
  }
}

VideoQualityTest::VideoQualityTest(
    std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory)
    : clock_(Clock::GetRealTimeClock()), receive_logs_(0), send_logs_(0) {
  payload_type_map_ = test::CallTest::payload_type_map_;
  RTC_DCHECK(payload_type_map_.find(kPayloadTypeH264) ==
             payload_type_map_.end());
  RTC_DCHECK(payload_type_map_.find(kPayloadTypeVP8) ==
             payload_type_map_.end());
  RTC_DCHECK(payload_type_map_.find(kPayloadTypeVP9) ==
             payload_type_map_.end());
  payload_type_map_[kPayloadTypeH264] = webrtc::MediaType::VIDEO;
  payload_type_map_[kPayloadTypeVP8] = webrtc::MediaType::VIDEO;
  payload_type_map_[kPayloadTypeVP9] = webrtc::MediaType::VIDEO;

  fec_controller_factory_ = std::move(fec_controller_factory);
}

VideoQualityTest::Params::Params()
    : call({false, BitrateConstraints(), 0}),
      video{{false, 640, 480, 30, 50, 800, 800, false, "VP8", 1, -1, 0, false,
             false, false, ""},
            {false, 640, 480, 30, 50, 800, 800, false, "VP8", 1, -1, 0, false,
             false, false, ""}},
      audio({false, false, false}),
      screenshare{{false, false, 10, 0}, {false, false, 10, 0}},
      analyzer({"", 0.0, 0.0, 0, "", ""}),
      pipe(),
      ss{{std::vector<VideoStream>(), 0, 0, -1, InterLayerPredMode::kOn,
          std::vector<SpatialLayer>()},
         {std::vector<VideoStream>(), 0, 0, -1, InterLayerPredMode::kOn,
          std::vector<SpatialLayer>()}},
      logging({false, "", "", ""}) {}

VideoQualityTest::Params::~Params() = default;

void VideoQualityTest::TestBody() {}

std::string VideoQualityTest::GenerateGraphTitle() const {
  std::stringstream ss;
  ss << params_.video[0].codec;
  ss << " (" << params_.video[0].target_bitrate_bps / 1000 << "kbps";
  ss << ", " << params_.video[0].fps << " FPS";
  if (params_.screenshare[0].scroll_duration)
    ss << ", " << params_.screenshare[0].scroll_duration << "s scroll";
  if (params_.ss[0].streams.size() > 1)
    ss << ", Stream #" << params_.ss[0].selected_stream;
  if (params_.ss[0].num_spatial_layers > 1)
    ss << ", Layer #" << params_.ss[0].selected_sl;
  ss << ")";
  return ss.str();
}

void VideoQualityTest::CheckParams() {
  for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
    // Iterate over primary and secondary video streams.
    if (!params_.video[video_idx].enabled)
      return;
    // Add a default stream in none specified.
    if (params_.ss[video_idx].streams.empty())
      params_.ss[video_idx].streams.push_back(
          VideoQualityTest::DefaultVideoStream(params_, video_idx));
    if (params_.ss[video_idx].num_spatial_layers == 0)
      params_.ss[video_idx].num_spatial_layers = 1;

    if (params_.pipe.loss_percent != 0 ||
        params_.pipe.queue_length_packets != 0) {
      // Since LayerFilteringTransport changes the sequence numbers, we can't
      // use that feature with pack loss, since the NACK request would end up
      // retransmitting the wrong packets.
      RTC_CHECK(params_.ss[video_idx].selected_sl == -1 ||
                params_.ss[video_idx].selected_sl ==
                    params_.ss[video_idx].num_spatial_layers - 1);
      RTC_CHECK(params_.video[video_idx].selected_tl == -1 ||
                params_.video[video_idx].selected_tl ==
                    params_.video[video_idx].num_temporal_layers - 1);
    }

    // TODO(ivica): Should max_bitrate_bps == -1 represent inf max bitrate, as
    // it does in some parts of the code?
    RTC_CHECK_GE(params_.video[video_idx].max_bitrate_bps,
                 params_.video[video_idx].target_bitrate_bps);
    RTC_CHECK_GE(params_.video[video_idx].target_bitrate_bps,
                 params_.video[video_idx].min_bitrate_bps);
    RTC_CHECK_LT(params_.video[video_idx].selected_tl,
                 params_.video[video_idx].num_temporal_layers);
    RTC_CHECK_LE(params_.ss[video_idx].selected_stream,
                 params_.ss[video_idx].streams.size());
    for (const VideoStream& stream : params_.ss[video_idx].streams) {
      RTC_CHECK_GE(stream.min_bitrate_bps, 0);
      RTC_CHECK_GE(stream.target_bitrate_bps, stream.min_bitrate_bps);
      RTC_CHECK_GE(stream.max_bitrate_bps, stream.target_bitrate_bps);
    }
    // TODO(ivica): Should we check if the sum of all streams/layers is equal to
    // the total bitrate? We anyway have to update them in the case bitrate
    // estimator changes the total bitrates.
    RTC_CHECK_GE(params_.ss[video_idx].num_spatial_layers, 1);
    RTC_CHECK_LE(params_.ss[video_idx].selected_sl,
                 params_.ss[video_idx].num_spatial_layers);
    RTC_CHECK(
        params_.ss[video_idx].spatial_layers.empty() ||
        params_.ss[video_idx].spatial_layers.size() ==
            static_cast<size_t>(params_.ss[video_idx].num_spatial_layers));
    if (params_.video[video_idx].codec == "VP8") {
      RTC_CHECK_EQ(params_.ss[video_idx].num_spatial_layers, 1);
    } else if (params_.video[video_idx].codec == "VP9") {
      RTC_CHECK_EQ(params_.ss[video_idx].streams.size(), 1);
    }
    RTC_CHECK_GE(params_.call.num_thumbnails, 0);
    if (params_.call.num_thumbnails > 0) {
      RTC_CHECK_EQ(params_.ss[video_idx].num_spatial_layers, 1);
      RTC_CHECK_EQ(params_.ss[video_idx].streams.size(), 3);
      RTC_CHECK_EQ(params_.video[video_idx].num_temporal_layers, 3);
      RTC_CHECK_EQ(params_.video[video_idx].codec, "VP8");
    }
    // Dual streams with FEC not supported in tests yet.
    RTC_CHECK(!params_.video[video_idx].flexfec || num_video_streams_ == 1);
    RTC_CHECK(!params_.video[video_idx].ulpfec || num_video_streams_ == 1);
  }
}

// Static.
std::vector<int> VideoQualityTest::ParseCSV(const std::string& str) {
  // Parse comma separated nonnegative integers, where some elements may be
  // empty. The empty values are replaced with -1.
  // E.g. "10,-20,,30,40" --> {10, 20, -1, 30,40}
  // E.g. ",,10,,20," --> {-1, -1, 10, -1, 20, -1}
  std::vector<int> result;
  if (str.empty())
    return result;

  const char* p = str.c_str();
  int value = -1;
  int pos;
  while (*p) {
    if (*p == ',') {
      result.push_back(value);
      value = -1;
      ++p;
      continue;
    }
    RTC_CHECK_EQ(sscanf(p, "%d%n", &value, &pos), 1)
        << "Unexpected non-number value.";
    p += pos;
  }
  result.push_back(value);
  return result;
}

// Static.
VideoStream VideoQualityTest::DefaultVideoStream(const Params& params,
                                                 size_t video_idx) {
  VideoStream stream;
  stream.width = params.video[video_idx].width;
  stream.height = params.video[video_idx].height;
  stream.max_framerate = params.video[video_idx].fps;
  stream.min_bitrate_bps = params.video[video_idx].min_bitrate_bps;
  stream.target_bitrate_bps = params.video[video_idx].target_bitrate_bps;
  stream.max_bitrate_bps = params.video[video_idx].max_bitrate_bps;
  stream.max_qp = kDefaultMaxQp;
  stream.num_temporal_layers = params.video[video_idx].num_temporal_layers;
  stream.active = true;
  return stream;
}

// Static.
VideoStream VideoQualityTest::DefaultThumbnailStream() {
  VideoStream stream;
  stream.width = 320;
  stream.height = 180;
  stream.max_framerate = 7;
  stream.min_bitrate_bps = 7500;
  stream.target_bitrate_bps = 37500;
  stream.max_bitrate_bps = 50000;
  stream.max_qp = kDefaultMaxQp;
  return stream;
}

// Static.
void VideoQualityTest::FillScalabilitySettings(
    Params* params,
    size_t video_idx,
    const std::vector<std::string>& stream_descriptors,
    int num_streams,
    size_t selected_stream,
    int num_spatial_layers,
    int selected_sl,
    InterLayerPredMode inter_layer_pred,
    const std::vector<std::string>& sl_descriptors) {
  if (params->ss[video_idx].streams.empty() &&
      params->ss[video_idx].infer_streams) {
    webrtc::VideoEncoderConfig encoder_config;
    encoder_config.codec_type =
        PayloadStringToCodecType(params->video[video_idx].codec);
    encoder_config.content_type =
        params->screenshare[video_idx].enabled
            ? webrtc::VideoEncoderConfig::ContentType::kScreen
            : webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo;
    encoder_config.max_bitrate_bps = params->video[video_idx].max_bitrate_bps;
    encoder_config.min_transmit_bitrate_bps =
        params->video[video_idx].min_transmit_bps;
    encoder_config.number_of_streams = num_streams;
    encoder_config.spatial_layers = params->ss[video_idx].spatial_layers;
    encoder_config.simulcast_layers = std::vector<VideoStream>(num_streams);
    encoder_config.video_stream_factory =
        new rtc::RefCountedObject<cricket::EncoderStreamFactory>(
            params->video[video_idx].codec, kDefaultMaxQp,
            params->video[video_idx].fps,
            params->screenshare[video_idx].enabled, true);
    params->ss[video_idx].streams =
        encoder_config.video_stream_factory->CreateEncoderStreams(
            static_cast<int>(params->video[video_idx].width),
            static_cast<int>(params->video[video_idx].height), encoder_config);
  } else {
    // Read VideoStream and SpatialLayer elements from a list of comma separated
    // lists. To use a default value for an element, use -1 or leave empty.
    // Validity checks performed in CheckParams.
    RTC_CHECK(params->ss[video_idx].streams.empty());
    for (auto descriptor : stream_descriptors) {
      if (descriptor.empty())
        continue;
      VideoStream stream =
          VideoQualityTest::DefaultVideoStream(*params, video_idx);
      std::vector<int> v = VideoQualityTest::ParseCSV(descriptor);
      if (v[0] != -1)
        stream.width = static_cast<size_t>(v[0]);
      if (v[1] != -1)
        stream.height = static_cast<size_t>(v[1]);
      if (v[2] != -1)
        stream.max_framerate = v[2];
      if (v[3] != -1)
        stream.min_bitrate_bps = v[3];
      if (v[4] != -1)
        stream.target_bitrate_bps = v[4];
      if (v[5] != -1)
        stream.max_bitrate_bps = v[5];
      if (v.size() > 6 && v[6] != -1)
        stream.max_qp = v[6];
      if (v.size() > 7 && v[7] != -1) {
        stream.num_temporal_layers = v[7];
      } else {
        // Automatic TL thresholds for more than two layers not supported.
        RTC_CHECK_LE(params->video[video_idx].num_temporal_layers, 2);
      }
      params->ss[video_idx].streams.push_back(stream);
    }
  }

  params->ss[video_idx].num_spatial_layers = std::max(1, num_spatial_layers);
  params->ss[video_idx].selected_stream = selected_stream;

  params->ss[video_idx].selected_sl = selected_sl;
  params->ss[video_idx].inter_layer_pred = inter_layer_pred;
  RTC_CHECK(params->ss[video_idx].spatial_layers.empty());
  for (auto descriptor : sl_descriptors) {
    if (descriptor.empty())
      continue;
    std::vector<int> v = VideoQualityTest::ParseCSV(descriptor);
    RTC_CHECK_EQ(v.size(), 7);

    SpatialLayer layer = {0};
    layer.width = v[0];
    layer.height = v[1];
    layer.numberOfTemporalLayers = v[2];
    layer.maxBitrate = v[3];
    layer.minBitrate = v[4];
    layer.targetBitrate = v[5];
    layer.qpMax = v[6];
    layer.active = true;

    params->ss[video_idx].spatial_layers.push_back(layer);
  }
}

void VideoQualityTest::SetupVideo(Transport* send_transport,
                                  Transport* recv_transport) {
  size_t total_streams_used = 0;
  size_t num_flexfec_streams = params_.video[0].flexfec ? 1 : 0;
  CreateAudioAndFecSendConfigs(0, num_flexfec_streams, send_transport);
  CreateMatchingAudioAndFecConfigs(recv_transport);
  video_receive_configs_.clear();
  video_send_configs_.clear();
  video_encoder_configs_.clear();
  allocated_decoders_.clear();
  bool decode_all_receive_streams = true;
  size_t num_video_substreams = params_.ss[0].streams.size();
  RTC_CHECK(num_video_streams_ > 0);
  video_encoder_configs_.resize(num_video_streams_);
  for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
    video_send_configs_.push_back(VideoSendStream::Config(send_transport));
    video_encoder_configs_.push_back(VideoEncoderConfig());
    num_video_substreams = params_.ss[video_idx].streams.size();
    RTC_CHECK_GT(num_video_substreams, 0);
    CreateVideoSendConfig(&video_send_configs_[video_idx], num_video_substreams,
                          total_streams_used, send_transport);

    int payload_type;
    if (params_.video[video_idx].codec == "H264") {
      payload_type = kPayloadTypeH264;
    } else if (params_.video[video_idx].codec == "VP8") {
      payload_type = kPayloadTypeVP8;
    } else if (params_.video[video_idx].codec == "VP9") {
      payload_type = kPayloadTypeVP9;
    } else if (params_.video[video_idx].codec == "multiplex") {
      payload_type = kPayloadTypeVP9;
    } else {
      RTC_NOTREACHED() << "Codec not supported!";
      return;
    }
    video_send_configs_[video_idx].encoder_settings.encoder_factory =
        &video_encoder_factory_;

    video_send_configs_[video_idx].rtp.payload_name =
        params_.video[video_idx].codec;
    video_send_configs_[video_idx].rtp.payload_type = payload_type;
    video_send_configs_[video_idx].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
    video_send_configs_[video_idx].rtp.rtx.payload_type = kSendRtxPayloadType;
    for (size_t i = 0; i < num_video_substreams; ++i) {
      video_send_configs_[video_idx].rtp.rtx.ssrcs.push_back(
          kSendRtxSsrcs[i + total_streams_used]);
    }
    video_send_configs_[video_idx].rtp.extensions.clear();
    if (params_.call.send_side_bwe) {
      video_send_configs_[video_idx].rtp.extensions.push_back(
          RtpExtension(RtpExtension::kTransportSequenceNumberUri,
                       test::kTransportSequenceNumberExtensionId));
    } else {
      video_send_configs_[video_idx].rtp.extensions.push_back(RtpExtension(
          RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
    }
    video_send_configs_[video_idx].rtp.extensions.push_back(
        RtpExtension(RtpExtension::kVideoContentTypeUri,
                     test::kVideoContentTypeExtensionId));
    video_send_configs_[video_idx].rtp.extensions.push_back(RtpExtension(
        RtpExtension::kVideoTimingUri, test::kVideoTimingExtensionId));

    video_encoder_configs_[video_idx].video_format.name =
        params_.video[video_idx].codec;

    video_encoder_configs_[video_idx].codec_type =
        PayloadStringToCodecType(params_.video[video_idx].codec);

    video_encoder_configs_[video_idx].min_transmit_bitrate_bps =
        params_.video[video_idx].min_transmit_bps;

    video_send_configs_[video_idx].suspend_below_min_bitrate =
        params_.video[video_idx].suspend_below_min_bitrate;

    video_encoder_configs_[video_idx].number_of_streams =
        params_.ss[video_idx].streams.size();
    video_encoder_configs_[video_idx].max_bitrate_bps = 0;
    for (size_t i = 0; i < params_.ss[video_idx].streams.size(); ++i) {
      video_encoder_configs_[video_idx].max_bitrate_bps +=
          params_.ss[video_idx].streams[i].max_bitrate_bps;
    }
    if (params_.ss[video_idx].infer_streams) {
      video_encoder_configs_[video_idx].simulcast_layers =
          std::vector<VideoStream>(params_.ss[video_idx].streams.size());
      video_encoder_configs_[video_idx].video_stream_factory =
          new rtc::RefCountedObject<cricket::EncoderStreamFactory>(
              params_.video[video_idx].codec,
              params_.ss[video_idx].streams[0].max_qp,
              params_.video[video_idx].fps,
              params_.screenshare[video_idx].enabled, true);
    } else {
      video_encoder_configs_[video_idx].video_stream_factory =
          new rtc::RefCountedObject<VideoStreamFactory>(
              params_.ss[video_idx].streams);
    }

    video_encoder_configs_[video_idx].spatial_layers =
        params_.ss[video_idx].spatial_layers;

    std::vector<VideoReceiveStream::Config> new_receive_configs =
        CreateMatchingVideoReceiveConfigs(video_send_configs_[video_idx],
                                          recv_transport);

    decode_all_receive_streams = params_.ss[video_idx].selected_stream ==
                                 params_.ss[video_idx].streams.size();

    for (size_t i = 0; i < num_video_substreams; ++i) {
      new_receive_configs[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
      new_receive_configs[i].rtp.rtx_ssrc =
          kSendRtxSsrcs[i + total_streams_used];
      new_receive_configs[i]
          .rtp.rtx_associated_payload_types[kSendRtxPayloadType] = payload_type;
      new_receive_configs[i].rtp.transport_cc = params_.call.send_side_bwe;
      new_receive_configs[i].rtp.remb = !params_.call.send_side_bwe;
      // Enable RTT calculation so NTP time estimator will work.
      new_receive_configs[i].rtp.rtcp_xr.receiver_reference_time_report = true;
      // Force fake decoders on non-selected simulcast streams.
      if (!decode_all_receive_streams &&
          i != params_.ss[video_idx].selected_stream) {
        VideoReceiveStream::Decoder decoder;
        decoder.decoder = new test::FakeDecoder();
        decoder.payload_type = video_send_configs_[video_idx].rtp.payload_type;
        decoder.payload_name = video_send_configs_[video_idx].rtp.payload_name;
        new_receive_configs[i].decoders.clear();
        allocated_decoders_.emplace_back(decoder.decoder);
        new_receive_configs[i].decoders.push_back(decoder);
      }
    }

    for (VideoReceiveStream::Config& config : new_receive_configs) {
      video_receive_configs_.push_back(config.Copy());
    }

    if (params_.screenshare[video_idx].enabled) {
      // Fill out codec settings.
      video_encoder_configs_[video_idx].content_type =
          VideoEncoderConfig::ContentType::kScreen;
      degradation_preference_ = DegradationPreference::MAINTAIN_RESOLUTION;
      if (params_.video[video_idx].codec == "VP8") {
        VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
        vp8_settings.denoisingOn = false;
        vp8_settings.frameDroppingOn = false;
        vp8_settings.numberOfTemporalLayers = static_cast<unsigned char>(
            params_.video[video_idx].num_temporal_layers);
        video_encoder_configs_[video_idx].encoder_specific_settings =
            new rtc::RefCountedObject<
                VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
      } else if (params_.video[video_idx].codec == "VP9") {
        VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
        vp9_settings.denoisingOn = false;
        vp9_settings.frameDroppingOn = false;
        vp9_settings.numberOfTemporalLayers = static_cast<unsigned char>(
            params_.video[video_idx].num_temporal_layers);
        vp9_settings.numberOfSpatialLayers = static_cast<unsigned char>(
            params_.ss[video_idx].num_spatial_layers);
        vp9_settings.interLayerPred = params_.ss[video_idx].inter_layer_pred;
        video_encoder_configs_[video_idx].encoder_specific_settings =
            new rtc::RefCountedObject<
                VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
      }
    } else if (params_.ss[video_idx].num_spatial_layers > 1) {
      // If SVC mode without screenshare, still need to set codec specifics.
      RTC_CHECK(params_.video[video_idx].codec == "VP9");
      VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
      vp9_settings.numberOfTemporalLayers = static_cast<unsigned char>(
          params_.video[video_idx].num_temporal_layers);
      vp9_settings.numberOfSpatialLayers =
          static_cast<unsigned char>(params_.ss[video_idx].num_spatial_layers);
      vp9_settings.interLayerPred = params_.ss[video_idx].inter_layer_pred;
      video_encoder_configs_[video_idx].encoder_specific_settings =
          new rtc::RefCountedObject<
              VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
    } else if (params_.video[video_idx].automatic_scaling) {
      if (params_.video[video_idx].codec == "VP8") {
        VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
        vp8_settings.automaticResizeOn = true;
        video_encoder_configs_[video_idx].encoder_specific_settings =
            new rtc::RefCountedObject<
                VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
      } else if (params_.video[video_idx].codec == "VP9") {
        VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
        vp9_settings.automaticResizeOn = true;
        video_encoder_configs_[video_idx].encoder_specific_settings =
            new rtc::RefCountedObject<
                VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
      } else {
        RTC_NOTREACHED() << "Automatic scaling not supported for codec "
                         << params_.video[video_idx].codec << ", stream "
                         << video_idx;
      }
    }
    total_streams_used += num_video_substreams;
  }

  // FEC supported only for single video stream mode yet.
  if (params_.video[0].flexfec) {
    video_send_configs_[0].rtp.flexfec.payload_type = kFlexfecPayloadType;
    video_send_configs_[0].rtp.flexfec.ssrc = kFlexfecSendSsrc;
    if (decode_all_receive_streams) {
      for (uint32_t media_ssrc : video_send_configs_[0].rtp.ssrcs) {
        video_send_configs_[0].rtp.flexfec.protected_media_ssrcs.push_back(
            media_ssrc);
      }
    } else {
      video_send_configs_[0].rtp.flexfec.protected_media_ssrcs = {
          kVideoSendSsrcs[params_.ss[0].selected_stream]};
    }

    // The matching receive config is _not_ created by
    // CreateMatchingReceiveConfigs, since VideoQualityTest is not a BaseTest.
    // Set up the receive config manually instead.
    FlexfecReceiveStream::Config flexfec_receive_config(recv_transport);
    flexfec_receive_config.payload_type =
        video_send_configs_[0].rtp.flexfec.payload_type;
    flexfec_receive_config.remote_ssrc =
        video_send_configs_[0].rtp.flexfec.ssrc;
    flexfec_receive_config.protected_media_ssrcs =
        video_send_configs_[0].rtp.flexfec.protected_media_ssrcs;
    flexfec_receive_config.local_ssrc = kReceiverLocalVideoSsrc;
    flexfec_receive_config.transport_cc = params_.call.send_side_bwe;
    if (params_.call.send_side_bwe) {
      flexfec_receive_config.rtp_header_extensions.push_back(
          RtpExtension(RtpExtension::kTransportSequenceNumberUri,
                       test::kTransportSequenceNumberExtensionId));
    } else {
      flexfec_receive_config.rtp_header_extensions.push_back(RtpExtension(
          RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
    }
    flexfec_receive_configs_.push_back(flexfec_receive_config);
    if (num_video_substreams > 0) {
      video_receive_configs_[0].rtp.protected_by_flexfec = true;
    }
  }

  if (params_.video[0].ulpfec) {
    video_send_configs_[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
    video_send_configs_[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
    video_send_configs_[0].rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;

    if (decode_all_receive_streams) {
      for (auto it = video_receive_configs_.begin();
           it != video_receive_configs_.end(); ++it) {
        it->rtp.red_payload_type =
            video_send_configs_[0].rtp.ulpfec.red_payload_type;
        it->rtp.ulpfec_payload_type =
            video_send_configs_[0].rtp.ulpfec.ulpfec_payload_type;
        it->rtp.rtx_associated_payload_types
            [video_send_configs_[0].rtp.ulpfec.red_rtx_payload_type] =
            video_send_configs_[0].rtp.ulpfec.red_payload_type;
      }
    } else {
      video_receive_configs_[params_.ss[0].selected_stream]
          .rtp.red_payload_type =
          video_send_configs_[0].rtp.ulpfec.red_payload_type;
      video_receive_configs_[params_.ss[0].selected_stream]
          .rtp.ulpfec_payload_type =
          video_send_configs_[0].rtp.ulpfec.ulpfec_payload_type;
      video_receive_configs_[params_.ss[0].selected_stream]
          .rtp.rtx_associated_payload_types
              [video_send_configs_[0].rtp.ulpfec.red_rtx_payload_type] =
          video_send_configs_[0].rtp.ulpfec.red_payload_type;
    }
  }
}

void VideoQualityTest::SetupThumbnails(Transport* send_transport,
                                       Transport* recv_transport) {
  for (int i = 0; i < params_.call.num_thumbnails; ++i) {
    // Thumbnails will be send in the other way: from receiver_call to
    // sender_call.
    VideoSendStream::Config thumbnail_send_config(recv_transport);
    thumbnail_send_config.rtp.ssrcs.push_back(kThumbnailSendSsrcStart + i);
    // TODO(nisse): Could use a simpler VP8-only encoder factory.
    thumbnail_send_config.encoder_settings.encoder_factory =
        &video_encoder_factory_;
    thumbnail_send_config.rtp.payload_name = params_.video[0].codec;
    thumbnail_send_config.rtp.payload_type = kPayloadTypeVP8;
    thumbnail_send_config.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
    thumbnail_send_config.rtp.rtx.payload_type = kSendRtxPayloadType;
    thumbnail_send_config.rtp.rtx.ssrcs.push_back(kThumbnailRtxSsrcStart + i);
    thumbnail_send_config.rtp.extensions.clear();
    if (params_.call.send_side_bwe) {
      thumbnail_send_config.rtp.extensions.push_back(
          RtpExtension(RtpExtension::kTransportSequenceNumberUri,
                       test::kTransportSequenceNumberExtensionId));
    } else {
      thumbnail_send_config.rtp.extensions.push_back(RtpExtension(
          RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
    }

    VideoEncoderConfig thumbnail_encoder_config;
    thumbnail_encoder_config.codec_type = kVideoCodecVP8;
    thumbnail_encoder_config.video_format.name = "VP8";
    thumbnail_encoder_config.min_transmit_bitrate_bps = 7500;
    thumbnail_send_config.suspend_below_min_bitrate =
        params_.video[0].suspend_below_min_bitrate;
    thumbnail_encoder_config.number_of_streams = 1;
    thumbnail_encoder_config.max_bitrate_bps = 50000;
    if (params_.ss[0].infer_streams) {
      thumbnail_encoder_config.video_stream_factory =
          new rtc::RefCountedObject<VideoStreamFactory>(params_.ss[0].streams);
    } else {
      thumbnail_encoder_config.simulcast_layers = std::vector<VideoStream>(1);
      thumbnail_encoder_config.video_stream_factory =
          new rtc::RefCountedObject<cricket::EncoderStreamFactory>(
              params_.video[0].codec, params_.ss[0].streams[0].max_qp,
              params_.video[0].fps, params_.screenshare[0].enabled, true);
    }
    thumbnail_encoder_config.spatial_layers = params_.ss[0].spatial_layers;

    VideoReceiveStream::Config thumbnail_receive_config(send_transport);
    thumbnail_receive_config.rtp.remb = false;
    thumbnail_receive_config.rtp.transport_cc = true;
    thumbnail_receive_config.rtp.local_ssrc = kReceiverLocalVideoSsrc;
    for (const RtpExtension& extension : thumbnail_send_config.rtp.extensions)
      thumbnail_receive_config.rtp.extensions.push_back(extension);
    thumbnail_receive_config.renderer = &fake_renderer_;

    VideoReceiveStream::Decoder decoder =
        test::CreateMatchingDecoder(thumbnail_send_config);
    allocated_decoders_.push_back(
        std::unique_ptr<VideoDecoder>(decoder.decoder));
    thumbnail_receive_config.decoders.clear();
    thumbnail_receive_config.decoders.push_back(decoder);
    thumbnail_receive_config.rtp.remote_ssrc =
        thumbnail_send_config.rtp.ssrcs[0];

    thumbnail_receive_config.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
    thumbnail_receive_config.rtp.rtx_ssrc = kThumbnailRtxSsrcStart + i;
    thumbnail_receive_config.rtp
        .rtx_associated_payload_types[kSendRtxPayloadType] = kPayloadTypeVP8;
    thumbnail_receive_config.rtp.transport_cc = params_.call.send_side_bwe;
    thumbnail_receive_config.rtp.remb = !params_.call.send_side_bwe;

    thumbnail_encoder_configs_.push_back(thumbnail_encoder_config.Copy());
    thumbnail_send_configs_.push_back(thumbnail_send_config.Copy());
    thumbnail_receive_configs_.push_back(thumbnail_receive_config.Copy());
  }

  for (int i = 0; i < params_.call.num_thumbnails; ++i) {
    thumbnail_send_streams_.push_back(receiver_call_->CreateVideoSendStream(
        thumbnail_send_configs_[i].Copy(),
        thumbnail_encoder_configs_[i].Copy()));
    thumbnail_receive_streams_.push_back(sender_call_->CreateVideoReceiveStream(
        thumbnail_receive_configs_[i].Copy()));
  }
}

void VideoQualityTest::DestroyThumbnailStreams() {
  for (VideoSendStream* thumbnail_send_stream : thumbnail_send_streams_) {
    receiver_call_->DestroyVideoSendStream(thumbnail_send_stream);
  }
  thumbnail_send_streams_.clear();
  for (VideoReceiveStream* thumbnail_receive_stream :
       thumbnail_receive_streams_) {
    sender_call_->DestroyVideoReceiveStream(thumbnail_receive_stream);
  }
  thumbnail_send_streams_.clear();
  thumbnail_receive_streams_.clear();
  for (std::unique_ptr<test::VideoCapturer>& video_caputurer :
       thumbnail_capturers_) {
    video_caputurer.reset();
  }
}

void VideoQualityTest::SetupThumbnailCapturers(size_t num_thumbnail_streams) {
  VideoStream thumbnail = DefaultThumbnailStream();
  for (size_t i = 0; i < num_thumbnail_streams; ++i) {
    thumbnail_capturers_.emplace_back(test::FrameGeneratorCapturer::Create(
        static_cast<int>(thumbnail.width), static_cast<int>(thumbnail.height),
        absl::nullopt, absl::nullopt, thumbnail.max_framerate, clock_));
    RTC_DCHECK(thumbnail_capturers_.back());
  }
}

std::unique_ptr<test::FrameGenerator> VideoQualityTest::CreateFrameGenerator(
    size_t video_idx) {
  // Setup frame generator.
  const size_t kWidth = 1850;
  const size_t kHeight = 1110;
  std::unique_ptr<test::FrameGenerator> frame_generator;
  if (params_.screenshare[video_idx].generate_slides) {
    frame_generator = test::FrameGenerator::CreateSlideGenerator(
        kWidth, kHeight,
        params_.screenshare[video_idx].slide_change_interval *
            params_.video[video_idx].fps);
  } else {
    std::vector<std::string> slides = params_.screenshare[video_idx].slides;
    if (slides.size() == 0) {
      slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv"));
      slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv"));
      slides.push_back(test::ResourcePath("photo_1850_1110", "yuv"));
      slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv"));
    }
    if (params_.screenshare[video_idx].scroll_duration == 0) {
      // Cycle image every slide_change_interval seconds.
      frame_generator = test::FrameGenerator::CreateFromYuvFile(
          slides, kWidth, kHeight,
          params_.screenshare[video_idx].slide_change_interval *
              params_.video[video_idx].fps);
    } else {
      RTC_CHECK_LE(params_.video[video_idx].width, kWidth);
      RTC_CHECK_LE(params_.video[video_idx].height, kHeight);
      RTC_CHECK_GT(params_.screenshare[video_idx].slide_change_interval, 0);
      const int kPauseDurationMs =
          (params_.screenshare[video_idx].slide_change_interval -
           params_.screenshare[video_idx].scroll_duration) *
          1000;
      RTC_CHECK_LE(params_.screenshare[video_idx].scroll_duration,
                   params_.screenshare[video_idx].slide_change_interval);

      frame_generator = test::FrameGenerator::CreateScrollingInputFromYuvFiles(
          clock_, slides, kWidth, kHeight, params_.video[video_idx].width,
          params_.video[video_idx].height,
          params_.screenshare[video_idx].scroll_duration * 1000,
          kPauseDurationMs);
    }
  }
  return frame_generator;
}

void VideoQualityTest::CreateCapturers() {
  video_capturers_.resize(num_video_streams_);
  for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
    if (params_.screenshare[video_idx].enabled) {
      std::unique_ptr<test::FrameGenerator> frame_generator =
          CreateFrameGenerator(video_idx);
      test::FrameGeneratorCapturer* frame_generator_capturer =
          new test::FrameGeneratorCapturer(clock_, std::move(frame_generator),
                                           params_.video[video_idx].fps);
      EXPECT_TRUE(frame_generator_capturer->Init());
      video_capturers_[video_idx].reset(frame_generator_capturer);
    } else {
      if (params_.video[video_idx].clip_name == "Generator") {
        video_capturers_[video_idx].reset(test::FrameGeneratorCapturer::Create(
            static_cast<int>(params_.video[video_idx].width),
            static_cast<int>(params_.video[video_idx].height), absl::nullopt,
            absl::nullopt, params_.video[video_idx].fps, clock_));
      } else if (params_.video[video_idx].clip_name == "GeneratorI420A") {
        video_capturers_[video_idx].reset(test::FrameGeneratorCapturer::Create(
            static_cast<int>(params_.video[video_idx].width),
            static_cast<int>(params_.video[video_idx].height),
            test::FrameGenerator::OutputType::I420A, absl::nullopt,
            params_.video[video_idx].fps, clock_));
      } else if (params_.video[video_idx].clip_name.empty()) {
        video_capturers_[video_idx].reset(test::VcmCapturer::Create(
            params_.video[video_idx].width, params_.video[video_idx].height,
            params_.video[video_idx].fps,
            params_.video[video_idx].capture_device_index));
        if (!video_capturers_[video_idx]) {
          // Failed to get actual camera, use chroma generator as backup.
          video_capturers_[video_idx].reset(
              test::FrameGeneratorCapturer::Create(
                  static_cast<int>(params_.video[video_idx].width),
                  static_cast<int>(params_.video[video_idx].height),
                  absl::nullopt, absl::nullopt, params_.video[video_idx].fps,
                  clock_));
        }
      } else {
        video_capturers_[video_idx].reset(
            test::FrameGeneratorCapturer::CreateFromYuvFile(
                test::ResourcePath(params_.video[video_idx].clip_name, "yuv"),
                params_.video[video_idx].width, params_.video[video_idx].height,
                params_.video[video_idx].fps, clock_));
        ASSERT_TRUE(video_capturers_[video_idx])
            << "Could not create capturer for "
            << params_.video[video_idx].clip_name
            << ".yuv. Is this resource file present?";
      }
    }
    RTC_DCHECK(video_capturers_[video_idx].get());
  }
}

std::unique_ptr<test::LayerFilteringTransport>
VideoQualityTest::CreateSendTransport() {
  return absl::make_unique<test::LayerFilteringTransport>(
      &task_queue_, params_.pipe, sender_call_.get(), kPayloadTypeVP8,
      kPayloadTypeVP9, params_.video[0].selected_tl, params_.ss[0].selected_sl,
      payload_type_map_, kVideoSendSsrcs[0],
      static_cast<uint32_t>(kVideoSendSsrcs[0] + params_.ss[0].streams.size() -
                            1));
}

std::unique_ptr<test::DirectTransport>
VideoQualityTest::CreateReceiveTransport() {
  return absl::make_unique<test::DirectTransport>(
      &task_queue_, params_.pipe, receiver_call_.get(), payload_type_map_);
}

void VideoQualityTest::CreateVideoStreams() {
  RTC_DCHECK(video_send_streams_.empty());
  RTC_DCHECK(video_receive_streams_.empty());
  RTC_DCHECK_EQ(video_send_configs_.size(), num_video_streams_);

  // We currently only support testing external fec controllers with a single
  // VideoSendStream.
  if (fec_controller_factory_.get()) {
    RTC_DCHECK_LE(video_send_configs_.size(), 1);
  }

  // TODO(http://crbug/818127):
  // Remove this workaround when ALR is not screenshare-specific.
  std::list<size_t> streams_creation_order;
  for (size_t i = 0; i < video_send_configs_.size(); ++i) {
    // If dual streams are created, add the screenshare stream last.
    if (video_encoder_configs_[i].content_type ==
        VideoEncoderConfig::ContentType::kScreen) {
      streams_creation_order.push_back(i);
    } else {
      streams_creation_order.push_front(i);
    }
  }

  video_send_streams_.resize(video_send_configs_.size(), nullptr);

  for (size_t i : streams_creation_order) {
    if (fec_controller_factory_.get()) {
      video_send_streams_[i] = sender_call_->CreateVideoSendStream(
          video_send_configs_[i].Copy(), video_encoder_configs_[i].Copy(),
          fec_controller_factory_->CreateFecController());
    } else {
      video_send_streams_[i] = sender_call_->CreateVideoSendStream(
          video_send_configs_[i].Copy(), video_encoder_configs_[i].Copy());
    }
  }
  for (size_t i = 0; i < video_receive_configs_.size(); ++i) {
    video_receive_streams_.push_back(receiver_call_->CreateVideoReceiveStream(
        video_receive_configs_[i].Copy()));
  }

  AssociateFlexfecStreamsWithVideoStreams();
}

void VideoQualityTest::DestroyStreams() {
  CallTest::DestroyStreams();

  for (VideoSendStream* video_send_stream : video_send_streams_)
    sender_call_->DestroyVideoSendStream(video_send_stream);
}

void VideoQualityTest::RunWithAnalyzer(const Params& params) {
  rtc::LogMessage::SetLogToStderr(params.logging.logs);
  num_video_streams_ = params.call.dual_video ? 2 : 1;
  std::unique_ptr<test::LayerFilteringTransport> send_transport;
  std::unique_ptr<test::DirectTransport> recv_transport;
  FILE* graph_data_output_file = nullptr;
  std::unique_ptr<VideoAnalyzer> analyzer;

  params_ = params;

  RTC_CHECK(!params_.audio.enabled);
  // TODO(ivica): Merge with RunWithRenderer and use a flag / argument to
  // differentiate between the analyzer and the renderer case.
  CheckParams();

  if (!params_.analyzer.graph_data_output_filename.empty()) {
    graph_data_output_file =
        fopen(params_.analyzer.graph_data_output_filename.c_str(), "w");
    RTC_CHECK(graph_data_output_file)
        << "Can't open the file " << params_.analyzer.graph_data_output_filename
        << "!";
  }

  if (!params.logging.rtc_event_log_name.empty()) {
    send_event_log_ = RtcEventLog::Create(RtcEventLog::EncodingType::Legacy);
    recv_event_log_ = RtcEventLog::Create(RtcEventLog::EncodingType::Legacy);
    std::unique_ptr<RtcEventLogOutputFile> send_output(
        absl::make_unique<RtcEventLogOutputFile>(
            params.logging.rtc_event_log_name + "_send",
            RtcEventLog::kUnlimitedOutput));
    std::unique_ptr<RtcEventLogOutputFile> recv_output(
        absl::make_unique<RtcEventLogOutputFile>(
            params.logging.rtc_event_log_name + "_recv",
            RtcEventLog::kUnlimitedOutput));
    bool event_log_started =
        send_event_log_->StartLogging(std::move(send_output),
                                      RtcEventLog::kImmediateOutput) &&
        recv_event_log_->StartLogging(std::move(recv_output),
                                      RtcEventLog::kImmediateOutput);
    RTC_DCHECK(event_log_started);
  } else {
    send_event_log_ = RtcEventLog::CreateNull();
    recv_event_log_ = RtcEventLog::CreateNull();
  }

  Call::Config send_call_config(send_event_log_.get());
  Call::Config recv_call_config(recv_event_log_.get());
  send_call_config.bitrate_config = params.call.call_bitrate_config;
  recv_call_config.bitrate_config = params.call.call_bitrate_config;

  task_queue_.SendTask([this, &send_call_config, &recv_call_config,
                        &send_transport, &recv_transport]() {
    CreateCalls(send_call_config, recv_call_config);
    send_transport = CreateSendTransport();
    recv_transport = CreateReceiveTransport();
  });

  std::string graph_title = params_.analyzer.graph_title;
  if (graph_title.empty())
    graph_title = VideoQualityTest::GenerateGraphTitle();
  bool is_quick_test_enabled = field_trial::IsEnabled("WebRTC-QuickPerfTest");
  analyzer = absl::make_unique<VideoAnalyzer>(
      send_transport.get(), params_.analyzer.test_label,
      params_.analyzer.avg_psnr_threshold, params_.analyzer.avg_ssim_threshold,
      is_quick_test_enabled
          ? kFramesSentInQuickTest
          : params_.analyzer.test_durations_secs * params_.video[0].fps,
      graph_data_output_file, graph_title,
      kVideoSendSsrcs[params_.ss[0].selected_stream],
      kSendRtxSsrcs[params_.ss[0].selected_stream],
      static_cast<size_t>(params_.ss[0].selected_stream),
      params.ss[0].selected_sl, params_.video[0].selected_tl,
      is_quick_test_enabled, clock_, params_.logging.rtp_dump_name);

  task_queue_.SendTask([&]() {
    analyzer->SetCall(sender_call_.get());
    analyzer->SetReceiver(receiver_call_->Receiver());
    send_transport->SetReceiver(analyzer.get());
    recv_transport->SetReceiver(sender_call_->Receiver());

    SetupVideo(analyzer.get(), recv_transport.get());
    SetupThumbnails(analyzer.get(), recv_transport.get());
    video_receive_configs_[params_.ss[0].selected_stream].renderer =
        analyzer.get();
    video_send_configs_[0].pre_encode_callback = analyzer->pre_encode_proxy();
    RTC_DCHECK(!video_send_configs_[0].post_encode_callback);
    video_send_configs_[0].post_encode_callback = analyzer.get();

    CreateFlexfecStreams();
    CreateVideoStreams();
    analyzer->SetSendStream(video_send_streams_[0]);
    if (video_receive_streams_.size() == 1)
      analyzer->SetReceiveStream(video_receive_streams_[0]);

    video_send_streams_[0]->SetSource(analyzer->OutputInterface(),
                                      degradation_preference_);
    SetupThumbnailCapturers(params_.call.num_thumbnails);
    for (size_t i = 0; i < thumbnail_send_streams_.size(); ++i) {
      thumbnail_send_streams_[i]->SetSource(thumbnail_capturers_[i].get(),
                                            degradation_preference_);
    }

    CreateCapturers();

    analyzer->SetSource(video_capturers_[0].get(), params_.ss[0].infer_streams);

    for (size_t video_idx = 1; video_idx < num_video_streams_; ++video_idx) {
      video_send_streams_[video_idx]->SetSource(
          video_capturers_[video_idx].get(), degradation_preference_);
    }

    StartEncodedFrameLogs(video_send_streams_[0]);
    StartEncodedFrameLogs(
        video_receive_streams_[params_.ss[0].selected_stream]);
    for (VideoSendStream* video_send_stream : video_send_streams_)
      video_send_stream->Start();
    for (VideoSendStream* thumbnail_send_stream : thumbnail_send_streams_)
      thumbnail_send_stream->Start();
    for (VideoReceiveStream* receive_stream : video_receive_streams_)
      receive_stream->Start();
    for (VideoReceiveStream* thumbnail_receive_stream :
         thumbnail_receive_streams_)
      thumbnail_receive_stream->Start();

    analyzer->StartMeasuringCpuProcessTime();

    for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
      video_capturers_[video_idx]->Start();
    }
    for (std::unique_ptr<test::VideoCapturer>& video_caputurer :
         thumbnail_capturers_) {
      video_caputurer->Start();
    }
  });

  analyzer->Wait();

  event_log_->StopLogging();

  task_queue_.SendTask([&]() {
    for (std::unique_ptr<test::VideoCapturer>& video_caputurer :
         thumbnail_capturers_)
      video_caputurer->Stop();
    for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
      video_capturers_[video_idx]->Stop();
    }
    for (VideoReceiveStream* thumbnail_receive_stream :
         thumbnail_receive_streams_)
      thumbnail_receive_stream->Stop();
    for (VideoReceiveStream* receive_stream : video_receive_streams_)
      receive_stream->Stop();
    for (VideoSendStream* thumbnail_send_stream : thumbnail_send_streams_)
      thumbnail_send_stream->Stop();
    for (VideoSendStream* video_send_stream : video_send_streams_)
      video_send_stream->Stop();

    DestroyStreams();
    DestroyThumbnailStreams();

    if (graph_data_output_file)
      fclose(graph_data_output_file);

    video_capturers_.clear();
    send_transport.reset();
    recv_transport.reset();

    DestroyCalls();
  });
}

void VideoQualityTest::SetupAudio(Transport* transport,
                                  AudioReceiveStream** audio_receive_stream) {
  audio_send_config_ = AudioSendStream::Config(transport);
  audio_send_config_.rtp.ssrc = kAudioSendSsrc;

  // Add extension to enable audio send side BWE, and allow audio bit rate
  // adaptation.
  audio_send_config_.rtp.extensions.clear();
  if (params_.call.send_side_bwe) {
    audio_send_config_.rtp.extensions.push_back(
        webrtc::RtpExtension(webrtc::RtpExtension::kTransportSequenceNumberUri,
                             test::kTransportSequenceNumberExtensionId));
    audio_send_config_.min_bitrate_bps = kOpusMinBitrateBps;
    audio_send_config_.max_bitrate_bps = kOpusBitrateFbBps;
  }
  audio_send_config_.send_codec_spec = AudioSendStream::Config::SendCodecSpec(
      kAudioSendPayloadType,
      {"OPUS",
       48000,
       2,
       {{"usedtx", (params_.audio.dtx ? "1" : "0")}, {"stereo", "1"}}});
  audio_send_config_.encoder_factory = audio_encoder_factory_;
  audio_send_stream_ = sender_call_->CreateAudioSendStream(audio_send_config_);

  AudioReceiveStream::Config audio_config;
  audio_config.rtp.local_ssrc = kReceiverLocalAudioSsrc;
  audio_config.rtcp_send_transport = transport;
  audio_config.rtp.remote_ssrc = audio_send_config_.rtp.ssrc;
  audio_config.rtp.transport_cc = params_.call.send_side_bwe;
  audio_config.rtp.extensions = audio_send_config_.rtp.extensions;
  audio_config.decoder_factory = audio_decoder_factory_;
  audio_config.decoder_map = {{kAudioSendPayloadType, {"OPUS", 48000, 2}}};
  if (params_.video[0].enabled && params_.audio.sync_video)
    audio_config.sync_group = kSyncGroup;

  *audio_receive_stream =
      receiver_call_->CreateAudioReceiveStream(audio_config);
}

void VideoQualityTest::RunWithRenderers(const Params& params) {
  rtc::LogMessage::SetLogToStderr(params.logging.logs);
  num_video_streams_ = params.call.dual_video ? 2 : 1;
  std::unique_ptr<test::LayerFilteringTransport> send_transport;
  std::unique_ptr<test::DirectTransport> recv_transport;
  std::unique_ptr<test::VideoRenderer> local_preview;
  std::vector<std::unique_ptr<test::VideoRenderer>> loopback_renderers;
  AudioReceiveStream* audio_receive_stream = nullptr;

  task_queue_.SendTask([&]() {
    params_ = params;
    CheckParams();

    // TODO(ivica): Remove bitrate_config and use the default Call::Config(), to
    // match the full stack tests.
    Call::Config call_config(event_log_.get());
    call_config.bitrate_config = params_.call.call_bitrate_config;

    rtc::scoped_refptr<TestAudioDeviceModule> fake_audio_device =
        TestAudioDeviceModule::CreateTestAudioDeviceModule(
            TestAudioDeviceModule::CreatePulsedNoiseCapturer(32000, 48000),
            TestAudioDeviceModule::CreateDiscardRenderer(48000), 1.f);

    if (params_.audio.enabled) {
      AudioState::Config audio_state_config;
      audio_state_config.audio_mixer = AudioMixerImpl::Create();
      audio_state_config.audio_processing = AudioProcessingBuilder().Create();
      audio_state_config.audio_device_module = fake_audio_device;
      call_config.audio_state = AudioState::Create(audio_state_config);
      fake_audio_device->RegisterAudioCallback(
          call_config.audio_state->audio_transport());
    }

    CreateCalls(call_config, call_config);

    // TODO(minyue): consider if this is a good transport even for audio only
    // calls.
    send_transport = CreateSendTransport();

    recv_transport = CreateReceiveTransport();

    // TODO(ivica): Use two calls to be able to merge with RunWithAnalyzer or at
    // least share as much code as possible. That way this test would also match
    // the full stack tests better.
    send_transport->SetReceiver(receiver_call_->Receiver());
    recv_transport->SetReceiver(sender_call_->Receiver());

    if (params_.video[0].enabled) {
      // Create video renderers.
      local_preview.reset(test::VideoRenderer::Create(
          "Local Preview", params_.video[0].width, params_.video[0].height));

      SetupVideo(send_transport.get(), recv_transport.get());
      video_send_configs_[0].pre_encode_callback = local_preview.get();

      size_t num_streams_processed = 0;
      for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
        const size_t selected_stream_id = params_.ss[video_idx].selected_stream;
        const size_t num_streams = params_.ss[video_idx].streams.size();
        if (selected_stream_id == num_streams) {
          for (size_t stream_id = 0; stream_id < num_streams; ++stream_id) {
            std::ostringstream oss;
            oss << "Loopback Video #" << video_idx << " - Stream #"
                << static_cast<int>(stream_id);
            loopback_renderers.emplace_back(test::VideoRenderer::Create(
                oss.str().c_str(),
                params_.ss[video_idx].streams[stream_id].width,
                params_.ss[video_idx].streams[stream_id].height));
            video_receive_configs_[stream_id + num_streams_processed].renderer =
                loopback_renderers.back().get();
            if (params_.audio.enabled && params_.audio.sync_video)
              video_receive_configs_[stream_id + num_streams_processed]
                  .sync_group = kSyncGroup;
          }
        } else {
          std::ostringstream oss;
          oss << "Loopback Video #" << video_idx;
          loopback_renderers.emplace_back(test::VideoRenderer::Create(
              oss.str().c_str(),
              params_.ss[video_idx].streams[selected_stream_id].width,
              params_.ss[video_idx].streams[selected_stream_id].height));
          video_receive_configs_[selected_stream_id + num_streams_processed]
              .renderer = loopback_renderers.back().get();
          if (params_.audio.enabled && params_.audio.sync_video)
            video_receive_configs_[num_streams_processed + selected_stream_id]
                .sync_group = kSyncGroup;
        }
        num_streams_processed += num_streams;
      }
      CreateFlexfecStreams();
      CreateVideoStreams();

      CreateCapturers();
      for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
        video_send_streams_[video_idx]->SetSource(
            video_capturers_[video_idx].get(), degradation_preference_);
      }
    }

    if (params_.audio.enabled) {
      SetupAudio(send_transport.get(), &audio_receive_stream);
    }

    for (VideoReceiveStream* receive_stream : video_receive_streams_)
      StartEncodedFrameLogs(receive_stream);
    StartEncodedFrameLogs(video_send_streams_[0]);

    // Start sending and receiving video.
    if (params_.video[0].enabled) {
      for (VideoReceiveStream* video_receive_stream : video_receive_streams_)
        video_receive_stream->Start();
      for (VideoSendStream* video_send_stream : video_send_streams_)
        video_send_stream->Start();
      for (auto& video_capturer : video_capturers_)
        video_capturer->Start();
    }

    if (params_.audio.enabled) {
      // Start receiving audio.
      audio_receive_stream->Start();

      // Start sending audio.
      audio_send_stream_->Start();
    }
  });

  test::PressEnterToContinue();

  task_queue_.SendTask([&]() {
    if (params_.audio.enabled) {
      // Stop sending audio.
      audio_send_stream_->Stop();

      // Stop receiving audio.
      audio_receive_stream->Stop();
    }

    // Stop receiving and sending video.
    if (params_.video[0].enabled) {
      for (auto& video_capturer : video_capturers_)
        video_capturer->Stop();
      for (VideoSendStream* video_send_stream : video_send_streams_)
        video_send_stream->Stop();
      DestroyStreams();
    }

    video_capturers_.clear();
    send_transport.reset();
    recv_transport.reset();

    local_preview.reset();
    loopback_renderers.clear();

    DestroyCalls();
  });
}

void VideoQualityTest::StartEncodedFrameLogs(VideoSendStream* stream) {
  if (!params_.logging.encoded_frame_base_path.empty()) {
    std::ostringstream str;
    str << send_logs_++;
    std::string prefix =
        params_.logging.encoded_frame_base_path + "." + str.str() + ".send.";
    stream->EnableEncodedFrameRecording(
        std::vector<rtc::PlatformFile>(
            {rtc::CreatePlatformFile(prefix + "1.ivf"),
             rtc::CreatePlatformFile(prefix + "2.ivf"),
             rtc::CreatePlatformFile(prefix + "3.ivf")}),
        100000000);
  }
}

void VideoQualityTest::StartEncodedFrameLogs(VideoReceiveStream* stream) {
  if (!params_.logging.encoded_frame_base_path.empty()) {
    std::ostringstream str;
    str << receive_logs_++;
    std::string path =
        params_.logging.encoded_frame_base_path + "." + str.str() + ".recv.ivf";
    stream->EnableEncodedFrameRecording(rtc::CreatePlatformFile(path),
                                        100000000);
  }
}
}  // namespace webrtc
