Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Unified Diff: remoting/test/test_video_renderer.cc

Issue 1219923011: Added image pattern comparison logic for test interface and fixture. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: "Added image pattern comparison logic" Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/test/app_remoting_latency_test_fixture.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/test/test_video_renderer.cc
diff --git a/remoting/test/test_video_renderer.cc b/remoting/test/test_video_renderer.cc
index 75dd2c9511ba614425c8230dcebcd5e82bbcb23f..4e20f625eafcba07ee0e58ce2a542c2ac3311005 100644
--- a/remoting/test/test_video_renderer.cc
+++ b/remoting/test/test_video_renderer.cc
@@ -4,6 +4,9 @@
#include "remoting/test/test_video_renderer.h"
+#include <algorithm>
+#include <cmath>
liaoyuke 2015/07/08 18:58:15 Usage: algorithm: std::min, std::max, cmath: sqrt
+
#include "base/bind.h"
#include "base/logging.h"
#include "base/synchronization/lock.h"
@@ -15,6 +18,10 @@
#include "remoting/proto/video.pb.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+namespace {
+const int kBytesPerPixel = 4;
+} // namespace
+
namespace remoting {
namespace test {
@@ -45,6 +52,35 @@ class TestVideoRenderer::Core {
const base::Closure& image_pattern_matched_callback);
private:
+ // Converts a set of RGB color to the RgbaColor format by adding the alpha
+ // values of 0x00.
+ RgbaColor ColorEncode(const int red, const int green, const int blue) const;
joedow 2015/07/09 03:03:43 Why are the int values const here? ints are passe
liaoyuke 2015/07/09 18:18:32 I think you are right, they shouldn't be const
+
+ // Converts a RgbaColor instance to an array of RGBA colors.
+ scoped_ptr<int> ColorDecode(const RgbaColor& rgba_color) const;
+
+ // Returns true if |rect2| falls within |rect1|, allowing for certain amount
+ // of error specified by a fuzzy threshold.
+ bool ContainsRect(const webrtc::DesktopRect& rect1,
+ const webrtc::DesktopRect& rect2) const;
+
+ // Expand the |accumulating_rect_| to a minimum rectangle that contains both
+ // |rect| and itself.
+ void MergeRectToAccumulatingRect(const webrtc::DesktopRect& rect);
+
+ // Update |accumulating_color_| to reflect the average color value of pixels
+ // fall within |accumulating_rect_|.
+ void UpdateAccumulatingColor();
+
+ // Compares |accumulating_color_| to |expected_color_|.
+ // Returns true if the root mean square of the errors in the R, G and B
+ // components does not exceed a fuzzy threshold.
+ bool ExpectedColorIsMatched() const;
+
+ // Returns true if |expected_rect_| and |accumulating_rect_| contains each
+ // other and expected color is matched.
+ bool ExpectedImagePatternIsMatched() const;
+
// Used to ensure Core methods are called on the same thread.
base::ThreadChecker thread_checker_;
@@ -77,6 +113,9 @@ class TestVideoRenderer::Core {
// Used to store the callback when expected pattern is matched.
base::Closure image_pattern_matched_callback_;
+ // Used to account for video frame resizing and lossy encoding.
+ const double fuzzy_threshold_ = 0.05;
joedow 2015/07/09 03:03:43 Does this need to be a class member or can it just
liaoyuke 2015/07/09 18:18:32 Done.
+
DISALLOW_COPY_AND_ASSIGN(Core);
};
@@ -91,6 +130,8 @@ TestVideoRenderer::Core::~Core() {
void TestVideoRenderer::Core::Initialize() {
DCHECK(thread_checker_.CalledOnValidThread());
+
+ accumulating_rect_ = webrtc::DesktopRect::MakeLTRB(0, 0, 0, 0);
}
void TestVideoRenderer::Core::SetCodecForDecoding(
@@ -172,9 +213,26 @@ void TestVideoRenderer::Core::ProcessVideoPacket(
main_task_runner_->PostTask(FROM_HERE, done);
- // TODO(liaoyuke): Update |accumulating_rect_| and |accumulating_color_|, then
- // compare to the expected image pattern to check whether the pattern is
- // matched or not and update |image_pattern_matched| accordingly.
+ // Check to see if a image pattern matched reply is passed in.
+ if (!image_pattern_matched_callback_.is_null()) {
joedow 2015/07/09 03:03:43 This be simpler if you return here if the callback
liaoyuke 2015/07/09 18:18:32 Done.
+ for (webrtc::DesktopRegion::Iterator dirty_region(updated_region_);
+ !dirty_region.IsAtEnd(); dirty_region.Advance()) {
+ webrtc::DesktopRect dirty_rect = dirty_region.rect();
+
+ // Dirty rects not falling within |expected_rect_| doesn't affect the
+ // result.
+ if (ContainsRect(expected_rect_, dirty_rect)) {
+ MergeRectToAccumulatingRect(dirty_rect);
+ }
+ }
+
+ UpdateAccumulatingColor();
+ if (ExpectedImagePatternIsMatched()) {
+ image_pattern_matched_callback_.Run();
+ image_pattern_matched_callback_.Reset();
joedow 2015/07/09 03:03:43 base::ResetAndReturn() can replace lines 231 and 2
liaoyuke 2015/07/09 18:18:32 Done.
+ accumulating_rect_ = webrtc::DesktopRect::MakeLTRB(0, 0, 0, 0);
+ }
+ }
}
void TestVideoRenderer::Core::SetImagePatternAndMatchedCallback(
@@ -188,6 +246,96 @@ void TestVideoRenderer::Core::SetImagePatternAndMatchedCallback(
image_pattern_matched_callback_ = image_pattern_matched_callback;
}
+RgbaColor TestVideoRenderer::Core::ColorEncode(const int red,
+ const int green,
+ const int blue) const {
+ RgbaColor rgba_color = red;
+ rgba_color = (rgba_color << 8) + green;
+ rgba_color = (rgba_color << 8) + blue;
+ rgba_color = (rgba_color << 8) + 0;
+
+ return rgba_color;
+}
+
+scoped_ptr<int> TestVideoRenderer::Core::ColorDecode(
+ const RgbaColor& rgba_color) const {
joedow 2015/07/09 03:03:43 If you are going to return an array, you want scop
+ int* rgba_colors = new int[3];
+ uint32 mask = (1 << 9) - 1;
+ rgba_colors[2] = ((rgba_color >> 8) & mask);
+ rgba_colors[1] = ((rgba_color >> 16) & mask);
+ rgba_colors[0] = ((rgba_color >> 24) & mask);
+
+ return make_scoped_ptr(rgba_colors);
+}
+
+bool TestVideoRenderer::Core::ContainsRect(
joedow 2015/07/09 03:03:43 rect1 and rect2 aren't quite descriptive enough, w
liaoyuke 2015/07/09 18:18:32 Done.
+ const webrtc::DesktopRect& rect1,
+ const webrtc::DesktopRect& rect2) const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!image_pattern_matched_callback_.is_null());
joedow 2015/07/09 03:03:43 Does it matter if the callback is not null here?
liaoyuke 2015/07/09 18:18:32 At first, I thought this function will only be cal
+
+ return rect2.left() >= (1 - fuzzy_threshold_) * rect1.left() &&
+ rect2.top() >= (1 - fuzzy_threshold_) * rect1.top() &&
+ rect2.right() <= (1 + fuzzy_threshold_) * rect1.right() &&
+ rect2.bottom() <= (1 + fuzzy_threshold_) * rect1.bottom();
+}
+
+void TestVideoRenderer::Core::MergeRectToAccumulatingRect(
+ const webrtc::DesktopRect& rect) {
+ if (accumulating_rect_.width() == 0 && accumulating_rect_.height() == 0) {
joedow 2015/07/09 03:03:43 if (!accumulating_rect_.width() && !accumulating_r
liaoyuke 2015/07/09 18:18:32 I think it's not possible, that's why I use it as
+ accumulating_rect_ = rect;
+ } else {
+ accumulating_rect_ = webrtc::DesktopRect::MakeLTRB(
+ std::min(accumulating_rect_.left(), rect.left()),
+ std::min(accumulating_rect_.top(), rect.top()),
+ std::max(accumulating_rect_.right(), rect.right()),
+ std::max(accumulating_rect_.bottom(), rect.bottom()));
+ }
+}
+
+void TestVideoRenderer::Core::UpdateAccumulatingColor() {
+ int red_sum = 0;
+ int green_sum = 0;
+ int blue_sum = 0;
+ for (int y = accumulating_rect_.top(); y < accumulating_rect_.bottom(); ++y) {
+ for (int x = accumulating_rect_.left(); x < accumulating_rect_.right();
+ ++x) {
+ int offset =
+ y * kBytesPerPixel * screen_size_.width() + x * kBytesPerPixel;
joedow 2015/07/09 03:03:43 some parens would help with the readability here
liaoyuke 2015/07/09 18:18:32 Done.
+ red_sum += buffer_->data()[offset + 2];
+ green_sum += buffer_->data()[offset + 1];
liaoyuke 2015/07/09 18:18:32 Here, I should mention that the decoded frame is i
+ blue_sum += buffer_->data()[offset + 0];
+ }
+ }
+
+ int area = screen_size_.width() * screen_size_.height();
+ accumulating_color_ =
+ ColorEncode(red_sum / area, green_sum / area, blue_sum / area);
+}
+
+bool TestVideoRenderer::Core::ExpectedColorIsMatched() const {
+ scoped_ptr<int> decoded_expected_color = ColorDecode(expected_color_);
+ scoped_ptr<int> decoded_accumulating_color = ColorDecode(accumulating_color_);
+ double error_sum_squares = 0;
+ for (int i = 0; i < 3; i++) {
+ double expected_value =
+ static_cast<double>(decoded_expected_color.get()[i]);
+ double accumulating_value =
+ static_cast<double>(decoded_accumulating_color.get()[i]);
+ double error = expected_value - accumulating_value;
+ error /= 255.0;
+ error_sum_squares += error * error;
+ }
+
+ return sqrt(error_sum_squares / 3) < fuzzy_threshold_;
+}
+
+bool TestVideoRenderer::Core::ExpectedImagePatternIsMatched() const {
+ return ContainsRect(accumulating_rect_, expected_rect_) &&
+ ContainsRect(expected_rect_, accumulating_rect_) &&
+ ExpectedColorIsMatched();
+}
+
TestVideoRenderer::TestVideoRenderer()
: video_decode_thread_(
new base::Thread("TestVideoRendererVideoDecodingThread")),
« no previous file with comments | « remoting/test/app_remoting_latency_test_fixture.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698