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/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/synchronization/lock.h" | 12 #include "base/synchronization/lock.h" |
13 #include "base/thread_task_runner_handle.h" | 13 #include "base/thread_task_runner_handle.h" |
14 #include "base/threading/thread.h" | 14 #include "base/threading/thread.h" |
15 #include "remoting/codec/video_decoder.h" | 15 #include "remoting/codec/video_decoder.h" |
16 #include "remoting/codec/video_decoder_verbatim.h" | 16 #include "remoting/codec/video_decoder_verbatim.h" |
17 #include "remoting/codec/video_decoder_vpx.h" | 17 #include "remoting/codec/video_decoder_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 "third_party/webrtc/modules/desktop_capture/desktop_frame.h" | 20 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
20 | 21 |
21 namespace { | 22 namespace { |
22 | |
23 // Used to store a RGB color, and it can be converted from uint32_t. | |
24 struct RGBValue { | |
25 RGBValue(int r, int g, int b) : red(r), green(g), blue(b) {} | |
26 | |
27 int red; | |
28 int green; | |
29 int blue; | |
30 }; | |
31 | |
32 // Convert an uint32_t to a RGBValue. | |
33 RGBValue ConvertUint32ToRGBValue(uint32_t color) { | |
34 RGBValue rgb_value((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF); | |
35 return rgb_value; | |
36 } | |
37 | |
38 // Used to account for frame resizing and lossy encoding error in percentage. | 23 // Used to account for frame resizing and lossy encoding error in percentage. |
39 // The average color usually only varies by 1 on each channel, so 0.01 is large | 24 // The average color usually only varies by 1 on each channel, so 0.01 is large |
40 // enough to allow variations while not being flaky for false negative cases. | 25 // enough to allow variations while not being flaky for false negative cases. |
41 const double kMaxColorError = 0.01; | 26 const double kMaxColorError = 0.01; |
42 } // namespace | 27 } // namespace |
43 | 28 |
44 namespace remoting { | 29 namespace remoting { |
45 namespace test { | 30 namespace test { |
46 | 31 |
47 // Implements video decoding functionality. | 32 // Implements video decoding functionality. |
(...skipping 12 matching lines...) Expand all Loading... |
60 // Initialize a decoder to decode video packets. | 45 // Initialize a decoder to decode video packets. |
61 void SetCodecForDecoding(const protocol::ChannelConfig::Codec codec); | 46 void SetCodecForDecoding(const protocol::ChannelConfig::Codec codec); |
62 | 47 |
63 // Returns a copy of the current frame. | 48 // Returns a copy of the current frame. |
64 scoped_ptr<webrtc::DesktopFrame> GetCurrentFrameForTest() const; | 49 scoped_ptr<webrtc::DesktopFrame> GetCurrentFrameForTest() const; |
65 | 50 |
66 // Set expected image pattern for comparison and the callback will be called | 51 // Set expected image pattern for comparison and the callback will be called |
67 // when the pattern is matched. | 52 // when the pattern is matched. |
68 void ExpectAverageColorInRect( | 53 void ExpectAverageColorInRect( |
69 const webrtc::DesktopRect& expected_rect, | 54 const webrtc::DesktopRect& expected_rect, |
70 uint32_t expected_avg_color, | 55 const RGBValue& expected_avg_color, |
71 const base::Closure& image_pattern_matched_callback); | 56 const base::Closure& image_pattern_matched_callback); |
72 | 57 |
73 private: | 58 private: |
74 // Returns average color of pixels fall within |rect| on the current frame. | 59 // Returns average color of pixels fall within |rect| on the current frame. |
75 RGBValue CalculateAverageColorValue(const webrtc::DesktopRect& rect) const; | 60 RGBValue CalculateAverageColorValue(const webrtc::DesktopRect& rect) const; |
76 | 61 |
77 // Compares |candidate_avg_value| to |expected_avg_color_|. | 62 // Compares |candidate_avg_value| to |expected_avg_color_|. |
78 // Returns true if the root mean square of the errors in the R, G and B | 63 // Returns true if the root mean square of the errors in the R, G and B |
79 // components does not exceed a given limit. | 64 // components does not exceed a given limit. |
80 bool ExpectedAverageColorIsMatched(const RGBValue& candidate_avg_value) const; | 65 bool ExpectedAverageColorIsMatched(const RGBValue& candidate_avg_value) const; |
(...skipping 14 matching lines...) Expand all Loading... |
95 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; | 80 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; |
96 | 81 |
97 // Used to store decoded video frame. | 82 // Used to store decoded video frame. |
98 scoped_ptr<webrtc::DesktopFrame> frame_; | 83 scoped_ptr<webrtc::DesktopFrame> frame_; |
99 | 84 |
100 // Protects access to |frame_|. | 85 // Protects access to |frame_|. |
101 mutable base::Lock lock_; | 86 mutable base::Lock lock_; |
102 | 87 |
103 // Used to store the expected image pattern. | 88 // Used to store the expected image pattern. |
104 webrtc::DesktopRect expected_rect_; | 89 webrtc::DesktopRect expected_rect_; |
105 uint32_t expected_avg_color_; | 90 RGBValue expected_avg_color_; |
106 | 91 |
107 // Used to store the callback when expected pattern is matched. | 92 // Used to store the callback when expected pattern is matched. |
108 base::Closure image_pattern_matched_callback_; | 93 base::Closure image_pattern_matched_callback_; |
109 | 94 |
110 DISALLOW_COPY_AND_ASSIGN(Core); | 95 DISALLOW_COPY_AND_ASSIGN(Core); |
111 }; | 96 }; |
112 | 97 |
113 TestVideoRenderer::Core::Core() | 98 TestVideoRenderer::Core::Core() |
114 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()) { | 99 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()) { |
115 thread_checker_.DetachFromThread(); | 100 thread_checker_.DetachFromThread(); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 << " " << accumulating_avg_value.blue; | 202 << " " << accumulating_avg_value.blue; |
218 | 203 |
219 if (ExpectedAverageColorIsMatched(accumulating_avg_value)) { | 204 if (ExpectedAverageColorIsMatched(accumulating_avg_value)) { |
220 main_task_runner_->PostTask( | 205 main_task_runner_->PostTask( |
221 FROM_HERE, base::ResetAndReturn(&image_pattern_matched_callback_)); | 206 FROM_HERE, base::ResetAndReturn(&image_pattern_matched_callback_)); |
222 } | 207 } |
223 } | 208 } |
224 | 209 |
225 void TestVideoRenderer::Core::ExpectAverageColorInRect( | 210 void TestVideoRenderer::Core::ExpectAverageColorInRect( |
226 const webrtc::DesktopRect& expected_rect, | 211 const webrtc::DesktopRect& expected_rect, |
227 uint32_t expected_avg_color, | 212 const RGBValue& expected_avg_color, |
228 const base::Closure& image_pattern_matched_callback) { | 213 const base::Closure& image_pattern_matched_callback) { |
229 DCHECK(thread_checker_.CalledOnValidThread()); | 214 DCHECK(thread_checker_.CalledOnValidThread()); |
230 | 215 |
231 expected_rect_ = expected_rect; | 216 expected_rect_ = expected_rect; |
232 expected_avg_color_ = expected_avg_color; | 217 expected_avg_color_ = expected_avg_color; |
233 image_pattern_matched_callback_ = image_pattern_matched_callback; | 218 image_pattern_matched_callback_ = image_pattern_matched_callback; |
234 } | 219 } |
235 | 220 |
236 RGBValue TestVideoRenderer::Core::CalculateAverageColorValue( | 221 RGBValue TestVideoRenderer::Core::CalculateAverageColorValue( |
237 const webrtc::DesktopRect& rect) const { | 222 const webrtc::DesktopRect& rect) const { |
(...skipping 17 matching lines...) Expand all Loading... |
255 } | 240 } |
256 } | 241 } |
257 | 242 |
258 int area = rect.width() * rect.height(); | 243 int area = rect.width() * rect.height(); |
259 RGBValue rgb_value(red_sum / area, green_sum / area, blue_sum / area); | 244 RGBValue rgb_value(red_sum / area, green_sum / area, blue_sum / area); |
260 return rgb_value; | 245 return rgb_value; |
261 } | 246 } |
262 | 247 |
263 bool TestVideoRenderer::Core::ExpectedAverageColorIsMatched( | 248 bool TestVideoRenderer::Core::ExpectedAverageColorIsMatched( |
264 const RGBValue& candidate_avg_value) const { | 249 const RGBValue& candidate_avg_value) const { |
265 RGBValue expected_avg_value = ConvertUint32ToRGBValue(expected_avg_color_); | |
266 double error_sum_squares = 0; | 250 double error_sum_squares = 0; |
267 double red_error = expected_avg_value.red - candidate_avg_value.red; | 251 double red_error = expected_avg_color_.red - candidate_avg_value.red; |
268 double green_error = expected_avg_value.green - candidate_avg_value.green; | 252 double green_error = expected_avg_color_.green - candidate_avg_value.green; |
269 double blue_error = expected_avg_value.blue - candidate_avg_value.blue; | 253 double blue_error = expected_avg_color_.blue - candidate_avg_value.blue; |
270 error_sum_squares = red_error * red_error + green_error * green_error + | 254 error_sum_squares = red_error * red_error + green_error * green_error + |
271 blue_error * blue_error; | 255 blue_error * blue_error; |
272 error_sum_squares /= (255.0 * 255.0); | 256 error_sum_squares /= (255.0 * 255.0); |
273 | 257 |
274 return sqrt(error_sum_squares / 3) < kMaxColorError; | 258 return sqrt(error_sum_squares / 3) < kMaxColorError; |
275 } | 259 } |
276 | 260 |
277 TestVideoRenderer::TestVideoRenderer() | 261 TestVideoRenderer::TestVideoRenderer() |
278 : video_decode_thread_( | 262 : video_decode_thread_( |
279 new base::Thread("TestVideoRendererVideoDecodingThread")), | 263 new base::Thread("TestVideoRendererVideoDecodingThread")), |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 | 339 |
356 scoped_ptr<webrtc::DesktopFrame> TestVideoRenderer::GetCurrentFrameForTest() | 340 scoped_ptr<webrtc::DesktopFrame> TestVideoRenderer::GetCurrentFrameForTest() |
357 const { | 341 const { |
358 DCHECK(thread_checker_.CalledOnValidThread()); | 342 DCHECK(thread_checker_.CalledOnValidThread()); |
359 | 343 |
360 return core_->GetCurrentFrameForTest(); | 344 return core_->GetCurrentFrameForTest(); |
361 } | 345 } |
362 | 346 |
363 void TestVideoRenderer::ExpectAverageColorInRect( | 347 void TestVideoRenderer::ExpectAverageColorInRect( |
364 const webrtc::DesktopRect& expected_rect, | 348 const webrtc::DesktopRect& expected_rect, |
365 uint32_t expected_avg_color, | 349 const RGBValue& expected_avg_color, |
366 const base::Closure& image_pattern_matched_callback) { | 350 const base::Closure& image_pattern_matched_callback) { |
367 DCHECK(thread_checker_.CalledOnValidThread()); | 351 DCHECK(thread_checker_.CalledOnValidThread()); |
368 DCHECK(!expected_rect.is_empty()) << "Expected rect cannot be empty"; | 352 DCHECK(!expected_rect.is_empty()) << "Expected rect cannot be empty"; |
369 | 353 |
370 DVLOG(2) << "TestVideoRenderer::SetImagePatternAndMatchedCallback() Called"; | 354 DVLOG(2) << "TestVideoRenderer::SetImagePatternAndMatchedCallback() Called"; |
371 video_decode_task_runner_->PostTask( | 355 video_decode_task_runner_->PostTask( |
372 FROM_HERE, | 356 FROM_HERE, |
373 base::Bind(&Core::ExpectAverageColorInRect, base::Unretained(core_.get()), | 357 base::Bind(&Core::ExpectAverageColorInRect, base::Unretained(core_.get()), |
374 expected_rect, expected_avg_color, | 358 expected_rect, expected_avg_color, |
375 image_pattern_matched_callback)); | 359 image_pattern_matched_callback)); |
376 } | 360 } |
377 | 361 |
378 } // namespace test | 362 } // namespace test |
379 } // namespace remoting | 363 } // namespace remoting |
OLD | NEW |