OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include <memory> | 11 #include <memory> |
12 | 12 |
13 #include "testing/gmock/include/gmock/gmock.h" | 13 #include "testing/gmock/include/gmock/gmock.h" |
14 #include "webrtc/base/constructormagic.h" | 14 #include "webrtc/base/constructormagic.h" |
15 #include "webrtc/modules/desktop_capture/desktop_region.h" | |
16 #include "webrtc/modules/desktop_capture/desktop_geometry.h" | |
15 #include "webrtc/modules/desktop_capture/differ.h" | 17 #include "webrtc/modules/desktop_capture/differ.h" |
16 #include "webrtc/modules/desktop_capture/differ_block.h" | 18 #include "webrtc/modules/desktop_capture/differ_block.h" |
17 | 19 |
18 namespace webrtc { | 20 namespace webrtc { |
19 | 21 |
20 // 96x96 screen gives a 4x4 grid of blocks. | 22 // 96x96 screen gives a 4x4 grid of blocks. |
21 const int kScreenWidth= 96; | 23 const int kScreenWidth= 96; |
22 const int kScreenHeight = 96; | 24 const int kScreenHeight = 96; |
23 | 25 |
24 // To test partial blocks, we need a width and height that are not multiples | 26 // To test partial blocks, we need a width and height that are not multiples |
(...skipping 22 matching lines...) Expand all Loading... | |
47 curr_.reset(new uint8_t[buffer_size_]); | 49 curr_.reset(new uint8_t[buffer_size_]); |
48 memset(curr_.get(), 0, buffer_size_); | 50 memset(curr_.get(), 0, buffer_size_); |
49 } | 51 } |
50 | 52 |
51 void ClearBuffer(uint8_t* buffer) { | 53 void ClearBuffer(uint8_t* buffer) { |
52 memset(buffer, 0, buffer_size_); | 54 memset(buffer, 0, buffer_size_); |
53 } | 55 } |
54 | 56 |
55 // Here in DifferTest so that tests can access private methods of Differ. | 57 // Here in DifferTest so that tests can access private methods of Differ. |
56 void MarkDirtyBlocks(const uint8_t* prev_buffer, const uint8_t* curr_buffer) { | 58 void MarkDirtyBlocks(const uint8_t* prev_buffer, const uint8_t* curr_buffer) { |
57 differ_->MarkDirtyBlocks(prev_buffer, curr_buffer); | 59 differ_->MarkDirtyBlocks(prev_buffer, curr_buffer, |
60 DesktopRect::MakeWH(width_, height_)); | |
58 } | 61 } |
59 | 62 |
60 void MergeBlocks(DesktopRegion* dirty) { | 63 void MergeBlocks(DesktopRegion* dirty) { |
61 differ_->MergeBlocks(dirty); | 64 differ_->MergeBlocks(dirty); |
62 } | 65 } |
63 | 66 |
64 // Convenience method to count rectangles in a region. | 67 // Convenience method to count rectangles in a region. |
65 int RegionRectCount(const DesktopRegion& region) { | 68 int RegionRectCount(const DesktopRegion& region) { |
66 int count = 0; | 69 int count = 0; |
67 for (DesktopRegion::Iterator iter(region); | 70 for (DesktopRegion::Iterator iter(region); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
151 } | 154 } |
152 | 155 |
153 // Verify that |region| contains a rectangle defined by |x|, |y|, |width| and | 156 // Verify that |region| contains a rectangle defined by |x|, |y|, |width| and |
154 // |height|. | 157 // |height|. |
155 // |x|, |y|, |width| and |height| are specified in block (not pixel) units. | 158 // |x|, |y|, |width| and |height| are specified in block (not pixel) units. |
156 bool CheckDirtyRegionContainsRect(const DesktopRegion& region, | 159 bool CheckDirtyRegionContainsRect(const DesktopRegion& region, |
157 int x, int y, | 160 int x, int y, |
158 int width, int height) { | 161 int width, int height) { |
159 DesktopRect r = | 162 DesktopRect r = |
160 DesktopRect::MakeXYWH(x * kBlockSize, y * kBlockSize, | 163 DesktopRect::MakeXYWH(x * kBlockSize, y * kBlockSize, |
161 width * kBlockSize, height * kBlockSize); | 164 width * kBlockSize, height * kBlockSize); |
162 for (DesktopRegion::Iterator i(region); !i.IsAtEnd(); i.Advance()) { | 165 for (DesktopRegion::Iterator i(region); !i.IsAtEnd(); i.Advance()) { |
163 if (i.rect().equals(r)) | 166 if (i.rect().equals(r)) |
164 return true; | 167 return true; |
165 } | 168 } |
166 return false; | 169 return false; |
167 } | 170 } |
168 | 171 |
172 bool CheckDirtyRegionContainsPartialRect(const DesktopRegion& region, | |
Jamie
2016/08/03 23:52:26
"Partial" is used in the differ to refer to sub-kB
Hzj_jie
2016/08/04 02:28:07
The "partial" here means one of the dirty regions
| |
173 int x, int y, | |
174 int width, int height) { | |
175 DesktopRect r = | |
176 DesktopRect::MakeXYWH(x * kBlockSize, y * kBlockSize, | |
177 width * kBlockSize, height * kBlockSize); | |
178 for (DesktopRegion::Iterator i(region); !i.IsAtEnd(); i.Advance()) { | |
179 if (r.ContainsRect(i.rect())) | |
180 return true; | |
181 } | |
182 return false; | |
183 } | |
184 | |
169 // Mark the range of blocks specified and then verify that they are | 185 // Mark the range of blocks specified and then verify that they are |
170 // merged correctly. | 186 // merged correctly. |
171 // Only one rectangular region of blocks can be checked with this routine. | 187 // Only one rectangular region of blocks can be checked with this routine. |
172 bool MarkBlocksAndCheckMerge(int x_origin, int y_origin, | 188 bool MarkBlocksAndCheckMerge(int x_origin, int y_origin, |
173 int width, int height) { | 189 int width, int height) { |
174 ClearDiffInfo(); | 190 ClearDiffInfo(); |
175 MarkBlocks(x_origin, y_origin, width, height); | 191 MarkBlocks(x_origin, y_origin, width, height); |
176 | 192 |
177 DesktopRegion dirty; | 193 DesktopRegion dirty; |
178 MergeBlocks(&dirty); | 194 MergeBlocks(&dirty); |
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
644 MarkBlocks(1, 2, 1, 1); | 660 MarkBlocks(1, 2, 1, 1); |
645 | 661 |
646 dirty.Clear(); | 662 dirty.Clear(); |
647 MergeBlocks(&dirty); | 663 MergeBlocks(&dirty); |
648 | 664 |
649 ASSERT_EQ(2, RegionRectCount(dirty)); | 665 ASSERT_EQ(2, RegionRectCount(dirty)); |
650 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 2, 2)); | 666 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 2, 2)); |
651 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 2, 1, 1)); | 667 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 2, 1, 1)); |
652 } | 668 } |
653 | 669 |
670 TEST_F(DifferTest, ScreenSizeWithEmptyHints) { | |
671 InitDiffer(kScreenWidth, kScreenHeight); | |
672 DesktopRegion dirty; | |
673 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), DesktopRegion(), | |
674 &dirty); | |
675 ASSERT_EQ(0, RegionRectCount(dirty)); | |
676 } | |
677 | |
678 TEST_F(DifferTest, OneDirtyBlockWithHints) { | |
679 // Initialize a 3 x 3 screen. | |
680 // +---+---+---+ | |
681 // | | | | | |
682 // +---+---+---+ | |
683 // | | X | | | |
684 // +---+---+---+ | |
685 // | | | | | |
686 // +---+---+---+ | |
687 InitDiffer(kScreenWidth, kScreenHeight); | |
688 WritePixel(curr_.get(), kBlockSize, kBlockSize, 0x11223344); | |
689 DesktopRegion dirty; | |
690 dirty.AddRect( | |
691 DesktopRect::MakeXYWH(kBlockSize, kBlockSize, kBlockSize, kBlockSize)); | |
692 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
693 ASSERT_EQ(1, RegionRectCount(dirty)); | |
694 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 1, 1, 1)); | |
695 | |
696 dirty.Clear(); | |
697 dirty.AddRect(DesktopRect::MakeXYWH(kBlockSize >> 1, kBlockSize >> 1, | |
698 kBlockSize, kBlockSize)); | |
699 dirty.AddRect(DesktopRect::MakeXYWH(kBlockSize * 1.5, kBlockSize * 1.5, | |
700 kBlockSize >> 1, kBlockSize >> 1)); | |
701 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
702 ASSERT_EQ(1, RegionRectCount(dirty)); | |
703 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 1, 1, 1)); | |
704 } | |
705 | |
706 TEST_F(DifferTest, MultipleDirtyBlocksWithHints) { | |
707 // Initialize a 3 x 3 screen. | |
708 // +---+---+---+ | |
709 // | | | | | |
710 // +---+---+---+ | |
711 // | | X | | | |
712 // +---+---+---+ | |
713 // | | | X | | |
714 // +---+---+---+ | |
715 InitDiffer(kScreenWidth, kScreenHeight); | |
716 WritePixel(curr_.get(), kBlockSize, kBlockSize, 0x11223344); | |
717 WritePixel(curr_.get(), kBlockSize * 2, kBlockSize * 2, 0x11223344); | |
718 DesktopRegion dirty; | |
719 dirty.AddRect(DesktopRect::MakeXYWH(kBlockSize, kBlockSize, | |
720 kBlockSize * 2, kBlockSize * 2)); | |
721 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
722 ASSERT_EQ(2, RegionRectCount(dirty)); | |
723 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 1, 1, 1)); | |
724 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 2, 1, 1)); | |
725 | |
726 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
727 ASSERT_EQ(2, RegionRectCount(dirty)); | |
728 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 1, 1, 1)); | |
729 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 2, 1, 1)); | |
730 | |
731 dirty.Clear(); | |
732 dirty.AddRect(DesktopRect::MakeXYWH(0, 0, kBlockSize * 2, kBlockSize * 2)); | |
733 dirty.AddRect( | |
734 DesktopRect::MakeXYWH(0, kBlockSize * 2, kBlockSize * 3, kBlockSize)); | |
735 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
736 ASSERT_EQ(2, RegionRectCount(dirty)); | |
737 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 1, 1, 1)); | |
738 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 2, 1, 1)); | |
739 | |
740 dirty.Clear(); | |
741 dirty.AddRect(DesktopRect::MakeXYWH(0, 0, kBlockSize, kBlockSize)); | |
742 dirty.AddRect( | |
743 DesktopRect::MakeXYWH(0, kBlockSize, kBlockSize * 2, kBlockSize)); | |
744 dirty.AddRect( | |
745 DesktopRect::MakeXYWH(0, kBlockSize * 2, kBlockSize * 3, kBlockSize)); | |
746 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
747 ASSERT_EQ(2, RegionRectCount(dirty)); | |
748 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 1, 1, 1)); | |
749 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 2, 1, 1)); | |
750 | |
751 dirty.Clear(); | |
752 dirty.AddRect(DesktopRect::MakeXYWH(kBlockSize >> 1, kBlockSize >> 1, | |
753 kBlockSize, kBlockSize)); | |
754 dirty.AddRect(DesktopRect::MakeXYWH(kBlockSize * 1.5, kBlockSize, | |
755 kBlockSize * 1.5, kBlockSize * 2)); | |
756 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
757 ASSERT_EQ(2, RegionRectCount(dirty)); | |
758 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 1, 1, 1)); | |
759 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 2, 1, 1)); | |
760 } | |
761 | |
762 TEST_F(DifferTest, MultipleDirtyBlocksWithHints2) { | |
763 // Initialize a 4 x 4 screen. | |
764 // +---+---+---+---+ | |
765 // | X | | | | | |
766 // +---+---+---+---+ | |
767 // | | | | | | |
768 // +---+---+---+---+ | |
769 // | | | | | | |
770 // +---+---+---+---+ | |
771 // | | | | X | | |
772 // +---+---+---+---+ | |
773 InitDiffer(4 * kBlockSize, 4 * kBlockSize); | |
774 WritePixel(curr_.get(), 0, 0, 0x11223344); | |
775 WritePixel(curr_.get(), kBlockSize * 3, kBlockSize * 3, 0x11223344); | |
776 DesktopRegion dirty; | |
777 dirty.AddRect( | |
778 DesktopRect::MakeXYWH(0, 0, kBlockSize * 4, kBlockSize * 4)); | |
779 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
780 ASSERT_EQ(2, RegionRectCount(dirty)); | |
781 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 1, 1)); | |
782 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 3, 3, 1, 1)); | |
783 | |
784 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
785 ASSERT_EQ(2, RegionRectCount(dirty)); | |
786 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 1, 1)); | |
787 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 3, 3, 1, 1)); | |
788 | |
789 dirty.Clear(); | |
790 dirty.AddRect(DesktopRect::MakeXYWH(0, 0, kBlockSize, kBlockSize)); | |
791 dirty.AddRect( | |
792 DesktopRect::MakeXYWH(kBlockSize, kBlockSize, kBlockSize, kBlockSize)); | |
793 dirty.AddRect(DesktopRect::MakeXYWH(kBlockSize * 3, kBlockSize * 3, | |
794 kBlockSize, kBlockSize)); | |
795 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
796 ASSERT_EQ(2, RegionRectCount(dirty)); | |
797 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 1, 1)); | |
798 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 3, 3, 1, 1)); | |
799 | |
800 dirty.Clear(); | |
801 dirty.AddRect(DesktopRect::MakeXYWH(0, 0, kBlockSize * 2, kBlockSize * 2)); | |
802 dirty.AddRect(DesktopRect::MakeXYWH(kBlockSize * 2, kBlockSize * 2, | |
803 kBlockSize * 2, kBlockSize * 2)); | |
804 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
805 ASSERT_EQ(2, RegionRectCount(dirty)); | |
806 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 1, 1)); | |
807 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 3, 3, 1, 1)); | |
808 | |
809 dirty.Clear(); | |
810 // Note, even the hints does not cover entire block, we should still be able | |
811 // to detect it. | |
812 dirty.AddRect(DesktopRect::MakeXYWH(0, 0, kBlockSize >> 1, kBlockSize >> 1)); | |
813 dirty.AddRect(DesktopRect::MakeXYWH(kBlockSize * 2.5, kBlockSize * 2.5, | |
814 kBlockSize, kBlockSize)); | |
815 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
816 ASSERT_EQ(2, RegionRectCount(dirty)); | |
817 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 1, 1)); | |
818 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 3, 3, 1, 1)); | |
819 } | |
820 | |
821 TEST_F(DifferTest, PartialScreenSizeWithHints) { | |
822 // Initialize a 4 x 4 screen, the right and bottom blocks do not have a | |
823 // kBlockSize size. | |
824 // +---+---+---+---+ | |
825 // | X | | | | | |
826 // +---+---+---+---+ | |
827 // | | | | | | |
828 // +---+---+---+---+ | |
829 // | | | | | | |
830 // +---+---+---+---+ | |
831 // | | | | X | | |
832 // +---+---+---+---+ | |
833 InitDiffer(4 * kBlockSize - (kBlockSize >> 1), | |
834 4 * kBlockSize - (kBlockSize >> 1)); | |
835 WritePixel(curr_.get(), 0, 0, 0x11223344); | |
836 WritePixel(curr_.get(), kBlockSize * 3, kBlockSize * 3, 0x11223344); | |
837 DesktopRegion dirty; | |
838 dirty.AddRect(DesktopRect::MakeXYWH(0, 0, | |
839 4 * kBlockSize - (kBlockSize >> 1), | |
840 4 * kBlockSize - (kBlockSize >> 1))); | |
841 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
842 ASSERT_EQ(2, RegionRectCount(dirty)); | |
843 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 1, 1)); | |
844 ASSERT_TRUE(CheckDirtyRegionContainsPartialRect(dirty, 3, 3, 1, 1)); | |
845 | |
846 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
847 ASSERT_EQ(2, RegionRectCount(dirty)); | |
848 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 1, 1)); | |
849 ASSERT_TRUE(CheckDirtyRegionContainsPartialRect(dirty, 3, 3, 1, 1)); | |
850 | |
851 dirty.Clear(); | |
852 dirty.AddRect(DesktopRect::MakeXYWH(0, 0, kBlockSize, kBlockSize)); | |
853 dirty.AddRect( | |
854 DesktopRect::MakeXYWH(kBlockSize, kBlockSize, kBlockSize, kBlockSize)); | |
855 dirty.AddRect(DesktopRect::MakeXYWH(kBlockSize * 3, kBlockSize * 3, | |
856 kBlockSize, kBlockSize)); | |
857 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
858 ASSERT_EQ(2, RegionRectCount(dirty)); | |
859 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 1, 1)); | |
860 ASSERT_TRUE(CheckDirtyRegionContainsPartialRect(dirty, 3, 3, 1, 1)); | |
861 | |
862 dirty.Clear(); | |
863 dirty.AddRect(DesktopRect::MakeXYWH(0, 0, kBlockSize * 2, kBlockSize * 2)); | |
864 dirty.AddRect(DesktopRect::MakeXYWH(kBlockSize * 2, kBlockSize * 2, | |
865 kBlockSize * 1.5, kBlockSize * 1.5)); | |
866 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
867 ASSERT_EQ(2, RegionRectCount(dirty)); | |
868 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 1, 1)); | |
869 ASSERT_TRUE(CheckDirtyRegionContainsPartialRect(dirty, 3, 3, 1, 1)); | |
870 | |
871 dirty.Clear(); | |
872 // Note, even the hints does not cover entire block, we should still be able | |
873 // to detect it. | |
874 dirty.AddRect(DesktopRect::MakeXYWH(0, 0, kBlockSize >> 1, kBlockSize >> 1)); | |
875 dirty.AddRect(DesktopRect::MakeXYWH(kBlockSize * 2.5, kBlockSize * 2.5, | |
876 kBlockSize, kBlockSize)); | |
877 differ_->CalcDirtyRegionWithHints(prev_.get(), curr_.get(), dirty, &dirty); | |
878 ASSERT_EQ(2, RegionRectCount(dirty)); | |
879 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 1, 1)); | |
880 ASSERT_TRUE(CheckDirtyRegionContainsPartialRect(dirty, 3, 3, 1, 1)); | |
881 } | |
882 | |
654 } // namespace webrtc | 883 } // namespace webrtc |
OLD | NEW |