| 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/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| 11 #include "base/time/time.h" | 11 #include "base/time/time.h" |
| 12 #include "media/base/video_frame.h" | 12 #include "media/base/video_frame.h" |
| 13 #include "media/base/yuv_convert.h" | 13 #include "media/base/yuv_convert.h" |
| 14 #include "third_party/libyuv/include/libyuv/convert.h" | 14 #include "third_party/libyuv/include/libyuv/convert.h" |
| 15 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h" | 15 #include "third_party/skia/include/core/SkRegion.h" |
| 16 | 16 |
| 17 #if defined(OS_POSIX) | 17 #if defined(OS_POSIX) |
| 18 #include <pwd.h> | 18 #include <pwd.h> |
| 19 #include <sys/types.h> | 19 #include <sys/types.h> |
| 20 #include <unistd.h> | 20 #include <unistd.h> |
| 21 #endif // defined(OS_POSIX) | 21 #endif // defined(OS_POSIX) |
| 22 | 22 |
| 23 using media::VideoFrame; | 23 using media::VideoFrame; |
| 24 | 24 |
| 25 namespace remoting { | 25 namespace remoting { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 int y_offset = CalculateYOffset(x, y, y_stride); | 66 int y_offset = CalculateYOffset(x, y, y_stride); |
| 67 int uv_offset = CalculateUVOffset(x, y, uv_stride);; | 67 int uv_offset = CalculateUVOffset(x, y, uv_stride);; |
| 68 | 68 |
| 69 libyuv::ARGBToI420(rgb_plane + rgb_offset, rgb_stride, | 69 libyuv::ARGBToI420(rgb_plane + rgb_offset, rgb_stride, |
| 70 y_plane + y_offset, y_stride, | 70 y_plane + y_offset, y_stride, |
| 71 u_plane + uv_offset, uv_stride, | 71 u_plane + uv_offset, uv_stride, |
| 72 v_plane + uv_offset, uv_stride, | 72 v_plane + uv_offset, uv_stride, |
| 73 width, height); | 73 width, height); |
| 74 } | 74 } |
| 75 | 75 |
| 76 void ConvertAndScaleYUVToRGB32Rect( | 76 void ConvertAndScaleYUVToRGB32Rect(const uint8* source_yplane, |
| 77 const uint8* source_yplane, | 77 const uint8* source_uplane, |
| 78 const uint8* source_uplane, | 78 const uint8* source_vplane, |
| 79 const uint8* source_vplane, | 79 int source_ystride, |
| 80 int source_ystride, | 80 int source_uvstride, |
| 81 int source_uvstride, | 81 const SkISize& source_size, |
| 82 const webrtc::DesktopSize& source_size, | 82 const SkIRect& source_buffer_rect, |
| 83 const webrtc::DesktopRect& source_buffer_rect, | 83 uint8* dest_buffer, |
| 84 uint8* dest_buffer, | 84 int dest_stride, |
| 85 int dest_stride, | 85 const SkISize& dest_size, |
| 86 const webrtc::DesktopSize& dest_size, | 86 const SkIRect& dest_buffer_rect, |
| 87 const webrtc::DesktopRect& dest_buffer_rect, | 87 const SkIRect& dest_rect) { |
| 88 const webrtc::DesktopRect& dest_rect) { | |
| 89 // N.B. It is caller's responsibility to check if strides are large enough. We | 88 // N.B. It is caller's responsibility to check if strides are large enough. We |
| 90 // cannot do it here anyway. | 89 // cannot do it here anyway. |
| 91 DCHECK(DoesRectContain(webrtc::DesktopRect::MakeSize(source_size), | 90 DCHECK(SkIRect::MakeSize(source_size).contains(source_buffer_rect)); |
| 92 source_buffer_rect)); | 91 DCHECK(SkIRect::MakeSize(dest_size).contains(dest_buffer_rect)); |
| 93 DCHECK(DoesRectContain(webrtc::DesktopRect::MakeSize(dest_size), | 92 DCHECK(dest_buffer_rect.contains(dest_rect)); |
| 94 dest_buffer_rect)); | 93 DCHECK(ScaleRect(source_buffer_rect, source_size, dest_size). |
| 95 DCHECK(DoesRectContain(dest_buffer_rect, dest_rect)); | 94 contains(dest_rect)); |
| 96 DCHECK(DoesRectContain(ScaleRect(source_buffer_rect, source_size, dest_size), | |
| 97 dest_rect)); | |
| 98 | 95 |
| 99 // If the source and/or destination buffers don't start at (0, 0) | 96 // If the source and/or destination buffers don't start at (0, 0) |
| 100 // offset the pointers to pretend we have complete buffers. | 97 // offset the pointers to pretend we have complete buffers. |
| 101 int y_offset = - CalculateYOffset(source_buffer_rect.left(), | 98 int y_offset = - CalculateYOffset(source_buffer_rect.x(), |
| 102 source_buffer_rect.top(), | 99 source_buffer_rect.y(), |
| 103 source_ystride); | 100 source_ystride); |
| 104 int uv_offset = - CalculateUVOffset(source_buffer_rect.left(), | 101 int uv_offset = - CalculateUVOffset(source_buffer_rect.x(), |
| 105 source_buffer_rect.top(), | 102 source_buffer_rect.y(), |
| 106 source_uvstride); | 103 source_uvstride); |
| 107 int rgb_offset = - CalculateRGBOffset(dest_buffer_rect.left(), | 104 int rgb_offset = - CalculateRGBOffset(dest_buffer_rect.x(), |
| 108 dest_buffer_rect.top(), | 105 dest_buffer_rect.y(), |
| 109 dest_stride); | 106 dest_stride); |
| 110 | 107 |
| 111 // See if scaling is needed. | 108 // See if scaling is needed. |
| 112 if (source_size.equals(dest_size)) { | 109 if (source_size == dest_size) { |
| 113 // Calculate the inner rectangle that can be copied by the optimized | 110 // Calculate the inner rectangle that can be copied by the optimized |
| 114 // libyuv::I420ToARGB(). | 111 // libyuv::I420ToARGB(). |
| 115 webrtc::DesktopRect inner_rect = | 112 SkIRect inner_rect = |
| 116 webrtc::DesktopRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left() + 1), | 113 SkIRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left() + 1), |
| 117 RoundToTwosMultiple(dest_rect.top() + 1), | 114 RoundToTwosMultiple(dest_rect.top() + 1), |
| 118 dest_rect.right(), dest_rect.bottom()); | 115 dest_rect.right(), |
| 116 dest_rect.bottom()); |
| 119 | 117 |
| 120 // Offset pointers to point to the top left corner of the inner rectangle. | 118 // Offset pointers to point to the top left corner of the inner rectangle. |
| 121 y_offset += CalculateYOffset(inner_rect.left(), inner_rect.top(), | 119 y_offset += CalculateYOffset(inner_rect.x(), inner_rect.y(), |
| 122 source_ystride); | 120 source_ystride); |
| 123 uv_offset += CalculateUVOffset(inner_rect.left(), inner_rect.top(), | 121 uv_offset += CalculateUVOffset(inner_rect.x(), inner_rect.y(), |
| 124 source_uvstride); | 122 source_uvstride); |
| 125 rgb_offset += CalculateRGBOffset(inner_rect.left(), inner_rect.top(), | 123 rgb_offset += CalculateRGBOffset(inner_rect.x(), inner_rect.y(), |
| 126 dest_stride); | 124 dest_stride); |
| 127 | 125 |
| 128 libyuv::I420ToARGB(source_yplane + y_offset, source_ystride, | 126 libyuv::I420ToARGB(source_yplane + y_offset, source_ystride, |
| 129 source_uplane + uv_offset, source_uvstride, | 127 source_uplane + uv_offset, source_uvstride, |
| 130 source_vplane + uv_offset, source_uvstride, | 128 source_vplane + uv_offset, source_uvstride, |
| 131 dest_buffer + rgb_offset, dest_stride, | 129 dest_buffer + rgb_offset, dest_stride, |
| 132 inner_rect.width(), inner_rect.height()); | 130 inner_rect.width(), inner_rect.height()); |
| 133 | 131 |
| 134 // Now see if some pixels weren't copied due to alignment. | 132 // Now see if some pixels weren't copied due to alignment. |
| 135 if (!dest_rect.equals(inner_rect)) { | 133 if (dest_rect != inner_rect) { |
| 136 webrtc::DesktopRect outer_rect = | 134 SkIRect outer_rect = |
| 137 webrtc::DesktopRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left()), | 135 SkIRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left()), |
| 138 RoundToTwosMultiple(dest_rect.top()), | 136 RoundToTwosMultiple(dest_rect.top()), |
| 139 dest_rect.right(), dest_rect.bottom()); | 137 dest_rect.right(), |
| 138 dest_rect.bottom()); |
| 140 | 139 |
| 141 webrtc::DesktopVector offset(outer_rect.left() - inner_rect.left(), | 140 SkIPoint offset = SkIPoint::Make(outer_rect.x() - inner_rect.x(), |
| 142 outer_rect.top() - inner_rect.top()); | 141 outer_rect.y() - inner_rect.y()); |
| 143 | 142 |
| 144 // Offset the pointers to point to the top left corner of the outer | 143 // Offset the pointers to point to the top left corner of the outer |
| 145 // rectangle. | 144 // rectangle. |
| 146 y_offset += CalculateYOffset(offset.x(), offset.y(), source_ystride); | 145 y_offset += CalculateYOffset(offset.x(), offset.y(), source_ystride); |
| 147 uv_offset += CalculateUVOffset(offset.x(), offset.y(), source_uvstride); | 146 uv_offset += CalculateUVOffset(offset.x(), offset.y(), source_uvstride); |
| 148 rgb_offset += CalculateRGBOffset(offset.x(), offset.y(), dest_stride); | 147 rgb_offset += CalculateRGBOffset(offset.x(), offset.y(), dest_stride); |
| 149 | 148 |
| 150 // Draw unaligned edges. | 149 // Draw unaligned edges. |
| 151 webrtc::DesktopRegion edges(dest_rect); | 150 SkRegion edges(dest_rect); |
| 152 edges.Subtract(inner_rect); | 151 edges.op(inner_rect, SkRegion::kDifference_Op); |
| 153 for (webrtc::DesktopRegion::Iterator i(edges); !i.IsAtEnd(); | 152 for (SkRegion::Iterator i(edges); !i.done(); i.next()) { |
| 154 i.Advance()) { | 153 SkIRect rect(i.rect()); |
| 155 webrtc::DesktopRect rect = i.rect(); | 154 rect.offset(- outer_rect.left(), - outer_rect.top()); |
| 156 rect.Translate(-outer_rect.left(), -outer_rect.top()); | |
| 157 media::ScaleYUVToRGB32WithRect(source_yplane + y_offset, | 155 media::ScaleYUVToRGB32WithRect(source_yplane + y_offset, |
| 158 source_uplane + uv_offset, | 156 source_uplane + uv_offset, |
| 159 source_vplane + uv_offset, | 157 source_vplane + uv_offset, |
| 160 dest_buffer + rgb_offset, | 158 dest_buffer + rgb_offset, |
| 161 source_size.width(), | 159 source_size.width(), |
| 162 source_size.height(), | 160 source_size.height(), |
| 163 dest_size.width(), | 161 dest_size.width(), |
| 164 dest_size.height(), | 162 dest_size.height(), |
| 165 rect.left(), | 163 rect.left(), |
| 166 rect.top(), | 164 rect.top(), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 187 source_ystride, | 185 source_ystride, |
| 188 source_uvstride, | 186 source_uvstride, |
| 189 dest_stride); | 187 dest_stride); |
| 190 } | 188 } |
| 191 } | 189 } |
| 192 | 190 |
| 193 int RoundToTwosMultiple(int x) { | 191 int RoundToTwosMultiple(int x) { |
| 194 return x & (~1); | 192 return x & (~1); |
| 195 } | 193 } |
| 196 | 194 |
| 197 webrtc::DesktopRect AlignRect(const webrtc::DesktopRect& rect) { | 195 SkIRect AlignRect(const SkIRect& rect) { |
| 198 int x = RoundToTwosMultiple(rect.left()); | 196 int x = RoundToTwosMultiple(rect.left()); |
| 199 int y = RoundToTwosMultiple(rect.top()); | 197 int y = RoundToTwosMultiple(rect.top()); |
| 200 int right = RoundToTwosMultiple(rect.right() + 1); | 198 int right = RoundToTwosMultiple(rect.right() + 1); |
| 201 int bottom = RoundToTwosMultiple(rect.bottom() + 1); | 199 int bottom = RoundToTwosMultiple(rect.bottom() + 1); |
| 202 return webrtc::DesktopRect::MakeLTRB(x, y, right, bottom); | 200 return SkIRect::MakeLTRB(x, y, right, bottom); |
| 203 } | 201 } |
| 204 | 202 |
| 205 webrtc::DesktopRect ScaleRect(const webrtc::DesktopRect& rect, | 203 SkIRect ScaleRect(const SkIRect& rect, |
| 206 const webrtc::DesktopSize& in_size, | 204 const SkISize& in_size, |
| 207 const webrtc::DesktopSize& out_size) { | 205 const SkISize& out_size) { |
| 208 int left = (rect.left() * out_size.width()) / in_size.width(); | 206 int left = (rect.left() * out_size.width()) / in_size.width(); |
| 209 int top = (rect.top() * out_size.height()) / in_size.height(); | 207 int top = (rect.top() * out_size.height()) / in_size.height(); |
| 210 int right = (rect.right() * out_size.width() + in_size.width() - 1) / | 208 int right = (rect.right() * out_size.width() + in_size.width() - 1) / |
| 211 in_size.width(); | 209 in_size.width(); |
| 212 int bottom = (rect.bottom() * out_size.height() + in_size.height() - 1) / | 210 int bottom = (rect.bottom() * out_size.height() + in_size.height() - 1) / |
| 213 in_size.height(); | 211 in_size.height(); |
| 214 return webrtc::DesktopRect::MakeLTRB(left, top, right, bottom); | 212 return SkIRect::MakeLTRB(left, top, right, bottom); |
| 215 } | 213 } |
| 216 | 214 |
| 217 void CopyRGB32Rect(const uint8* source_buffer, | 215 void CopyRGB32Rect(const uint8* source_buffer, |
| 218 int source_stride, | 216 int source_stride, |
| 219 const webrtc::DesktopRect& source_buffer_rect, | 217 const SkIRect& source_buffer_rect, |
| 220 uint8* dest_buffer, | 218 uint8* dest_buffer, |
| 221 int dest_stride, | 219 int dest_stride, |
| 222 const webrtc::DesktopRect& dest_buffer_rect, | 220 const SkIRect& dest_buffer_rect, |
| 223 const webrtc::DesktopRect& dest_rect) { | 221 const SkIRect& dest_rect) { |
| 224 DCHECK(DoesRectContain(dest_buffer_rect, dest_rect)); | 222 DCHECK(dest_buffer_rect.contains(dest_rect)); |
| 225 DCHECK(DoesRectContain(source_buffer_rect, dest_rect)); | 223 DCHECK(source_buffer_rect.contains(dest_rect)); |
| 226 | 224 |
| 227 // Get the address of the starting point. | 225 // Get the address of the starting point. |
| 228 source_buffer += CalculateRGBOffset( | 226 source_buffer += CalculateRGBOffset(dest_rect.x() - source_buffer_rect.x(), |
| 229 dest_rect.left() - source_buffer_rect.left(), | 227 dest_rect.y() - source_buffer_rect.y(), |
| 230 dest_rect.top() - source_buffer_rect.top(), | 228 source_stride); |
| 231 source_stride); | 229 dest_buffer += CalculateRGBOffset(dest_rect.x() - dest_buffer_rect.x(), |
| 232 dest_buffer += CalculateRGBOffset( | 230 dest_rect.y() - dest_buffer_rect.y(), |
| 233 dest_rect.left() - dest_buffer_rect.left(), | 231 source_stride); |
| 234 dest_rect.top() - dest_buffer_rect.top(), | |
| 235 source_stride); | |
| 236 | 232 |
| 237 // Copy pixels in the rectangle line by line. | 233 // Copy pixels in the rectangle line by line. |
| 238 const int bytes_per_line = kBytesPerPixelRGB32 * dest_rect.width(); | 234 const int bytes_per_line = kBytesPerPixelRGB32 * dest_rect.width(); |
| 239 for (int i = 0 ; i < dest_rect.height(); ++i) { | 235 for (int i = 0 ; i < dest_rect.height(); ++i) { |
| 240 memcpy(dest_buffer, source_buffer, bytes_per_line); | 236 memcpy(dest_buffer, source_buffer, bytes_per_line); |
| 241 source_buffer += source_stride; | 237 source_buffer += source_stride; |
| 242 dest_buffer += dest_stride; | 238 dest_buffer += dest_stride; |
| 243 } | 239 } |
| 244 } | 240 } |
| 245 | 241 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 scoped_ptr<char[]> buf(new char[buf_size]); | 321 scoped_ptr<char[]> buf(new char[buf_size]); |
| 326 struct passwd passwd; | 322 struct passwd passwd; |
| 327 struct passwd* passwd_result = NULL; | 323 struct passwd* passwd_result = NULL; |
| 328 getpwuid_r(getuid(), &passwd, buf.get(), buf_size, &passwd_result); | 324 getpwuid_r(getuid(), &passwd, buf.get(), buf_size, &passwd_result); |
| 329 return passwd_result ? passwd_result->pw_name : std::string(); | 325 return passwd_result ? passwd_result->pw_name : std::string(); |
| 330 #else // !defined(OS_POSIX) | 326 #else // !defined(OS_POSIX) |
| 331 return std::string(); | 327 return std::string(); |
| 332 #endif // defined(OS_POSIX) | 328 #endif // defined(OS_POSIX) |
| 333 } | 329 } |
| 334 | 330 |
| 335 bool DoesRectContain(const webrtc::DesktopRect& a, | |
| 336 const webrtc::DesktopRect& b) { | |
| 337 webrtc::DesktopRect intersection(a); | |
| 338 intersection.IntersectWith(b); | |
| 339 return intersection.equals(b); | |
| 340 } | |
| 341 | |
| 342 } // namespace remoting | 331 } // namespace remoting |
| OLD | NEW |