Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Unified Diff: remoting/test/protocol_perftest.cc

Issue 1642793002: Add performance test for WebRTC protocol. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@client_webrtc_support
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/test/fake_socket_factory.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/test/protocol_perftest.cc
diff --git a/remoting/test/protocol_perftest.cc b/remoting/test/protocol_perftest.cc
index bbafe9455247c34cb7744735ed2c99400706eaad..3695b75b2bca63106a7b05ca3a21cd5bf766c7f5 100644
--- a/remoting/test/protocol_perftest.cc
+++ b/remoting/test/protocol_perftest.cc
@@ -12,6 +12,7 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task_runner_util.h"
#include "base/thread_task_runner_handle.h"
#include "jingle/glue/thread_wrapper.h"
#include "net/base/test_data_directory.h"
@@ -21,9 +22,12 @@
#include "remoting/client/chromoting_client.h"
#include "remoting/client/client_context.h"
#include "remoting/client/client_user_interface.h"
+#include "remoting/codec/video_decoder_verbatim.h"
+#include "remoting/codec/video_decoder_vpx.h"
#include "remoting/host/chromoting_host.h"
#include "remoting/host/chromoting_host_context.h"
#include "remoting/host/fake_desktop_environment.h"
+#include "remoting/protocol/frame_consumer.h"
#include "remoting/protocol/jingle_session_manager.h"
#include "remoting/protocol/me2me_host_authenticator_factory.h"
#include "remoting/protocol/negotiating_client_authenticator.h"
@@ -32,6 +36,7 @@
#include "remoting/protocol/video_frame_pump.h"
#include "remoting/protocol/video_renderer.h"
#include "remoting/signaling/fake_signal_strategy.h"
+#include "remoting/test/cyclic_frame_generator.h"
#include "remoting/test/fake_network_dispatcher.h"
#include "remoting/test/fake_port_allocator.h"
#include "remoting/test/fake_socket_factory.h"
@@ -41,6 +46,8 @@ namespace remoting {
using protocol::ChannelConfig;
+namespace {
+
const char kHostJid[] = "host_jid@example.com/host";
const char kHostOwner[] = "jane.doe@example.com";
const char kClientJid[] = "jane.doe@example.com/client";
@@ -73,23 +80,37 @@ class FakeCursorShapeStub : public protocol::CursorShapeStub {
void SetCursorShape(const protocol::CursorShapeInfo& cursor_shape) override{};
};
+scoped_ptr<webrtc::DesktopFrame> DoDecodeFrame(
+ VideoDecoder* decoder,
+ VideoPacket* packet,
+ scoped_ptr<webrtc::DesktopFrame> frame) {
+ if (!decoder->DecodePacket(*packet, frame.get()))
+ frame.reset();
+ return frame;
+}
+
+} // namespace
+
class ProtocolPerfTest
: public testing::Test,
public testing::WithParamInterface<NetworkPerformanceParams>,
public ClientUserInterface,
public protocol::VideoRenderer,
public protocol::VideoStub,
+ public protocol::FrameConsumer,
public HostStatusObserver {
public:
ProtocolPerfTest()
: host_thread_("host"),
capture_thread_("capture"),
- encode_thread_("encode") {
+ encode_thread_("encode"),
+ decode_thread_("decode") {
protocol::VideoFramePump::EnableTimestampsForTests();
host_thread_.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
capture_thread_.Start();
encode_thread_.Start();
+ decode_thread_.Start();
}
virtual ~ProtocolPerfTest() {
@@ -123,26 +144,57 @@ class ProtocolPerfTest
// VideoRenderer interface.
void OnSessionConfig(const protocol::SessionConfig& config) override {}
protocol::VideoStub* GetVideoStub() override { return this; }
- protocol::FrameConsumer* GetFrameConsumer() override {
- NOTREACHED();
- return nullptr;
- }
+ protocol::FrameConsumer* GetFrameConsumer() override { return this; }
// protocol::VideoStub interface.
- void ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet,
+ void ProcessVideoPacket(scoped_ptr<VideoPacket> packet,
const base::Closure& done) override {
- if (video_packet->data().empty()) {
+ if (packet->data().empty()) {
// Ignore keep-alive packets
done.Run();
return;
}
- last_video_packet_ = std::move(video_packet);
+ if (packet->format().has_screen_width() &&
+ packet->format().has_screen_height()) {
+ frame_size_.set(packet->format().screen_width(),
+ packet->format().screen_height());
+ }
+
+ scoped_ptr<webrtc::DesktopFrame> frame(
+ new webrtc::BasicDesktopFrame(frame_size_));
+ base::PostTaskAndReplyWithResult(
+ decode_thread_.task_runner().get(), FROM_HERE,
+ base::Bind(&DoDecodeFrame, video_decoder_.get(), packet.get(),
+ base::Passed(&frame)),
+ base::Bind(&ProtocolPerfTest::OnFrameDecoded, base::Unretained(this),
+ base::Passed(&packet), done));
+ }
+
+ void OnFrameDecoded(scoped_ptr<VideoPacket> packet,
+ const base::Closure& done,
+ scoped_ptr<webrtc::DesktopFrame> frame) {
+ last_video_packet_ = std::move(packet);
+ DrawFrame(std::move(frame), done);
+ }
+
+ // protocol::FrameConsumer interface.
+ scoped_ptr<webrtc::DesktopFrame> AllocateFrame(
+ const webrtc::DesktopSize& size) override {
+ return make_scoped_ptr(new webrtc::BasicDesktopFrame(size));
+ }
+ void DrawFrame(scoped_ptr<webrtc::DesktopFrame> frame,
+ const base::Closure& done) override {
+ last_video_frame_ = std::move(frame);
if (!on_frame_task_.is_null())
on_frame_task_.Run();
+ if (!done.is_null())
+ done.Run();
+ }
- done.Run();
+ protocol::FrameConsumer::PixelFormat GetPixelFormat() override {
+ return FORMAT_BGRA;
}
// HostStatusObserver interface.
@@ -170,11 +222,22 @@ class ProtocolPerfTest
connecting_loop_->Quit();
}
- void ReceiveFrame(base::TimeDelta* latency) {
+ scoped_ptr<webrtc::DesktopFrame> ReceiveFrame() {
+ last_video_frame_.reset();
+
waiting_frames_loop_.reset(new base::RunLoop());
on_frame_task_ = waiting_frames_loop_->QuitClosure();
waiting_frames_loop_->Run();
+ EXPECT_TRUE(last_video_frame_);
+ return std::move(last_video_frame_);
+ }
+
+ void ReceiveFrameAndGetLatency(base::TimeDelta* latency) {
+ last_video_packet_.reset();
+
+ ReceiveFrame();
+
if (latency) {
base::TimeTicks timestamp =
base::TimeTicks::FromInternalValue(last_video_packet_->timestamp());
@@ -182,14 +245,15 @@ class ProtocolPerfTest
}
}
- void ReceiveFrames(int frames, base::TimeDelta* max_latency) {
+ void ReceiveMultipleFramesAndGetMaxLatency(int frames,
+ base::TimeDelta* max_latency) {
if (max_latency)
*max_latency = base::TimeDelta();
for (int i = 0; i < frames; ++i) {
base::TimeDelta latency;
- ReceiveFrame(&latency);
+ ReceiveFrameAndGetLatency(&latency);
if (max_latency && latency > *max_latency) {
*max_latency = latency;
@@ -201,7 +265,8 @@ class ProtocolPerfTest
// should call WaitConnected() to wait until connection is established. The
// host is started on |host_thread_| while the client works on the main
// thread.
- void StartHostAndClient(protocol::ChannelConfig::Codec video_codec) {
+ void StartHostAndClient(bool use_webrtc,
+ protocol::ChannelConfig::Codec video_codec) {
fake_network_dispatcher_ = new FakeNetworkDispatcher();
client_signaling_.reset(new FakeSignalStrategy(kClientJid));
@@ -214,6 +279,19 @@ class ProtocolPerfTest
protocol_config_->mutable_video_configs()->push_back(
protocol::ChannelConfig(
protocol::ChannelConfig::TRANSPORT_STREAM, 2, video_codec));
+ protocol_config_->set_webrtc_supported(use_webrtc);
+ protocol_config_->set_ice_supported(!use_webrtc);
+
+ switch (video_codec) {
+ case ChannelConfig::CODEC_VERBATIM:
+ video_decoder_.reset(new VideoDecoderVerbatim());
+ break;
+ case ChannelConfig::CODEC_VP8:
+ video_decoder_ = VideoDecoderVpx::CreateForVP8();
+ break;
+ default:
+ NOTREACHED();
+ }
host_thread_.task_runner()->PostTask(
FROM_HERE,
@@ -307,7 +385,7 @@ class ProtocolPerfTest
scoped_refptr<protocol::TransportContext> transport_context(
new protocol::TransportContext(
host_signaling_.get(), std::move(port_allocator_factory),
- network_settings, protocol::TransportRole::SERVER));
+ network_settings, protocol::TransportRole::CLIENT));
std::vector<protocol::AuthenticationMethod> auth_methods;
auth_methods.push_back(protocol::AuthenticationMethod::Spake2(
@@ -332,6 +410,61 @@ class ProtocolPerfTest
secret_fetched_callback.Run("123456");
}
+ void MeasureTotalLatency(bool webrtc) {
+ scoped_refptr<test::CyclicFrameGenerator> frame_generator =
+ test::CyclicFrameGenerator::Create();
+ frame_generator->set_draw_barcode(true);
+
+ desktop_environment_factory_.set_frame_generator(base::Bind(
+ &test::CyclicFrameGenerator::GenerateFrame, frame_generator));
+
+ StartHostAndClient(webrtc, protocol::ChannelConfig::CODEC_VP8);
+ ASSERT_NO_FATAL_FAILURE(WaitConnected());
+
+ base::TimeDelta total_latency_big_frames;
+ int big_frame_count = 0;
+ base::TimeDelta total_latency_small_frames;
+ int small_frame_count = 0;
+
+ int last_frame_id = -1;
+ for (int i = 0; i < 30; ++i) {
+ scoped_ptr<webrtc::DesktopFrame> frame = ReceiveFrame();
+ test::CyclicFrameGenerator::FrameInfo frame_info =
+ frame_generator->IdentifyFrame(frame.get());
+ base::TimeDelta latency = base::TimeTicks::Now() - frame_info.timestamp;
+
+ if (frame_info.frame_id > last_frame_id) {
+ last_frame_id = frame_info.frame_id;
+
+ switch (frame_info.type) {
+ case test::CyclicFrameGenerator::FrameType::EMPTY:
+ NOTREACHED();
+ break;
+ case test::CyclicFrameGenerator::FrameType::FULL:
+ total_latency_big_frames += latency;
+ ++big_frame_count;
+ break;
+ case test::CyclicFrameGenerator::FrameType::CURSOR:
+ total_latency_small_frames += latency;
+ ++small_frame_count;
+ break;
+ }
+ } else {
+ LOG(ERROR) << "Unexpected duplicate frame " << frame_info.frame_id;
+ }
+ }
+
+ CHECK(big_frame_count);
+ VLOG(0) << "Average latency for big frames: "
+ << (total_latency_big_frames / big_frame_count).InMillisecondsF();
+
+ if (small_frame_count) {
+ VLOG(0)
+ << "Average latency for small frames: "
+ << (total_latency_small_frames / small_frame_count).InMillisecondsF();
+ }
+ }
+
base::MessageLoopForIO message_loop_;
scoped_refptr<FakeNetworkDispatcher> fake_network_dispatcher_;
@@ -339,6 +472,7 @@ class ProtocolPerfTest
base::Thread host_thread_;
base::Thread capture_thread_;
base::Thread encode_thread_;
+ base::Thread decode_thread_;
FakeDesktopEnvironmentFactory desktop_environment_factory_;
FakeCursorShapeStub cursor_shape_stub_;
@@ -351,6 +485,8 @@ class ProtocolPerfTest
scoped_ptr<ChromotingHost> host_;
scoped_ptr<ClientContext> client_context_;
scoped_ptr<ChromotingClient> client_;
+ webrtc::DesktopSize frame_size_;
+ scoped_ptr<VideoDecoder> video_decoder_;
scoped_ptr<base::RunLoop> connecting_loop_;
scoped_ptr<base::RunLoop> waiting_frames_loop_;
@@ -361,6 +497,7 @@ class ProtocolPerfTest
base::Closure on_frame_task_;
scoped_ptr<VideoPacket> last_video_packet_;
+ scoped_ptr<webrtc::DesktopFrame> last_video_frame_;
private:
DISALLOW_COPY_AND_ASSIGN(ProtocolPerfTest);
@@ -400,17 +537,17 @@ INSTANTIATE_TEST_CASE_P(
NetworkPerformanceParams(100000, 200000, 130, 5, 0.01)));
TEST_P(ProtocolPerfTest, StreamFrameRate) {
- StartHostAndClient(protocol::ChannelConfig::CODEC_VP8);
+ StartHostAndClient(false, protocol::ChannelConfig::CODEC_VP8);
ASSERT_NO_FATAL_FAILURE(WaitConnected());
base::TimeDelta latency;
- ReceiveFrame(&latency);
+ ReceiveFrameAndGetLatency(&latency);
LOG(INFO) << "First frame latency: " << latency.InMillisecondsF() << "ms";
- ReceiveFrames(20, nullptr);
+ ReceiveMultipleFramesAndGetMaxLatency(20, nullptr);
base::TimeTicks started = base::TimeTicks::Now();
- ReceiveFrames(40, &latency);
+ ReceiveMultipleFramesAndGetMaxLatency(40, &latency);
base::TimeDelta elapsed = base::TimeTicks::Now() - started;
LOG(INFO) << "Frame rate: " << (40.0 / elapsed.InSecondsF());
LOG(INFO) << "Maximum latency: " << latency.InMillisecondsF() << "ms";
@@ -464,10 +601,10 @@ TEST_P(ProtocolPerfTest, IntermittentChanges) {
base::Bind(&IntermittentChangeFrameGenerator::GenerateFrame,
new IntermittentChangeFrameGenerator()));
- StartHostAndClient(protocol::ChannelConfig::CODEC_VERBATIM);
+ StartHostAndClient(false, protocol::ChannelConfig::CODEC_VERBATIM);
ASSERT_NO_FATAL_FAILURE(WaitConnected());
- ReceiveFrame(nullptr);
+ ReceiveFrameAndGetLatency(nullptr);
base::TimeDelta expected = GetParam().latency_average;
if (GetParam().bandwidth > 0) {
@@ -481,7 +618,7 @@ TEST_P(ProtocolPerfTest, IntermittentChanges) {
const int kFrames = 5;
for (int i = 0; i < kFrames; ++i) {
base::TimeDelta latency;
- ReceiveFrame(&latency);
+ ReceiveFrameAndGetLatency(&latency);
LOG(INFO) << "Latency: " << latency.InMillisecondsF()
<< "ms Encode: " << last_video_packet_->encode_time_ms()
<< "ms Capture: " << last_video_packet_->capture_time_ms()
@@ -492,4 +629,12 @@ TEST_P(ProtocolPerfTest, IntermittentChanges) {
LOG(INFO) << "Average: " << (sum / kFrames).InMillisecondsF();
}
+TEST_P(ProtocolPerfTest, TotalLatencyIce) {
+ MeasureTotalLatency(false);
+}
+
+TEST_P(ProtocolPerfTest, TotalLatencyWebrtc) {
+ MeasureTotalLatency(true);
+}
+
} // namespace remoting
« no previous file with comments | « remoting/test/fake_socket_factory.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698