dual_buffer_frame_consumer_unittest.cc 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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 "remoting/client/dual_buffer_frame_consumer.h"
  5. #include <memory>
  6. #include "base/bind.h"
  7. #include "base/callback_helpers.h"
  8. #include "testing/gtest/include/gtest/gtest.h"
  9. #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
  10. #include "third_party/webrtc/modules/desktop_capture/shared_desktop_frame.h"
  11. namespace remoting {
  12. namespace {
  13. webrtc::DesktopFrame* GetUnderlyingFrame(
  14. const std::unique_ptr<webrtc::DesktopFrame>& frame) {
  15. return reinterpret_cast<webrtc::SharedDesktopFrame*>(frame.get())->
  16. GetUnderlyingFrame();
  17. }
  18. void FillRGBARect(uint8_t r,
  19. uint8_t g,
  20. uint8_t b,
  21. uint8_t a,
  22. const webrtc::DesktopRect& rect,
  23. webrtc::DesktopFrame* frame) {
  24. for (int x = 0; x < rect.width(); x++) {
  25. for (int y = 0; y < rect.height(); y++) {
  26. uint8_t* data = frame->GetFrameDataAtPos(
  27. rect.top_left().add(webrtc::DesktopVector(x, y)));
  28. data[0] = r;
  29. data[1] = g;
  30. data[2] = b;
  31. data[3] = a;
  32. }
  33. }
  34. frame->mutable_updated_region()->SetRect(rect);
  35. }
  36. void CheckFrameColor(uint8_t r,
  37. uint8_t g,
  38. uint8_t b,
  39. uint8_t a,
  40. const webrtc::DesktopVector& pos,
  41. const webrtc::DesktopFrame& frame) {
  42. uint8_t* data = frame.GetFrameDataAtPos(pos);
  43. EXPECT_EQ(r, data[0]);
  44. EXPECT_EQ(g, data[1]);
  45. EXPECT_EQ(b, data[2]);
  46. EXPECT_EQ(a, data[3]);
  47. }
  48. } // namespace
  49. class DualBufferFrameConsumerTest : public testing::Test {
  50. public:
  51. void SetUp() override;
  52. protected:
  53. std::unique_ptr<DualBufferFrameConsumer> consumer_;
  54. std::unique_ptr<webrtc::DesktopFrame> received_frame_;
  55. base::OnceClosure done_closure_;
  56. private:
  57. void OnFrameReceived(std::unique_ptr<webrtc::DesktopFrame> frame,
  58. base::OnceClosure done);
  59. };
  60. void DualBufferFrameConsumerTest::SetUp() {
  61. consumer_ = std::make_unique<DualBufferFrameConsumer>(
  62. base::BindRepeating(&DualBufferFrameConsumerTest::OnFrameReceived,
  63. base::Unretained(this)),
  64. nullptr, protocol::FrameConsumer::FORMAT_RGBA);
  65. }
  66. void DualBufferFrameConsumerTest::OnFrameReceived(
  67. std::unique_ptr<webrtc::DesktopFrame> frame,
  68. base::OnceClosure done) {
  69. received_frame_ = std::move(frame);
  70. done_closure_ = std::move(done);
  71. }
  72. TEST_F(DualBufferFrameConsumerTest, AllocateOneFrame) {
  73. std::unique_ptr<webrtc::DesktopFrame> frame =
  74. consumer_->AllocateFrame(webrtc::DesktopSize(16, 16));
  75. ASSERT_TRUE(frame->size().equals(webrtc::DesktopSize(16, 16)));
  76. webrtc::DesktopFrame* raw_frame = frame.get();
  77. consumer_->DrawFrame(std::move(frame), base::NullCallback());
  78. EXPECT_EQ(raw_frame, received_frame_.get());
  79. }
  80. TEST_F(DualBufferFrameConsumerTest, BufferRotation) {
  81. webrtc::DesktopSize size16x16(16, 16);
  82. std::unique_ptr<webrtc::DesktopFrame> frame =
  83. consumer_->AllocateFrame(size16x16);
  84. webrtc::DesktopFrame* underlying_frame_1 = GetUnderlyingFrame(frame);
  85. consumer_->DrawFrame(std::move(frame), base::NullCallback());
  86. frame = consumer_->AllocateFrame(size16x16);
  87. webrtc::DesktopFrame* underlying_frame_2 = GetUnderlyingFrame(frame);
  88. EXPECT_NE(underlying_frame_1, underlying_frame_2);
  89. consumer_->DrawFrame(std::move(frame), base::NullCallback());
  90. frame = consumer_->AllocateFrame(size16x16);
  91. webrtc::DesktopFrame* underlying_frame_3 = GetUnderlyingFrame(frame);
  92. EXPECT_EQ(underlying_frame_1, underlying_frame_3);
  93. consumer_->DrawFrame(std::move(frame), base::NullCallback());
  94. frame = consumer_->AllocateFrame(size16x16);
  95. webrtc::DesktopFrame* underlying_frame_4 = GetUnderlyingFrame(frame);
  96. EXPECT_EQ(underlying_frame_2, underlying_frame_4);
  97. consumer_->DrawFrame(std::move(frame), base::NullCallback());
  98. }
  99. TEST_F(DualBufferFrameConsumerTest, DrawAndMergeFrames) {
  100. webrtc::DesktopSize size2x2(2, 2);
  101. // X means uninitialized color.
  102. // Frame 1:
  103. // RR
  104. // RR
  105. std::unique_ptr<webrtc::DesktopFrame> frame =
  106. consumer_->AllocateFrame(size2x2);
  107. FillRGBARect(0xff, 0, 0, 0xff, webrtc::DesktopRect::MakeXYWH(0, 0, 2, 2),
  108. frame.get());
  109. consumer_->DrawFrame(std::move(frame), base::NullCallback());
  110. // Frame 2:
  111. // GG
  112. // XX
  113. frame = consumer_->AllocateFrame(size2x2);
  114. FillRGBARect(0, 0xff, 0, 0xff, webrtc::DesktopRect::MakeXYWH(0, 0, 2, 1),
  115. frame.get());
  116. consumer_->DrawFrame(std::move(frame), base::NullCallback());
  117. // Merged Frame:
  118. // GG
  119. // RR
  120. consumer_->RequestFullDesktopFrame();
  121. ASSERT_TRUE(received_frame_->size().equals(size2x2));
  122. CheckFrameColor(0, 0xff, 0, 0xff, webrtc::DesktopVector(0, 0),
  123. *received_frame_);
  124. CheckFrameColor(0xff, 0, 0, 0xff, webrtc::DesktopVector(0, 1),
  125. *received_frame_);
  126. CheckFrameColor(0, 0xff, 0, 0xff, webrtc::DesktopVector(1, 0),
  127. *received_frame_);
  128. CheckFrameColor(0xff, 0, 0, 0xff, webrtc::DesktopVector(1, 1),
  129. *received_frame_);
  130. // Frame 3:
  131. // BX
  132. // BX
  133. frame = consumer_->AllocateFrame(size2x2);
  134. FillRGBARect(0, 0, 0xff, 0xff, webrtc::DesktopRect::MakeXYWH(0, 0, 1, 2),
  135. frame.get());
  136. consumer_->DrawFrame(std::move(frame), base::NullCallback());
  137. // Merged Frame:
  138. // BG
  139. // BR
  140. consumer_->RequestFullDesktopFrame();
  141. ASSERT_TRUE(received_frame_->size().equals(size2x2));
  142. CheckFrameColor(0, 0, 0xff, 0xff, webrtc::DesktopVector(0, 0),
  143. *received_frame_);
  144. CheckFrameColor(0, 0, 0xff, 0xff, webrtc::DesktopVector(0, 1),
  145. *received_frame_);
  146. CheckFrameColor(0, 0xff, 0, 0xff, webrtc::DesktopVector(1, 0),
  147. *received_frame_);
  148. CheckFrameColor(0xff, 0, 0, 0xff, webrtc::DesktopVector(1, 1),
  149. *received_frame_);
  150. }
  151. TEST_F(DualBufferFrameConsumerTest, ChangeScreenSizeAndReallocateBuffers) {
  152. webrtc::DesktopSize size16x16(16, 16);
  153. std::unique_ptr<webrtc::DesktopFrame> frame =
  154. consumer_->AllocateFrame(size16x16);
  155. webrtc::DesktopFrame* underlying_frame_1 = GetUnderlyingFrame(frame);
  156. consumer_->DrawFrame(std::move(frame), base::NullCallback());
  157. frame = consumer_->AllocateFrame(size16x16);
  158. webrtc::DesktopFrame* underlying_frame_2 = GetUnderlyingFrame(frame);
  159. EXPECT_NE(underlying_frame_1, underlying_frame_2);
  160. consumer_->DrawFrame(std::move(frame), base::NullCallback());
  161. webrtc::DesktopSize size32x32(32, 32);
  162. frame = consumer_->AllocateFrame(size32x32);
  163. webrtc::DesktopFrame* underlying_frame_3 = GetUnderlyingFrame(frame);
  164. EXPECT_NE(underlying_frame_1, underlying_frame_3);
  165. consumer_->DrawFrame(std::move(frame), base::NullCallback());
  166. frame = consumer_->AllocateFrame(size32x32);
  167. webrtc::DesktopFrame* underlying_frame_4 = GetUnderlyingFrame(frame);
  168. EXPECT_NE(underlying_frame_2, underlying_frame_4);
  169. consumer_->DrawFrame(std::move(frame), base::NullCallback());
  170. }
  171. } // namespace remoting