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

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

Issue 2348803003: Remove differ from ScreenCapturer implementations (Closed)
Patch Set: Comment on the XDamage scenario in screen_capturer_x11.cc Created 4 years, 2 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
(Empty)
1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/desktop_capture/differ.h"
12
13 #include "string.h"
14
15 #include "webrtc/modules/desktop_capture/differ_block.h"
16 #include "webrtc/system_wrappers/include/logging.h"
17
18 namespace webrtc {
19
20 Differ::Differ(int width, int height, int bpp, int stride) {
21 // Dimensions of screen.
22 width_ = width;
23 height_ = height;
24 bytes_per_pixel_ = bpp;
25 bytes_per_row_ = stride;
26
27 // Calc number of blocks (full and partial) required to cover entire image.
28 // One additional row/column is added as a boundary on the right & bottom.
29 diff_info_width_ = ((width_ + kBlockSize - 1) / kBlockSize) + 1;
30 diff_info_height_ = ((height_ + kBlockSize - 1) / kBlockSize) + 1;
31 diff_info_size_ = diff_info_width_ * diff_info_height_ * sizeof(bool);
32 diff_info_.reset(new bool[diff_info_size_]);
33 }
34
35 Differ::~Differ() {}
36
37 void Differ::CalcDirtyRegion(const uint8_t* prev_buffer,
38 const uint8_t* curr_buffer,
39 DesktopRegion* region) {
40 // Identify all the blocks that contain changed pixels.
41 MarkDirtyBlocks(prev_buffer, curr_buffer);
42
43 // Now that we've identified the blocks that have changed, merge adjacent
44 // blocks to minimize the number of rects that we return.
45 MergeBlocks(region);
46 }
47
48 void Differ::MarkDirtyBlocks(const uint8_t* prev_buffer,
49 const uint8_t* curr_buffer) {
50 memset(diff_info_.get(), 0, diff_info_size_);
51
52 // Calc number of full blocks.
53 int x_full_blocks = width_ / kBlockSize;
54 int y_full_blocks = height_ / kBlockSize;
55
56 // Calc size of partial blocks which may be present on right and bottom edge.
57 int partial_column_width = width_ - (x_full_blocks * kBlockSize);
58 int partial_row_height = height_ - (y_full_blocks * kBlockSize);
59
60 // Offset from the start of one block-column to the next.
61 int block_x_offset = bytes_per_pixel_ * kBlockSize;
62 // Offset from the start of one block-row to the next.
63 int block_y_stride = (width_ * bytes_per_pixel_) * kBlockSize;
64 // Offset from the start of one diff_info row to the next.
65 int diff_info_stride = diff_info_width_ * sizeof(bool);
66
67 const uint8_t* prev_block_row_start = prev_buffer;
68 const uint8_t* curr_block_row_start = curr_buffer;
69 bool* diff_info_row_start = diff_info_.get();
70
71 for (int y = 0; y < y_full_blocks; y++) {
72 const uint8_t* prev_block = prev_block_row_start;
73 const uint8_t* curr_block = curr_block_row_start;
74 bool* diff_info = diff_info_row_start;
75
76 for (int x = 0; x < x_full_blocks; x++) {
77 // Mark this block as being modified so that it gets incorporated into
78 // a dirty rect.
79 *diff_info = BlockDifference(prev_block, curr_block, bytes_per_row_);
80 prev_block += block_x_offset;
81 curr_block += block_x_offset;
82 diff_info += sizeof(bool);
83 }
84
85 // If there is a partial column at the end, handle it.
86 // This condition should rarely, if ever, occur.
87 if (partial_column_width != 0) {
88 *diff_info = !PartialBlocksEqual(prev_block, curr_block, bytes_per_row_,
89 partial_column_width, kBlockSize);
90 diff_info += sizeof(bool);
91 }
92
93 // Update pointers for next row.
94 prev_block_row_start += block_y_stride;
95 curr_block_row_start += block_y_stride;
96 diff_info_row_start += diff_info_stride;
97 }
98
99 // 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
101 // 'partial column' case.
102 if (partial_row_height != 0) {
103 const uint8_t* prev_block = prev_block_row_start;
104 const uint8_t* curr_block = curr_block_row_start;
105 bool* diff_info = diff_info_row_start;
106 for (int x = 0; x < x_full_blocks; x++) {
107 *diff_info = !PartialBlocksEqual(prev_block, curr_block,
108 bytes_per_row_,
109 kBlockSize, partial_row_height);
110 prev_block += block_x_offset;
111 curr_block += block_x_offset;
112 diff_info += sizeof(bool);
113 }
114 if (partial_column_width != 0) {
115 *diff_info = !PartialBlocksEqual(prev_block, curr_block, bytes_per_row_,
116 partial_column_width,
117 partial_row_height);
118 diff_info += sizeof(bool);
119 }
120 }
121 }
122
123 bool Differ::PartialBlocksEqual(const uint8_t* prev_buffer,
124 const uint8_t* curr_buffer,
125 int stride, int width, int height) {
126 int width_bytes = width * bytes_per_pixel_;
127 for (int y = 0; y < height; y++) {
128 if (memcmp(prev_buffer, curr_buffer, width_bytes) != 0)
129 return false;
130 prev_buffer += bytes_per_row_;
131 curr_buffer += bytes_per_row_;
132 }
133 return true;
134 }
135
136 void Differ::MergeBlocks(DesktopRegion* region) {
137 region->Clear();
138
139 bool* diff_info_row_start = diff_info_.get();
140 int diff_info_stride = diff_info_width_ * sizeof(bool);
141
142 for (int y = 0; y < diff_info_height_; y++) {
143 bool* diff_info = diff_info_row_start;
144 for (int x = 0; x < diff_info_width_; x++) {
145 if (*diff_info) {
146 // We've found a modified block. Look at blocks to the right and below
147 // to group this block with as many others as we can.
148 int left = x * kBlockSize;
149 int top = y * kBlockSize;
150 int width = 1;
151 int height = 1;
152 *diff_info = false;
153
154 // Group with blocks to the right.
155 // We can keep looking until we find an unchanged block because we
156 // have a boundary block which is never marked as having diffs.
157 bool* right = diff_info + 1;
158 while (*right) {
159 *right++ = false;
160 width++;
161 }
162
163 // Group with blocks below.
164 // The entire width of blocks that we matched above much match for
165 // each row that we add.
166 bool* bottom = diff_info;
167 bool found_new_row;
168 do {
169 found_new_row = true;
170 bottom += diff_info_stride;
171 right = bottom;
172 for (int x2 = 0; x2 < width; x2++) {
173 if (!*right++) {
174 found_new_row = false;
175 }
176 }
177
178 if (found_new_row) {
179 height++;
180
181 // We need to go back and erase the diff markers so that we don't
182 // try to add these blocks a second time.
183 right = bottom;
184 for (int x2 = 0; x2 < width; x2++) {
185 *right++ = false;
186 }
187 }
188 } while (found_new_row);
189
190 // Add rect to list of dirty rects.
191 width *= kBlockSize;
192 if (left + width > width_) {
193 width = width_ - left;
194 }
195 height *= kBlockSize;
196 if (top + height > height_) {
197 height = height_ - top;
198 }
199 region->AddRect(DesktopRect::MakeXYWH(left, top, width, height));
200 }
201
202 // Increment to next block in this row.
203 diff_info++;
204 }
205
206 // Go to start of next row.
207 diff_info_row_start += diff_info_stride;
208 }
209 }
210
211 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/desktop_capture/differ.h ('k') | webrtc/modules/desktop_capture/differ_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698