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

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/strings/match.h"
#include "api/call/transport.h"
#include "api/environment/environment.h"
#include "api/make_ref_counted.h"
#include "api/media_types.h"
#include "api/rtp_headers.h"
#include "api/rtp_parameters.h"
#include "api/scoped_refptr.h"
#include "api/test/create_frame_generator.h"
#include "api/test/frame_generator_interface.h"
#include "api/test/video/function_video_decoder_factory.h"
#include "api/test/video/function_video_encoder_factory.h"
#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#include "api/video/builtin_video_bitrate_allocator_factory.h"
#include "api/video/video_codec_type.h"
#include "api/video/video_frame.h"
#include "api/video/video_sink_interface.h"
#include "api/video_codecs/scalability_mode.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_codec.h"
#include "api/video_codecs/video_encoder.h"
#include "call/flexfec_receive_stream.h"
#include "call/video_receive_stream.h"
#include "call/video_send_stream.h"
#include "media/engine/internal_decoder_factory.h"
#include "media/engine/internal_encoder_factory.h"
#include "media/engine/webrtc_video_engine.h"
#include "modules/video_coding/svc/scalability_mode_util.h"
#include "rtc_base/checks.h"
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/synchronization/mutex.h"
#include "system_wrappers/include/clock.h"
#include "test/encoder_settings.h"
#include "test/fake_decoder.h"
#include "test/fake_encoder.h"
#include "test/fake_vp8_encoder.h"
#include "test/frame_generator_capturer.h"
#include "test/scenario/call_client.h"
#include "test/scenario/column_printer.h"
#include "test/scenario/hardware_codecs.h"
#include "test/scenario/scenario_config.h"
#include "test/scenario/video_frame_matcher.h"
#include "test/testsupport/file_utils.h"
#include "test/video_test_constants.h"
#include "video/config/video_encoder_config.h"

