/*
 *  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 <utility>

#include "absl/algorithm/container.h"
#include "absl/strings/match.h"
#include "absl/types/optional.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,
    absl::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;
  }
}
absl::optional<int> FakeVoiceMediaReceiveChannel::GetBaseMinimumPlayoutDelayMs(
    uint32_t ssrc) const {
  const auto it = output_delays_.find(ssrc);
  if (it != output_delays_.end()) {
    return it->second;
  }
  return absl::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,
    absl::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_;
}
absl::optional<Codec> FakeVoiceMediaSendChannel::GetSendCodec() const {
  if (!send_codecs_.empty()) {
    return send_codecs_.front();
  }
  return absl::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));
}
absl::optional<Codec> FakeVideoMediaSendChannel::GetSendCodec() const {
  if (send_codecs_.empty()) {
    return absl::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;
  }
}
absl::optional<int> FakeVideoMediaReceiveChannel::GetBaseMinimumPlayoutDelayMs(
    uint32_t ssrc) const {
  const auto it = output_delays_.find(ssrc);
  if (it != output_delays_.end()) {
    return it->second;
  }
  return absl::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;
}
absl::optional<webrtc::AudioDeviceModule::Stats>
FakeVoiceEngine::GetAudioDeviceStats() {
  return absl::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
