/*
 *  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 "media/base/fake_media_engine.h"

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

#include "absl/functional/any_invocable.h"
#include "absl/strings/match.h"
#include "api/audio/audio_device.h"
#include "api/audio_options.h"
#include "api/call/audio_sink.h"
#include "api/crypto/crypto_options.h"
#include "api/environment/environment.h"
#include "api/field_trials_view.h"
#include "api/make_ref_counted.h"
#include "api/rtp_packet_infos.h"
#include "api/rtp_parameters.h"
#include "api/scoped_refptr.h"
#include "api/task_queue/task_queue_base.h"
#include "api/units/timestamp.h"
#include "api/video/recordable_encoded_frame.h"
#include "api/video/video_bitrate_allocator_factory.h"
#include "api/video/video_sink_interface.h"
#include "api/video/video_source_interface.h"
#include "api/video_codecs/sdp_video_format.h"
#include "call/audio_state.h"
#include "call/call.h"
#include "media/base/audio_source.h"
#include "media/base/codec.h"
#include "media/base/media_channel.h"
#include "media/base/media_config.h"
#include "media/base/media_constants.h"
#include "media/base/media_engine.h"
#include "media/base/stream_params.h"
#include "rtc_base/checks.h"
#include "rtc_base/system/file_wrapper.h"

namespace webrtc {

FakeVoiceMediaReceiveChannel::DtmfInfo::DtmfInfo(uint32_t ssrc,
                                                 int event_code,
                                                 int duration)
    : ssrc(ssrc), event_code(event_code), duration(duration) {}

FakeVoiceMediaReceiveChannel::VoiceChannelAudioSink::VoiceChannelAudioSink(
    AudioSource* source)
    : source_(source) {
  source_->SetSink(this);
}
FakeVoiceMediaReceiveChannel::VoiceChannelAudioSink::~VoiceChannelAudioSink() {
  if (source_) {
    source_->SetSink(nullptr);
  }
}
void FakeVoiceMediaReceiveChannel::VoiceChannelAudioSink::OnData(
    const void* /* audio_data */,
    int /* bits_per_sample */,
    int /* sample_rate */,
    size_t /* number_of_channels */,
    size_t /* number_of_frames */,
    std::optional<int64_t> /* absolute_capture_timestamp_ms */) {}
void FakeVoiceMediaReceiveChannel::VoiceChannelAudioSink::OnClose() {
  source_ = nullptr;
}
AudioSource* FakeVoiceMediaReceiveChannel::VoiceChannelAudioSink::source()
    const {
  return source_;
}