namespace webrtc {
namespace test {
namespace {
enum : int {  // The first valid value is 1.
  kTransportSequenceNumberExtensionId = 1,
  kAbsSendTimeExtensionId,
  kVideoContentTypeExtensionId,
  kVideoRotationRtpExtensionId,
};

uint8_t CodecTypeToPayloadType(VideoCodecType codec_type) {
  switch (codec_type) {
    case VideoCodecType::kVideoCodecGeneric:
      return VideoTestConstants::kFakeVideoSendPayloadType;
    case VideoCodecType::kVideoCodecVP8:
      return VideoTestConstants::kPayloadTypeVP8;
    case VideoCodecType::kVideoCodecVP9:
      return VideoTestConstants::kPayloadTypeVP9;
    case VideoCodecType::kVideoCodecH264:
      return VideoTestConstants::kPayloadTypeH264;
    case VideoCodecType::kVideoCodecH265:
      return VideoTestConstants::kPayloadTypeH265;
    default:
      RTC_DCHECK_NOTREACHED();
  }
  return {};
}

VideoEncoderConfig::ContentType ConvertContentType(
    VideoStreamConfig::Encoder::ContentType content_type) {
  switch (content_type) {
    case VideoStreamConfig::Encoder::ContentType::kVideo:
      return VideoEncoderConfig::ContentType::kRealtimeVideo;
    case VideoStreamConfig::Encoder::ContentType::kScreen:
      return VideoEncoderConfig::ContentType::kScreen;
  }
}

std::string TransformFilePath(std::string path) {
  static const std::string resource_prefix = "res://";
  int ext_pos = path.rfind('.');
  if (ext_pos < 0) {
    return test::ResourcePath(path, "yuv");
  } else if (absl::StartsWith(path, resource_prefix)) {
    std::string name = path.substr(resource_prefix.length(), ext_pos);
    std::string ext = path.substr(ext_pos, path.size());
    return test::ResourcePath(name, ext);
  }
  return path;
}

VideoSendStream::Config CreateVideoSendStreamConfig(
    VideoStreamConfig config,
    std::vector<uint32_t> ssrcs,
    std::vector<uint32_t> rtx_ssrcs,
    Transport* send_transport) {
  VideoSendStream::Config send_config(send_transport);
  send_config.rtp.payload_name = CodecTypeToPayloadString(config.encoder.codec);
  send_config.rtp.payload_type = CodecTypeToPayloadType(config.encoder.codec);
  send_config.rtp.nack.rtp_history_ms =
      config.stream.nack_history_time.ms<int>();

  send_config.rtp.ssrcs = ssrcs;
  send_config.rtp.extensions = GetVideoRtpExtensions(config);

  if (config.stream.use_rtx) {
    send_config.rtp.rtx.payload_type = VideoTestConstants::kSendRtxPayloadType;
    send_config.rtp.rtx.ssrcs = rtx_ssrcs;
  }
  if (config.stream.use_flexfec) {
    send_config.rtp.flexfec.payload_type =
        VideoTestConstants::kFlexfecPayloadType;
    send_config.rtp.flexfec.ssrc = VideoTestConstants::kFlexfecSendSsrc;
    send_config.rtp.flexfec.protected_media_ssrcs = ssrcs;
  }
  if (config.stream.use_ulpfec) {
    send_config.rtp.ulpfec.red_payload_type =
        VideoTestConstants::kRedPayloadType;
    send_config.rtp.ulpfec.ulpfec_payload_type =
        VideoTestConstants::kUlpfecPayloadType;
    send_config.rtp.ulpfec.red_rtx_payload_type =
        VideoTestConstants::kRtxRedPayloadType;
  }
  return send_config;
}
scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
CreateVp9SpecificSettings(VideoStreamConfig video_config) {
  constexpr auto kScreen = VideoStreamConfig::Encoder::ContentType::kScreen;
  VideoStreamConfig::Encoder conf = video_config.encoder;
  VideoCodecVP9 vp9 = VideoEncoder::GetDefaultVp9Settings();
  // TODO(bugs.webrtc.org/11607): Support separate scalability mode per
  // simulcast stream.
  ScalabilityMode scalability_mode = conf.simulcast_streams[0];
  vp9.keyFrameInterval = conf.key_frame_interval.value_or(0);
  vp9.numberOfTemporalLayers =
      ScalabilityModeToNumTemporalLayers(scalability_mode);
  vp9.numberOfSpatialLayers =
      ScalabilityModeToNumSpatialLayers(scalability_mode);
  vp9.interLayerPred = ScalabilityModeToInterLayerPredMode(scalability_mode);

  if (conf.content_type == kScreen &&
      (video_config.source.framerate > 5 || vp9.numberOfSpatialLayers >= 3)) {
    vp9.flexibleMode = true;
  }

  if (conf.content_type == kScreen || vp9.numberOfTemporalLayers > 1 ||
      vp9.numberOfSpatialLayers > 1) {
    vp9.automaticResizeOn = false;
    vp9.denoisingOn = false;
  } else {
    vp9.automaticResizeOn = conf.single.automatic_scaling;
    vp9.denoisingOn = conf.single.denoising;
  }
  return make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9);
}

scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
CreateVp8SpecificSettings(VideoStreamConfig config) {
  VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
  vp8_settings.keyFrameInterval = config.encoder.key_frame_interval.value_or(0);
  // TODO(bugs.webrtc.org/11607): Support separate scalability mode per
  // simulcast stream.
  ScalabilityMode scalability_mode = config.encoder.simulcast_streams[0];
  vp8_settings.numberOfTemporalLayers =
      ScalabilityModeToNumTemporalLayers(scalability_mode);
  if (vp8_settings.numberOfTemporalLayers > 1 ||
      config.encoder.simulcast_streams.size() > 1) {
    vp8_settings.automaticResizeOn = false;
    vp8_settings.denoisingOn = false;
  } else {
    vp8_settings.automaticResizeOn = config.encoder.single.automatic_scaling;
    vp8_settings.denoisingOn = config.encoder.single.denoising;
  }
  return make_ref_counted<VideoEncoderConfig::Vp8EncoderSpecificSettings>(
      vp8_settings);
}

scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
CreateH264SpecificSettings(VideoStreamConfig config) {
  RTC_DCHECK_EQ(config.encoder.simulcast_streams.size(), 1);
  RTC_DCHECK(config.encoder.simulcast_streams[0] == ScalabilityMode::kL1T1);
  // TODO(bugs.webrtc.org/6883): Set a key frame interval as a setting that
  // isn't codec specific.
  RTC_CHECK_EQ(0, config.encoder.key_frame_interval.value_or(0));
  return nullptr;
}

scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
CreateEncoderSpecificSettings(VideoStreamConfig config) {
  using Codec = VideoStreamConfig::Encoder::Codec;
  switch (config.encoder.codec) {
    case Codec::kVideoCodecH264:
      return CreateH264SpecificSettings(config);
    case Codec::kVideoCodecVP8:
      return CreateVp8SpecificSettings(config);
    case Codec::kVideoCodecVP9:
      return CreateVp9SpecificSettings(config);
    case Codec::kVideoCodecGeneric:
    case Codec::kVideoCodecAV1:
    case Codec::kVideoCodecH265:
      return nullptr;
  }
}

VideoEncoderConfig CreateVideoEncoderConfig(VideoStreamConfig config) {
  VideoEncoder::EncoderInfo encoder_info;
  VideoEncoderConfig encoder_config;
  encoder_config.codec_type = config.encoder.codec;
  encoder_config.content_type = ConvertContentType(config.encoder.content_type);
  encoder_config.video_format =
      SdpVideoFormat(CodecTypeToPayloadString(config.encoder.codec), {});

  encoder_config.number_of_streams = config.encoder.simulcast_streams.size();
  encoder_config.simulcast_layers =
      std::vector<VideoStream>(encoder_config.number_of_streams);
  encoder_config.min_transmit_bitrate_bps = config.stream.pad_to_rate.bps();

  // TODO(srte): Base this on encoder capabilities.
  encoder_config.max_bitrate_bps =
      config.encoder.max_data_rate.value_or(DataRate::KilobitsPerSec(10000))
          .bps();

  encoder_config.frame_drop_enabled = config.encoder.frame_dropping;
  encoder_config.encoder_specific_settings =
      CreateEncoderSpecificSettings(config);

  for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
    auto& layer = encoder_config.simulcast_layers[i];
    if (config.encoder.max_framerate) {
      layer.max_framerate = *config.encoder.max_framerate;
      layer.min_bitrate_bps = config.encoder.min_data_rate->bps_or(-1);
    }
    layer.scalability_mode = config.encoder.simulcast_streams[i];
  }

