codec_perftest.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/logging.h"
  5. #include "base/test/simple_test_tick_clock.h"
  6. #include "base/time/time.h"
  7. #include "remoting/codec/video_encoder_vpx.h"
  8. #include "remoting/proto/video.pb.h"
  9. #include "remoting/test/cyclic_frame_generator.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
  12. namespace remoting {
  13. namespace test {
  14. constexpr auto kIntervalBetweenFrames = base::Seconds(1) / 30;
  15. struct CodecParams {
  16. CodecParams(bool use_vp9, bool lossless, bool lossless_color)
  17. : use_vp9(use_vp9), lossless(lossless), lossless_color(lossless_color) {}
  18. bool use_vp9;
  19. bool lossless;
  20. bool lossless_color;
  21. };
  22. class CodecPerfTest : public testing::Test,
  23. public testing::WithParamInterface<CodecParams> {
  24. public:
  25. void SetUp() override {
  26. if (GetParam().use_vp9) {
  27. encoder_ = VideoEncoderVpx::CreateForVP9();
  28. encoder_->SetLosslessEncode(GetParam().lossless);
  29. encoder_->SetLosslessColor(GetParam().lossless_color);
  30. } else {
  31. encoder_ = VideoEncoderVpx::CreateForVP8();
  32. }
  33. encoder_->SetTickClockForTests(&clock_);
  34. frame_generator_ = CyclicFrameGenerator::Create();
  35. frame_generator_->SetTickClock(&clock_);
  36. }
  37. protected:
  38. base::SimpleTestTickClock clock_;
  39. scoped_refptr<CyclicFrameGenerator> frame_generator_;
  40. std::unique_ptr<VideoEncoderVpx> encoder_;
  41. };
  42. INSTANTIATE_TEST_SUITE_P(VP8,
  43. CodecPerfTest,
  44. ::testing::Values(CodecParams(false, false, false)));
  45. INSTANTIATE_TEST_SUITE_P(VP9,
  46. CodecPerfTest,
  47. ::testing::Values(CodecParams(true, false, false)));
  48. INSTANTIATE_TEST_SUITE_P(VP9Lossless,
  49. CodecPerfTest,
  50. ::testing::Values(CodecParams(true, true, false)));
  51. INSTANTIATE_TEST_SUITE_P(VP9LosslessColor,
  52. CodecPerfTest,
  53. ::testing::Values(CodecParams(true, false, true)));
  54. TEST_P(CodecPerfTest, EncodeLatency) {
  55. const int kTotalFrames = 300;
  56. base::TimeDelta total_latency;
  57. base::TimeDelta total_latency_big_frames;
  58. int big_frame_count = 0;
  59. base::TimeDelta total_latency_small_frames;
  60. int small_frame_count = 0;
  61. base::TimeDelta total_latency_empty_frames;
  62. int empty_frame_count = 0;
  63. int total_bytes = 0;
  64. for (int i = 0; i < kTotalFrames; ++i) {
  65. std::unique_ptr<webrtc::DesktopFrame> frame =
  66. frame_generator_->GenerateFrame(nullptr);
  67. base::TimeTicks started = base::TimeTicks::Now();
  68. std::unique_ptr<VideoPacket> packet = encoder_->Encode(*frame);
  69. base::TimeTicks ended = base::TimeTicks::Now();
  70. base::TimeDelta latency = ended - started;
  71. total_latency += latency;
  72. if (packet)
  73. total_bytes += packet->data().size();
  74. switch (frame_generator_->last_frame_type()) {
  75. case CyclicFrameGenerator::ChangeType::NO_CHANGES:
  76. total_latency_empty_frames += latency;
  77. ++empty_frame_count;
  78. break;
  79. case CyclicFrameGenerator::ChangeType::FULL:
  80. total_latency_big_frames += latency;
  81. ++big_frame_count;
  82. break;
  83. case CyclicFrameGenerator::ChangeType::CURSOR:
  84. total_latency_small_frames += latency;
  85. ++small_frame_count;
  86. break;
  87. }
  88. clock_.Advance(kIntervalBetweenFrames);
  89. }
  90. VLOG(0) << "Total time: " << total_latency.InMillisecondsF();
  91. VLOG(0) << "Average encode latency: "
  92. << (total_latency / kTotalFrames).InMillisecondsF();
  93. CHECK(big_frame_count);
  94. VLOG(0) << "Average encode latency for big frames: "
  95. << (total_latency_big_frames / big_frame_count).InMillisecondsF();
  96. if (small_frame_count) {
  97. VLOG(0) << "Average encode latency for small frames: "
  98. << (total_latency_small_frames / small_frame_count)
  99. .InMillisecondsF();
  100. }
  101. if (empty_frame_count) {
  102. VLOG(0) << "Average encode latency for empty frames: "
  103. << (total_latency_empty_frames / empty_frame_count)
  104. .InMillisecondsF();
  105. }
  106. VLOG(0) << "Encoded bytes: " << total_bytes;
  107. }
  108. TEST_P(CodecPerfTest, MaxFramerate) {
  109. const int kTotalFrames = 100;
  110. base::TimeDelta total_latency;
  111. // Update the whole screen on every frame.
  112. frame_generator_->set_frame_cycle_period(kIntervalBetweenFrames);
  113. for (int i = 0; i < kTotalFrames; ++i) {
  114. std::unique_ptr<webrtc::DesktopFrame> frame =
  115. frame_generator_->GenerateFrame(nullptr);
  116. base::TimeTicks started = base::TimeTicks::Now();
  117. std::unique_ptr<VideoPacket> packet = encoder_->Encode(*frame);
  118. base::TimeTicks ended = base::TimeTicks::Now();
  119. base::TimeDelta latency = ended - started;
  120. total_latency += latency;
  121. clock_.Advance(kIntervalBetweenFrames);
  122. }
  123. VLOG(0) << "Max framerate: " << kTotalFrames / total_latency.InSecondsF();
  124. }
  125. } // namespace test
  126. } // namespace remoting