diff options
author | fbarchard@chromium.org <fbarchard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-11 20:17:21 +0000 |
---|---|---|
committer | fbarchard@chromium.org <fbarchard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-11 20:17:21 +0000 |
commit | 16ffdc51c3d43b06cc6d4e2f9fa44ed038ead859 (patch) | |
tree | 38aa5676951697429e0c0b30685d3118da0b0927 | |
parent | 6844556bce70cce0be205e458cea4422e56c210f (diff) | |
download | chromium_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.cc | 48 | ||||
-rw-r--r-- | remoting/host/differ_block.h | 12 | ||||
-rw-r--r-- | remoting/host/differ_block_unittest.cc | 77 |
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 |