FakeVoiceMediaReceiveChannel::FakeVoiceMediaReceiveChannel(
    const AudioOptions& options,
    TaskQueueBase* network_thread)
    : RtpReceiveChannelHelper<VoiceMediaReceiveChannelInterface>(
          network_thread),
      max_bps_(-1) {
  output_scalings_[0] = 1.0;  // For default channel.
  SetOptions(options);
}
FakeVoiceMediaReceiveChannel::~FakeVoiceMediaReceiveChannel() = default;
const std::vector<Codec>& FakeVoiceMediaReceiveChannel::recv_codecs() const {
  return recv_codecs_;
}
const std::vector<FakeVoiceMediaReceiveChannel::DtmfInfo>&
FakeVoiceMediaReceiveChannel::dtmf_info_queue() const {
  return dtmf_info_queue_;
}
const AudioOptions& FakeVoiceMediaReceiveChannel::options() const {
  return options_;
}
int FakeVoiceMediaReceiveChannel::max_bps() const {
  return max_bps_;
}
bool FakeVoiceMediaReceiveChannel::SetReceiverParameters(
    const AudioReceiverParameters& params) {
  set_recv_rtcp_parameters(params.rtcp);
  return (SetRecvCodecs(params.codecs) &&
          SetRecvRtpHeaderExtensions(params.extensions));
}
void FakeVoiceMediaReceiveChannel::SetReceive(bool receive) {
  set_playout(receive);
}
bool FakeVoiceMediaReceiveChannel::HasSource(uint32_t ssrc) const {
  return local_sinks_.find(ssrc) != local_sinks_.end();
}
bool FakeVoiceMediaReceiveChannel::AddRecvStream(const StreamParams& sp) {
  if (!RtpReceiveChannelHelper<
          VoiceMediaReceiveChannelInterface>::AddRecvStream(sp))
    return false;
  output_scalings_[sp.first_ssrc()] = 1.0;
  output_delays_[sp.first_ssrc()] = 0;
  return true;
}
bool FakeVoiceMediaReceiveChannel::RemoveRecvStream(uint32_t ssrc) {
  if (!RtpReceiveChannelHelper<
          VoiceMediaReceiveChannelInterface>::RemoveRecvStream(ssrc))
    return false;
  output_scalings_.erase(ssrc);
  output_delays_.erase(ssrc);
  return true;
}
bool FakeVoiceMediaReceiveChannel::SetOutputVolume(uint32_t ssrc,
                                                   double volume) {
  if (output_scalings_.find(ssrc) != output_scalings_.end()) {
    output_scalings_[ssrc] = volume;
    return true;
  }
  return false;
}
bool FakeVoiceMediaReceiveChannel::SetDefaultOutputVolume(double volume) {
  for (auto& entry : output_scalings_) {
    entry.second = volume;
  }
  return true;
}
bool FakeVoiceMediaReceiveChannel::GetOutputVolume(uint32_t ssrc,
                                                   double* volume) {
  if (output_scalings_.find(ssrc) == output_scalings_.end())
    return false;
  *volume = output_scalings_[ssrc];
  return true;
}
bool FakeVoiceMediaReceiveChannel::SetBaseMinimumPlayoutDelayMs(uint32_t ssrc,
                                                                int delay_ms) {
  if (output_delays_.find(ssrc) == output_delays_.end()) {
    return false;
  } else {
    output_delays_[ssrc] = delay_ms;
    return true;
  }
}
std::optional<int> FakeVoiceMediaReceiveChannel::GetBaseMinimumPlayoutDelayMs(
    uint32_t ssrc) const {
  const auto it = output_delays_.find(ssrc);
  if (it != output_delays_.end()) {
    return it->second;
  }
  return std::nullopt;
}
bool FakeVoiceMediaReceiveChannel::GetStats(
    VoiceMediaReceiveInfo* /* info */,
    bool /* get_and_clear_legacy_stats */) {
  return false;
}
absl::AnyInvocable<std::optional<VoiceMediaReceiveInfo>()>
FakeVoiceMediaReceiveChannel::GetStatsTask(bool reset_legacy) {
  return [this, reset_legacy]() -> std::optional<VoiceMediaReceiveInfo> {
    VoiceMediaReceiveInfo info;
    if (GetStats(&info, reset_legacy)) {
      return info;
    }
    return std::nullopt;
  };
}
void FakeVoiceMediaReceiveChannel::SetRawAudioSink(
    uint32_t /* ssrc */,
    std::unique_ptr<AudioSinkInterface> sink) {
  sink_ = std::move(sink);
}
void FakeVoiceMediaReceiveChannel::SetDefaultRawAudioSink(
    std::unique_ptr<AudioSinkInterface> sink) {
  sink_ = std::move(sink);
}
bool FakeVoiceMediaReceiveChannel::SetRecvCodecs(
    const std::vector<Codec>& codecs) {
  if (fail_set_recv_codecs()) {
    // Fake the failure in SetRecvCodecs.
    return false;
  }
  recv_codecs_ = codecs;
  return true;
}
bool FakeVoiceMediaReceiveChannel::SetMaxSendBandwidth(int bps) {
  max_bps_ = bps;
  return true;
}
bool FakeVoiceMediaReceiveChannel::SetOptions(const AudioOptions& options) {
  // Does a "merge" of current options and set options.
  options_.SetAll(options);
  return true;
}

