/*
 *  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 "rtc_base/checks.h"

namespace cricket {
using webrtc::TaskQueueBase;

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

FakeVoiceMediaChannel::VoiceChannelAudioSink::VoiceChannelAudioSink(
    AudioSource* source)
    : source_(source) {
  source_->SetSink(this);
}
FakeVoiceMediaChannel::VoiceChannelAudioSink::~VoiceChannelAudioSink() {
  if (source_) {
    source_->SetSink(nullptr);
  }
}
void FakeVoiceMediaChannel::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 FakeVoiceMediaChannel::VoiceChannelAudioSink::OnClose() {
  source_ = nullptr;
}
AudioSource* FakeVoiceMediaChannel::VoiceChannelAudioSink::source() const {
  return source_;
}

FakeVoiceMediaChannel::FakeVoiceMediaChannel(MediaChannel::Role role,
                                             FakeVoiceEngine* engine,
                                             const AudioOptions& options,
                                             TaskQueueBase* network_thread)
    : RtpHelper<VoiceMediaChannel>(role, network_thread),
      engine_(engine),
      max_bps_(-1) {
  output_scalings_[0] = 1.0;  // For default channel.
  SetOptions(options);
}
FakeVoiceMediaChannel::~FakeVoiceMediaChannel() {
  if (engine_) {
    engine_->UnregisterChannel(this);
  }
}
const std::vector<AudioCodec>& FakeVoiceMediaChannel::recv_codecs() const {
  return recv_codecs_;
}
const std::vector<AudioCodec>& FakeVoiceMediaChannel::send_codecs() const {
  return send_codecs_;
}
const std::vector<AudioCodec>& FakeVoiceMediaChannel::codecs() const {
  return send_codecs();
}
const std::vector<FakeVoiceMediaChannel::DtmfInfo>&
FakeVoiceMediaChannel::dtmf_info_queue() const {
  return dtmf_info_queue_;
}
const AudioOptions& FakeVoiceMediaChannel::options() const {
  return options_;
}
int FakeVoiceMediaChannel::max_bps() const {
  return max_bps_;
}
bool FakeVoiceMediaChannel::SetSendParameters(
    const AudioSendParameters& params) {
  set_send_rtcp_parameters(params.rtcp);
  return (SetSendCodecs(params.codecs) &&
          SetSendExtmapAllowMixed(params.extmap_allow_mixed) &&
          SetSendRtpHeaderExtensions(params.extensions) &&
          SetMaxSendBandwidth(params.max_bandwidth_bps) &&
          SetOptions(params.options));
}
bool FakeVoiceMediaChannel::SetRecvParameters(
    const AudioRecvParameters& params) {
  set_recv_rtcp_parameters(params.rtcp);
  return (SetRecvCodecs(params.codecs) &&
          SetRecvRtpHeaderExtensions(params.extensions));
}
void FakeVoiceMediaChannel::SetPlayout(bool playout) {
  set_playout(playout);
}
void FakeVoiceMediaChannel::SetSend(bool send) {
  set_sending(send);
}
bool FakeVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
                                         bool enable,
                                         const AudioOptions* options,
                                         AudioSource* source) {
  if (!SetLocalSource(ssrc, source)) {
    return false;
  }
  if (!RtpHelper<VoiceMediaChannel>::MuteStream(ssrc, !enable)) {
    return false;
  }
  if (enable && options) {
    return SetOptions(*options);
  }
  return true;
}
bool FakeVoiceMediaChannel::HasSource(uint32_t ssrc) const {
  return local_sinks_.find(ssrc) != local_sinks_.end();
}
bool FakeVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
  if (!RtpHelper<VoiceMediaChannel>::AddRecvStream(sp))
    return false;
  output_scalings_[sp.first_ssrc()] = 1.0;
  output_delays_[sp.first_ssrc()] = 0;
  return true;
}
bool FakeVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
  if (!RtpHelper<VoiceMediaChannel>::RemoveRecvStream(ssrc))
    return false;
  output_scalings_.erase(ssrc);
  output_delays_.erase(ssrc);
  return true;
}
bool FakeVoiceMediaChannel::CanInsertDtmf() {
  for (std::vector<AudioCodec>::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 FakeVoiceMediaChannel::InsertDtmf(uint32_t ssrc,
                                       int event_code,
                                       int duration) {
  dtmf_info_queue_.push_back(DtmfInfo(ssrc, event_code, duration));
  return true;
}
bool FakeVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
  if (output_scalings_.find(ssrc) != output_scalings_.end()) {
    output_scalings_[ssrc] = volume;
    return true;
  }
  return false;
}
bool FakeVoiceMediaChannel::SetDefaultOutputVolume(double volume) {
  for (auto& entry : output_scalings_) {
    entry.second = volume;
  }
  return true;
}
bool FakeVoiceMediaChannel::GetOutputVolume(uint32_t ssrc, double* volume) {
  if (output_scalings_.find(ssrc) == output_scalings_.end())
    return false;
  *volume = output_scalings_[ssrc];
  return true;
}
bool FakeVoiceMediaChannel::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> FakeVoiceMediaChannel::GetBaseMinimumPlayoutDelayMs(
    uint32_t ssrc) const {
  const auto it = output_delays_.find(ssrc);
  if (it != output_delays_.end()) {
    return it->second;
  }
  return absl::nullopt;
}
bool FakeVoiceMediaChannel::GetSendStats(VoiceMediaSendInfo* info) {
  return false;
}
bool FakeVoiceMediaChannel::GetReceiveStats(VoiceMediaReceiveInfo* info,
                                            bool get_and_clear_legacy_stats) {
  return false;
}
void FakeVoiceMediaChannel::SetRawAudioSink(
    uint32_t ssrc,
    std::unique_ptr<webrtc::AudioSinkInterface> sink) {
  sink_ = std::move(sink);
}
void FakeVoiceMediaChannel::SetDefaultRawAudioSink(
    std::unique_ptr<webrtc::AudioSinkInterface> sink) {
  sink_ = std::move(sink);
}
std::vector<webrtc::RtpSource> FakeVoiceMediaChannel::GetSources(
    uint32_t ssrc) const {
  return std::vector<webrtc::RtpSource>();
}
bool FakeVoiceMediaChannel::SetRecvCodecs(
    const std::vector<AudioCodec>& codecs) {
  if (fail_set_recv_codecs()) {
    // Fake the failure in SetRecvCodecs.
    return false;
  }
  recv_codecs_ = codecs;
  return true;
}
bool FakeVoiceMediaChannel::SetSendCodecs(
    const std::vector<AudioCodec>& codecs) {
  if (fail_set_send_codecs()) {
    // Fake the failure in SetSendCodecs.
    return false;
  }
  send_codecs_ = codecs;
  return true;
}
bool FakeVoiceMediaChannel::SetMaxSendBandwidth(int bps) {
  max_bps_ = bps;
  return true;
}
bool FakeVoiceMediaChannel::SetOptions(const AudioOptions& options) {
  // Does a "merge" of current options and set options.
  options_.SetAll(options);
  return true;
}
bool FakeVoiceMediaChannel::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 FakeVoiceMediaChannel::DtmfInfo& info,
                     uint32_t ssrc,
                     int event_code,
                     int duration) {
  return (info.duration == duration && info.event_code == event_code &&
          info.ssrc == ssrc);
}

FakeVideoMediaChannel::FakeVideoMediaChannel(MediaChannel::Role role,
                                             FakeVideoEngine* engine,
                                             const VideoOptions& options,
                                             TaskQueueBase* network_thread)
    : RtpHelper<VideoMediaChannel>(role, network_thread),
      engine_(engine),
      max_bps_(-1) {
  SetOptions(options);
}
FakeVideoMediaChannel::~FakeVideoMediaChannel() {
  if (engine_) {
    engine_->UnregisterChannel(this);
  }
}
const std::vector<VideoCodec>& FakeVideoMediaChannel::recv_codecs() const {
  return recv_codecs_;
}
const std::vector<VideoCodec>& FakeVideoMediaChannel::send_codecs() const {
  return send_codecs_;
}
const std::vector<VideoCodec>& FakeVideoMediaChannel::codecs() const {
  return send_codecs();
}
bool FakeVideoMediaChannel::rendering() const {
  return playout();
}
const VideoOptions& FakeVideoMediaChannel::options() const {
  return options_;
}
const std::map<uint32_t, rtc::VideoSinkInterface<webrtc::VideoFrame>*>&
FakeVideoMediaChannel::sinks() const {
  return sinks_;
}
int FakeVideoMediaChannel::max_bps() const {
  return max_bps_;
}
bool FakeVideoMediaChannel::SetSendParameters(
    const VideoSendParameters& params) {
  set_send_rtcp_parameters(params.rtcp);
  return (SetSendCodecs(params.codecs) &&
          SetSendExtmapAllowMixed(params.extmap_allow_mixed) &&
          SetSendRtpHeaderExtensions(params.extensions) &&
          SetMaxSendBandwidth(params.max_bandwidth_bps));
}
bool FakeVideoMediaChannel::SetRecvParameters(
    const VideoRecvParameters& params) {
  set_recv_rtcp_parameters(params.rtcp);
  return (SetRecvCodecs(params.codecs) &&
          SetRecvRtpHeaderExtensions(params.extensions));
}
bool FakeVideoMediaChannel::AddSendStream(const StreamParams& sp) {
  return RtpHelper<VideoMediaChannel>::AddSendStream(sp);
}
bool FakeVideoMediaChannel::RemoveSendStream(uint32_t ssrc) {
  return RtpHelper<VideoMediaChannel>::RemoveSendStream(ssrc);
}
bool FakeVideoMediaChannel::GetSendCodec(VideoCodec* send_codec) {
  if (send_codecs_.empty()) {
    return false;
  }
  *send_codec = send_codecs_[0];
  return true;
}
bool FakeVideoMediaChannel::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 FakeVideoMediaChannel::SetDefaultSink(
    rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) {}
bool FakeVideoMediaChannel::HasSink(uint32_t ssrc) const {
  return sinks_.find(ssrc) != sinks_.end() && sinks_.at(ssrc) != nullptr;
}
bool FakeVideoMediaChannel::SetSend(bool send) {
  return set_sending(send);
}
bool FakeVideoMediaChannel::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 FakeVideoMediaChannel::HasSource(uint32_t ssrc) const {
  return sources_.find(ssrc) != sources_.end() && sources_.at(ssrc) != nullptr;
}
bool FakeVideoMediaChannel::AddRecvStream(const StreamParams& sp) {
  if (!RtpHelper<VideoMediaChannel>::AddRecvStream(sp))
    return false;
  sinks_[sp.first_ssrc()] = NULL;
  output_delays_[sp.first_ssrc()] = 0;
  return true;
}
bool FakeVideoMediaChannel::RemoveRecvStream(uint32_t ssrc) {
  if (!RtpHelper<VideoMediaChannel>::RemoveRecvStream(ssrc))
    return false;
  sinks_.erase(ssrc);
  output_delays_.erase(ssrc);
  return true;
}
void FakeVideoMediaChannel::FillBitrateInfo(BandwidthEstimationInfo* bwe_info) {
}
bool FakeVideoMediaChannel::GetSendStats(VideoMediaSendInfo* info) {
  return false;
}
bool FakeVideoMediaChannel::GetReceiveStats(VideoMediaReceiveInfo* info) {
  return false;
}
std::vector<webrtc::RtpSource> FakeVideoMediaChannel::GetSources(
    uint32_t ssrc) const {
  return {};
}
bool FakeVideoMediaChannel::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> FakeVideoMediaChannel::GetBaseMinimumPlayoutDelayMs(
    uint32_t ssrc) const {
  const auto it = output_delays_.find(ssrc);
  if (it != output_delays_.end()) {
    return it->second;
  }
  return absl::nullopt;
}
bool FakeVideoMediaChannel::SetRecvCodecs(
    const std::vector<VideoCodec>& codecs) {
  if (fail_set_recv_codecs()) {
    // Fake the failure in SetRecvCodecs.
    return false;
  }
  recv_codecs_ = codecs;
  return true;
}
bool FakeVideoMediaChannel::SetSendCodecs(
    const std::vector<VideoCodec>& codecs) {
  if (fail_set_send_codecs()) {
    // Fake the failure in SetSendCodecs.
    return false;
  }
  send_codecs_ = codecs;

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

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

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

void FakeVideoMediaChannel::ClearRecordableEncodedFrameCallback(uint32_t ssrc) {
}

void FakeVideoMediaChannel::RequestRecvKeyFrame(uint32_t ssrc) {}
void FakeVideoMediaChannel::GenerateSendKeyFrame(
    uint32_t ssrc,
    const std::vector<std::string>& rids) {}

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({AudioCodec(101, "fake_audio_codec", 0, 0, 1)});
}
void FakeVoiceEngine::Init() {}
rtc::scoped_refptr<webrtc::AudioState> FakeVoiceEngine::GetAudioState() const {
  return rtc::scoped_refptr<webrtc::AudioState>();
}
VoiceMediaChannel* FakeVoiceEngine::CreateMediaChannel(
    MediaChannel::Role role,
    webrtc::Call* call,
    const MediaConfig& config,
    const AudioOptions& options,
    const webrtc::CryptoOptions& crypto_options,
    webrtc::AudioCodecPairId codec_pair_id) {
  if (fail_create_channel_) {
    return nullptr;
  }

  FakeVoiceMediaChannel* ch =
      new FakeVoiceMediaChannel(role, this, options, call->network_thread());
  switch (role) {
    case MediaChannel::Role::kSend:
      send_channels_.push_back(ch);
      break;
    case MediaChannel::Role::kReceive:
      receive_channels_.push_back(ch);
      break;
    case MediaChannel::Role::kBoth:
      send_channels_.push_back(ch);
      receive_channels_.push_back(ch);
      break;
    default:
      RTC_CHECK_NOTREACHED();
  }
  return ch;
}
FakeVoiceMediaChannel* FakeVoiceEngine::GetSendChannel(size_t index) {
  return (send_channels_.size() > index) ? send_channels_[index] : NULL;
}
FakeVoiceMediaChannel* FakeVoiceEngine::GetReceiveChannel(size_t index) {
  return (receive_channels_.size() > index) ? receive_channels_[index] : NULL;
}
void FakeVoiceEngine::UnregisterChannel(VoiceMediaChannel* channel) {
  switch (channel->role()) {
    case MediaChannel::Role::kSend:
      send_channels_.erase(absl::c_find(send_channels_, channel));
      break;
    case MediaChannel::Role::kReceive:
      receive_channels_.erase(absl::c_find(receive_channels_, channel));
      break;
    case MediaChannel::Role::kBoth:
      send_channels_.erase(absl::c_find(send_channels_, channel));
      receive_channels_.erase(absl::c_find(receive_channels_, channel));
      break;
    default:
      RTC_CHECK_NOTREACHED();
  }
}
const std::vector<AudioCodec>& FakeVoiceEngine::send_codecs() const {
  return send_codecs_;
}
const std::vector<AudioCodec>& FakeVoiceEngine::recv_codecs() const {
  return recv_codecs_;
}
void FakeVoiceEngine::SetCodecs(const std::vector<AudioCodec>& codecs) {
  send_codecs_ = codecs;
  recv_codecs_ = codecs;
}
void FakeVoiceEngine::SetRecvCodecs(const std::vector<AudioCodec>& codecs) {
  recv_codecs_ = codecs;
}
void FakeVoiceEngine::SetSendCodecs(const std::vector<AudioCodec>& 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(VideoCodec(0, "fake_video_codec"));
  recv_codecs_.push_back(VideoCodec(0, "fake_video_codec"));
}
bool FakeVideoEngine::SetOptions(const VideoOptions& options) {
  options_ = options;
  return true;
}
VideoMediaChannel* FakeVideoEngine::CreateMediaChannel(
    MediaChannel::Role role,
    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;
  }

  FakeVideoMediaChannel* ch =
      new FakeVideoMediaChannel(role, this, options, call->network_thread());
  switch (role) {
    case MediaChannel::Role::kSend:
      send_channels_.emplace_back(ch);
      break;
    case MediaChannel::Role::kReceive:
      receive_channels_.emplace_back(ch);
      break;
    case MediaChannel::Role::kBoth:
      send_channels_.push_back(ch);
      receive_channels_.push_back(ch);
      break;
    default:
      RTC_CHECK_NOTREACHED();
  }
  return ch;
}
FakeVideoMediaChannel* FakeVideoEngine::GetSendChannel(size_t index) {
  return (send_channels_.size() > index) ? send_channels_[index] : nullptr;
}
FakeVideoMediaChannel* FakeVideoEngine::GetReceiveChannel(size_t index) {
  return (receive_channels_.size() > index) ? receive_channels_[index]
                                            : nullptr;
}
void FakeVideoEngine::UnregisterChannel(VideoMediaChannel* channel) {
  switch (channel->role()) {
    case MediaChannel::Role::kSend: {
      auto it = absl::c_find(send_channels_, channel);
      RTC_DCHECK(it != send_channels_.end());
      send_channels_.erase(it);
    } break;
    case MediaChannel::Role::kReceive: {
      auto it = absl::c_find(receive_channels_, channel);
      RTC_DCHECK(it != receive_channels_.end());
      receive_channels_.erase(it);
    } break;
    case MediaChannel::Role::kBoth: {
      auto it = absl::c_find(send_channels_, channel);
      RTC_DCHECK(it != send_channels_.end());
      send_channels_.erase(it);
      it = absl::c_find(receive_channels_, channel);
      RTC_DCHECK(it != receive_channels_.end());
      receive_channels_.erase(it);
    } break;
    default:
      RTC_CHECK_NOTREACHED();
  }
}
std::vector<VideoCodec> FakeVideoEngine::send_codecs(bool use_rtx) const {
  return send_codecs_;
}

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

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

void FakeVideoEngine::SetRecvCodecs(const std::vector<VideoCodec>& 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<AudioCodec>& codecs) {
  voice_->SetCodecs(codecs);
}
void FakeMediaEngine::SetAudioRecvCodecs(
    const std::vector<AudioCodec>& codecs) {
  voice_->SetRecvCodecs(codecs);
}
void FakeMediaEngine::SetAudioSendCodecs(
    const std::vector<AudioCodec>& codecs) {
  voice_->SetSendCodecs(codecs);
}
void FakeMediaEngine::SetVideoCodecs(const std::vector<VideoCodec>& codecs) {
  video_->SetSendCodecs(codecs);
  video_->SetRecvCodecs(codecs);
}

FakeVoiceMediaChannel* FakeMediaEngine::GetVoiceSendChannel(size_t index) {
  return voice_->GetSendChannel(index);
}
FakeVideoMediaChannel* FakeMediaEngine::GetVideoSendChannel(size_t index) {
  return video_->GetSendChannel(index);
}
FakeVoiceMediaChannel* FakeMediaEngine::GetVoiceReceiveChannel(size_t index) {
  return voice_->GetReceiveChannel(index);
}
FakeVideoMediaChannel* FakeMediaEngine::GetVideoReceiveChannel(size_t index) {
  return video_->GetReceiveChannel(index);
}

void FakeMediaEngine::set_fail_create_channel(bool fail) {
  voice_->fail_create_channel_ = fail;
  video_->fail_create_channel_ = fail;
}

}  // namespace cricket