  return encoder_config;
}

std::unique_ptr<FrameGeneratorInterface> CreateImageSlideGenerator(
    Clock* clock,
    VideoStreamConfig::Source::Slides slides,
    int framerate) {
  std::vector<std::string> paths = slides.images.paths;
  for (std::string& path : paths)
    path = TransformFilePath(path);
  if (slides.images.crop.width || slides.images.crop.height) {
    TimeDelta pause_duration =
        slides.change_interval - slides.images.crop.scroll_duration;
    RTC_CHECK_GE(pause_duration, TimeDelta::Zero());
    int crop_width = slides.images.crop.width.value_or(slides.images.width);
    int crop_height = slides.images.crop.height.value_or(slides.images.height);
    RTC_CHECK_LE(crop_width, slides.images.width);
    RTC_CHECK_LE(crop_height, slides.images.height);
    return CreateScrollingInputFromYuvFilesFrameGenerator(
        clock, paths, slides.images.width, slides.images.height, crop_width,
        crop_height, slides.images.crop.scroll_duration.ms(),
        pause_duration.ms());
  } else {
    return CreateFromYuvFileFrameGenerator(
        paths, slides.images.width, slides.images.height,
        slides.change_interval.seconds<double>() * framerate);
  }
}

std::unique_ptr<FrameGeneratorInterface> CreateFrameGenerator(
    Clock* clock,
    VideoStreamConfig::Source source) {
  using Capture = VideoStreamConfig::Source::Capture;
  switch (source.capture) {
    case Capture::kGenerator:
      return CreateSquareFrameGenerator(
          source.generator.width, source.generator.height,
          source.generator.pixel_format, /*num_squares*/ std::nullopt);
    case Capture::kVideoFile:
      RTC_CHECK(source.video_file.width && source.video_file.height);
      return CreateFromYuvFileFrameGenerator(
          {TransformFilePath(source.video_file.name)}, source.video_file.width,
          source.video_file.height, /*frame_repeat_count*/ 1);
    case Capture::kGenerateSlides:
      return CreateSlideFrameGenerator(
          source.slides.generator.width, source.slides.generator.height,
          source.slides.change_interval.seconds<double>() * source.framerate);
    case Capture::kImageSlides:
      return CreateImageSlideGenerator(clock, source.slides, source.framerate);
  }
}

VideoReceiveStreamInterface::Config CreateVideoReceiveStreamConfig(
    VideoStreamConfig config,
    Transport* feedback_transport,
    VideoDecoderFactory* decoder_factory,
    VideoReceiveStreamInterface::Decoder decoder,
    VideoSinkInterface<VideoFrame>* renderer,
    uint32_t local_ssrc,
    uint32_t ssrc,
    uint32_t rtx_ssrc) {
  VideoReceiveStreamInterface::Config recv(feedback_transport);
  recv.rtp.local_ssrc = local_ssrc;

  RTC_DCHECK(!config.stream.use_rtx ||
             config.stream.nack_history_time > TimeDelta::Zero());
  recv.rtp.nack.rtp_history_ms = config.stream.nack_history_time.ms();
  recv.rtp.protected_by_flexfec = config.stream.use_flexfec;
  recv.rtp.remote_ssrc = ssrc;
  recv.decoder_factory = decoder_factory;
  recv.decoders.push_back(decoder);
  recv.renderer = renderer;
  if (config.stream.use_rtx) {
    recv.rtp.rtx_ssrc = rtx_ssrc;
    recv.rtp
        .rtx_associated_payload_types[VideoTestConstants::kSendRtxPayloadType] =
        CodecTypeToPayloadType(config.encoder.codec);
  }
  if (config.stream.use_ulpfec) {
    recv.rtp.red_payload_type = VideoTestConstants::kRedPayloadType;
    recv.rtp.ulpfec_payload_type = VideoTestConstants::kUlpfecPayloadType;
    recv.rtp
        .rtx_associated_payload_types[VideoTestConstants::kRtxRedPayloadType] =
        VideoTestConstants::kRedPayloadType;
  }
  recv.sync_group = config.render.sync_group;
  return recv;
}
}  // namespace

