[go: nahoru, domu]

blob: f7d850c35617474da48ff7eaa86a99c987fc24bd [file] [log] [blame]
Avi Drissmand6cdf9b2022-09-15 19:52:531// Copyright 2015 The Chromium Authors
sergeyu13bca692015-08-20 02:02:182// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "remoting/client/software_video_renderer.h"
6
avi5a080f012015-12-22 23:15:437#include <stdint.h>
8
avi954c9c12017-01-11 16:52:379#include <memory>
sergeyu42ad7c02015-12-24 00:20:5110#include <utility>
sergeyu13bca692015-08-20 02:02:1811#include <vector>
12
Avi Drissman135261e2023-01-11 22:43:1513#include "base/functional/bind.h"
sergeyu13bca692015-08-20 02:02:1814#include "base/run_loop.h"
Gabriel Charettec7108742019-08-23 03:31:4015#include "base/test/task_environment.h"
sergeyu13bca692015-08-20 02:02:1816#include "base/threading/thread.h"
yuweih6d9bb4a2016-07-22 19:45:0817#include "remoting/client/client_context.h"
sergeyu13bca692015-08-20 02:02:1818#include "remoting/codec/video_encoder_verbatim.h"
19#include "remoting/proto/video.pb.h"
sergeyu480531b2016-01-05 19:12:4220#include "remoting/protocol/frame_consumer.h"
sergeyu13bca692015-08-20 02:02:1821#include "remoting/protocol/session_config.h"
22#include "testing/gtest/include/gtest/gtest.h"
23#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
24
25using webrtc::DesktopFrame;
26
27namespace remoting {
28
29namespace {
30
31const int kFrameWidth = 200;
32const int kFrameHeight = 200;
33
sergeyu480531b2016-01-05 19:12:4234class TestFrameConsumer : public protocol::FrameConsumer {
sergeyu13bca692015-08-20 02:02:1835 public:
Chris Watkins6fe52aa2017-11-28 03:24:0536 TestFrameConsumer() = default;
37 ~TestFrameConsumer() override = default;
sergeyu13bca692015-08-20 02:02:1838
dcheng0765c492016-04-06 22:41:5339 std::unique_ptr<DesktopFrame> WaitForNextFrame(
Joey Scarr00b7c1f2020-02-13 03:34:0340 base::OnceClosure* out_done_callback) {
sergeyu13bca692015-08-20 02:02:1841 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
Peter Boström42afa23f2021-04-02 22:10:4642 frame_run_loop_ = std::make_unique<base::RunLoop>();
sergeyu13bca692015-08-20 02:02:1843 frame_run_loop_->Run();
44 frame_run_loop_.reset();
Joey Scarr00b7c1f2020-02-13 03:34:0345 *out_done_callback = std::move(last_frame_done_callback_);
sergeyu42ad7c02015-12-24 00:20:5146 return std::move(last_frame_);
sergeyu13bca692015-08-20 02:02:1847 }
48
49 // FrameConsumer interface.
dcheng0765c492016-04-06 22:41:5350 std::unique_ptr<DesktopFrame> AllocateFrame(
sergeyu13bca692015-08-20 02:02:1851 const webrtc::DesktopSize& size) override {
52 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
Jinho Bang138fde32018-01-18 23:13:4253 return std::make_unique<webrtc::BasicDesktopFrame>(size);
sergeyu13bca692015-08-20 02:02:1854 }
55
dcheng0765c492016-04-06 22:41:5356 void DrawFrame(std::unique_ptr<DesktopFrame> frame,
Joey Scarr00b7c1f2020-02-13 03:34:0357 base::OnceClosure done) override {
sergeyu13bca692015-08-20 02:02:1858 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
sergeyu42ad7c02015-12-24 00:20:5159 last_frame_ = std::move(frame);
Joey Scarr00b7c1f2020-02-13 03:34:0360 last_frame_done_callback_ = std::move(done);
sergeyu13bca692015-08-20 02:02:1861 frame_run_loop_->Quit();
62 }
63
64 PixelFormat GetPixelFormat() override {
65 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
66 return FORMAT_BGRA;
67 }
68
69 private:
70 base::ThreadChecker thread_checker_;
71
dcheng0765c492016-04-06 22:41:5372 std::unique_ptr<base::RunLoop> frame_run_loop_;
sergeyu13bca692015-08-20 02:02:1873
dcheng0765c492016-04-06 22:41:5374 std::unique_ptr<DesktopFrame> last_frame_;
Joey Scarr00b7c1f2020-02-13 03:34:0375 base::OnceClosure last_frame_done_callback_;
sergeyu13bca692015-08-20 02:02:1876};
77
dcheng0765c492016-04-06 22:41:5378std::unique_ptr<DesktopFrame> CreateTestFrame(int index) {
79 std::unique_ptr<DesktopFrame> frame(new webrtc::BasicDesktopFrame(
sergeyu13bca692015-08-20 02:02:1880 webrtc::DesktopSize(kFrameWidth, kFrameHeight)));
81
82 for (int y = 0; y < kFrameHeight; y++) {
83 for (int x = 0; x < kFrameWidth; x++) {
84 uint8_t* out = frame->data() + x * DesktopFrame::kBytesPerPixel +
85 y * frame->stride();
86 out[0] = index + x + y * kFrameWidth;
87 out[1] = index + x + y * kFrameWidth + 1;
88 out[2] = index + x + y * kFrameWidth + 2;
89 out[3] = 0;
90 }
91 }
92
93 if (index == 0) {
94 frame->mutable_updated_region()->SetRect(
95 webrtc::DesktopRect::MakeWH(kFrameWidth, kFrameHeight));
96 } else {
97 frame->mutable_updated_region()->SetRect(
98 webrtc::DesktopRect::MakeWH(index, index));
99 }
100
sergeyu42ad7c02015-12-24 00:20:51101 return frame;
sergeyu13bca692015-08-20 02:02:18102}
103
104// Returns true when frames a and b are equivalent.
105bool CompareFrames(const DesktopFrame& a, const DesktopFrame& b) {
106 if (!a.size().equals(b.size()) ||
107 !a.updated_region().Equals(b.updated_region())) {
108 return false;
109 }
110
111 for (webrtc::DesktopRegion::Iterator i(a.updated_region()); !i.IsAtEnd();
112 i.Advance()) {
113 for (int row = i.rect().top(); row < i.rect().bottom(); ++row) {
114 if (memcmp(a.data() + a.stride() * row +
115 i.rect().left() * DesktopFrame::kBytesPerPixel,
116 b.data() + b.stride() * row +
117 i.rect().left() * DesktopFrame::kBytesPerPixel,
118 i.rect().width() * DesktopFrame::kBytesPerPixel) != 0) {
119 return false;
120 }
121 }
122 }
123
124 return true;
125}
126
127// Helper to set value at |out| to 1.
128void SetTrue(int* out) {
129 *out = 1;
130}
131
132} // namespace
133
134class SoftwareVideoRendererTest : public ::testing::Test {
135 public:
yuweih6d9bb4a2016-07-22 19:45:08136 SoftwareVideoRendererTest() : context_(nullptr) {
137 context_.Start();
Peter Boström42afa23f2021-04-02 22:10:46138 renderer_ = std::make_unique<SoftwareVideoRenderer>(&frame_consumer_);
yuweih6d9bb4a2016-07-22 19:45:08139 renderer_->Initialize(context_, nullptr);
sergeyu13bca692015-08-20 02:02:18140 renderer_->OnSessionConfig(
141 *protocol::SessionConfig::ForTestWithVerbatimVideo());
142 }
143
144 protected:
Gabriel Charettedf0a7442019-09-05 17:32:35145 base::test::SingleThreadTaskEnvironment task_environment_;
yuweih6d9bb4a2016-07-22 19:45:08146 ClientContext context_;
sergeyu13bca692015-08-20 02:02:18147
148 TestFrameConsumer frame_consumer_;
dcheng0765c492016-04-06 22:41:53149 std::unique_ptr<SoftwareVideoRenderer> renderer_;
sergeyu13bca692015-08-20 02:02:18150
151 VideoEncoderVerbatim encoder_;
152};
153
154TEST_F(SoftwareVideoRendererTest, DecodeFrame) {
155 const int kFrameCount = 5;
156
avi954c9c12017-01-11 16:52:37157 std::vector<std::unique_ptr<DesktopFrame>> test_frames;
sergeyu13bca692015-08-20 02:02:18158
159 // std::vector<bool> doesn't allow to get pointer to individual values, so
160 // int needs to be used instead.
161 std::vector<int> callback_called(kFrameCount);
162
163 for (int frame_index = 0; frame_index < kFrameCount; frame_index++) {
164 test_frames.push_back(CreateTestFrame(frame_index));
165 callback_called[frame_index] = 0;
166
167 renderer_->ProcessVideoPacket(
sergeyu2becb6012016-09-13 18:41:32168 encoder_.Encode(*test_frames[frame_index]),
Evan Stadeb36ca0a52020-03-12 15:56:52169 base::BindOnce(&SetTrue, &(callback_called[frame_index])));
sergeyu13bca692015-08-20 02:02:18170 }
171
172 for (int frame_index = 0; frame_index < kFrameCount; frame_index++) {
Joey Scarr00b7c1f2020-02-13 03:34:03173 base::OnceClosure done_callback;
dcheng0765c492016-04-06 22:41:53174 std::unique_ptr<DesktopFrame> decoded_frame =
sergeyu13bca692015-08-20 02:02:18175 frame_consumer_.WaitForNextFrame(&done_callback);
176
177 EXPECT_FALSE(callback_called[frame_index]);
Joey Scarr00b7c1f2020-02-13 03:34:03178 std::move(done_callback).Run();
sergeyu13bca692015-08-20 02:02:18179 EXPECT_TRUE(callback_called[frame_index]);
180
181 EXPECT_TRUE(CompareFrames(*test_frames[frame_index], *decoded_frame));
182 }
183}
184
185} // namespace remoting