From 2e0319b8d2aa7544e2d51b0a7e7acd353cf578e3 Mon Sep 17 00:00:00 2001 From: sergeyu Date: Wed, 20 Jan 2016 13:21:54 -0800 Subject: [PATCH] Implement new video encoder performance tests, for VP9/VP8 comparison. The old encoder perf tests (in VideoEncoderVpxTest) were not providing very realistic results because: - They were measuring performance on frames with random data. - They were testing the case when the whole frame is changing every time. - They were using real clock, which affects results. This change implements new tests that provide closer approximation to how the codec is being used. CyclicFrameGenerator added in this test will also be used to test performance of the new WebRTC-based protocol. Review URL: https://codereview.chromium.org/1601303002 Cr-Commit-Position: refs/heads/master@{#370491} --- remoting/BUILD.gn | 4 +- remoting/codec/codec_test.cc | 44 ------ remoting/codec/video_encoder_vpx.cc | 13 +- remoting/codec/video_encoder_vpx.h | 6 + remoting/codec/video_encoder_vpx_perftest.cc | 64 -------- remoting/remoting_test.gypi | 7 +- remoting/test/BUILD.gn | 3 + remoting/test/DEPS | 1 + remoting/test/codec_perftest.cc | 158 +++++++++++++++++++ remoting/test/cyclic_frame_generator.cc | 119 ++++++++++++++ remoting/test/cyclic_frame_generator.h | 88 +++++++++++ remoting/test/data/download.sh | 20 +++ 12 files changed, 409 insertions(+), 118 deletions(-) delete mode 100644 remoting/codec/video_encoder_vpx_perftest.cc create mode 100644 remoting/test/codec_perftest.cc create mode 100644 remoting/test/cyclic_frame_generator.cc create mode 100644 remoting/test/cyclic_frame_generator.h create mode 100755 remoting/test/data/download.sh diff --git a/remoting/BUILD.gn b/remoting/BUILD.gn index c6360cd003e949..d75e99e69b251b 100644 --- a/remoting/BUILD.gn +++ b/remoting/BUILD.gn @@ -164,9 +164,7 @@ if (!is_mac) { if (enable_remoting_host) { test("remoting_perftests") { sources = [ - "codec/codec_test.cc", - "codec/codec_test.h", - "codec/video_encoder_vpx_perftest.cc", + "test/codec_perftest.cc", "test/protocol_perftest.cc", ] diff --git a/remoting/codec/codec_test.cc b/remoting/codec/codec_test.cc index 0c4f431d1048f0..3da37936c5cc23 100644 --- a/remoting/codec/codec_test.cc +++ b/remoting/codec/codec_test.cc @@ -343,48 +343,4 @@ void TestVideoEncoderDecoderGradient(VideoEncoder* encoder, decoder_tester.VerifyResultsApprox(max_error_limit, mean_error_limit); } -float MeasureVideoEncoderFpsWithSize(VideoEncoder* encoder, - const DesktopSize& size) { - scoped_ptr frame(PrepareFrame(size)); - frame->mutable_updated_region()->SetRect(DesktopRect::MakeSize(size)); - std::list frames; - frames.push_back(frame.get()); - return MeasureVideoEncoderFpsWithFrames(encoder, frames); -} - -float MeasureVideoEncoderFpsWithFrames(VideoEncoder* encoder, - const std::list& frames) { - const base::TimeDelta kTestTime = base::TimeDelta::FromSeconds(1); - - // Encode some frames to "warm up" the encoder (i.e. to let it set up initial - // structures, establish a stable working set, etc), then encode at least - // kMinimumFrameCount frames to measure the encoder's performance. - const int kWarmUpFrameCount = 10; - const int kMinimumFrameCount = 10; - base::TimeTicks start_time; - base::TimeDelta elapsed; - std::list test_frames; - int frame_count; - for (frame_count = 0; - (frame_count < kMinimumFrameCount + kWarmUpFrameCount || - elapsed < kTestTime); - ++frame_count) { - if (frame_count == kWarmUpFrameCount) { - start_time = base::TimeTicks::Now(); - } - - if (test_frames.empty()) { - test_frames = frames; - } - scoped_ptr packet = encoder->Encode(*test_frames.front()); - test_frames.pop_front(); - - if (frame_count >= kWarmUpFrameCount) { - elapsed = base::TimeTicks::Now() - start_time; - } - } - - return (frame_count * base::TimeDelta::FromSeconds(1)) / elapsed; -} - } // namespace remoting diff --git a/remoting/codec/video_encoder_vpx.cc b/remoting/codec/video_encoder_vpx.cc index 57a1d5afbda366..2a5894d4657810 100644 --- a/remoting/codec/video_encoder_vpx.cc +++ b/remoting/codec/video_encoder_vpx.cc @@ -242,6 +242,10 @@ scoped_ptr VideoEncoderVpx::CreateForVP9() { VideoEncoderVpx::~VideoEncoderVpx() {} +void VideoEncoderVpx::SetTickClockForTests(base::TickClock* tick_clock) { + clock_ = tick_clock; +} + void VideoEncoderVpx::SetLosslessEncode(bool want_lossless) { if (use_vp9_ && (want_lossless != lossless_encode_)) { lossless_encode_ = want_lossless; @@ -296,7 +300,7 @@ scoped_ptr VideoEncoderVpx::Encode( } // Do the actual encoding. - int timestamp = (base::TimeTicks::Now() - timestamp_base_).InMilliseconds(); + int timestamp = (clock_->NowTicks() - timestamp_base_).InMilliseconds(); vpx_codec_err_t ret = vpx_codec_encode( codec_.get(), image_.get(), timestamp, 1, 0, VPX_DL_REALTIME); DCHECK_EQ(ret, VPX_CODEC_OK) @@ -345,8 +349,9 @@ scoped_ptr VideoEncoderVpx::Encode( } VideoEncoderVpx::VideoEncoderVpx(bool use_vp9) - : use_vp9_(use_vp9), encode_unchanged_frame_(false) { -} + : use_vp9_(use_vp9), + encode_unchanged_frame_(false), + clock_(&default_tick_clock_) {} void VideoEncoderVpx::Configure(const webrtc::DesktopSize& size) { DCHECK(use_vp9_ || !lossless_color_); @@ -376,7 +381,7 @@ void VideoEncoderVpx::Configure(const webrtc::DesktopSize& size) { // (Re)Set the base for frame timestamps if the codec is being (re)created. if (!codec_) { - timestamp_base_ = base::TimeTicks::Now(); + timestamp_base_ = clock_->NowTicks(); } // Fetch a default configuration for the desired codec. diff --git a/remoting/codec/video_encoder_vpx.h b/remoting/codec/video_encoder_vpx.h index 83c3549b54dc67..35d5f670e51513 100644 --- a/remoting/codec/video_encoder_vpx.h +++ b/remoting/codec/video_encoder_vpx.h @@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/macros.h" +#include "base/time/default_tick_clock.h" #include "base/time/time.h" #include "remoting/codec/scoped_vpx_codec.h" #include "remoting/codec/video_encoder.h" @@ -31,6 +32,8 @@ class VideoEncoderVpx : public VideoEncoder { ~VideoEncoderVpx() override; + void SetTickClockForTests(base::TickClock* tick_clock); + // VideoEncoder interface. void SetLosslessEncode(bool want_lossless) override; void SetLosslessColor(bool want_lossless) override; @@ -84,6 +87,9 @@ class VideoEncoderVpx : public VideoEncoder { // Used to help initialize VideoPackets from DesktopFrames. VideoEncoderHelper helper_; + base::DefaultTickClock default_tick_clock_; + base::TickClock* clock_; + DISALLOW_COPY_AND_ASSIGN(VideoEncoderVpx); }; diff --git a/remoting/codec/video_encoder_vpx_perftest.cc b/remoting/codec/video_encoder_vpx_perftest.cc deleted file mode 100644 index 0c2cf7f5519016..00000000000000 --- a/remoting/codec/video_encoder_vpx_perftest.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/codec/video_encoder_vpx.h" - -#include - -#include -#include - -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "remoting/codec/codec_test.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" - -using webrtc::DesktopSize; - -namespace remoting { - -// Measure the performance of the VP8 encoder. -TEST(VideoEncoderVpxTest, MeasureVp8Fps) { - scoped_ptr encoder(VideoEncoderVpx::CreateForVP8()); - - const DesktopSize kFrameSizes[] = { - DesktopSize(1280, 1024), DesktopSize(1920, 1200) - }; - - for (size_t i = 0; i < arraysize(kFrameSizes); ++i) { - float fps = - MeasureVideoEncoderFpsWithSize(encoder.get(), kFrameSizes[i]); - LOG(ERROR) << kFrameSizes[i].width() << "x" << kFrameSizes[i].height() - << ": " << fps << "fps"; - } -} - -// Measure the performance of the VP9 encoder. -TEST(VideoEncoderVpxTest, MeasureVp9Fps) { - const DesktopSize kFrameSizes[] = { - DesktopSize(1280, 1024), DesktopSize(1920, 1200) - }; - - for (int lossless_mode = 0; lossless_mode < 4; ++lossless_mode) { - bool lossless_color = lossless_mode & 1; - bool lossless_encode = lossless_mode & 2; - - scoped_ptr encoder(VideoEncoderVpx::CreateForVP9()); - encoder->SetLosslessColor(lossless_color); - encoder->SetLosslessEncode(lossless_encode); - - for (size_t i = 0; i < arraysize(kFrameSizes); ++i) { - float fps = - MeasureVideoEncoderFpsWithSize(encoder.get(), kFrameSizes[i]); - LOG(ERROR) << kFrameSizes[i].width() << "x" << kFrameSizes[i].height() - << "(" << (lossless_encode ? "lossless" : "lossy ") << ")" - << "(" << (lossless_color ? "I444" : "I420") << ")" - << ": " << fps << "fps"; - } - } -} - -} // namespace remoting diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi index fe8edf4868a523..56efae367f4876 100644 --- a/remoting/remoting_test.gypi +++ b/remoting/remoting_test.gypi @@ -11,6 +11,7 @@ 'dependencies': [ '../base/base.gyp:base', '../net/net.gyp:net_test_support', + '../skia/skia.gyp:skia', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', 'remoting_base', @@ -65,6 +66,8 @@ 'test/connection_setup_info.h', 'test/connection_time_observer.cc', 'test/connection_time_observer.h', + 'test/cyclic_frame_generator.cc', + 'test/cyclic_frame_generator.h', 'test/fake_access_token_fetcher.cc', 'test/fake_access_token_fetcher.h', 'test/fake_app_remoting_report_issue_request.cc', @@ -557,9 +560,7 @@ ], 'sources': [ 'base/run_all_unittests.cc', - 'codec/codec_test.cc', - 'codec/codec_test.h', - 'codec/video_encoder_vpx_perftest.cc', + 'test/codec_perftest.cc', 'test/protocol_perftest.cc', ], 'conditions': [ diff --git a/remoting/test/BUILD.gn b/remoting/test/BUILD.gn index fd014ff10e8cdd..8bc132fbee6ea4 100644 --- a/remoting/test/BUILD.gn +++ b/remoting/test/BUILD.gn @@ -18,6 +18,8 @@ source_set("test_support") { "connection_setup_info.h", "connection_time_observer.cc", "connection_time_observer.h", + "cyclic_frame_generator.cc", + "cyclic_frame_generator.h", "fake_access_token_fetcher.cc", "fake_access_token_fetcher.h", "fake_app_remoting_report_issue_request.cc", @@ -76,6 +78,7 @@ source_set("test_support") { deps = [ "//google_apis", + "//skia", "//testing/gmock", "//testing/gtest", "//third_party/libjingle", diff --git a/remoting/test/DEPS b/remoting/test/DEPS index ef749455875ea6..485d2905341e7c 100644 --- a/remoting/test/DEPS +++ b/remoting/test/DEPS @@ -8,4 +8,5 @@ include_rules = [ "+remoting/signaling", "+ui/gfx", "+ui/events/keycodes/dom", + "+third_party/skia", ] diff --git a/remoting/test/codec_perftest.cc b/remoting/test/codec_perftest.cc new file mode 100644 index 00000000000000..e157b88763b69c --- /dev/null +++ b/remoting/test/codec_perftest.cc @@ -0,0 +1,158 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/simple_test_tick_clock.h" +#include "remoting/codec/video_encoder_vpx.h" +#include "remoting/proto/video.pb.h" +#include "remoting/test/cyclic_frame_generator.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" + +namespace remoting { +namespace test { + +static const int kIntervalBetweenFramesMs = 33; + +struct CodecParams { + CodecParams(bool use_vp9, bool lossless, bool lossless_color) + : use_vp9(use_vp9), lossless(lossless), lossless_color(lossless_color) {} + + bool use_vp9; + bool lossless; + bool lossless_color; +}; + +class CodecPerfTest : public testing::Test, + public testing::WithParamInterface { + public: + void SetUp() override { + if (GetParam().use_vp9) { + encoder_ = VideoEncoderVpx::CreateForVP9(); + encoder_->SetLosslessEncode(GetParam().lossless); + encoder_->SetLosslessColor(GetParam().lossless_color); + } else { + encoder_ = VideoEncoderVpx::CreateForVP8(); + } + encoder_->SetTickClockForTests(&clock_); + + frame_generator_ = CyclicFrameGenerator::Create(); + frame_generator_->SetTickClock(&clock_); + } + + protected: + base::SimpleTestTickClock clock_; + scoped_refptr frame_generator_; + scoped_ptr encoder_; +}; + +INSTANTIATE_TEST_CASE_P(VP8, + CodecPerfTest, + ::testing::Values(CodecParams(false, false, false))); +INSTANTIATE_TEST_CASE_P(VP9, + CodecPerfTest, + ::testing::Values(CodecParams(true, false, false))); +INSTANTIATE_TEST_CASE_P(VP9Lossless, + CodecPerfTest, + ::testing::Values(CodecParams(true, true, false))); +INSTANTIATE_TEST_CASE_P(VP9LosslessColor, + CodecPerfTest, + ::testing::Values(CodecParams(true, false, true))); + +TEST_P(CodecPerfTest, EncodeLatency) { + const int kTotalFrames = 300; + base::TimeDelta total_latency; + + base::TimeDelta total_latency_big_frames; + int big_frame_count = 0; + base::TimeDelta total_latency_small_frames; + int small_frame_count = 0; + base::TimeDelta total_latency_empty_frames; + int empty_frame_count = 0; + + int total_bytes = 0; + + for (int i = 0; i < kTotalFrames; ++i) { + scoped_ptr frame = + frame_generator_->GenerateFrame(nullptr); + base::TimeTicks started = base::TimeTicks::Now(); + + scoped_ptr packet = encoder_->Encode(*frame); + + base::TimeTicks ended = base::TimeTicks::Now(); + base::TimeDelta latency = ended - started; + + total_latency += latency; + if (packet) + total_bytes += packet->data().size(); + + switch (frame_generator_->last_frame_type()) { + case CyclicFrameGenerator::FrameType::EMPTY: + total_latency_empty_frames += latency; + ++empty_frame_count; + break; + case CyclicFrameGenerator::FrameType::FULL: + total_latency_big_frames += latency; + ++big_frame_count; + break; + case CyclicFrameGenerator::FrameType::CURSOR: + total_latency_small_frames += latency; + ++small_frame_count; + break; + } + + clock_.Advance(base::TimeDelta::FromMilliseconds(kIntervalBetweenFramesMs)); + } + + VLOG(0) << "Total time: " << total_latency.InMillisecondsF(); + VLOG(0) << "Average encode latency: " + << (total_latency / kTotalFrames).InMillisecondsF(); + + CHECK(big_frame_count); + VLOG(0) << "Average encode latency for big frames: " + << (total_latency_big_frames / big_frame_count).InMillisecondsF(); + + if (small_frame_count) { + VLOG(0) << "Average encode latency for small frames: " + << (total_latency_small_frames / small_frame_count) + .InMillisecondsF(); + } + + if (empty_frame_count) { + VLOG(0) << "Average encode latency for empty frames: " + << (total_latency_empty_frames / empty_frame_count) + .InMillisecondsF(); + } + + VLOG(0) << "Encoded bytes: " << total_bytes; +} + +TEST_P(CodecPerfTest, MaxFramerate) { + const int kTotalFrames = 100; + base::TimeDelta total_latency; + + // Update the whole screen on every frame. + frame_generator_->set_frame_cycle_period( + base::TimeDelta::FromMilliseconds(kIntervalBetweenFramesMs)); + + for (int i = 0; i < kTotalFrames; ++i) { + scoped_ptr frame = + frame_generator_->GenerateFrame(nullptr); + base::TimeTicks started = base::TimeTicks::Now(); + + scoped_ptr packet = encoder_->Encode(*frame); + + base::TimeTicks ended = base::TimeTicks::Now(); + base::TimeDelta latency = ended - started; + + total_latency += latency; + + clock_.Advance(base::TimeDelta::FromMilliseconds(kIntervalBetweenFramesMs)); + } + + VLOG(0) << "Max framerate: " + << (kTotalFrames * base::TimeDelta::FromSeconds(1) / total_latency); +} + +} // namespace test +} // namespace remoting diff --git a/remoting/test/cyclic_frame_generator.cc b/remoting/test/cyclic_frame_generator.cc new file mode 100644 index 00000000000000..2fb3753ed35500 --- /dev/null +++ b/remoting/test/cyclic_frame_generator.cc @@ -0,0 +1,119 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/test/cyclic_frame_generator.h" + +#include "base/base_paths.h" +#include "base/files/file_util.h" +#include "base/path_service.h" +#include "base/time/default_tick_clock.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" +#include "ui/gfx/codec/png_codec.h" + +namespace remoting { +namespace test { + +namespace { + +scoped_ptr LoadDesktopFrameFromPng( + const base::FilePath& file_path) { + std::string file_content; + if (!base::ReadFileToString(file_path, &file_content)) + LOG(FATAL) << "Failed to read " << file_path.MaybeAsASCII() + << ". Please run remoting/test/data/download.sh"; + SkBitmap bitmap; + gfx::PNGCodec::Decode(reinterpret_cast(file_content.data()), + file_content.size(), &bitmap); + scoped_ptr frame(new webrtc::BasicDesktopFrame( + webrtc::DesktopSize(bitmap.width(), bitmap.height()))); + bitmap.copyPixelsTo(frame->data(), + frame->stride() * frame->size().height(), + frame->stride()); + return frame; +} + +} // namespace + +// static +scoped_refptr CyclicFrameGenerator::Create() { + base::FilePath test_data_path; + PathService::Get(base::DIR_SOURCE_ROOT, &test_data_path); + test_data_path = test_data_path.Append(FILE_PATH_LITERAL("remoting")); + test_data_path = test_data_path.Append(FILE_PATH_LITERAL("test")); + test_data_path = test_data_path.Append(FILE_PATH_LITERAL("data")); + + std::vector> frames; + frames.push_back( + LoadDesktopFrameFromPng(test_data_path.AppendASCII("test_frame1.png"))); + frames.push_back( + LoadDesktopFrameFromPng(test_data_path.AppendASCII("test_frame2.png"))); + return new CyclicFrameGenerator(std::move(frames)); +} + +CyclicFrameGenerator::CyclicFrameGenerator( + std::vector> reference_frames) + : reference_frames_(std::move(reference_frames)), + clock_(&default_tick_clock_), + started_time_(clock_->NowTicks()) { + CHECK(!reference_frames_.empty()); + screen_size_ = reference_frames_[0]->size(); + for (const auto& frame : reference_frames_) { + CHECK(screen_size_.equals(frame->size())) + << "All reference frames should have the same size."; + } +} +CyclicFrameGenerator::~CyclicFrameGenerator() {} + +void CyclicFrameGenerator::SetTickClock(base::TickClock* tick_clock) { + clock_ = tick_clock; + started_time_ = clock_->NowTicks(); +} + +scoped_ptr CyclicFrameGenerator::GenerateFrame( + webrtc::DesktopCapturer::Callback* callback) { + base::TimeTicks now = clock_->NowTicks(); + int reference_frame = + ((now - started_time_) / frame_cycle_period_) % reference_frames_.size(); + bool cursor_state = ((now - started_time_) / cursor_blink_period_) % 2; + + scoped_ptr frame( + new webrtc::BasicDesktopFrame(screen_size_)); + frame->CopyPixelsFrom(*reference_frames_[reference_frame], + webrtc::DesktopVector(), + webrtc::DesktopRect::MakeSize(screen_size_)); + + // Render the cursor. + webrtc::DesktopRect cursor_rect = + webrtc::DesktopRect::MakeXYWH(20, 20, 2, 20); + if (cursor_state) { + for (int y = cursor_rect.top(); y < cursor_rect.bottom(); ++y) { + memset(frame->data() + y * frame->stride() + + cursor_rect.left() * webrtc::DesktopFrame::kBytesPerPixel, + 0, cursor_rect.width() * webrtc::DesktopFrame::kBytesPerPixel); + } + } + + if (last_reference_frame_ != reference_frame) { + // The whole frame has changed. + frame->mutable_updated_region()->AddRect( + webrtc::DesktopRect::MakeSize(screen_size_)); + last_frame_type_ = FrameType::FULL; + } else if (last_cursor_state_ != cursor_state) { + // Cursor state has changed. + frame->mutable_updated_region()->AddRect(cursor_rect); + last_frame_type_ = FrameType::CURSOR; + } else { + // No changes. + last_frame_type_ = FrameType::EMPTY; + } + last_reference_frame_ = reference_frame; + last_cursor_state_ = cursor_state; + + return frame; +} + +} // namespace test +} // namespace remoting diff --git a/remoting/test/cyclic_frame_generator.h b/remoting/test/cyclic_frame_generator.h new file mode 100644 index 00000000000000..50acad08f8e6ae --- /dev/null +++ b/remoting/test/cyclic_frame_generator.h @@ -0,0 +1,88 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_TEST_CYCLIC_FRAME_GENERATOR_H_ +#define REMOTING_TEST_CYCLIC_FRAME_GENERATOR_H_ + +#include + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/time/default_tick_clock.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" + +namespace remoting { +namespace test { + +// CyclicFrameGenerator generates a sequence of frames that approximates +// properties of a real video stream when using a desktop applications. It +// loads a sequence of reference frames and switches between them with the +// specified frequency (every 2 seconds by default). Between reference frames it +// also generate frames with small changes which simulate a blinking cursor. +class CyclicFrameGenerator + : public base::RefCountedThreadSafe { + public: + enum class FrameType { + // Frame had no changes. + EMPTY, + + // Whole screen changed. + FULL, + + // Cursor state has changed. + CURSOR, + }; + + static scoped_refptr Create(); + + CyclicFrameGenerator( + std::vector> reference_frames); + + void set_frame_cycle_period(base::TimeDelta frame_cycle_period) { + frame_cycle_period_ = frame_cycle_period; + } + + void set_cursor_blink_period(base::TimeDelta cursor_blink_period) { + cursor_blink_period_ = cursor_blink_period; + } + + void SetTickClock(base::TickClock* tick_clock); + + scoped_ptr GenerateFrame( + webrtc::DesktopCapturer::Callback* callback); + + FrameType last_frame_type() { return last_frame_type_; } + + private: + ~CyclicFrameGenerator(); + friend class base::RefCountedThreadSafe; + + std::vector> reference_frames_; + base::DefaultTickClock default_tick_clock_; + base::TickClock* clock_; + webrtc::DesktopSize screen_size_; + + // By default switch between reference frames every 2 seconds. + base::TimeDelta frame_cycle_period_ = base::TimeDelta::FromSeconds(2); + + // By default blink the cursor 4 times per seconds. + base::TimeDelta cursor_blink_period_ = base::TimeDelta::FromMilliseconds(250); + + // Index of the reference frame used to render the last generated frame. + int last_reference_frame_ = -1; + + // True if the cursor was rendered on the last generated frame. + bool last_cursor_state_ = false; + + FrameType last_frame_type_ = FrameType::EMPTY; + + base::TimeTicks started_time_; + + DISALLOW_COPY_AND_ASSIGN(CyclicFrameGenerator); +}; + +} // namespace test +} // namespace remoting + +#endif // REMOTING_TEST_CYCLIC_FRAME_GENERATOR_H_ diff --git a/remoting/test/data/download.sh b/remoting/test/data/download.sh new file mode 100755 index 00000000000000..106a8835a7d891 --- /dev/null +++ b/remoting/test/data/download.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This script downloads test files used by some remoting perf tests.The files +# are stored on Google Cloud Storage. + +set -e + +SRC_DIR="$(readlink -f "$(dirname "$0")")" + +for file_index in 1 2; do + file_name=test_frame${file_index}.png + file_path="${SRC_DIR}/${file_name}" + if [ ! -e "${file_path}" ] ; then + curl -L "https://storage.googleapis.com/chromoting-test-data/${file_name}" \ + > "${file_path}" + fi +done