std::vector<RtpExtension> GetVideoRtpExtensions(
    const VideoStreamConfig config) {
  std::vector<RtpExtension> res = {
      RtpExtension(RtpExtension::kVideoContentTypeUri,
                   kVideoContentTypeExtensionId),
      RtpExtension(RtpExtension::kVideoRotationUri,
                   kVideoRotationRtpExtensionId)};
  if (config.stream.packet_feedback) {
    res.push_back(RtpExtension(RtpExtension::kTransportSequenceNumberUri,
                               kTransportSequenceNumberExtensionId));
  }
  if (config.stream.abs_send_time) {
    res.push_back(
        RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeExtensionId));
  }
  return res;
}

SendVideoStream::SendVideoStream(CallClient* sender,
                                 VideoStreamConfig config,
                                 Transport* send_transport,
                                 VideoFrameMatcher* matcher)
    : sender_(sender), config_(config) {
  video_capturer_ = std::make_unique<FrameGeneratorCapturer>(
      &sender_->env_.clock(),
      CreateFrameGenerator(&sender_->env_.clock(), config.source),
      config.source.framerate, sender_->env_.task_queue_factory());
  video_capturer_->Init();

  using Encoder = VideoStreamConfig::Encoder;
  using Codec = VideoStreamConfig::Encoder::Codec;
  switch (config.encoder.implementation) {
    case Encoder::Implementation::kFake:
      encoder_factory_ = std::make_unique<FunctionVideoEncoderFactory>(
          [this](const Environment& env, const SdpVideoFormat& format) {
            MutexLock lock(&mutex_);
            std::unique_ptr<FakeEncoder> encoder;
            if (config_.encoder.codec == Codec::kVideoCodecVP8) {
              encoder = std::make_unique<test::FakeVp8Encoder>(env);
            } else if (config_.encoder.codec == Codec::kVideoCodecGeneric) {
              encoder = std::make_unique<test::FakeEncoder>(env);
            } else {
              RTC_DCHECK_NOTREACHED();
            }
            fake_encoders_.push_back(encoder.get());
            if (config_.encoder.fake.max_rate.IsFinite())
              encoder->SetMaxBitrate(config_.encoder.fake.max_rate.kbps());
            return encoder;
          });
      break;
    case VideoStreamConfig::Encoder::Implementation::kSoftware:
      encoder_factory_.reset(new InternalEncoderFactory());
      break;
    case VideoStreamConfig::Encoder::Implementation::kHardware:
      encoder_factory_ = CreateHardwareEncoderFactory();
      break;
  }
  RTC_CHECK(encoder_factory_);

  bitrate_allocator_factory_ = CreateBuiltinVideoBitrateAllocatorFactory();
  RTC_CHECK(bitrate_allocator_factory_);

  VideoEncoderConfig encoder_config = CreateVideoEncoderConfig(config);
  for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
    ssrcs_.push_back(sender->GetNextVideoSsrc());
    rtx_ssrcs_.push_back(sender->GetNextRtxSsrc());
  }
  VideoSendStream::Config send_config =
      CreateVideoSendStreamConfig(config, ssrcs_, rtx_ssrcs_, send_transport);
  send_config.encoder_settings.encoder_factory = encoder_factory_.get();
  send_config.encoder_settings.bitrate_allocator_factory =
      bitrate_allocator_factory_.get();
  send_config.suspend_below_min_bitrate =
      config.encoder.suspend_below_min_bitrate;

  video_capturer_->Start();
  sender_->SendTask([&] {
    if (config.stream.fec_controller_factory) {
      send_stream_ = sender_->call_->CreateVideoSendStream(
          std::move(send_config), std::move(encoder_config),
          config.stream.fec_controller_factory->CreateFecController(
              sender_->env_));
    } else {
      send_stream_ = sender_->call_->CreateVideoSendStream(
          std::move(send_config), std::move(encoder_config));
    }

    if (matcher->Active()) {
      frame_tap_ = std::make_unique<ForwardingCapturedFrameTap>(
          &sender_->env_.clock(), matcher, video_capturer_.get());
      send_stream_->SetSource(frame_tap_.get(),
                              config.encoder.degradation_preference);
    } else {
      send_stream_->SetSource(video_capturer_.get(),
                              config.encoder.degradation_preference);
    }
  });
}

