video_frame_pump_unittest.cc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // Copyright 2015 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/protocol/video_frame_pump.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/run_loop.h"
  11. #include "base/task/single_thread_task_runner.h"
  12. #include "base/test/task_environment.h"
  13. #include "remoting/base/auto_thread.h"
  14. #include "remoting/base/auto_thread_task_runner.h"
  15. #include "remoting/codec/video_encoder.h"
  16. #include "remoting/codec/video_encoder_verbatim.h"
  17. #include "remoting/proto/control.pb.h"
  18. #include "remoting/proto/video.pb.h"
  19. #include "remoting/protocol/fake_desktop_capturer.h"
  20. #include "remoting/protocol/protocol_mock_objects.h"
  21. #include "testing/gmock/include/gmock/gmock.h"
  22. #include "testing/gtest/include/gtest/gtest.h"
  23. #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
  24. using ::testing::_;
  25. using ::testing::AtLeast;
  26. using ::testing::DoAll;
  27. using ::testing::Expectation;
  28. using ::testing::InvokeWithoutArgs;
  29. using ::testing::Return;
  30. namespace remoting {
  31. namespace protocol {
  32. namespace {
  33. ACTION(FinishSend) {
  34. std::move(*arg1).Run();
  35. }
  36. std::unique_ptr<webrtc::DesktopFrame> CreateNullFrame(
  37. webrtc::SharedMemoryFactory* shared_memory_factory) {
  38. return nullptr;
  39. }
  40. std::unique_ptr<webrtc::DesktopFrame> CreateUnchangedFrame(
  41. webrtc::SharedMemoryFactory* shared_memory_factory) {
  42. const webrtc::DesktopSize kSize(800, 640);
  43. // updated_region() is already empty by default in new BasicDesktopFrames.
  44. return std::make_unique<webrtc::BasicDesktopFrame>(kSize);
  45. }
  46. class MockVideoEncoder : public VideoEncoder {
  47. public:
  48. MockVideoEncoder() = default;
  49. ~MockVideoEncoder() override = default;
  50. MOCK_METHOD1(SetLosslessEncode, void(bool));
  51. MOCK_METHOD1(SetLosslessColor, void(bool));
  52. MOCK_METHOD1(EncodePtr, VideoPacket*(const webrtc::DesktopFrame&));
  53. std::unique_ptr<VideoPacket> Encode(
  54. const webrtc::DesktopFrame& frame) override {
  55. return base::WrapUnique(EncodePtr(frame));
  56. }
  57. };
  58. } // namespace
  59. static const int kWidth = 640;
  60. static const int kHeight = 480;
  61. class ThreadCheckVideoEncoder : public VideoEncoderVerbatim {
  62. public:
  63. ThreadCheckVideoEncoder(
  64. scoped_refptr<base::SingleThreadTaskRunner> task_runner)
  65. : task_runner_(task_runner) {
  66. }
  67. ThreadCheckVideoEncoder(const ThreadCheckVideoEncoder&) = delete;
  68. ThreadCheckVideoEncoder& operator=(const ThreadCheckVideoEncoder&) = delete;
  69. ~ThreadCheckVideoEncoder() override {
  70. EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
  71. }
  72. std::unique_ptr<VideoPacket> Encode(
  73. const webrtc::DesktopFrame& frame) override {
  74. return std::make_unique<VideoPacket>();
  75. }
  76. private:
  77. scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  78. };
  79. class ThreadCheckDesktopCapturer : public webrtc::DesktopCapturer {
  80. public:
  81. ThreadCheckDesktopCapturer(
  82. scoped_refptr<base::SingleThreadTaskRunner> task_runner)
  83. : task_runner_(task_runner), callback_(nullptr) {}
  84. ThreadCheckDesktopCapturer(const ThreadCheckDesktopCapturer&) = delete;
  85. ThreadCheckDesktopCapturer& operator=(const ThreadCheckDesktopCapturer&) =
  86. delete;
  87. ~ThreadCheckDesktopCapturer() override {
  88. EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
  89. }
  90. void Start(Callback* callback) override {
  91. EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
  92. EXPECT_FALSE(callback_);
  93. EXPECT_TRUE(callback);
  94. callback_ = callback;
  95. }
  96. void CaptureFrame() override {
  97. EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
  98. std::unique_ptr<webrtc::DesktopFrame> frame(
  99. new webrtc::BasicDesktopFrame(webrtc::DesktopSize(kWidth, kHeight)));
  100. frame->mutable_updated_region()->SetRect(
  101. webrtc::DesktopRect::MakeXYWH(0, 0, 10, 10));
  102. callback_->OnCaptureResult(webrtc::DesktopCapturer::Result::SUCCESS,
  103. std::move(frame));
  104. }
  105. bool GetSourceList(SourceList* sources) override {
  106. EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
  107. return false;
  108. }
  109. bool SelectSource(SourceId id) override {
  110. EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
  111. return true;
  112. }
  113. private:
  114. scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  115. raw_ptr<webrtc::DesktopCapturer::Callback> callback_;
  116. };
  117. class VideoFramePumpTest : public testing::Test {
  118. public:
  119. void SetUp() override;
  120. void TearDown() override;
  121. void StartVideoFramePump(std::unique_ptr<webrtc::DesktopCapturer> capturer,
  122. std::unique_ptr<VideoEncoder> encoder);
  123. protected:
  124. base::test::SingleThreadTaskEnvironment task_environment_;
  125. base::RunLoop run_loop_;
  126. scoped_refptr<AutoThreadTaskRunner> encode_task_runner_;
  127. scoped_refptr<AutoThreadTaskRunner> main_task_runner_;
  128. std::unique_ptr<VideoFramePump> pump_;
  129. MockVideoStub video_stub_;
  130. };
  131. void VideoFramePumpTest::SetUp() {
  132. main_task_runner_ = new AutoThreadTaskRunner(
  133. task_environment_.GetMainThreadTaskRunner(), run_loop_.QuitClosure());
  134. encode_task_runner_ = AutoThread::Create("encode", main_task_runner_);
  135. }
  136. void VideoFramePumpTest::TearDown() {
  137. pump_.reset();
  138. // Release the task runners, so that the test can quit.
  139. encode_task_runner_ = nullptr;
  140. main_task_runner_ = nullptr;
  141. // Run the MessageLoop until everything has torn down.
  142. run_loop_.Run();
  143. }
  144. // This test mocks capturer, encoder and network layer to simulate one capture
  145. // cycle.
  146. TEST_F(VideoFramePumpTest, StartAndStop) {
  147. std::unique_ptr<ThreadCheckDesktopCapturer> capturer(
  148. new ThreadCheckDesktopCapturer(main_task_runner_));
  149. std::unique_ptr<ThreadCheckVideoEncoder> encoder(
  150. new ThreadCheckVideoEncoder(encode_task_runner_));
  151. base::RunLoop run_loop;
  152. // When the first ProcessVideoPacket is received we stop the VideoFramePump.
  153. EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
  154. .WillOnce(DoAll(FinishSend(),
  155. InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)))
  156. .RetiresOnSaturation();
  157. // Start video frame capture.
  158. pump_ =
  159. std::make_unique<VideoFramePump>(encode_task_runner_, std::move(capturer),
  160. std::move(encoder), &video_stub_);
  161. // Run MessageLoop until the first frame is received.
  162. run_loop.Run();
  163. }
  164. // Tests that the pump handles null frames returned by the capturer.
  165. TEST_F(VideoFramePumpTest, NullFrame) {
  166. std::unique_ptr<FakeDesktopCapturer> capturer(new FakeDesktopCapturer);
  167. std::unique_ptr<MockVideoEncoder> encoder(new MockVideoEncoder);
  168. base::RunLoop run_loop;
  169. // Set up the capturer to return null frames.
  170. capturer->set_frame_generator(base::BindRepeating(&CreateNullFrame));
  171. // Expect that the VideoEncoder::Encode() method is never called.
  172. EXPECT_CALL(*encoder, EncodePtr(_)).Times(0);
  173. // When the first ProcessVideoPacket is received we stop the VideoFramePump.
  174. EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
  175. .WillOnce(DoAll(FinishSend(),
  176. InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)))
  177. .RetiresOnSaturation();
  178. // Start video frame capture.
  179. pump_ =
  180. std::make_unique<VideoFramePump>(encode_task_runner_, std::move(capturer),
  181. std::move(encoder), &video_stub_);
  182. // Run MessageLoop until the first frame is received..
  183. run_loop.Run();
  184. }
  185. // Tests how the pump handles unchanged frames returned by the capturer.
  186. TEST_F(VideoFramePumpTest, UnchangedFrame) {
  187. std::unique_ptr<FakeDesktopCapturer> capturer(new FakeDesktopCapturer);
  188. std::unique_ptr<MockVideoEncoder> encoder(new MockVideoEncoder);
  189. base::RunLoop run_loop;
  190. // Set up the capturer to return unchanged frames.
  191. capturer->set_frame_generator(base::BindRepeating(&CreateUnchangedFrame));
  192. // Expect that the VideoEncoder::Encode() method is called.
  193. EXPECT_CALL(*encoder, EncodePtr(_)).WillRepeatedly(Return(nullptr));
  194. // When the first ProcessVideoPacket is received we stop the VideoFramePump.
  195. // TODO(wez): Verify that the generated packet has no content here.
  196. EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
  197. .WillOnce(DoAll(FinishSend(),
  198. InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)))
  199. .RetiresOnSaturation();
  200. // Start video frame capture.
  201. pump_ =
  202. std::make_unique<VideoFramePump>(encode_task_runner_, std::move(capturer),
  203. std::move(encoder), &video_stub_);
  204. // Run MessageLoop until the first frame is received.
  205. run_loop.Run();
  206. }
  207. } // namespace protocol
  208. } // namespace remoting