2014-02-28 22:57:22 +01:00
|
|
|
/*
|
|
|
|
* libjingle
|
|
|
|
* Copyright 2004 Google Inc.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
|
|
* and/or other materials provided with the distribution.
|
|
|
|
* 3. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
|
|
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "talk/media/base/fakemediaengine.h"
|
|
|
|
#include "talk/media/base/fakenetworkinterface.h"
|
|
|
|
#include "talk/media/base/fakevideocapturer.h"
|
|
|
|
#include "talk/media/base/hybridvideoengine.h"
|
|
|
|
#include "talk/media/base/mediachannel.h"
|
|
|
|
#include "talk/media/base/testutils.h"
|
2014-08-13 19:26:08 +02:00
|
|
|
#include "webrtc/base/gunit.h"
|
2014-02-28 22:57:22 +01:00
|
|
|
|
|
|
|
static const cricket::VideoCodec kGenericCodec(97, "Generic", 640, 360, 30, 0);
|
|
|
|
static const cricket::VideoCodec kVp8Codec(100, "VP8", 640, 360, 30, 0);
|
|
|
|
static const cricket::VideoCodec kCodecsVp8Only[] = { kVp8Codec };
|
|
|
|
static const cricket::VideoCodec kCodecsGenericOnly[] = { kGenericCodec };
|
|
|
|
static const cricket::VideoCodec kCodecsVp8First[] = { kVp8Codec,
|
|
|
|
kGenericCodec };
|
|
|
|
static const cricket::VideoCodec kCodecsGenericFirst[] = { kGenericCodec,
|
|
|
|
kVp8Codec };
|
|
|
|
|
|
|
|
using cricket::StreamParams;
|
|
|
|
|
|
|
|
class FakeVp8VideoEngine : public cricket::FakeVideoEngine {
|
|
|
|
public:
|
|
|
|
FakeVp8VideoEngine() {
|
|
|
|
SetCodecs(MAKE_VECTOR(kCodecsVp8Only));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
class FakeGenericVideoEngine : public cricket::FakeVideoEngine {
|
|
|
|
public:
|
|
|
|
FakeGenericVideoEngine() {
|
|
|
|
SetCodecs(MAKE_VECTOR(kCodecsGenericOnly));
|
|
|
|
}
|
|
|
|
|
|
|
|
// For testing purposes, mimic the behavior of a media engine that throws out
|
|
|
|
// resolutions that don't match the codec list. A width or height of 0
|
|
|
|
// trivially will never match the codec list, so this is sufficient for
|
|
|
|
// testing the case we want (0x0).
|
|
|
|
virtual bool FindCodec(const cricket::VideoCodec& codec) {
|
|
|
|
if (codec.width == 0 || codec.height == 0) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return cricket::FakeVideoEngine::FindCodec(codec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
class HybridVideoEngineForTest : public cricket::HybridVideoEngine<
|
|
|
|
FakeVp8VideoEngine, FakeGenericVideoEngine> {
|
|
|
|
public:
|
|
|
|
HybridVideoEngineForTest()
|
|
|
|
:
|
|
|
|
num_ch1_send_on_(0),
|
|
|
|
num_ch1_send_off_(0),
|
|
|
|
send_width_(0),
|
|
|
|
send_height_(0) { }
|
|
|
|
cricket::FakeVideoEngine* sub_engine1() { return &video1_; }
|
|
|
|
cricket::FakeVideoEngine* sub_engine2() { return &video2_; }
|
|
|
|
|
|
|
|
// From base class HybridVideoEngine.
|
|
|
|
void OnSendChange1(cricket::VideoMediaChannel* channel1, bool send) {
|
|
|
|
if (send) {
|
|
|
|
++num_ch1_send_on_;
|
|
|
|
} else {
|
|
|
|
++num_ch1_send_off_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// From base class HybridVideoEngine
|
|
|
|
void OnNewSendResolution(int width, int height) {
|
|
|
|
send_width_ = width;
|
|
|
|
send_height_ = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
int num_ch1_send_on() const { return num_ch1_send_on_; }
|
|
|
|
int num_ch1_send_off() const { return num_ch1_send_off_; }
|
|
|
|
|
|
|
|
int send_width() const { return send_width_; }
|
|
|
|
int send_height() const { return send_height_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
int num_ch1_send_on_;
|
|
|
|
int num_ch1_send_off_;
|
|
|
|
|
|
|
|
int send_width_;
|
|
|
|
int send_height_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class HybridVideoEngineTest : public testing::Test {
|
|
|
|
public:
|
|
|
|
HybridVideoEngineTest() : sub_channel1_(NULL), sub_channel2_(NULL) {
|
|
|
|
}
|
|
|
|
~HybridVideoEngineTest() {
|
|
|
|
engine_.Terminate();
|
|
|
|
}
|
|
|
|
bool SetupEngine() {
|
2014-07-29 19:36:52 +02:00
|
|
|
bool result = engine_.Init(rtc::Thread::Current());
|
2014-02-28 22:57:22 +01:00
|
|
|
if (result) {
|
|
|
|
channel_.reset(engine_.CreateChannel(NULL));
|
|
|
|
result = (channel_.get() != NULL);
|
|
|
|
sub_channel1_ = engine_.sub_engine1()->GetChannel(0);
|
|
|
|
sub_channel2_ = engine_.sub_engine2()->GetChannel(0);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
bool SetupRenderAndAddStream(const StreamParams& sp) {
|
|
|
|
if (!SetupEngine())
|
|
|
|
return false;
|
|
|
|
channel_->SetInterface(transport_.get());
|
|
|
|
return channel_->SetRecvCodecs(engine_.codecs()) &&
|
|
|
|
channel_->AddSendStream(sp) &&
|
|
|
|
channel_->SetRender(true);
|
|
|
|
}
|
|
|
|
void DeliverPacket(const void* data, int len) {
|
2014-07-29 19:36:52 +02:00
|
|
|
rtc::Buffer packet(data, len);
|
|
|
|
channel_->OnPacketReceived(&packet, rtc::CreatePacketTime(0));
|
2014-02-28 22:57:22 +01:00
|
|
|
}
|
|
|
|
void DeliverRtcp(const void* data, int len) {
|
2014-07-29 19:36:52 +02:00
|
|
|
rtc::Buffer packet(data, len);
|
|
|
|
channel_->OnRtcpReceived(&packet, rtc::CreatePacketTime(0));
|
2014-02-28 22:57:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void TestSetSendCodecs(cricket::FakeVideoEngine* sub_engine,
|
|
|
|
const std::vector<cricket::VideoCodec>& codecs) {
|
|
|
|
EXPECT_TRUE(SetupRenderAndAddStream(StreamParams::CreateLegacy(1234)));
|
|
|
|
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
|
|
|
|
cricket::FakeVideoMediaChannel* sub_channel = sub_engine->GetChannel(0);
|
|
|
|
ASSERT_EQ(1U, sub_channel->send_codecs().size());
|
|
|
|
EXPECT_EQ(codecs[0], sub_channel->send_codecs()[0]);
|
|
|
|
EXPECT_TRUE(channel_->SetSend(true));
|
|
|
|
EXPECT_TRUE(sub_channel->sending());
|
|
|
|
}
|
|
|
|
void TestSetSendBandwidth(cricket::FakeVideoEngine* sub_engine,
|
|
|
|
const std::vector<cricket::VideoCodec>& codecs,
|
|
|
|
int start_bitrate,
|
|
|
|
int max_bitrate) {
|
|
|
|
EXPECT_TRUE(SetupRenderAndAddStream(StreamParams::CreateLegacy(1234)));
|
|
|
|
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
|
|
|
|
EXPECT_TRUE(channel_->SetStartSendBandwidth(start_bitrate));
|
|
|
|
EXPECT_TRUE(channel_->SetMaxSendBandwidth(max_bitrate));
|
|
|
|
cricket::FakeVideoMediaChannel* sub_channel = sub_engine->GetChannel(0);
|
|
|
|
EXPECT_EQ(start_bitrate, sub_channel->start_bps());
|
|
|
|
EXPECT_EQ(max_bitrate, sub_channel->max_bps());
|
|
|
|
}
|
|
|
|
HybridVideoEngineForTest engine_;
|
2014-07-29 19:36:52 +02:00
|
|
|
rtc::scoped_ptr<cricket::HybridVideoMediaChannel> channel_;
|
|
|
|
rtc::scoped_ptr<cricket::FakeNetworkInterface> transport_;
|
2014-02-28 22:57:22 +01:00
|
|
|
cricket::FakeVideoMediaChannel* sub_channel1_;
|
|
|
|
cricket::FakeVideoMediaChannel* sub_channel2_;
|
|
|
|
};
|
|
|
|
|
|
|
|
TEST_F(HybridVideoEngineTest, StartupShutdown) {
|
2014-07-29 19:36:52 +02:00
|
|
|
EXPECT_TRUE(engine_.Init(rtc::Thread::Current()));
|
2014-02-28 22:57:22 +01:00
|
|
|
engine_.Terminate();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that SetDefaultVideoEncoderConfig passes down to both engines.
|
|
|
|
TEST_F(HybridVideoEngineTest, SetDefaultVideoEncoderConfig) {
|
|
|
|
cricket::VideoEncoderConfig config(
|
|
|
|
cricket::VideoCodec(105, "", 640, 400, 30, 0), 1, 2);
|
|
|
|
EXPECT_TRUE(engine_.SetDefaultEncoderConfig(config));
|
|
|
|
|
|
|
|
cricket::VideoEncoderConfig config_1 = config;
|
|
|
|
config_1.max_codec.name = kCodecsVp8Only[0].name;
|
|
|
|
EXPECT_EQ(config_1, engine_.sub_engine1()->default_encoder_config());
|
|
|
|
|
|
|
|
cricket::VideoEncoderConfig config_2 = config;
|
|
|
|
config_2.max_codec.name = kCodecsGenericOnly[0].name;
|
|
|
|
EXPECT_EQ(config_2, engine_.sub_engine2()->default_encoder_config());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that GetDefaultVideoEncoderConfig picks a meaningful encoder config
|
|
|
|
// based on the underlying engine config and then after a call to
|
|
|
|
// SetDefaultEncoderConfig on the hybrid engine.
|
|
|
|
TEST_F(HybridVideoEngineTest, SetDefaultVideoEncoderConfigDefaultValue) {
|
|
|
|
cricket::VideoEncoderConfig blank_config;
|
|
|
|
cricket::VideoEncoderConfig meaningful_config1(
|
|
|
|
cricket::VideoCodec(111, "abcd", 320, 240, 30, 0), 1, 2);
|
|
|
|
cricket::VideoEncoderConfig meaningful_config2(
|
|
|
|
cricket::VideoCodec(111, "abcd", 1280, 720, 30, 0), 1, 2);
|
|
|
|
cricket::VideoEncoderConfig meaningful_config3(
|
|
|
|
cricket::VideoCodec(111, "abcd", 640, 360, 30, 0), 1, 2);
|
|
|
|
engine_.sub_engine1()->SetDefaultEncoderConfig(blank_config);
|
|
|
|
engine_.sub_engine2()->SetDefaultEncoderConfig(blank_config);
|
|
|
|
EXPECT_EQ(blank_config, engine_.GetDefaultEncoderConfig());
|
|
|
|
|
|
|
|
engine_.sub_engine2()->SetDefaultEncoderConfig(meaningful_config2);
|
|
|
|
EXPECT_EQ(meaningful_config2, engine_.GetDefaultEncoderConfig());
|
|
|
|
|
|
|
|
engine_.sub_engine1()->SetDefaultEncoderConfig(meaningful_config1);
|
|
|
|
EXPECT_EQ(meaningful_config1, engine_.GetDefaultEncoderConfig());
|
|
|
|
|
|
|
|
EXPECT_TRUE(engine_.SetDefaultEncoderConfig(meaningful_config3));
|
|
|
|
// The overall config should now match, though the codec name will have been
|
|
|
|
// rewritten for the first media engine.
|
|
|
|
meaningful_config3.max_codec.name = kCodecsVp8Only[0].name;
|
|
|
|
EXPECT_EQ(meaningful_config3, engine_.GetDefaultEncoderConfig());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that our engine has the right codecs in the right order.
|
|
|
|
TEST_F(HybridVideoEngineTest, CheckCodecs) {
|
|
|
|
const std::vector<cricket::VideoCodec>& c = engine_.codecs();
|
|
|
|
ASSERT_EQ(2U, c.size());
|
|
|
|
EXPECT_EQ(kVp8Codec, c[0]);
|
|
|
|
EXPECT_EQ(kGenericCodec, c[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that our engine has the right caps.
|
|
|
|
TEST_F(HybridVideoEngineTest, CheckCaps) {
|
|
|
|
EXPECT_EQ(cricket::VIDEO_SEND | cricket::VIDEO_RECV,
|
|
|
|
engine_.GetCapabilities());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that we can create and destroy a channel.
|
|
|
|
TEST_F(HybridVideoEngineTest, CreateChannel) {
|
|
|
|
EXPECT_TRUE(SetupEngine());
|
|
|
|
EXPECT_TRUE(sub_channel1_ != NULL);
|
|
|
|
EXPECT_TRUE(sub_channel2_ != NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that we properly handle failures in CreateChannel.
|
|
|
|
TEST_F(HybridVideoEngineTest, CreateChannelFail) {
|
|
|
|
engine_.sub_engine1()->set_fail_create_channel(true);
|
|
|
|
EXPECT_FALSE(SetupEngine());
|
|
|
|
EXPECT_TRUE(channel_.get() == NULL);
|
|
|
|
EXPECT_TRUE(sub_channel1_ == NULL);
|
|
|
|
EXPECT_TRUE(sub_channel2_ == NULL);
|
|
|
|
engine_.sub_engine1()->set_fail_create_channel(false);
|
|
|
|
engine_.sub_engine2()->set_fail_create_channel(true);
|
|
|
|
EXPECT_FALSE(SetupEngine());
|
|
|
|
EXPECT_TRUE(channel_.get() == NULL);
|
|
|
|
EXPECT_TRUE(sub_channel1_ == NULL);
|
|
|
|
EXPECT_TRUE(sub_channel2_ == NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that we set our inbound codecs and settings properly.
|
|
|
|
TEST_F(HybridVideoEngineTest, SetLocalDescription) {
|
|
|
|
EXPECT_TRUE(SetupEngine());
|
|
|
|
channel_->SetInterface(transport_.get());
|
|
|
|
EXPECT_TRUE(channel_->SetRecvCodecs(engine_.codecs()));
|
|
|
|
ASSERT_EQ(1U, sub_channel1_->recv_codecs().size());
|
|
|
|
ASSERT_EQ(1U, sub_channel2_->recv_codecs().size());
|
|
|
|
EXPECT_EQ(kVp8Codec, sub_channel1_->recv_codecs()[0]);
|
|
|
|
EXPECT_EQ(kGenericCodec, sub_channel2_->recv_codecs()[0]);
|
|
|
|
StreamParams stream;
|
|
|
|
stream.id = "TestStream";
|
|
|
|
stream.ssrcs.push_back(1234);
|
|
|
|
stream.cname = "5678";
|
|
|
|
EXPECT_TRUE(channel_->AddSendStream(stream));
|
|
|
|
EXPECT_EQ(1234U, sub_channel1_->send_ssrc());
|
|
|
|
EXPECT_EQ(1234U, sub_channel2_->send_ssrc());
|
|
|
|
EXPECT_EQ("5678", sub_channel1_->rtcp_cname());
|
|
|
|
EXPECT_EQ("5678", sub_channel2_->rtcp_cname());
|
|
|
|
EXPECT_TRUE(channel_->SetRender(true));
|
|
|
|
// We've called SetRender, so we should be playing out, but not yet sending.
|
|
|
|
EXPECT_TRUE(sub_channel1_->playout());
|
|
|
|
EXPECT_TRUE(sub_channel2_->playout());
|
|
|
|
EXPECT_FALSE(sub_channel1_->sending());
|
|
|
|
EXPECT_FALSE(sub_channel2_->sending());
|
|
|
|
// We may get SetSend(false) calls during call setup.
|
|
|
|
// Since this causes no change in state, they should no-op and return true.
|
|
|
|
EXPECT_TRUE(channel_->SetSend(false));
|
|
|
|
EXPECT_FALSE(sub_channel1_->sending());
|
|
|
|
EXPECT_FALSE(sub_channel2_->sending());
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(HybridVideoEngineTest, OnNewSendResolution) {
|
|
|
|
EXPECT_TRUE(SetupEngine());
|
|
|
|
EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsVp8First)));
|
|
|
|
EXPECT_EQ(640, engine_.send_width());
|
|
|
|
EXPECT_EQ(360, engine_.send_height());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that we converge to the active channel for engine 1.
|
|
|
|
TEST_F(HybridVideoEngineTest, SetSendCodecs1) {
|
|
|
|
// This will nuke the object that sub_channel2_ points to.
|
|
|
|
TestSetSendCodecs(engine_.sub_engine1(), MAKE_VECTOR(kCodecsVp8First));
|
|
|
|
EXPECT_TRUE(engine_.sub_engine2()->GetChannel(0) == NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that we converge to the active channel for engine 2.
|
|
|
|
TEST_F(HybridVideoEngineTest, SetSendCodecs2) {
|
|
|
|
// This will nuke the object that sub_channel1_ points to.
|
|
|
|
TestSetSendCodecs(engine_.sub_engine2(), MAKE_VECTOR(kCodecsGenericFirst));
|
|
|
|
EXPECT_TRUE(engine_.sub_engine1()->GetChannel(0) == NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that we don't accidentally eat 0x0 in SetSendCodecs
|
|
|
|
TEST_F(HybridVideoEngineTest, SetSendCodecs0x0) {
|
|
|
|
EXPECT_TRUE(SetupRenderAndAddStream(StreamParams::CreateLegacy(1234)));
|
|
|
|
// Send using generic codec, but with 0x0 resolution.
|
|
|
|
std::vector<cricket::VideoCodec> codecs(MAKE_VECTOR(kCodecsGenericFirst));
|
|
|
|
codecs.resize(1);
|
|
|
|
codecs[0].width = 0;
|
|
|
|
codecs[0].height = 0;
|
|
|
|
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test setting the send bandwidth for VP8.
|
|
|
|
TEST_F(HybridVideoEngineTest, SetSendBandwidth1) {
|
|
|
|
TestSetSendBandwidth(engine_.sub_engine1(),
|
|
|
|
MAKE_VECTOR(kCodecsVp8First),
|
|
|
|
100000,
|
|
|
|
384000);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test setting the send bandwidth for a generic codec.
|
|
|
|
TEST_F(HybridVideoEngineTest, SetSendBandwidth2) {
|
|
|
|
TestSetSendBandwidth(engine_.sub_engine2(),
|
|
|
|
MAKE_VECTOR(kCodecsGenericFirst),
|
|
|
|
100001,
|
|
|
|
384002);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that we dump RTP packets that arrive early.
|
|
|
|
TEST_F(HybridVideoEngineTest, HandleEarlyRtp) {
|
|
|
|
static const uint8 kPacket[1024] = { 0 };
|
|
|
|
static const uint8 kRtcp[1024] = { 1 };
|
|
|
|
EXPECT_TRUE(SetupRenderAndAddStream(StreamParams::CreateLegacy(1234)));
|
|
|
|
DeliverPacket(kPacket, sizeof(kPacket));
|
|
|
|
DeliverRtcp(kRtcp, sizeof(kRtcp));
|
|
|
|
EXPECT_TRUE(sub_channel1_->CheckNoRtp());
|
|
|
|
EXPECT_TRUE(sub_channel2_->CheckNoRtp());
|
|
|
|
EXPECT_TRUE(sub_channel1_->CheckNoRtcp());
|
|
|
|
EXPECT_TRUE(sub_channel2_->CheckNoRtcp());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that we properly pass on normal RTP packets.
|
|
|
|
TEST_F(HybridVideoEngineTest, HandleRtp) {
|
|
|
|
static const uint8 kPacket[1024] = { 0 };
|
|
|
|
static const uint8 kRtcp[1024] = { 1 };
|
|
|
|
EXPECT_TRUE(SetupRenderAndAddStream(StreamParams::CreateLegacy(1234)));
|
|
|
|
EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsVp8First)));
|
|
|
|
EXPECT_TRUE(channel_->SetSend(true));
|
|
|
|
DeliverPacket(kPacket, sizeof(kPacket));
|
|
|
|
DeliverRtcp(kRtcp, sizeof(kRtcp));
|
|
|
|
EXPECT_TRUE(sub_channel1_->CheckRtp(kPacket, sizeof(kPacket)));
|
|
|
|
EXPECT_TRUE(sub_channel1_->CheckRtcp(kRtcp, sizeof(kRtcp)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that we properly connect media error signal.
|
|
|
|
TEST_F(HybridVideoEngineTest, MediaErrorSignal) {
|
|
|
|
cricket::VideoMediaErrorCatcher catcher;
|
|
|
|
|
|
|
|
// Verify no signal from either channel before the active channel is set.
|
|
|
|
EXPECT_TRUE(SetupEngine());
|
|
|
|
channel_->SignalMediaError.connect(&catcher,
|
|
|
|
&cricket::VideoMediaErrorCatcher::OnError);
|
|
|
|
sub_channel1_->SignalMediaError(1, cricket::VideoMediaChannel::ERROR_OTHER);
|
|
|
|
EXPECT_EQ(0U, catcher.ssrc());
|
|
|
|
sub_channel2_->SignalMediaError(2,
|
|
|
|
cricket::VideoMediaChannel::ERROR_REC_DEVICE_OPEN_FAILED);
|
|
|
|
EXPECT_EQ(0U, catcher.ssrc());
|
|
|
|
|
|
|
|
// Set vp8 as active channel and verify that a signal comes from it.
|
|
|
|
EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsVp8First)));
|
|
|
|
sub_channel1_->SignalMediaError(1, cricket::VideoMediaChannel::ERROR_OTHER);
|
|
|
|
EXPECT_EQ(cricket::VideoMediaChannel::ERROR_OTHER, catcher.error());
|
|
|
|
EXPECT_EQ(1U, catcher.ssrc());
|
|
|
|
|
|
|
|
// Set generic codec as active channel and verify that a signal comes from it.
|
|
|
|
EXPECT_TRUE(SetupEngine());
|
|
|
|
channel_->SignalMediaError.connect(&catcher,
|
|
|
|
&cricket::VideoMediaErrorCatcher::OnError);
|
|
|
|
EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsGenericFirst)));
|
|
|
|
sub_channel2_->SignalMediaError(2,
|
|
|
|
cricket::VideoMediaChannel::ERROR_REC_DEVICE_OPEN_FAILED);
|
|
|
|
EXPECT_EQ(cricket::VideoMediaChannel::ERROR_REC_DEVICE_OPEN_FAILED,
|
|
|
|
catcher.error());
|
|
|
|
EXPECT_EQ(2U, catcher.ssrc());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that SetSend doesn't re-enter.
|
|
|
|
TEST_F(HybridVideoEngineTest, RepeatSetSend) {
|
|
|
|
EXPECT_TRUE(SetupEngine());
|
|
|
|
EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsVp8First)));
|
|
|
|
|
|
|
|
// Verify initial status.
|
|
|
|
EXPECT_FALSE(channel_->sending());
|
|
|
|
EXPECT_FALSE(sub_channel1_->sending());
|
|
|
|
EXPECT_EQ(0, engine_.num_ch1_send_on());
|
|
|
|
EXPECT_EQ(0, engine_.num_ch1_send_off());
|
|
|
|
|
|
|
|
// Verfiy SetSend(true) works correctly.
|
|
|
|
EXPECT_TRUE(channel_->SetSend(true));
|
|
|
|
EXPECT_TRUE(channel_->sending());
|
|
|
|
EXPECT_TRUE(sub_channel1_->sending());
|
|
|
|
EXPECT_EQ(1, engine_.num_ch1_send_on());
|
|
|
|
EXPECT_EQ(0, engine_.num_ch1_send_off());
|
|
|
|
|
|
|
|
// SetSend(true) again and verify nothing changes.
|
|
|
|
EXPECT_TRUE(channel_->SetSend(true));
|
|
|
|
EXPECT_TRUE(channel_->sending());
|
|
|
|
EXPECT_TRUE(sub_channel1_->sending());
|
|
|
|
EXPECT_EQ(1, engine_.num_ch1_send_on());
|
|
|
|
EXPECT_EQ(0, engine_.num_ch1_send_off());
|
|
|
|
|
|
|
|
// Verify SetSend(false) works correctly.
|
|
|
|
EXPECT_TRUE(channel_->SetSend(false));
|
|
|
|
EXPECT_FALSE(channel_->sending());
|
|
|
|
EXPECT_FALSE(sub_channel1_->sending());
|
|
|
|
EXPECT_EQ(1, engine_.num_ch1_send_on());
|
|
|
|
EXPECT_EQ(1, engine_.num_ch1_send_off());
|
|
|
|
|
|
|
|
// SetSend(false) again and verfiy nothing changes.
|
|
|
|
EXPECT_TRUE(channel_->SetSend(false));
|
|
|
|
EXPECT_FALSE(channel_->sending());
|
|
|
|
EXPECT_FALSE(sub_channel1_->sending());
|
|
|
|
EXPECT_EQ(1, engine_.num_ch1_send_on());
|
|
|
|
EXPECT_EQ(1, engine_.num_ch1_send_off());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that SetOptions.
|
|
|
|
TEST_F(HybridVideoEngineTest, SetOptions) {
|
|
|
|
cricket::VideoOptions vmo;
|
|
|
|
vmo.video_high_bitrate.Set(true);
|
|
|
|
vmo.system_low_adaptation_threshhold.Set(0.10f);
|
|
|
|
EXPECT_TRUE(SetupEngine());
|
|
|
|
EXPECT_TRUE(channel_->SetOptions(vmo));
|
|
|
|
|
|
|
|
bool high_bitrate;
|
|
|
|
float low;
|
|
|
|
EXPECT_TRUE(sub_channel1_->GetOptions(&vmo));
|
|
|
|
EXPECT_TRUE(vmo.video_high_bitrate.Get(&high_bitrate));
|
|
|
|
EXPECT_TRUE(high_bitrate);
|
|
|
|
EXPECT_TRUE(vmo.system_low_adaptation_threshhold.Get(&low));
|
|
|
|
EXPECT_EQ(0.10f, low);
|
|
|
|
EXPECT_TRUE(sub_channel2_->GetOptions(&vmo));
|
|
|
|
EXPECT_TRUE(vmo.video_high_bitrate.Get(&high_bitrate));
|
|
|
|
EXPECT_TRUE(high_bitrate);
|
|
|
|
EXPECT_TRUE(vmo.system_low_adaptation_threshhold.Get(&low));
|
|
|
|
EXPECT_EQ(0.10f, low);
|
|
|
|
|
|
|
|
vmo.video_high_bitrate.Set(false);
|
|
|
|
vmo.system_low_adaptation_threshhold.Set(0.50f);
|
|
|
|
|
|
|
|
EXPECT_TRUE(channel_->SetOptions(vmo));
|
|
|
|
EXPECT_TRUE(sub_channel1_->GetOptions(&vmo));
|
|
|
|
EXPECT_TRUE(vmo.video_high_bitrate.Get(&high_bitrate));
|
|
|
|
EXPECT_FALSE(high_bitrate);
|
|
|
|
EXPECT_TRUE(vmo.system_low_adaptation_threshhold.Get(&low));
|
|
|
|
EXPECT_EQ(0.50f, low);
|
|
|
|
EXPECT_TRUE(sub_channel2_->GetOptions(&vmo));
|
|
|
|
EXPECT_TRUE(vmo.video_high_bitrate.Get(&high_bitrate));
|
|
|
|
EXPECT_FALSE(high_bitrate);
|
|
|
|
EXPECT_TRUE(vmo.system_low_adaptation_threshhold.Get(&low));
|
|
|
|
EXPECT_EQ(0.50f, low);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(HybridVideoEngineTest, SetCapturer) {
|
|
|
|
EXPECT_TRUE(SetupEngine());
|
|
|
|
// Set vp8 as active channel and verify that capturer can be set.
|
|
|
|
EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsVp8First)));
|
|
|
|
cricket::FakeVideoCapturer fake_video_capturer;
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(0, &fake_video_capturer));
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(0, NULL));
|
|
|
|
|
|
|
|
// Set generic codec active channel and verify that capturer can be set.
|
|
|
|
EXPECT_TRUE(SetupEngine());
|
|
|
|
EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsGenericFirst)));
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(0, &fake_video_capturer));
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(0, NULL));
|
|
|
|
}
|