SendVideoStream::~SendVideoStream() {
  sender_->SendTask(
      [this] { sender_->call_->DestroyVideoSendStream(send_stream_); });
}

void SendVideoStream::Start() {
  sender_->SendTask([this] {
    send_stream_->Start();
    sender_->call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
  });
}

void SendVideoStream::Stop() {
  sender_->SendTask([this] { send_stream_->Stop(); });
}

void SendVideoStream::UpdateConfig(
    std::function<void(VideoStreamConfig*)> modifier) {
  sender_->SendTask([&] {
    MutexLock lock(&mutex_);
    VideoStreamConfig prior_config = config_;
    modifier(&config_);
    if (prior_config.encoder.fake.max_rate != config_.encoder.fake.max_rate) {
      for (auto* encoder : fake_encoders_) {
        encoder->SetMaxBitrate(config_.encoder.fake.max_rate.kbps());
      }
    }
    // TODO(srte): Add more conditions that should cause reconfiguration.
    if (prior_config.encoder.max_framerate != config_.encoder.max_framerate ||
        prior_config.encoder.max_data_rate != config_.encoder.max_data_rate) {
      VideoEncoderConfig encoder_config = CreateVideoEncoderConfig(config_);
      send_stream_->ReconfigureVideoEncoder(std::move(encoder_config));
    }
    if (prior_config.source.framerate != config_.source.framerate) {
      SetCaptureFramerate(config_.source.framerate);
    }
  });
}

