OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/test/test_video_renderer.h" | 5 #include "remoting/test/test_video_renderer.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/memory/scoped_vector.h" | 9 #include "base/memory/scoped_vector.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/run_loop.h" | 11 #include "base/run_loop.h" |
12 #include "base/thread_task_runner_handle.h" | 12 #include "base/thread_task_runner_handle.h" |
13 #include "base/timer/timer.h" | 13 #include "base/timer/timer.h" |
14 #include "media/base/video_frame.h" | 14 #include "media/base/video_frame.h" |
15 #include "remoting/codec/video_encoder.h" | 15 #include "remoting/codec/video_encoder.h" |
16 #include "remoting/codec/video_encoder_verbatim.h" | 16 #include "remoting/codec/video_encoder_verbatim.h" |
17 #include "remoting/codec/video_encoder_vpx.h" | 17 #include "remoting/codec/video_encoder_vpx.h" |
18 #include "remoting/proto/video.pb.h" | 18 #include "remoting/proto/video.pb.h" |
| 19 #include "remoting/test/rgb_value.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
20 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" | 21 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
21 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h" | 22 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h" |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 // Used to verify if image pattern is matched. | 26 // Used to verify if image pattern is matched. |
26 void ProcessPacketDoneHandler(const base::Closure& done_closure, | 27 void ProcessPacketDoneHandler(const base::Closure& done_closure, |
27 bool* handler_called) { | 28 bool* handler_called) { |
28 *handler_called = true; | 29 *handler_called = true; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 scoped_ptr<VideoEncoder> encoder_; | 80 scoped_ptr<VideoEncoder> encoder_; |
80 | 81 |
81 private: | 82 private: |
82 // testing::Test interface. | 83 // testing::Test interface. |
83 void SetUp() override; | 84 void SetUp() override; |
84 | 85 |
85 // Set image pattern, send video packet and returns if the expected pattern is | 86 // Set image pattern, send video packet and returns if the expected pattern is |
86 // matched. | 87 // matched. |
87 bool SendPacketAndWaitForMatch(scoped_ptr<VideoPacket> packet, | 88 bool SendPacketAndWaitForMatch(scoped_ptr<VideoPacket> packet, |
88 const webrtc::DesktopRect& expected_rect, | 89 const webrtc::DesktopRect& expected_rect, |
89 uint32_t expected_average_color); | 90 const RGBValue& expected_average_color); |
90 | 91 |
91 // Returns the average color value of pixels fall within |rect|. | 92 // Returns the average color value of pixels fall within |rect|. |
92 // NOTE: Callers should not release the objects. | 93 // NOTE: Callers should not release the objects. |
93 uint32_t CalculateAverageColorValueForFrame( | 94 RGBValue CalculateAverageColorValueForFrame( |
94 const webrtc::DesktopFrame* frame, | 95 const webrtc::DesktopFrame* frame, |
95 const webrtc::DesktopRect& rect) const; | 96 const webrtc::DesktopRect& rect) const; |
96 | 97 |
97 // Return the mean error of two frames over all pixels, where error at each | 98 // Return the mean error of two frames over all pixels, where error at each |
98 // pixel is the root mean square of the errors in the R, G and B components, | 99 // pixel is the root mean square of the errors in the R, G and B components, |
99 // each normalized to [0, 1]. | 100 // each normalized to [0, 1]. |
100 double CalculateError(const webrtc::DesktopFrame* original_frame, | 101 double CalculateError(const webrtc::DesktopFrame* original_frame, |
101 const webrtc::DesktopFrame* decoded_frame) const; | 102 const webrtc::DesktopFrame* decoded_frame) const; |
102 | 103 |
103 // Fill a desktop frame with a gradient. | 104 // Fill a desktop frame with a gradient. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 | 162 |
162 // The original frame is compared to the decoded video frame to check that | 163 // The original frame is compared to the decoded video frame to check that |
163 // the mean error over all pixels does not exceed a given limit. | 164 // the mean error over all pixels does not exceed a given limit. |
164 double error = CalculateError(original_frame.get(), buffer_copy.get()); | 165 double error = CalculateError(original_frame.get(), buffer_copy.get()); |
165 EXPECT_LT(error, error_limit); | 166 EXPECT_LT(error, error_limit); |
166 } | 167 } |
167 | 168 |
168 bool TestVideoRendererTest::SendPacketAndWaitForMatch( | 169 bool TestVideoRendererTest::SendPacketAndWaitForMatch( |
169 scoped_ptr<VideoPacket> packet, | 170 scoped_ptr<VideoPacket> packet, |
170 const webrtc::DesktopRect& expected_rect, | 171 const webrtc::DesktopRect& expected_rect, |
171 uint32_t expected_average_color) { | 172 const RGBValue& expected_average_color) { |
172 DCHECK(!run_loop_ || !run_loop_->running()); | 173 DCHECK(!run_loop_ || !run_loop_->running()); |
173 DCHECK(!timer_->IsRunning()); | 174 DCHECK(!timer_->IsRunning()); |
174 run_loop_.reset(new base::RunLoop()); | 175 run_loop_.reset(new base::RunLoop()); |
175 | 176 |
176 // Set an extremely long time: 10 min to prevent bugs from hanging the system. | 177 // Set an extremely long time: 10 min to prevent bugs from hanging the system. |
177 // NOTE: We've seen cases which take up to 1 min to process a packet, so an | 178 // NOTE: We've seen cases which take up to 1 min to process a packet, so an |
178 // extremely long time as 10 min is chosen to avoid being variable/flaky. | 179 // extremely long time as 10 min is chosen to avoid being variable/flaky. |
179 timer_->Start(FROM_HERE, base::TimeDelta::FromMinutes(10), | 180 timer_->Start(FROM_HERE, base::TimeDelta::FromMinutes(10), |
180 run_loop_->QuitClosure()); | 181 run_loop_->QuitClosure()); |
181 | 182 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 void TestVideoRendererTest::TestImagePatternMatch( | 218 void TestVideoRendererTest::TestImagePatternMatch( |
218 int screen_width, | 219 int screen_width, |
219 int screen_height, | 220 int screen_height, |
220 const webrtc::DesktopRect& expected_rect, | 221 const webrtc::DesktopRect& expected_rect, |
221 bool expect_to_match) { | 222 bool expect_to_match) { |
222 DCHECK(encoder_); | 223 DCHECK(encoder_); |
223 DCHECK(test_video_renderer_); | 224 DCHECK(test_video_renderer_); |
224 | 225 |
225 scoped_ptr<webrtc::DesktopFrame> frame = | 226 scoped_ptr<webrtc::DesktopFrame> frame = |
226 CreateDesktopFrameWithGradient(screen_width, screen_height); | 227 CreateDesktopFrameWithGradient(screen_width, screen_height); |
227 uint32_t expected_average_color = | 228 RGBValue expected_average_color = |
228 CalculateAverageColorValueForFrame(frame.get(), expected_rect); | 229 CalculateAverageColorValueForFrame(frame.get(), expected_rect); |
229 scoped_ptr<VideoPacket> packet = encoder_->Encode(*frame.get()); | 230 scoped_ptr<VideoPacket> packet = encoder_->Encode(*frame.get()); |
230 | 231 |
231 if (expect_to_match) { | 232 if (expect_to_match) { |
232 EXPECT_TRUE(SendPacketAndWaitForMatch(packet.Pass(), expected_rect, | 233 EXPECT_TRUE(SendPacketAndWaitForMatch(packet.Pass(), expected_rect, |
233 expected_average_color)); | 234 expected_average_color)); |
234 } else { | 235 } else { |
235 // Shift each channel by 128. | 236 // Shift each channel by 128. |
236 // e.g. (10, 127, 200) -> (138, 255, 73). | 237 // e.g. (10, 127, 200) -> (138, 255, 73). |
237 // In this way, the error between expected color and true value is always | 238 // In this way, the error between expected color and true value is always |
238 // around 0.5. | 239 // around 0.5. |
239 int red_shift = (((expected_average_color >> 16) & 0xFF) + 128) % 255; | 240 int red_shift = (expected_average_color.red + 128) % 255; |
240 int green_shift = (((expected_average_color >> 8) & 0xFF) + 128) % 255; | 241 int green_shift = (expected_average_color.green + 128) % 255; |
241 int blue_shift = ((expected_average_color & 0xFF) + 128) % 255; | 242 int blue_shift = (expected_average_color.blue + 128) % 255; |
242 | 243 |
243 int expected_average_color_shift = | 244 RGBValue expected_average_color_shift = |
244 0xFF000000 | (red_shift << 16) | (green_shift << 8) | blue_shift; | 245 RGBValue(red_shift, green_shift, blue_shift); |
245 | 246 |
246 EXPECT_FALSE(SendPacketAndWaitForMatch(packet.Pass(), expected_rect, | 247 EXPECT_FALSE(SendPacketAndWaitForMatch(packet.Pass(), expected_rect, |
247 expected_average_color_shift)); | 248 expected_average_color_shift)); |
248 } | 249 } |
249 } | 250 } |
250 | 251 |
251 uint32_t TestVideoRendererTest::CalculateAverageColorValueForFrame( | 252 RGBValue TestVideoRendererTest::CalculateAverageColorValueForFrame( |
252 const webrtc::DesktopFrame* frame, | 253 const webrtc::DesktopFrame* frame, |
253 const webrtc::DesktopRect& rect) const { | 254 const webrtc::DesktopRect& rect) const { |
254 int red_sum = 0; | 255 int red_sum = 0; |
255 int green_sum = 0; | 256 int green_sum = 0; |
256 int blue_sum = 0; | 257 int blue_sum = 0; |
257 | 258 |
258 // Loop through pixels that fall within |accumulating_rect_| to obtain the | 259 // Loop through pixels that fall within |accumulating_rect_| to obtain the |
259 // average color value. | 260 // average color value. |
260 for (int y = rect.top(); y < rect.bottom(); ++y) { | 261 for (int y = rect.top(); y < rect.bottom(); ++y) { |
261 uint8_t* frame_pos = | 262 uint8_t* frame_pos = |
262 frame->data() + (y * frame->stride() + | 263 frame->data() + (y * frame->stride() + |
263 rect.left() * webrtc::DesktopFrame::kBytesPerPixel); | 264 rect.left() * webrtc::DesktopFrame::kBytesPerPixel); |
264 | 265 |
265 // Pixels of decoded video frame are presented in ARGB format. | 266 // Pixels of decoded video frame are presented in ARGB format. |
266 for (int x = 0; x < rect.width(); ++x) { | 267 for (int x = 0; x < rect.width(); ++x) { |
267 red_sum += frame_pos[2]; | 268 red_sum += frame_pos[2]; |
268 green_sum += frame_pos[1]; | 269 green_sum += frame_pos[1]; |
269 blue_sum += frame_pos[0]; | 270 blue_sum += frame_pos[0]; |
270 frame_pos += 4; | 271 frame_pos += 4; |
271 } | 272 } |
272 } | 273 } |
273 | 274 |
274 int area = rect.width() * rect.height(); | 275 int area = rect.width() * rect.height(); |
275 return 0xFF000000 | ((red_sum / area) << 16) | ((green_sum / area) << 8) | | 276 |
276 (blue_sum / area); | 277 return RGBValue(red_sum / area, green_sum / area, blue_sum / area); |
277 } | 278 } |
278 | 279 |
279 double TestVideoRendererTest::CalculateError( | 280 double TestVideoRendererTest::CalculateError( |
280 const webrtc::DesktopFrame* original_frame, | 281 const webrtc::DesktopFrame* original_frame, |
281 const webrtc::DesktopFrame* decoded_frame) const { | 282 const webrtc::DesktopFrame* decoded_frame) const { |
282 DCHECK(original_frame); | 283 DCHECK(original_frame); |
283 DCHECK(decoded_frame); | 284 DCHECK(decoded_frame); |
284 | 285 |
285 // Check size remains the same after encoding and decoding. | 286 // Check size remains the same after encoding and decoding. |
286 EXPECT_EQ(original_frame->size().width(), decoded_frame->size().width()); | 287 EXPECT_EQ(original_frame->size().width(), decoded_frame->size().width()); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 protocol::ChannelConfig::Codec::CODEC_VP8); | 434 protocol::ChannelConfig::Codec::CODEC_VP8); |
434 | 435 |
435 DCHECK(encoder_); | 436 DCHECK(encoder_); |
436 DCHECK(test_video_renderer_); | 437 DCHECK(test_video_renderer_); |
437 | 438 |
438 scoped_ptr<webrtc::DesktopFrame> frame = CreateDesktopFrameWithGradient( | 439 scoped_ptr<webrtc::DesktopFrame> frame = CreateDesktopFrameWithGradient( |
439 kDefaultScreenWidthPx, kDefaultScreenHeightPx); | 440 kDefaultScreenWidthPx, kDefaultScreenHeightPx); |
440 | 441 |
441 // Since we don't care whether expected image pattern is matched or not in | 442 // Since we don't care whether expected image pattern is matched or not in |
442 // this case, an expected color is chosen arbitrarily. | 443 // this case, an expected color is chosen arbitrarily. |
443 uint32_t black_color = 0xFF000000; | 444 RGBValue black_color = RGBValue(); |
444 | 445 |
445 // Set expected image pattern. | 446 // Set expected image pattern. |
446 test_video_renderer_->ExpectAverageColorInRect( | 447 test_video_renderer_->ExpectAverageColorInRect( |
447 kDefaultExpectedRect, black_color, base::Bind(&base::DoNothing)); | 448 kDefaultExpectedRect, black_color, base::Bind(&base::DoNothing)); |
448 | 449 |
449 // Post test video packet. | 450 // Post test video packet. |
450 scoped_ptr<VideoPacket> packet = encoder_->Encode(*frame.get()); | 451 scoped_ptr<VideoPacket> packet = encoder_->Encode(*frame.get()); |
451 test_video_renderer_->ProcessVideoPacket(packet.Pass(), | 452 test_video_renderer_->ProcessVideoPacket(packet.Pass(), |
452 base::Bind(&base::DoNothing)); | 453 base::Bind(&base::DoNothing)); |
453 } | 454 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 TEST_F(TestVideoRendererTest, VerifyImagePatternNotMatchForVERBATIM) { | 502 TEST_F(TestVideoRendererTest, VerifyImagePatternNotMatchForVERBATIM) { |
502 encoder_.reset(new VideoEncoderVerbatim()); | 503 encoder_.reset(new VideoEncoderVerbatim()); |
503 test_video_renderer_->SetCodecForDecoding( | 504 test_video_renderer_->SetCodecForDecoding( |
504 protocol::ChannelConfig::Codec::CODEC_VERBATIM); | 505 protocol::ChannelConfig::Codec::CODEC_VERBATIM); |
505 TestImagePatternMatch(kDefaultScreenWidthPx, kDefaultScreenHeightPx, | 506 TestImagePatternMatch(kDefaultScreenWidthPx, kDefaultScreenHeightPx, |
506 kDefaultExpectedRect, false); | 507 kDefaultExpectedRect, false); |
507 } | 508 } |
508 | 509 |
509 } // namespace test | 510 } // namespace test |
510 } // namespace remoting | 511 } // namespace remoting |
OLD | NEW |