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

Side by Side Diff: remoting/base/util.cc

Issue 9320025: Introducing a helper wrapper for YUV-to-RGB convertion and/or scaling. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Make VC++ happy, take two. Created 8 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/base/util.h" 5 #include "remoting/base/util.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/stringprintf.h" 10 #include "base/stringprintf.h"
(...skipping 30 matching lines...) Expand all
41 return 0; 41 return 0;
42 } 42 }
43 } 43 }
44 44
45 // Helper methods to calculate plane offset given the coordinates. 45 // Helper methods to calculate plane offset given the coordinates.
46 static int CalculateRGBOffset(int x, int y, int stride) { 46 static int CalculateRGBOffset(int x, int y, int stride) {
47 return stride * y + GetBytesPerPixel(media::VideoFrame::RGB32) * x; 47 return stride * y + GetBytesPerPixel(media::VideoFrame::RGB32) * x;
48 } 48 }
49 49
50 static int CalculateYOffset(int x, int y, int stride) { 50 static int CalculateYOffset(int x, int y, int stride) {
51 DCHECK(((x & 1) == 0) && ((y & 1) == 0));
51 return stride * y + x; 52 return stride * y + x;
52 } 53 }
53 54
54 static int CalculateUVOffset(int x, int y, int stride) { 55 static int CalculateUVOffset(int x, int y, int stride) {
56 DCHECK(((x & 1) == 0) && ((y & 1) == 0));
55 return stride * y / 2 + x / 2; 57 return stride * y / 2 + x / 2;
56 } 58 }
57 59
58 void ConvertYUVToRGB32WithRect(const uint8* y_plane,
59 const uint8* u_plane,
60 const uint8* v_plane,
61 uint8* rgb_plane,
62 const SkIRect& rect,
63 int y_stride,
64 int uv_stride,
65 int rgb_stride) {
66 DCHECK((rect.x() & 1) == 0 && (rect.y() & 1) == 0);
67 int rgb_offset = CalculateRGBOffset(rect.left(), rect.top(), rgb_stride);
68 int y_offset = CalculateYOffset(rect.left(), rect.top(), y_stride);
69 int uv_offset = CalculateUVOffset(rect.left(), rect.top(), uv_stride);
70
71 media::ConvertYUVToRGB32(y_plane + y_offset,
72 u_plane + uv_offset,
73 v_plane + uv_offset,
74 rgb_plane + rgb_offset,
75 rect.width(),
76 rect.height(),
77 y_stride,
78 uv_stride,
79 rgb_stride,
80 media::YV12);
81 }
82
83 void ConvertRGB32ToYUVWithRect(const uint8* rgb_plane, 60 void ConvertRGB32ToYUVWithRect(const uint8* rgb_plane,
84 uint8* y_plane, 61 uint8* y_plane,
85 uint8* u_plane, 62 uint8* u_plane,
86 uint8* v_plane, 63 uint8* v_plane,
87 int x, 64 int x,
88 int y, 65 int y,
89 int width, 66 int width,
90 int height, 67 int height,
91 int rgb_stride, 68 int rgb_stride,
92 int y_stride, 69 int y_stride,
93 int uv_stride) { 70 int uv_stride) {
94 int rgb_offset = CalculateRGBOffset(x, y, rgb_stride); 71 int rgb_offset = CalculateRGBOffset(x, y, rgb_stride);
95 int y_offset = CalculateYOffset(x, y, y_stride); 72 int y_offset = CalculateYOffset(x, y, y_stride);
96 int uv_offset = CalculateUVOffset(x, y, uv_stride);; 73 int uv_offset = CalculateUVOffset(x, y, uv_stride);;
97 74
98 media::ConvertRGB32ToYUV(rgb_plane + rgb_offset, 75 media::ConvertRGB32ToYUV(rgb_plane + rgb_offset,
99 y_plane + y_offset, 76 y_plane + y_offset,
100 u_plane + uv_offset, 77 u_plane + uv_offset,
101 v_plane + uv_offset, 78 v_plane + uv_offset,
102 width, 79 width,
103 height, 80 height,
104 rgb_stride, 81 rgb_stride,
105 y_stride, 82 y_stride,
106 uv_stride); 83 uv_stride);
107 } 84 }
108 85
86 void ConvertAndScaleYUVToRGB32Rect(const uint8* source_yplane,
87 const uint8* source_uplane,
88 const uint8* source_vplane,
89 int source_ystride,
90 int source_uvstride,
91 const SkISize& source_size,
92 const SkIRect& source_buffer_rect,
93 uint8* dest_buffer,
94 int dest_stride,
95 const SkISize& dest_size,
96 const SkIRect& dest_buffer_rect,
97 const SkIRect& dest_rect) {
98 // N.B. It is caller's responsibility to check if strides are large enough. We
99 // cannot do it here anyway.
100 DCHECK(SkIRect::MakeSize(source_size).contains(source_buffer_rect));
101 DCHECK(SkIRect::MakeSize(dest_size).contains(dest_buffer_rect));
102 DCHECK(dest_buffer_rect.contains(dest_rect));
103 DCHECK(ScaleRect(source_buffer_rect, source_size, dest_size).
104 contains(dest_rect));
105
106 // The top left corner coordinates of YUV buffer should have even X and Y
107 // coordinates.
108 DCHECK(source_buffer_rect == AlignRect(source_buffer_rect));
Wez 2012/02/03 22:40:35 Don't CalculateYOffset() and CalculateUVOffset() a
alexeypa (please no reviews) 2012/02/03 23:29:35 Done.
109
110 // If the source and/or destination buffers don't start at (0, 0)
111 // offset the pointers to pretend we have complete buffers.
112 int y_offset = - CalculateYOffset(source_buffer_rect.x(),
113 source_buffer_rect.y(),
114 source_ystride);
115 int uv_offset = - CalculateUVOffset(source_buffer_rect.x(),
116 source_buffer_rect.y(),
117 source_uvstride);
118 int rgb_offset = - CalculateRGBOffset(dest_buffer_rect.x(),
119 dest_buffer_rect.y(),
120 dest_stride);
121
122 // See if scaling is needed.
123 if (source_size == dest_size) {
124 // Calculate the inner rectangle that can be copied by the optimized
125 // ConvertYUVToRGB32().
Wez 2012/02/03 22:40:35 Why are we calculating a smaller aligned rect than
alexeypa (please no reviews) 2012/02/03 23:29:35 We are not allowed to touch pixels outside of the
Wez 2012/02/04 01:03:43 I think it's reasonable to require the caller to a
alexeypa (please no reviews) 2012/02/06 05:45:16 I'll stick to this approach for now. However I'll
126 SkIRect inner_rect =
127 SkIRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left() + 1),
128 RoundToTwosMultiple(dest_rect.top() + 1),
129 RoundToTwosMultiple(dest_rect.right()),
130 RoundToTwosMultiple(dest_rect.bottom()));
131
132 // Offset pointers to point to the top left corner of the inner rectangle.
133 y_offset += CalculateYOffset(inner_rect.x(), inner_rect.y(),
134 source_ystride);
135 uv_offset += CalculateUVOffset(inner_rect.x(), inner_rect.y(),
136 source_uvstride);
137 rgb_offset += CalculateRGBOffset(inner_rect.x(), inner_rect.y(),
138 dest_stride);
139
140 media::ConvertYUVToRGB32(source_yplane + y_offset,
141 source_uplane + uv_offset,
142 source_vplane + uv_offset,
143 dest_buffer + rgb_offset,
144 inner_rect.width(),
145 inner_rect.height(),
146 source_ystride,
147 source_uvstride,
148 dest_stride,
149 media::YV12);
150
151 // Now see if some pixels weren't copied due to alignment.
Wez 2012/02/03 22:40:35 Why not just align the top and left of the rectang
alexeypa (please no reviews) 2012/02/03 23:29:35 There are a few reasons I settled on this approach
Wez 2012/02/04 01:03:43 Your point is that in the 1:1 case the caller need
alexeypa (please no reviews) 2012/02/06 05:45:16 Done.
152 SkIRect outer_rect = AlignRect(dest_rect);
153 SkIPoint offset = SkIPoint::Make(outer_rect.x() - inner_rect.x(),
154 outer_rect.y() - inner_rect.y());
155
156 // Offset the pointers to point to the top left corner of the outer
157 // rectangle.
158 y_offset += CalculateYOffset(offset.x(), offset.y(), source_ystride);
159 uv_offset += CalculateUVOffset(offset.x(), offset.y(), source_uvstride);
160 rgb_offset += CalculateRGBOffset(offset.x(), offset.y(), dest_stride);
161
162 // Draw the top line.
163 if (inner_rect.top() != dest_rect.top()) {
164 media::ScaleYUVToRGB32WithRect(source_yplane + y_offset,
165 source_uplane + uv_offset,
166 source_vplane + uv_offset,
167 dest_buffer + rgb_offset,
168 source_size.width(),
169 source_size.height(),
170 dest_size.width(),
171 dest_size.height(),
172 dest_rect.left() - outer_rect.left(),
173 dest_rect.top() - outer_rect.top(),
174 dest_rect.right() - outer_rect.left(),
175 inner_rect.top() - outer_rect.top(),
176 source_ystride,
177 source_uvstride,
178 dest_stride);
179 }
180
181 // Draw the bottom line.
182 if (inner_rect.bottom() != dest_rect.bottom()) {
183 media::ScaleYUVToRGB32WithRect(source_yplane + y_offset,
184 source_uplane + uv_offset,
185 source_vplane + uv_offset,
186 dest_buffer + rgb_offset,
187 source_size.width(),
188 source_size.height(),
189 dest_size.width(),
190 dest_size.height(),
191 dest_rect.left() - outer_rect.left(),
192 inner_rect.bottom() - outer_rect.top(),
193 dest_rect.right() - outer_rect.left(),
194 dest_rect.bottom() - outer_rect.top(),
195 source_ystride,
196 source_uvstride,
197 dest_stride);
198 }
199
200 // Draw the left column.
201 if (inner_rect.left() != dest_rect.left()) {
202 media::ScaleYUVToRGB32WithRect(source_yplane + y_offset,
203 source_uplane + uv_offset,
204 source_vplane + uv_offset,
205 dest_buffer + rgb_offset,
206 source_size.width(),
207 source_size.height(),
208 dest_size.width(),
209 dest_size.height(),
210 dest_rect.left() - outer_rect.left(),
211 dest_rect.top() - outer_rect.top(),
212 inner_rect.left() - outer_rect.left(),
213 dest_rect.bottom() - outer_rect.top(),
214 source_ystride,
215 source_uvstride,
216 dest_stride);
217 }
218
219 // Draw the right column.
220 if (inner_rect.right() != dest_rect.right()) {
221 media::ScaleYUVToRGB32WithRect(source_yplane + y_offset,
222 source_uplane + uv_offset,
223 source_vplane + uv_offset,
224 dest_buffer + rgb_offset,
225 source_size.width(),
226 source_size.height(),
227 dest_size.width(),
228 dest_size.height(),
229 inner_rect.right() - outer_rect.left(),
230 dest_rect.top() - outer_rect.top(),
231 dest_rect.right() - outer_rect.left(),
232 dest_rect.bottom() - outer_rect.top(),
233 source_ystride,
234 source_uvstride,
235 dest_stride);
236 }
237 } else {
238 media::ScaleYUVToRGB32WithRect(source_yplane + y_offset,
239 source_uplane + uv_offset,
240 source_vplane + uv_offset,
241 dest_buffer + rgb_offset,
242 source_size.width(),
243 source_size.height(),
244 dest_size.width(),
245 dest_size.height(),
246 dest_rect.left(),
247 dest_rect.top(),
248 dest_rect.right(),
249 dest_rect.bottom(),
250 source_ystride,
251 source_uvstride,
252 dest_stride);
253 }
254 }
255
109 int RoundToTwosMultiple(int x) { 256 int RoundToTwosMultiple(int x) {
110 return x & (~1); 257 return x & (~1);
111 } 258 }
112 259
113 SkIRect AlignRect(const SkIRect& rect) { 260 SkIRect AlignRect(const SkIRect& rect) {
114 int x = RoundToTwosMultiple(rect.left()); 261 int x = RoundToTwosMultiple(rect.left());
115 int y = RoundToTwosMultiple(rect.top()); 262 int y = RoundToTwosMultiple(rect.top());
116 int right = RoundToTwosMultiple(rect.right() + 1); 263 int right = RoundToTwosMultiple(rect.right() + 1);
117 int bottom = RoundToTwosMultiple(rect.bottom() + 1); 264 int bottom = RoundToTwosMultiple(rect.bottom() + 1);
118 return SkIRect::MakeLTRB(x, y, right, bottom); 265 return SkIRect::MakeLTRB(x, y, right, bottom);
(...skipping 27 matching lines...) Expand all
146 // Copy pixels in the rectangle line by line. 293 // Copy pixels in the rectangle line by line.
147 const int bytes_per_line = bytes_per_pixel * rect.width(); 294 const int bytes_per_line = bytes_per_pixel * rect.width();
148 const int height = rect.height(); 295 const int height = rect.height();
149 for (int i = 0 ; i < height; ++i) { 296 for (int i = 0 ; i < height; ++i) {
150 memcpy(dest_plane, src_plane, bytes_per_line); 297 memcpy(dest_plane, src_plane, bytes_per_line);
151 src_plane += src_plane_stride; 298 src_plane += src_plane_stride;
152 dest_plane += dest_plane_stride; 299 dest_plane += dest_plane_stride;
153 } 300 }
154 } 301 }
155 302
303 void CopyRGB32Rect(const uint8* source_buffer,
304 int source_stride,
305 const SkIRect& source_buffer_rect,
306 uint8* dest_buffer,
307 int dest_stride,
308 const SkIRect& dest_buffer_rect,
309 const SkIRect& dest_rect) {
310 DCHECK(dest_buffer_rect.contains(dest_rect));
311 DCHECK(source_buffer_rect.contains(dest_rect));
312
313 // Get the address of the starting point.
314 int source_offset = CalculateRGBOffset(dest_rect.x() - source_buffer_rect.x(),
315 dest_rect.y() - source_buffer_rect.y(),
316 source_stride);
317 int dest_offset = CalculateRGBOffset(dest_rect.x() - dest_buffer_rect.x(),
318 dest_rect.y() - dest_buffer_rect.y(),
319 source_stride);
320
321 // Copy bits.
322 CopyRect(source_buffer + source_offset,
323 source_stride,
324 dest_buffer + dest_offset,
325 dest_stride,
326 GetBytesPerPixel(media::VideoFrame::RGB32),
327 SkIRect::MakeWH(dest_rect.width(), dest_rect.height()));
Wez 2012/02/03 22:40:35 Is there no SkRect::size() method?
alexeypa (please no reviews) 2012/02/03 23:29:35 Nope. SkIRect.offset does not work as well because
328 }
329
156 } // namespace remoting 330 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698