void SendVideoStream::UpdateActiveLayers(std::vector<bool> active_layers) {
  sender_->task_queue_.PostTask([this, active_layers] {
    MutexLock lock(&mutex_);
    VideoEncoderConfig encoder_config = CreateVideoEncoderConfig(config_);
    RTC_CHECK_EQ(encoder_config.simulcast_layers.size(), active_layers.size());
    for (size_t i = 0; i < encoder_config.simulcast_layers.size(); ++i)
      encoder_config.simulcast_layers[i].active = active_layers[i];
    send_stream_->ReconfigureVideoEncoder(std::move(encoder_config));
  });
}

bool SendVideoStream::UsingSsrc(uint32_t ssrc) const {
  for (uint32_t owned : ssrcs_) {
    if (owned == ssrc)
      return true;
  }
  return false;
}

bool SendVideoStream::UsingRtxSsrc(uint32_t ssrc) const {
  for (uint32_t owned : rtx_ssrcs_) {
    if (owned == ssrc)
      return true;
  }
  return false;
}

void SendVideoStream::SetCaptureFramerate(int framerate) {
  sender_->SendTask([&] { video_capturer_->ChangeFramerate(framerate); });
}

VideoSendStream::Stats SendVideoStream::GetStats() const {
  return send_stream_->GetStats();
}

ColumnPrinter SendVideoStream::StatsPrinter() {
  return ColumnPrinter::Lambda(
      "video_target_rate video_sent_rate width height",
      [this](SimpleStringBuilder& sb) {
        VideoSendStream::Stats video_stats = send_stream_->GetStats();
        int width = 0;
        int height = 0;
        for (const auto& stream_stat : video_stats.substreams) {
          width = std::max(width, stream_stat.second.width);
          height = std::max(height, stream_stat.second.height);
        }
        sb.AppendFormat("%.0lf %.0lf %i %i",
                        video_stats.target_media_bitrate_bps / 8.0,
                        video_stats.media_bitrate_bps / 8.0, width, height);
      },
      64);
}

