webrtc_m130/media/base/fake_media_engine.cc
Philipp Hancke f21cdb0afa Add RTP header extension API regression tests
which describe the existing behavior that necessitated the revert
  b396e2b159b060791954495d68278a55e8f72092

Also change the fake media engine audio clockrate to 8000 instead
of 0 and the fake media engine video payload type to something but
0 as this value seems to be treated specially by the video engine
and is a payload type reserved for PCMU.

BUG=chromium:1051821

Change-Id: Ib0a345d59baba50a565f01685d240e41584367e6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/299000
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39699}
2023-03-28 11:06:24 +00:00

684 lines
22 KiB
C++

/*
* 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", 8000, 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(111, "fake_video_codec"));
recv_codecs_.push_back(VideoCodec(111, "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