FakeVoiceMediaSendChannel::DtmfInfo::DtmfInfo(uint32_t ssrc,
                                              int event_code,
                                              int duration)
    : ssrc(ssrc), event_code(event_code), duration(duration) {}

FakeVoiceMediaSendChannel::VoiceChannelAudioSink::VoiceChannelAudioSink(
    AudioSource* source)
    : source_(source) {
  source_->SetSink(this);
}
FakeVoiceMediaSendChannel::VoiceChannelAudioSink::~VoiceChannelAudioSink() {
  if (source_) {
    source_->SetSink(nullptr);
  }
}
void FakeVoiceMediaSendChannel::VoiceChannelAudioSink::OnData(
    const void* /* audio_data */,
    int /* bits_per_sample */,
    int /* sample_rate */,
    size_t /* number_of_channels */,
    size_t /* number_of_frames */,
    std::optional<int64_t> /* absolute_capture_timestamp_ms */) {}
void FakeVoiceMediaSendChannel::VoiceChannelAudioSink::OnClose() {
  source_ = nullptr;
}
AudioSource* FakeVoiceMediaSendChannel::VoiceChannelAudioSink::source() const {
  return source_;
}

FakeVoiceMediaSendChannel::FakeVoiceMediaSendChannel(
    const AudioOptions& options,
    TaskQueueBase* network_thread)
    : RtpSendChannelHelper<VoiceMediaSendChannelInterface>(network_thread),
      max_bps_(-1) {
  output_scalings_[0] = 1.0;  // For default channel.
  SetOptions(options);
}
FakeVoiceMediaSendChannel::~FakeVoiceMediaSendChannel() = default;
const std::vector<Codec>& FakeVoiceMediaSendChannel::send_codecs() const {
  return send_codecs_;
}
std::optional<Codec> FakeVoiceMediaSendChannel::GetSendCodec() const {
  if (!send_codecs_.empty()) {
    return send_codecs_.front();
  }
  return std::nullopt;
}
const std::vector<FakeVoiceMediaSendChannel::DtmfInfo>&
FakeVoiceMediaSendChannel::dtmf_info_queue() const {
  return dtmf_info_queue_;
}
const AudioOptions& FakeVoiceMediaSendChannel::options() const {
  return options_;
}
int FakeVoiceMediaSendChannel::max_bps() const {
  return max_bps_;
}
bool FakeVoiceMediaSendChannel::SetSenderParameters(
    const AudioSenderParameter& params) {
  set_send_rtcp_parameters(params.rtcp);
  SetExtmapAllowMixed(params.extmap_allow_mixed);
  return (SetSendCodecs(params.codecs) &&
          SetSendRtpHeaderExtensions(params.extensions) &&
          SetMaxSendBandwidth(params.max_bandwidth_bps) &&
          SetOptions(params.options));
}
bool FakeVoiceMediaSendChannel::SetSend(bool send) {
  return set_sending(send);
}
bool FakeVoiceMediaSendChannel::SetAudioSend(uint32_t ssrc,
                                             bool enable,
                                             const AudioOptions* options,
                                             AudioSource* source) {
  if (!SetLocalSource(ssrc, source)) {
    return false;
  }
  if (!RtpSendChannelHelper<VoiceMediaSendChannelInterface>::MuteStream(
          ssrc, !enable)) {
    return false;
  }
  if (enable && options) {
    return SetOptions(*options);
  }
  return true;
}
bool FakeVoiceMediaSendChannel::HasSource(uint32_t ssrc) const {
  return local_sinks_.find(ssrc) != local_sinks_.end();
}
bool FakeVoiceMediaSendChannel::CanInsertDtmf() {
  for (std::vector<Codec>::const_iterator it = send_codecs_.begin();
       it != send_codecs_.end(); ++it) {
    // Find the DTMF telephone event "codec".
    if (absl::EqualsIgnoreCase(it->name, "telephone-event")) {
      return true;
    }
  }
  return false;
}
bool FakeVoiceMediaSendChannel::InsertDtmf(uint32_t ssrc,
                                           int event_code,
                                           int duration) {
  dtmf_info_queue_.push_back(DtmfInfo(ssrc, event_code, duration));
  return true;
}
bool FakeVoiceMediaSendChannel::GetOutputVolume(uint32_t ssrc, double* volume) {
  if (output_scalings_.find(ssrc) == output_scalings_.end())
    return false;
  *volume = output_scalings_[ssrc];
  return true;
}
bool FakeVoiceMediaSendChannel::GetStats(VoiceMediaSendInfo* /* info */) {
  return false;
}
absl::AnyInvocable<std::optional<VoiceMediaSendInfo>()>
FakeVoiceMediaSendChannel::GetStatsTask() {
  return [this]() -> std::optional<VoiceMediaSendInfo> {
    VoiceMediaSendInfo info;
    if (GetStats(&info)) {
      return info;
    }
    return std::nullopt;
  };
}
bool FakeVoiceMediaSendChannel::SetSendCodecs(
    const std::vector<Codec>& codecs) {
  if (fail_set_send_codecs()) {
    // Fake the failure in SetSendCodecs.
    return false;
  }
  send_codecs_ = codecs;
  return true;
}
bool FakeVoiceMediaSendChannel::SetMaxSendBandwidth(int bps) {
  max_bps_ = bps;
  return true;
}
bool FakeVoiceMediaSendChannel::SetOptions(const AudioOptions& options) {
  // Does a "merge" of current options and set options.
  options_.SetAll(options);
  return true;
}
bool FakeVoiceMediaSendChannel::SetLocalSource(uint32_t ssrc,
                                               AudioSource* source) {
  auto it = local_sinks_.find(ssrc);
  if (source) {
    if (it != local_sinks_.end()) {
      RTC_CHECK(it->second->source() == source);
    } else {
      local_sinks_.insert(std::make_pair(
          ssrc, std::make_unique<VoiceChannelAudioSink>(source)));
    }
  } else {
    if (it != local_sinks_.end()) {
      local_sinks_.erase(it);
    }
  }
  return true;
}