ReceiveVideoStream::ReceiveVideoStream(CallClient* receiver,
                                       VideoStreamConfig config,
                                       SendVideoStream* send_stream,
                                       size_t chosen_stream,
                                       Transport* feedback_transport,
                                       VideoFrameMatcher* matcher)
    : receiver_(receiver), config_(config) {
  if (config.encoder.codec ==
          VideoStreamConfig::Encoder::Codec::kVideoCodecGeneric ||
      config.encoder.implementation == VideoStreamConfig::Encoder::kFake) {
    decoder_factory_ = std::make_unique<FunctionVideoDecoderFactory>(
        []() { return std::make_unique<FakeDecoder>(); });
  } else {
    decoder_factory_ = std::make_unique<InternalDecoderFactory>();
  }

  VideoReceiveStreamInterface::Decoder decoder =
      CreateMatchingDecoder(CodecTypeToPayloadType(config.encoder.codec),
                            CodecTypeToPayloadString(config.encoder.codec));
  size_t num_streams = config.encoder.simulcast_streams.size();
  for (size_t i = 0; i < num_streams; ++i) {
    VideoSinkInterface<VideoFrame>* renderer = &fake_renderer_;
    if (matcher->Active()) {
      render_taps_.emplace_back(std::make_unique<DecodedFrameTap>(
          &receiver_->env_.clock(), matcher, i));
      renderer = render_taps_.back().get();
    }
    auto recv_config = CreateVideoReceiveStreamConfig(
        config, feedback_transport, decoder_factory_.get(), decoder, renderer,
        receiver_->GetNextVideoLocalSsrc(), send_stream->ssrcs_[i],
        send_stream->rtx_ssrcs_[i]);
    if (config.stream.use_flexfec) {
      RTC_DCHECK(num_streams == 1);
      FlexfecReceiveStream::Config flexfec(feedback_transport);
      flexfec.payload_type = VideoTestConstants::kFlexfecPayloadType;
      flexfec.rtp.remote_ssrc = VideoTestConstants::kFlexfecSendSsrc;
      flexfec.protected_media_ssrcs = send_stream->rtx_ssrcs_;
      flexfec.rtp.local_ssrc = recv_config.rtp.local_ssrc;
      receiver_->ssrc_media_types_[flexfec.rtp.remote_ssrc] = MediaType::VIDEO;

      receiver_->SendTask([this, &flexfec] {
        flecfec_stream_ = receiver_->call_->CreateFlexfecReceiveStream(flexfec);
      });
    }
    receiver_->ssrc_media_types_[recv_config.rtp.remote_ssrc] =
        MediaType::VIDEO;
    if (config.stream.use_rtx)
      receiver_->ssrc_media_types_[recv_config.rtp.rtx_ssrc] = MediaType::VIDEO;
    receiver_->SendTask([this, &recv_config] {
      receive_streams_.push_back(
          receiver_->call_->CreateVideoReceiveStream(std::move(recv_config)));
    });
  }
}

ReceiveVideoStream::~ReceiveVideoStream() {
  receiver_->SendTask([this] {
    for (auto* recv_stream : receive_streams_)
      receiver_->call_->DestroyVideoReceiveStream(recv_stream);
    if (flecfec_stream_)
      receiver_->call_->DestroyFlexfecReceiveStream(flecfec_stream_);
  });
}

void ReceiveVideoStream::Start() {
  receiver_->SendTask([this] {
    for (auto* recv_stream : receive_streams_)
      recv_stream->Start();
    receiver_->call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
  });
}

void ReceiveVideoStream::Stop() {
  receiver_->SendTask([this] {
    for (auto* recv_stream : receive_streams_)
      recv_stream->Stop();
  });
}

VideoReceiveStreamInterface::Stats ReceiveVideoStream::GetStats() const {
  if (receive_streams_.empty())
    return VideoReceiveStreamInterface::Stats();
  // TODO(srte): Handle multiple receive streams.
  return receive_streams_.back()->GetStats();
}

VideoStreamPair::~VideoStreamPair() = default;

VideoStreamPair::VideoStreamPair(CallClient* sender,
                                 CallClient* receiver,
                                 VideoStreamConfig config)
    : config_(config),
      matcher_(config.hooks.frame_pair_handlers),
      send_stream_(sender, config, sender->transport_.get(), &matcher_),
      receive_stream_(receiver,
                      config,
                      &send_stream_,
                      /*chosen_stream=*/0,
                      receiver->transport_.get(),
                      &matcher_) {}

}  // namespace test
}  // namespace webrtc
