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

Side by Side Diff: webrtc/modules/desktop_capture/differ.cc

Issue 2202443002: [WebRTC] Add ScreenCapturerDifferWrapper to share Differ across ScreenCapturers (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 4 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 unified diff | Download patch
OLDNEW
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 "webrtc/modules/desktop_capture/differ.h" 11 #include "webrtc/modules/desktop_capture/differ.h"
12 12
13 #include "string.h" 13 #include "string.h"
14 14
15 #include "webrtc/base/checks.h"
16 #include "webrtc/modules/desktop_capture/desktop_region.h"
17 #include "webrtc/modules/desktop_capture/desktop_geometry.h"
15 #include "webrtc/modules/desktop_capture/differ_block.h" 18 #include "webrtc/modules/desktop_capture/differ_block.h"
16 #include "webrtc/system_wrappers/include/logging.h" 19 #include "webrtc/system_wrappers/include/logging.h"
17 20
18 namespace webrtc { 21 namespace webrtc {
19 22
20 Differ::Differ(int width, int height, int bpp, int stride) { 23 Differ::Differ(int width, int height, int bpp, int stride) :
21 // Dimensions of screen. 24 // Dimensions of screen.
22 width_ = width; 25 width_(width),
23 height_ = height; 26 height_(height),
24 bytes_per_pixel_ = bpp; 27 bytes_per_pixel_(bpp),
25 bytes_per_row_ = stride; 28 bytes_per_row_(stride),
26 29 // Calc number of blocks (full and partial) required to cover entire image.
27 // Calc number of blocks (full and partial) required to cover entire image. 30 // One additional row/column is added as a boundary on the right & bottom.
28 // One additional row/column is added as a boundary on the right & bottom. 31 diff_info_width_(((width_ + kBlockSize - 1) / kBlockSize) + 1),
29 diff_info_width_ = ((width_ + kBlockSize - 1) / kBlockSize) + 1; 32 diff_info_height_(((height_ + kBlockSize - 1) / kBlockSize) + 1),
30 diff_info_height_ = ((height_ + kBlockSize - 1) / kBlockSize) + 1; 33 diff_info_size_(diff_info_width_ * diff_info_height_ * sizeof(bool)),
31 diff_info_size_ = diff_info_width_ * diff_info_height_ * sizeof(bool); 34 diff_info_(new bool[diff_info_size_]) {}
32 diff_info_.reset(new bool[diff_info_size_]);
33 }
34 35
35 Differ::~Differ() {} 36 Differ::~Differ() {}
36 37
37 void Differ::CalcDirtyRegion(const uint8_t* prev_buffer, 38 void Differ::CalcDirtyRegion(const uint8_t* prev_buffer,
38 const uint8_t* curr_buffer, 39 const uint8_t* curr_buffer,
39 DesktopRegion* region) { 40 DesktopRegion* region) {
Jamie 2016/08/03 23:52:25 Maybe just call through to CalcDirtyRegionWithHint
Hzj_jie 2016/08/04 02:28:07 If you do not have concern with the unnecessary fo
41 // Reset internal dirty state to false.
42 memset(diff_info_.get(), 0, diff_info_size_);
43
40 // Identify all the blocks that contain changed pixels. 44 // Identify all the blocks that contain changed pixels.
41 MarkDirtyBlocks(prev_buffer, curr_buffer); 45 MarkDirtyBlocks(prev_buffer,
46 curr_buffer,
47 DesktopRect::MakeWH(width_, height_));
48
49 // Now that we've identified the blocks that have changed, merge adjacent
50 // blocks to minimize the number of rects that we return.
51 MergeBlocks(region);
52 }
53
54 void Differ::CalcDirtyRegionWithHints(const uint8_t* prev_buffer,
55 const uint8_t* curr_buffer,
56 const DesktopRegion& hints,
57 DesktopRegion* region) {
58 // Reset internal dirty state to false.
59 memset(diff_info_.get(), 0, diff_info_size_);
60
61 // Identify all the blocks that contain changed pixels.
62 for (auto it = DesktopRegion::Iterator(hints);
63 !it.IsAtEnd();
64 it.Advance()) {
65 MarkDirtyBlocks(prev_buffer, curr_buffer, it.rect());
66 }
42 67
43 // Now that we've identified the blocks that have changed, merge adjacent 68 // Now that we've identified the blocks that have changed, merge adjacent
44 // blocks to minimize the number of rects that we return. 69 // blocks to minimize the number of rects that we return.
45 MergeBlocks(region); 70 MergeBlocks(region);
46 } 71 }
47 72
48 void Differ::MarkDirtyBlocks(const uint8_t* prev_buffer, 73 void Differ::MarkDirtyBlocks(const uint8_t* prev_buffer,
49 const uint8_t* curr_buffer) { 74 const uint8_t* curr_buffer,
50 memset(diff_info_.get(), 0, diff_info_size_); 75 const DesktopRect& rect) {
76 RTC_DCHECK(rect.width() <= width_);
77 RTC_DCHECK(rect.height() <= height_);
51 78
52 // Calc number of full blocks. 79 if (rect.is_empty()) {
53 int x_full_blocks = width_ / kBlockSize; 80 return;
54 int y_full_blocks = height_ / kBlockSize; 81 }
82
83 // Calculate the range of blocks.
Jamie 2016/08/03 23:52:25 Since right and bottom are both past-the-end point
Hzj_jie 2016/08/04 02:28:07 This seems not correct to me, Case 1: considering
84 int x_start = rect.left() / kBlockSize;
85 int y_start = rect.top() / kBlockSize;
86 int x_end = (rect.right() + kBlockSize - 1) / kBlockSize;
87 int y_end = (rect.bottom() + kBlockSize - 1) / kBlockSize;
88 if (x_end * kBlockSize > width_) {
89 x_end--;
90 }
91 if (y_end * kBlockSize > height_) {
92 y_end--;
93 }
55 94
56 // Calc size of partial blocks which may be present on right and bottom edge. 95 // Calc size of partial blocks which may be present on right and bottom edge.
57 int partial_column_width = width_ - (x_full_blocks * kBlockSize); 96 int partial_column_width = rect.right() - (x_end * kBlockSize);
58 int partial_row_height = height_ - (y_full_blocks * kBlockSize); 97 int partial_row_height = rect.bottom() - (y_end * kBlockSize);
59 98
60 // Offset from the start of one block-column to the next. 99 // Offset from the start of one block-column to the next.
61 int block_x_offset = bytes_per_pixel_ * kBlockSize; 100 int block_x_offset = bytes_per_pixel_ * kBlockSize;
62 // Offset from the start of one block-row to the next. 101 // Offset from the start of one block-row to the next.
63 int block_y_stride = (width_ * bytes_per_pixel_) * kBlockSize; 102 int block_y_stride = (width_ * bytes_per_pixel_) * kBlockSize;
64 // Offset from the start of one diff_info row to the next. 103 // Offset from the start of one diff_info row to the next.
65 int diff_info_stride = diff_info_width_ * sizeof(bool); 104 int diff_info_stride = diff_info_width_ * sizeof(bool);
66 105
67 const uint8_t* prev_block_row_start = prev_buffer; 106 const uint8_t* prev_block_row_start =
68 const uint8_t* curr_block_row_start = curr_buffer; 107 prev_buffer + y_start * block_y_stride + x_start * block_x_offset;
69 bool* diff_info_row_start = diff_info_.get(); 108 const uint8_t* curr_block_row_start =
109 curr_buffer + (prev_block_row_start - prev_buffer);
110 bool* diff_info_row_start =
111 diff_info_.get() + y_start * diff_info_width_ + x_start;
70 112
71 for (int y = 0; y < y_full_blocks; y++) { 113 for (int y = y_start; y < y_end; y++) {
72 const uint8_t* prev_block = prev_block_row_start; 114 const uint8_t* prev_block = prev_block_row_start;
73 const uint8_t* curr_block = curr_block_row_start; 115 const uint8_t* curr_block = curr_block_row_start;
74 bool* diff_info = diff_info_row_start; 116 bool* diff_info = diff_info_row_start;
75 117
76 for (int x = 0; x < x_full_blocks; x++) { 118 for (int x = x_start; x < x_end; x++) {
77 // Mark this block as being modified so that it gets incorporated into 119 // Mark this block as being modified so that it gets incorporated into
78 // a dirty rect. 120 // a dirty rect.
79 *diff_info = BlockDifference(prev_block, curr_block, bytes_per_row_); 121 *diff_info = BlockDifference(prev_block, curr_block, bytes_per_row_);
80 prev_block += block_x_offset; 122 prev_block += block_x_offset;
81 curr_block += block_x_offset; 123 curr_block += block_x_offset;
82 diff_info += sizeof(bool); 124 diff_info += sizeof(bool);
Jamie 2016/08/03 23:52:25 This should just be diff_info++, I think, since po
Hzj_jie 2016/08/04 02:28:07 Oh, I have not noticed these lines (and three line
83 } 125 }
84 126
85 // If there is a partial column at the end, handle it. 127 // If there is a partial column at the end, handle it.
86 // This condition should rarely, if ever, occur. 128 // This condition should rarely, if ever, occur.
Jamie 2016/08/03 23:52:25 I suspect this is no longer true; it's rare when t
Hzj_jie 2016/08/04 02:28:06 We always try our best to cover the damage rectang
87 if (partial_column_width != 0) { 129 if (partial_column_width > 0) {
88 *diff_info = !PartialBlocksEqual(prev_block, curr_block, bytes_per_row_, 130 *diff_info = !PartialBlocksEqual(prev_block, curr_block, bytes_per_row_,
89 partial_column_width, kBlockSize); 131 partial_column_width, kBlockSize);
90 diff_info += sizeof(bool); 132 diff_info += sizeof(bool);
91 } 133 }
92 134
93 // Update pointers for next row. 135 // Update pointers for next row.
94 prev_block_row_start += block_y_stride; 136 prev_block_row_start += block_y_stride;
95 curr_block_row_start += block_y_stride; 137 curr_block_row_start += block_y_stride;
96 diff_info_row_start += diff_info_stride; 138 diff_info_row_start += diff_info_stride;
97 } 139 }
98 140
99 // If the screen height is not a multiple of the block size, then this 141 // If the screen height is not a multiple of the block size, then this
100 // handles the last partial row. This situation is far more common than the 142 // handles the last partial row. This situation is far more common than the
101 // 'partial column' case. 143 // 'partial column' case.
Jamie 2016/08/03 23:52:25 As above, this second sentence can be removed now.
Hzj_jie 2016/08/04 02:28:06 Done.
102 if (partial_row_height != 0) { 144 if (partial_row_height > 0) {
103 const uint8_t* prev_block = prev_block_row_start; 145 const uint8_t* prev_block = prev_block_row_start;
104 const uint8_t* curr_block = curr_block_row_start; 146 const uint8_t* curr_block = curr_block_row_start;
105 bool* diff_info = diff_info_row_start; 147 bool* diff_info = diff_info_row_start;
106 for (int x = 0; x < x_full_blocks; x++) { 148 for (int x = x_start; x < x_end; x++) {
107 *diff_info = !PartialBlocksEqual(prev_block, curr_block, 149 *diff_info = !PartialBlocksEqual(prev_block, curr_block, bytes_per_row_,
108 bytes_per_row_,
109 kBlockSize, partial_row_height); 150 kBlockSize, partial_row_height);
110 prev_block += block_x_offset; 151 prev_block += block_x_offset;
111 curr_block += block_x_offset; 152 curr_block += block_x_offset;
112 diff_info += sizeof(bool); 153 diff_info += sizeof(bool);
113 } 154 }
114 if (partial_column_width != 0) { 155 if (partial_column_width > 0) {
115 *diff_info = !PartialBlocksEqual(prev_block, curr_block, bytes_per_row_, 156 *diff_info = !PartialBlocksEqual(prev_block, curr_block, bytes_per_row_,
116 partial_column_width, 157 partial_column_width,
117 partial_row_height); 158 partial_row_height);
118 diff_info += sizeof(bool); 159 diff_info += sizeof(bool);
119 } 160 }
120 } 161 }
121 } 162 }
122 163
123 bool Differ::PartialBlocksEqual(const uint8_t* prev_buffer, 164 bool Differ::PartialBlocksEqual(const uint8_t* prev_buffer,
124 const uint8_t* curr_buffer, 165 const uint8_t* curr_buffer,
125 int stride, int width, int height) { 166 int stride, int width, int height) {
167 RTC_DCHECK(width > 0 && height > 0);
126 int width_bytes = width * bytes_per_pixel_; 168 int width_bytes = width * bytes_per_pixel_;
127 for (int y = 0; y < height; y++) { 169 for (int y = 0; y < height; y++) {
128 if (memcmp(prev_buffer, curr_buffer, width_bytes) != 0) 170 if (memcmp(prev_buffer, curr_buffer, width_bytes) != 0)
129 return false; 171 return false;
130 prev_buffer += bytes_per_row_; 172 prev_buffer += bytes_per_row_;
131 curr_buffer += bytes_per_row_; 173 curr_buffer += bytes_per_row_;
132 } 174 }
133 return true; 175 return true;
134 } 176 }
135 177
136 void Differ::MergeBlocks(DesktopRegion* region) { 178 void Differ::MergeBlocks(DesktopRegion* region) const {
137 region->Clear(); 179 region->Clear();
138 180
139 bool* diff_info_row_start = diff_info_.get(); 181 bool* diff_info_row_start = diff_info_.get();
140 int diff_info_stride = diff_info_width_ * sizeof(bool); 182 int diff_info_stride = diff_info_width_ * sizeof(bool);
141 183
142 for (int y = 0; y < diff_info_height_; y++) { 184 for (int y = 0; y < diff_info_height_; y++) {
143 bool* diff_info = diff_info_row_start; 185 bool* diff_info = diff_info_row_start;
144 for (int x = 0; x < diff_info_width_; x++) { 186 for (int x = 0; x < diff_info_width_; x++) {
145 if (*diff_info) { 187 if (*diff_info) {
146 // We've found a modified block. Look at blocks to the right and below 188 // We've found a modified block. Look at blocks to the right and below
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 // Increment to next block in this row. 244 // Increment to next block in this row.
203 diff_info++; 245 diff_info++;
204 } 246 }
205 247
206 // Go to start of next row. 248 // Go to start of next row.
207 diff_info_row_start += diff_info_stride; 249 diff_info_row_start += diff_info_stride;
208 } 250 }
209 } 251 }
210 252
211 } // namespace webrtc 253 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698