| 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 |