bool CompareDtmfInfo(const FakeVoiceMediaSendChannel::DtmfInfo& info,
                     uint32_t ssrc,
                     int event_code,
                     int duration) {
  return (info.duration == duration && info.event_code == event_code &&
          info.ssrc == ssrc);
}

FakeVideoMediaSendChannel::FakeVideoMediaSendChannel(
    const VideoOptions& options,
    TaskQueueBase* network_thread)
    : RtpSendChannelHelper<VideoMediaSendChannelInterface>(network_thread),
      max_bps_(-1) {
  SetOptions(options);
}
FakeVideoMediaSendChannel::~FakeVideoMediaSendChannel() = default;
const std::vector<Codec>& FakeVideoMediaSendChannel::send_codecs() const {
  return send_codecs_;
}
const VideoOptions& FakeVideoMediaSendChannel::options() const {
  return options_;
}
int FakeVideoMediaSendChannel::max_bps() const {
  return max_bps_;
}
bool FakeVideoMediaSendChannel::SetSenderParameters(
    const VideoSenderParameters& params) {
  set_send_rtcp_parameters(params.rtcp);
  SetExtmapAllowMixed(params.extmap_allow_mixed);
  return (SetSendCodecs(params.codecs) &&
          SetSendRtpHeaderExtensions(params.extensions) &&
          SetMaxSendBandwidth(params.max_bandwidth_bps));
}
std::optional<Codec> FakeVideoMediaSendChannel::GetSendCodec() const {
  if (send_codecs_.empty()) {
    return std::nullopt;
  }
  return send_codecs_[0];
}
bool FakeVideoMediaSendChannel::SetSend(bool send) {
  return set_sending(send);
}
bool FakeVideoMediaSendChannel::SetVideoSend(
    uint32_t ssrc,
    const VideoOptions* options,
    VideoSourceInterface<VideoFrame>* source) {
  if (options) {
    if (!SetOptions(*options)) {
      return false;
    }
  }
  sources_[ssrc] = source;
  return true;
}
bool FakeVideoMediaSendChannel::HasSource(uint32_t ssrc) const {
  return sources_.find(ssrc) != sources_.end() && sources_.at(ssrc) != nullptr;
}
void FakeVideoMediaSendChannel::FillBitrateInfo(
    BandwidthEstimationInfo* /* bwe_info */) {}
bool FakeVideoMediaSendChannel::GetStats(VideoMediaSendInfo* /* info */) {
  return false;
}
absl::AnyInvocable<std::optional<VideoMediaSendInfo>()>
FakeVideoMediaSendChannel::GetStatsTask() {
  return [this]() -> std::optional<VideoMediaSendInfo> {
    VideoMediaSendInfo info;
    if (GetStats(&info)) {
      return info;
    }
    return std::nullopt;
  };
}
bool FakeVideoMediaSendChannel::SetSendCodecs(
    const std::vector<Codec>& codecs) {
  if (fail_set_send_codecs()) {
    // Fake the failure in SetSendCodecs.
    return false;
  }
  send_codecs_ = codecs;

  return true;
}
bool FakeVideoMediaSendChannel::SetOptions(const VideoOptions& options) {
  options_ = options;
  return true;
}

bool FakeVideoMediaSendChannel::SetMaxSendBandwidth(int bps) {
  max_bps_ = bps;
  return true;
}
void FakeVideoMediaSendChannel::GenerateSendKeyFrame(
    uint32_t /* ssrc */,
    const std::vector<std::string>& /* rids */) {}

FakeVideoMediaReceiveChannel::FakeVideoMediaReceiveChannel(
    TaskQueueBase* network_thread)
    : RtpReceiveChannelHelper<VideoMediaReceiveChannelInterface>(
          network_thread),
      max_bps_(-1) {}
FakeVideoMediaReceiveChannel::~FakeVideoMediaReceiveChannel() = default;
const std::vector<Codec>& FakeVideoMediaReceiveChannel::recv_codecs() const {
  return recv_codecs_;
}
bool FakeVideoMediaReceiveChannel::rendering() const {
  return playout();
}

const std::map<uint32_t, VideoSinkInterface<VideoFrame>*>&
FakeVideoMediaReceiveChannel::sinks() const {
  return sinks_;
}
int FakeVideoMediaReceiveChannel::max_bps() const {
  return max_bps_;
}
bool FakeVideoMediaReceiveChannel::SetReceiverParameters(
    const VideoReceiverParameters& params) {
  set_recv_rtcp_parameters(params.rtcp);
  return (SetRecvCodecs(params.codecs) &&
          SetRecvRtpHeaderExtensions(params.extensions));
}
bool FakeVideoMediaReceiveChannel::SetSink(
    uint32_t ssrc,
    VideoSinkInterface<VideoFrame>* sink) {
  auto it = sinks_.find(ssrc);
  if (it == sinks_.end()) {
    return false;
  }
  it->second = sink;
  return true;
}
void FakeVideoMediaReceiveChannel::SetDefaultSink(
    VideoSinkInterface<VideoFrame>* /* sink */) {}
bool FakeVideoMediaReceiveChannel::HasSink(uint32_t ssrc) const {
  return sinks_.find(ssrc) != sinks_.end() && sinks_.at(ssrc) != nullptr;
}
bool FakeVideoMediaReceiveChannel::HasSource(uint32_t ssrc) const {
  return sources_.find(ssrc) != sources_.end() && sources_.at(ssrc) != nullptr;
}
bool FakeVideoMediaReceiveChannel::AddRecvStream(const StreamParams& sp) {
  if (!RtpReceiveChannelHelper<
          VideoMediaReceiveChannelInterface>::AddRecvStream(sp))
    return false;
  sinks_[sp.first_ssrc()] = nullptr;
  output_delays_[sp.first_ssrc()] = 0;
  return true;
}
bool FakeVideoMediaReceiveChannel::RemoveRecvStream(uint32_t ssrc) {
  if (!RtpReceiveChannelHelper<
          VideoMediaReceiveChannelInterface>::RemoveRecvStream(ssrc))
    return false;
  sinks_.erase(ssrc);
  output_delays_.erase(ssrc);
  return true;
}
bool FakeVideoMediaReceiveChannel::SetBaseMinimumPlayoutDelayMs(uint32_t ssrc,
                                                                int delay_ms) {
  if (output_delays_.find(ssrc) == output_delays_.end()) {
    return false;
  } else {
    output_delays_[ssrc] = delay_ms;
    return true;
  }
}
std::optional<int> FakeVideoMediaReceiveChannel::GetBaseMinimumPlayoutDelayMs(
    uint32_t ssrc) const {
  const auto it = output_delays_.find(ssrc);
  if (it != output_delays_.end()) {
    return it->second;
  }
  return std::nullopt;
}
bool FakeVideoMediaReceiveChannel::SetRecvCodecs(
    const std::vector<Codec>& codecs) {
  if (fail_set_recv_codecs()) {
    // Fake the failure in SetRecvCodecs.
    return false;
  }
  recv_codecs_ = codecs;
  return true;
}

bool FakeVideoMediaReceiveChannel::SetMaxSendBandwidth(int bps) {
  max_bps_ = bps;
  return true;
}

void FakeVideoMediaReceiveChannel::SetRecordableEncodedFrameCallback(
    uint32_t /* ssrc */,
    std::function<void(const RecordableEncodedFrame&)> /* callback */) {}

void FakeVideoMediaReceiveChannel::ClearRecordableEncodedFrameCallback(
    uint32_t /* ssrc */) {}

void FakeVideoMediaReceiveChannel::RequestRecvKeyFrame(uint32_t /* ssrc */) {}

bool FakeVideoMediaReceiveChannel::GetStats(VideoMediaReceiveInfo* /* info */) {
  return false;
}
absl::AnyInvocable<std::optional<VideoMediaReceiveInfo>()>
FakeVideoMediaReceiveChannel::GetStatsTask() {
  return [this]() -> std::optional<VideoMediaReceiveInfo> {
    VideoMediaReceiveInfo info;
    if (GetStats(&info)) {
      return info;
    }
    return std::nullopt;
  };
}

FakeVoiceEngine::FakeVoiceEngine()
    : encoder_factory_(make_ref_counted<FakeVoiceEncoderFactory>(this)),
      decoder_factory_(make_ref_counted<FakeVoiceDecoderFactory>(this)) {
  // Add a fake audio codec. Note that the name must not be "" as there are
  // sanity checks against that.
  SetCodecs({CreateAudioCodec(101, "fake_audio_codec", 8000, 1)});
}

void FakeVoiceEngine::Init() {}

void FakeVoiceEngine::Terminate() {}

scoped_refptr<AudioState> FakeVoiceEngine::GetAudioState() const {
  return scoped_refptr<AudioState>();
}
std::unique_ptr<VoiceMediaSendChannelInterface>
FakeVoiceEngine::CreateSendChannel(
    const Environment& /*env*/,
    Call* call,
    const MediaConfig& /* config */,
    const AudioOptions& options,
    const CryptoOptions& /* crypto_options */,
    absl::AnyInvocable<void()> /* parameters_changed_callback */) {
  std::unique_ptr<FakeVoiceMediaSendChannel> ch =
      std::make_unique<FakeVoiceMediaSendChannel>(options,
                                                  call->network_thread());
  return ch;
}
std::unique_ptr<VoiceMediaReceiveChannelInterface>
FakeVoiceEngine::CreateReceiveChannel(
    const Environment& /*env*/,
    Call* call,
    const MediaConfig& /* config */,
    const AudioOptions& options,
    const CryptoOptions& /* crypto_options */,
    absl::AnyInvocable<void(uint32_t ssrc)> /*on_first_packet*/,
    absl::AnyInvocable<void(uint32_t ssrc, const RtpPacketInfos&, Timestamp)
                           const> /* on_frame_delivered_callback */) {
  std::unique_ptr<FakeVoiceMediaReceiveChannel> ch =
      std::make_unique<FakeVoiceMediaReceiveChannel>(options,
                                                     call->network_thread());
  return ch;
}
const std::vector<Codec>& FakeVoiceEngine::LegacySendCodecs() const {
  return send_codecs_;
}
const std::vector<Codec>& FakeVoiceEngine::LegacyRecvCodecs() const {
  return recv_codecs_;
}
void FakeVoiceEngine::SetCodecs(const std::vector<Codec>& codecs) {
  send_codecs_ = codecs;
  recv_codecs_ = codecs;
}
void FakeVoiceEngine::SetRecvCodecs(const std::vector<Codec>& codecs) {
  recv_codecs_ = codecs;
}
void FakeVoiceEngine::SetSendCodecs(const std::vector<Codec>& codecs) {
  send_codecs_ = codecs;
}
int FakeVoiceEngine::GetInputLevel() {
  return 0;
}
bool FakeVoiceEngine::StartAecDump(FileWrapper /* file */,
                                   int64_t /* max_size_bytes */) {
  return false;
}
std::optional<AudioDeviceModule::Stats> FakeVoiceEngine::GetAudioDeviceStats() {
  return std::nullopt;
}
void FakeVoiceEngine::StopAecDump() {}

std::vector<RtpHeaderExtensionCapability>
FakeVoiceEngine::GetRtpHeaderExtensions(
    const FieldTrialsView* field_trials) const {
  return header_extensions_;
}

void FakeVoiceEngine::SetRtpHeaderExtensions(
    std::vector<RtpHeaderExtensionCapability> header_extensions) {
  header_extensions_ = std::move(header_extensions);
}

FakeVideoEngine::FakeVideoEngine()
    : encoder_factory_(std::make_unique<FakeVideoEncoderFactory>(this)),
      decoder_factory_(std::make_unique<FakeVideoDecoderFactory>(this)),
      capture_(false) {
  // Add a fake video codec. Note that the name must not be "" as there are
  // sanity checks against that.
  send_codecs_.push_back(CreateVideoCodec(111, "fake_video_codec"));
  recv_codecs_.push_back(CreateVideoCodec(111, "fake_video_codec"));
}
bool FakeVideoEngine::SetOptions(const VideoOptions& options) {
  options_ = options;
  return true;
}
std::unique_ptr<VideoMediaSendChannelInterface>
FakeVideoEngine::CreateSendChannel(
    const Environment& /* env */,
    Call* call,
    const MediaConfig& /* config */,
    const VideoOptions& options,
    const CryptoOptions& /* crypto_options */,
    VideoBitrateAllocatorFactory* /* video_bitrate_allocator_factory */,
    VideoMediaSendChannelInterface::EncoderSwitchRequestCallback
    /* video_encoder_switch_request_callback */,
    absl::AnyInvocable<void()> /* parameters_changed_callback */) {
  std::unique_ptr<FakeVideoMediaSendChannel> ch =
      std::make_unique<FakeVideoMediaSendChannel>(options,
                                                  call->network_thread());
  return ch;
}
std::unique_ptr<VideoMediaReceiveChannelInterface>
FakeVideoEngine::CreateReceiveChannel(
    const Environment& /* env */,
    Call* call,
    const MediaConfig& /* config */,
    const CryptoOptions& /* crypto_options */,
    absl::AnyInvocable<void(uint32_t ssrc)> /*on_first_packet*/,
    absl::AnyInvocable<void(uint32_t ssrc, const RtpPacketInfos&, Timestamp)
                           const> /* on_frame_delivered_callback */) {
  std::unique_ptr<FakeVideoMediaReceiveChannel> ch =
      std::make_unique<FakeVideoMediaReceiveChannel>(call->network_thread());
  return ch;
}
std::vector<Codec> FakeVideoEngine::LegacySendCodecs(bool use_rtx) const {
  if (use_rtx) {
    return send_codecs_;
  }
  std::vector<Codec> out;
  for (const auto& codec : send_codecs_) {
    if (codec.name != kRtxCodecName) {
      out.push_back(codec);
    }
  }
  return out;
}

std::vector<Codec> FakeVideoEngine::LegacyRecvCodecs(bool use_rtx) const {
  if (use_rtx) {
    return recv_codecs_;
  }
  std::vector<Codec> out;
  for (const auto& codec : recv_codecs_) {
    if (codec.name != kRtxCodecName) {
      out.push_back(codec);
    }
  }
  return out;
}

std::vector<SdpVideoFormat> FakeVideoEngine::GetSupportedFormats(
    bool is_decoder) const {
  if (is_decoder) {
    return decoder_factory_->GetSupportedFormats();
  } else {
    return encoder_factory_->GetSupportedFormats();
  }
}

void FakeVideoEngine::SetSendCodecs(const std::vector<Codec>& codecs) {
  send_codecs_ = codecs;
}

void FakeVideoEngine::SetRecvCodecs(const std::vector<Codec>& codecs) {
  recv_codecs_ = codecs;
}

bool FakeVideoEngine::SetCapture(bool capture) {
  capture_ = capture;
  return true;
}
std::vector<RtpHeaderExtensionCapability>
FakeVideoEngine::GetRtpHeaderExtensions(
    const FieldTrialsView* field_trials) const {
  return header_extensions_;
}
void FakeVideoEngine::SetRtpHeaderExtensions(
    std::vector<RtpHeaderExtensionCapability> header_extensions) {
  header_extensions_ = std::move(header_extensions);
}

FakeMediaEngine::FakeMediaEngine()
    : CompositeMediaEngine(std::make_unique<FakeVoiceEngine>(),
                           std::make_unique<FakeVideoEngine>()),
      voice_(static_cast<FakeVoiceEngine*>(&voice())),
      video_(static_cast<FakeVideoEngine*>(&video())) {}
FakeMediaEngine::~FakeMediaEngine() {}
void FakeMediaEngine::SetAudioCodecs(const std::vector<Codec>& codecs) {
  voice_->SetCodecs(codecs);
}
void FakeMediaEngine::SetAudioRecvCodecs(const std::vector<Codec>& codecs) {
  voice_->SetRecvCodecs(codecs);
}
void FakeMediaEngine::SetAudioSendCodecs(const std::vector<Codec>& codecs) {
  voice_->SetSendCodecs(codecs);
}
void FakeMediaEngine::SetVideoCodecs(const std::vector<Codec>& codecs) {
  video_->SetSendCodecs(codecs);
  video_->SetRecvCodecs(codecs);
}
void FakeMediaEngine::SetVideoRecvCodecs(const std::vector<Codec>& codecs) {
  video_->SetRecvCodecs(codecs);
}
void FakeMediaEngine::SetVideoSendCodecs(const std::vector<Codec>& codecs) {
  video_->SetSendCodecs(codecs);
}

}  // namespace webrtc
