Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |