/*
 *  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 <memory>
#include <optional>
#include <utility>

#include "absl/algorithm/container.h"
#include "absl/strings/match.h"
#include "media/base/media_channel.h"
#include "rtc_base/checks.h"

namespace cricket {
using webrtc::TaskQueueBase;

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::SetPlayout(bool playout) {
  set_playout(playout);
}
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;
}
void FakeVoiceMediaReceiveChannel::SetRawAudioSink(
    uint32_t /* ssrc */,
    std::unique_ptr<webrtc::AudioSinkInterface> sink) {
  sink_ = std::move(sink);
}
void FakeVoiceMediaReceiveChannel::SetDefaultRawAudioSink(
    std::unique_ptr<webrtc::AudioSinkInterface> sink) {
  sink_ = std::move(sink);
}
std::vector<webrtc::RtpSource> FakeVoiceMediaReceiveChannel::GetSources(
    uint32_t /* ssrc */) const {
  return std::vector<webrtc::RtpSource>();
}
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));
}
void FakeVoiceMediaSendChannel::SetSend(bool send) {
  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;
}
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 std::vector<Codec>& FakeVideoMediaSendChannel::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,
    rtc::VideoSourceInterface<webrtc::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;
}
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(
    const VideoOptions& options,
    TaskQueueBase* network_thread)
    : RtpReceiveChannelHelper<VideoMediaReceiveChannelInterface>(
          network_thread),
      max_bps_(-1) {
  SetOptions(options);
}
FakeVideoMediaReceiveChannel::~FakeVideoMediaReceiveChannel() = default;
const std::vector<Codec>& FakeVideoMediaReceiveChannel::recv_codecs() const {
  return recv_codecs_;
}
bool FakeVideoMediaReceiveChannel::rendering() const {
  return playout();
}
const VideoOptions& FakeVideoMediaReceiveChannel::options() const {
  return options_;
}
const std::map<uint32_t, rtc::VideoSinkInterface<webrtc::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,
    rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) {
  auto it = sinks_.find(ssrc);
  if (it == sinks_.end()) {
    return false;
  }
  it->second = sink;
  return true;
}
void FakeVideoMediaReceiveChannel::SetDefaultSink(
    rtc::VideoSinkInterface<webrtc::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()] = NULL;
  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;
}
std::vector<webrtc::RtpSource> FakeVideoMediaReceiveChannel::GetSources(
    uint32_t /* ssrc */) const {
  return {};
}
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::SetOptions(const VideoOptions& options) {
  options_ = options;
  return true;
}

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

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

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

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

bool FakeVideoMediaReceiveChannel::GetStats(VideoMediaReceiveInfo* /* info */) {
  return false;
}

FakeVoiceEngine::FakeVoiceEngine() : fail_create_channel_(false) {
  // Add a fake audio codec. Note that the name must not be "" as there are
  // sanity checks against that.
  SetCodecs({cricket::CreateAudioCodec(101, "fake_audio_codec", 8000, 1)});
}
void FakeVoiceEngine::Init() {}
rtc::scoped_refptr<webrtc::AudioState> FakeVoiceEngine::GetAudioState() const {
  return rtc::scoped_refptr<webrtc::AudioState>();
}
std::unique_ptr<VoiceMediaSendChannelInterface>
FakeVoiceEngine::CreateSendChannel(
    webrtc::Call* call,
    const MediaConfig& /* config */,
    const AudioOptions& options,
    const webrtc::CryptoOptions& /* crypto_options */,
    webrtc::AudioCodecPairId /* codec_pair_id */) {
  std::unique_ptr<FakeVoiceMediaSendChannel> ch =
      std::make_unique<FakeVoiceMediaSendChannel>(options,
                                                  call->network_thread());
  return ch;
}
std::unique_ptr<VoiceMediaReceiveChannelInterface>
FakeVoiceEngine::CreateReceiveChannel(
    webrtc::Call* call,
    const MediaConfig& /* config */,
    const AudioOptions& options,
    const webrtc::CryptoOptions& /* crypto_options */,
    webrtc::AudioCodecPairId /* codec_pair_id */) {
  std::unique_ptr<FakeVoiceMediaReceiveChannel> ch =
      std::make_unique<FakeVoiceMediaReceiveChannel>(options,
                                                     call->network_thread());
  return ch;
}
const std::vector<Codec>& FakeVoiceEngine::send_codecs() const {
  return send_codecs_;
}
const std::vector<Codec>& FakeVoiceEngine::recv_codecs() 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(webrtc::FileWrapper /* file */,
                                   int64_t /* max_size_bytes */) {
  return false;
}
std::optional<webrtc::AudioDeviceModule::Stats>
FakeVoiceEngine::GetAudioDeviceStats() {
  return std::nullopt;
}
void FakeVoiceEngine::StopAecDump() {}

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

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

FakeVideoEngine::FakeVideoEngine()
    : capture_(false), fail_create_channel_(false) {
  // Add a fake video codec. Note that the name must not be "" as there are
  // sanity checks against that.
  send_codecs_.push_back(cricket::CreateVideoCodec(111, "fake_video_codec"));
  recv_codecs_.push_back(cricket::CreateVideoCodec(111, "fake_video_codec"));
}
bool FakeVideoEngine::SetOptions(const VideoOptions& options) {
  options_ = options;
  return true;
}
std::unique_ptr<VideoMediaSendChannelInterface>
FakeVideoEngine::CreateSendChannel(
    webrtc::Call* call,
    const MediaConfig& /* config */,
    const VideoOptions& options,
    const webrtc::CryptoOptions& /* crypto_options */,
    webrtc::
        VideoBitrateAllocatorFactory* /* video_bitrate_allocator_factory */) {
  if (fail_create_channel_) {
    return nullptr;
  }

  std::unique_ptr<FakeVideoMediaSendChannel> ch =
      std::make_unique<FakeVideoMediaSendChannel>(options,
                                                  call->network_thread());
  return ch;
}
std::unique_ptr<VideoMediaReceiveChannelInterface>
FakeVideoEngine::CreateReceiveChannel(
    webrtc::Call* call,
    const MediaConfig& /* config */,
    const VideoOptions& options,
    const webrtc::CryptoOptions& /* crypto_options */) {
  if (fail_create_channel_) {
    return nullptr;
  }

  std::unique_ptr<FakeVideoMediaReceiveChannel> ch =
      std::make_unique<FakeVideoMediaReceiveChannel>(options,
                                                     call->network_thread());
  return ch;
}
std::vector<Codec> FakeVideoEngine::send_codecs(bool /* use_rtx */) const {
  return send_codecs_;
}

std::vector<Codec> FakeVideoEngine::recv_codecs(bool /* use_rtx */) const {
  return recv_codecs_;
}

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<webrtc::RtpHeaderExtensionCapability>
FakeVideoEngine::GetRtpHeaderExtensions() const {
  return header_extensions_;
}
void FakeVideoEngine::SetRtpHeaderExtensions(
    std::vector<webrtc::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::set_fail_create_channel(bool fail) {
  voice_->fail_create_channel_ = fail;
  video_->fail_create_channel_ = fail;
}

}  // namespace cricket
