summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfbarchard@chromium.org <fbarchard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-11 20:17:21 +0000
committerfbarchard@chromium.org <fbarchard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-11 20:17:21 +0000
commit16ffdc51c3d43b06cc6d4e2f9fa44ed038ead859 (patch)
tree38aa5676951697429e0c0b30685d3118da0b0927
parent6844556bce70cce0be205e458cea4422e56c210f (diff)
downloadchromium_src-16ffdc51c3d43b06cc6d4e2f9fa44ed038ead859.zip
chromium_src-16ffdc51c3d43b06cc6d4e2f9fa44ed038ead859.tar.gz
chromium_src-16ffdc51c3d43b06cc6d4e2f9fa44ed038ead859.tar.bz2
BlockDifference function that returns 0 or 1 depending if block is same or different.
BUG=none TEST=unittest updated and includes benchmarking. Review URL: http://codereview.chromium.org/2712006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49583 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--remoting/host/differ_block.cc48
-rw-r--r--remoting/host/differ_block.h12
-rw-r--r--remoting/host/differ_block_unittest.cc77
3 files changed, 99 insertions, 38 deletions
diff --git a/remoting/host/differ_block.cc b/remoting/host/differ_block.cc
index 4dfe58c..f7b785d 100644
--- a/remoting/host/differ_block.cc
+++ b/remoting/host/differ_block.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "differ_block.h"
+#include "remoting/host/differ_block.h"
#include <stdlib.h>
@@ -20,11 +20,6 @@
namespace remoting {
-// TODO(fbarchard): Use common header for block size.
-const int kBlockWidth = 32;
-const int kBlockHeight = 32;
-const int kBytesPerPixel = 3;
-
#if USE_SSE2
int BlockDifference(const uint8* image1, const uint8* image2, int stride) {
__m128i acc = _mm_setzero_si128();
@@ -58,25 +53,48 @@ int BlockDifference(const uint8* image1, const uint8* image2, int stride) {
v1 = _mm_loadu_si128(i2 + 5);
sad = _mm_sad_epu8(v0, v1);
acc = _mm_adds_epu16(acc, sad);
+ v0 = _mm_loadu_si128(i1 + 6);
+ v1 = _mm_loadu_si128(i2 + 6);
+ sad = _mm_sad_epu8(v0, v1);
+ acc = _mm_adds_epu16(acc, sad);
+ v0 = _mm_loadu_si128(i1 + 7);
+ v1 = _mm_loadu_si128(i2 + 7);
+ sad = _mm_sad_epu8(v0, v1);
+ acc = _mm_adds_epu16(acc, sad);
+ sad = _mm_shuffle_epi32(acc, 0xEE); // [acc3, acc2, acc3, acc2]
+ sad = _mm_adds_epu16(sad, acc);
+ int diff = _mm_cvtsi128_si32(sad);
+ if (diff) {
+ return 1;
+ }
image1 += stride;
image2 += stride;
}
- sad = _mm_shuffle_epi32(acc, 0xEE); // [acc3, acc2, acc3, acc2]
- sad = _mm_adds_epu16(sad, acc);
- int diff = _mm_cvtsi128_si32(sad);
- return diff;
+ return 0;
}
#else
int BlockDifference(const uint8* image1, const uint8* image2, int stride) {
- int diff = 0;
- for (int y = 0; y < kBlockHeight; ++y) {
- for (int x = 0; x < kBlockWidth * kBytesPerPixel; ++x) {
- diff += abs(image1[x] - image2[x]);
+ // Number of uint64s in each row of the block.
+ // This must be an integral number.
+ int int64s_per_row = (kBlockWidth * kBytesPerPixel) / sizeof(uint64);
+
+ for (int y = 0; y < kBlockHeight; y++) {
+ const uint64* prev = reinterpret_cast<const uint64*>(image1);
+ const uint64* curr = reinterpret_cast<const uint64*>(image2);
+
+ // Check each row in uint64-sized chunks.
+ // Note that this check may straddle multiple pixels. This is OK because
+ // we're interested in identifying whether or not there was change - we
+ // don't care what the actual change is.
+ for (int x = 0; x < int64s_per_row; x++) {
+ if (*prev++ != *curr++) {
+ return 1;
+ }
}
image1 += stride;
image2 += stride;
}
- return diff;
+ return 0;
}
#endif
diff --git a/remoting/host/differ_block.h b/remoting/host/differ_block.h
index 7b319b9..8ca538f 100644
--- a/remoting/host/differ_block.h
+++ b/remoting/host/differ_block.h
@@ -9,12 +9,14 @@
namespace remoting {
-// Low level functions to return the difference between 2 blocks of pixels.
-// The amount of difference is returned as an int.
+// Block size and format (BGRA 32 bit) are fixed.
+static const int kBlockWidth = 32;
+static const int kBlockHeight = 32;
+static const int kBytesPerPixel = 4;
+
+// Low level functions to compare 2 blocks of pixels.
// zero means the blocks are identical.
-// larger values indicate larger changes.
-// Pixel format of the captured screen may be platform specific, but constant.
-// Size of block is constant.
+// one means the blocks are different.
int BlockDifference(const uint8* image1, const uint8* image2, int stride);
diff --git a/remoting/host/differ_block_unittest.cc b/remoting/host/differ_block_unittest.cc
index 02bd0b3..3bf6cb4 100644
--- a/remoting/host/differ_block_unittest.cc
+++ b/remoting/host/differ_block_unittest.cc
@@ -8,9 +8,9 @@
namespace remoting {
-static const int kWidth = 32;
-static const int kHeight = 32;
-static const int kBytesPerPixel = 3;
+// Run 900 times to mimic 1280x720.
+// TODO(fbarchard): Remove benchmark once performance is non-issue.
+static const int kTimesToRun = 900;
static void GenerateData(uint8* data, int size) {
for (int i = 0; i < size; ++i) {
@@ -24,23 +24,64 @@ class EncodeDoneHandler
MOCK_METHOD0(EncodeDone, void());
};
-TEST(BlockDifferenceTest, BlockDifference) {
- // Prepare 2 blocks to compare.
- uint8 block1[kHeight * kWidth * kBytesPerPixel];
- uint8 block2[kHeight * kWidth * kBytesPerPixel];
- GenerateData(block1, sizeof(block1));
- memcpy(block2, block1, sizeof(block2));
+// Memory buffer large enough for 2 blocks aligned to 16 bytes.
+static const int kSizeOfBlock = kBlockHeight * kBlockWidth * kBytesPerPixel;
+uint8 block_buffer[kSizeOfBlock * 2 + 16];
+
+void PrepareBuffers(uint8* &block1, uint8* &block2) {
+ block1 = reinterpret_cast<uint8*>
+ ((reinterpret_cast<uintptr_t>(&block_buffer[0]) + 15) & ~15);
+ GenerateData(block1, kSizeOfBlock);
+ block2 = block1 + kSizeOfBlock;
+ memcpy(block2, block1, kSizeOfBlock);
+}
+
+TEST(BlockDifferenceTestSame, BlockDifference) {
+ uint8* block1;
+ uint8* block2;
+ PrepareBuffers(block1, block2);
// These blocks should match.
- int same = BlockDifference(block1, block2, kWidth * kBytesPerPixel);
- EXPECT_EQ(0, same);
-
- // Change block2 a little.
- block2[7] += 3;
- block2[sizeof(block2)-1] -= 5;
- // These blocks should not match. The difference should be 8.
- int not_same = BlockDifference(block1, block2, kWidth * kBytesPerPixel);
- EXPECT_EQ(8, not_same);
+ for (int i = 0; i < kTimesToRun; ++i) {
+ int result = BlockDifference(block1, block2, kBlockWidth * kBytesPerPixel);
+ EXPECT_EQ(0, result);
+ }
+}
+
+TEST(BlockDifferenceTestLast, BlockDifference) {
+ uint8* block1;
+ uint8* block2;
+ PrepareBuffers(block1, block2);
+ block2[kSizeOfBlock-2] += 1;
+
+ for (int i = 0; i < kTimesToRun; ++i) {
+ int result = BlockDifference(block1, block2, kBlockWidth * kBytesPerPixel);
+ EXPECT_EQ(1, result);
+ }
+}
+
+TEST(BlockDifferenceTestMid, BlockDifference) {
+ uint8* block1;
+ uint8* block2;
+ PrepareBuffers(block1, block2);
+ block2[kSizeOfBlock/2+1] += 1;
+
+ for (int i = 0; i < kTimesToRun; ++i) {
+ int result = BlockDifference(block1, block2, kBlockWidth * kBytesPerPixel);
+ EXPECT_EQ(1, result);
+ }
+}
+
+TEST(BlockDifferenceTestFirst, BlockDifference) {
+ uint8* block1;
+ uint8* block2;
+ PrepareBuffers(block1, block2);
+ block2[0] += 1;
+
+ for (int i = 0; i < kTimesToRun; ++i) {
+ int result = BlockDifference(block1, block2, kBlockWidth * kBytesPerPixel);
+ EXPECT_EQ(1, result);
+ }
}
} // namespace remoting