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" |
11 #include "base/time.h" | 11 #include "base/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/skia/include/core/SkRegion.h" |
14 | 15 |
15 using media::VideoFrame; | 16 using media::VideoFrame; |
16 | 17 |
17 namespace remoting { | 18 namespace remoting { |
18 | 19 |
19 // Do not write LOG messages in this routine since it is called from within | 20 // Do not write LOG messages in this routine since it is called from within |
20 // our LOG message handler. Bad things will happen. | 21 // our LOG message handler. Bad things will happen. |
21 std::string GetTimestampString() { | 22 std::string GetTimestampString() { |
22 base::Time t = base::Time::NowFromSystemTime(); | 23 base::Time t = base::Time::NowFromSystemTime(); |
23 base::Time::Exploded tex; | 24 base::Time::Exploded tex; |
(...skipping 17 matching lines...) Expand all Loading... |
41 return 0; | 42 return 0; |
42 } | 43 } |
43 } | 44 } |
44 | 45 |
45 // Helper methods to calculate plane offset given the coordinates. | 46 // Helper methods to calculate plane offset given the coordinates. |
46 static int CalculateRGBOffset(int x, int y, int stride) { | 47 static int CalculateRGBOffset(int x, int y, int stride) { |
47 return stride * y + GetBytesPerPixel(media::VideoFrame::RGB32) * x; | 48 return stride * y + GetBytesPerPixel(media::VideoFrame::RGB32) * x; |
48 } | 49 } |
49 | 50 |
50 static int CalculateYOffset(int x, int y, int stride) { | 51 static int CalculateYOffset(int x, int y, int stride) { |
| 52 DCHECK(((x & 1) == 0) && ((y & 1) == 0)); |
51 return stride * y + x; | 53 return stride * y + x; |
52 } | 54 } |
53 | 55 |
54 static int CalculateUVOffset(int x, int y, int stride) { | 56 static int CalculateUVOffset(int x, int y, int stride) { |
| 57 DCHECK(((x & 1) == 0) && ((y & 1) == 0)); |
55 return stride * y / 2 + x / 2; | 58 return stride * y / 2 + x / 2; |
56 } | 59 } |
57 | 60 |
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, | 61 void ConvertRGB32ToYUVWithRect(const uint8* rgb_plane, |
84 uint8* y_plane, | 62 uint8* y_plane, |
85 uint8* u_plane, | 63 uint8* u_plane, |
86 uint8* v_plane, | 64 uint8* v_plane, |
87 int x, | 65 int x, |
88 int y, | 66 int y, |
89 int width, | 67 int width, |
90 int height, | 68 int height, |
91 int rgb_stride, | 69 int rgb_stride, |
92 int y_stride, | 70 int y_stride, |
93 int uv_stride) { | 71 int uv_stride) { |
94 int rgb_offset = CalculateRGBOffset(x, y, rgb_stride); | 72 int rgb_offset = CalculateRGBOffset(x, y, rgb_stride); |
95 int y_offset = CalculateYOffset(x, y, y_stride); | 73 int y_offset = CalculateYOffset(x, y, y_stride); |
96 int uv_offset = CalculateUVOffset(x, y, uv_stride);; | 74 int uv_offset = CalculateUVOffset(x, y, uv_stride);; |
97 | 75 |
98 media::ConvertRGB32ToYUV(rgb_plane + rgb_offset, | 76 media::ConvertRGB32ToYUV(rgb_plane + rgb_offset, |
99 y_plane + y_offset, | 77 y_plane + y_offset, |
100 u_plane + uv_offset, | 78 u_plane + uv_offset, |
101 v_plane + uv_offset, | 79 v_plane + uv_offset, |
102 width, | 80 width, |
103 height, | 81 height, |
104 rgb_stride, | 82 rgb_stride, |
105 y_stride, | 83 y_stride, |
106 uv_stride); | 84 uv_stride); |
107 } | 85 } |
108 | 86 |
| 87 void ConvertAndScaleYUVToRGB32Rect(const uint8* source_yplane, |
| 88 const uint8* source_uplane, |
| 89 const uint8* source_vplane, |
| 90 int source_ystride, |
| 91 int source_uvstride, |
| 92 const SkISize& source_size, |
| 93 const SkIRect& source_buffer_rect, |
| 94 uint8* dest_buffer, |
| 95 int dest_stride, |
| 96 const SkISize& dest_size, |
| 97 const SkIRect& dest_buffer_rect, |
| 98 const SkIRect& dest_rect) { |
| 99 // N.B. It is caller's responsibility to check if strides are large enough. We |
| 100 // cannot do it here anyway. |
| 101 DCHECK(SkIRect::MakeSize(source_size).contains(source_buffer_rect)); |
| 102 DCHECK(SkIRect::MakeSize(dest_size).contains(dest_buffer_rect)); |
| 103 DCHECK(dest_buffer_rect.contains(dest_rect)); |
| 104 DCHECK(ScaleRect(source_buffer_rect, source_size, dest_size). |
| 105 contains(dest_rect)); |
| 106 |
| 107 // If the source and/or destination buffers don't start at (0, 0) |
| 108 // offset the pointers to pretend we have complete buffers. |
| 109 int y_offset = - CalculateYOffset(source_buffer_rect.x(), |
| 110 source_buffer_rect.y(), |
| 111 source_ystride); |
| 112 int uv_offset = - CalculateUVOffset(source_buffer_rect.x(), |
| 113 source_buffer_rect.y(), |
| 114 source_uvstride); |
| 115 int rgb_offset = - CalculateRGBOffset(dest_buffer_rect.x(), |
| 116 dest_buffer_rect.y(), |
| 117 dest_stride); |
| 118 |
| 119 // See if scaling is needed. |
| 120 if (source_size == dest_size) { |
| 121 // Calculate the inner rectangle that can be copied by the optimized |
| 122 // ConvertYUVToRGB32(). |
| 123 SkIRect inner_rect = |
| 124 SkIRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left() + 1), |
| 125 RoundToTwosMultiple(dest_rect.top() + 1), |
| 126 dest_rect.right(), |
| 127 dest_rect.bottom()); |
| 128 |
| 129 // Offset pointers to point to the top left corner of the inner rectangle. |
| 130 y_offset += CalculateYOffset(inner_rect.x(), inner_rect.y(), |
| 131 source_ystride); |
| 132 uv_offset += CalculateUVOffset(inner_rect.x(), inner_rect.y(), |
| 133 source_uvstride); |
| 134 rgb_offset += CalculateRGBOffset(inner_rect.x(), inner_rect.y(), |
| 135 dest_stride); |
| 136 |
| 137 media::ConvertYUVToRGB32(source_yplane + y_offset, |
| 138 source_uplane + uv_offset, |
| 139 source_vplane + uv_offset, |
| 140 dest_buffer + rgb_offset, |
| 141 inner_rect.width(), |
| 142 inner_rect.height(), |
| 143 source_ystride, |
| 144 source_uvstride, |
| 145 dest_stride, |
| 146 media::YV12); |
| 147 |
| 148 // Now see if some pixels weren't copied due to alignment. |
| 149 if (dest_rect != inner_rect) { |
| 150 SkIRect outer_rect = |
| 151 SkIRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left()), |
| 152 RoundToTwosMultiple(dest_rect.top()), |
| 153 dest_rect.right(), |
| 154 dest_rect.bottom()); |
| 155 |
| 156 SkIPoint offset = SkIPoint::Make(outer_rect.x() - inner_rect.x(), |
| 157 outer_rect.y() - inner_rect.y()); |
| 158 |
| 159 // Offset the pointers to point to the top left corner of the outer |
| 160 // rectangle. |
| 161 y_offset += CalculateYOffset(offset.x(), offset.y(), source_ystride); |
| 162 uv_offset += CalculateUVOffset(offset.x(), offset.y(), source_uvstride); |
| 163 rgb_offset += CalculateRGBOffset(offset.x(), offset.y(), dest_stride); |
| 164 |
| 165 // Draw unaligned edges. |
| 166 SkRegion edges(dest_rect); |
| 167 edges.op(inner_rect, SkRegion::kDifference_Op); |
| 168 for (SkRegion::Iterator i(edges); !i.done(); i.next()) { |
| 169 SkIRect rect(i.rect()); |
| 170 rect.offset(- outer_rect.left(), - outer_rect.top()); |
| 171 media::ScaleYUVToRGB32WithRect(source_yplane + y_offset, |
| 172 source_uplane + uv_offset, |
| 173 source_vplane + uv_offset, |
| 174 dest_buffer + rgb_offset, |
| 175 source_size.width(), |
| 176 source_size.height(), |
| 177 dest_size.width(), |
| 178 dest_size.height(), |
| 179 rect.left(), |
| 180 rect.top(), |
| 181 rect.right(), |
| 182 rect.bottom(), |
| 183 source_ystride, |
| 184 source_uvstride, |
| 185 dest_stride); |
| 186 } |
| 187 } |
| 188 } else { |
| 189 media::ScaleYUVToRGB32WithRect(source_yplane + y_offset, |
| 190 source_uplane + uv_offset, |
| 191 source_vplane + uv_offset, |
| 192 dest_buffer + rgb_offset, |
| 193 source_size.width(), |
| 194 source_size.height(), |
| 195 dest_size.width(), |
| 196 dest_size.height(), |
| 197 dest_rect.left(), |
| 198 dest_rect.top(), |
| 199 dest_rect.right(), |
| 200 dest_rect.bottom(), |
| 201 source_ystride, |
| 202 source_uvstride, |
| 203 dest_stride); |
| 204 } |
| 205 } |
| 206 |
109 int RoundToTwosMultiple(int x) { | 207 int RoundToTwosMultiple(int x) { |
110 return x & (~1); | 208 return x & (~1); |
111 } | 209 } |
112 | 210 |
113 SkIRect AlignRect(const SkIRect& rect) { | 211 SkIRect AlignRect(const SkIRect& rect) { |
114 int x = RoundToTwosMultiple(rect.left()); | 212 int x = RoundToTwosMultiple(rect.left()); |
115 int y = RoundToTwosMultiple(rect.top()); | 213 int y = RoundToTwosMultiple(rect.top()); |
116 int right = RoundToTwosMultiple(rect.right() + 1); | 214 int right = RoundToTwosMultiple(rect.right() + 1); |
117 int bottom = RoundToTwosMultiple(rect.bottom() + 1); | 215 int bottom = RoundToTwosMultiple(rect.bottom() + 1); |
118 return SkIRect::MakeLTRB(x, y, right, bottom); | 216 return SkIRect::MakeLTRB(x, y, right, bottom); |
(...skipping 27 matching lines...) Expand all Loading... |
146 // Copy pixels in the rectangle line by line. | 244 // Copy pixels in the rectangle line by line. |
147 const int bytes_per_line = bytes_per_pixel * rect.width(); | 245 const int bytes_per_line = bytes_per_pixel * rect.width(); |
148 const int height = rect.height(); | 246 const int height = rect.height(); |
149 for (int i = 0 ; i < height; ++i) { | 247 for (int i = 0 ; i < height; ++i) { |
150 memcpy(dest_plane, src_plane, bytes_per_line); | 248 memcpy(dest_plane, src_plane, bytes_per_line); |
151 src_plane += src_plane_stride; | 249 src_plane += src_plane_stride; |
152 dest_plane += dest_plane_stride; | 250 dest_plane += dest_plane_stride; |
153 } | 251 } |
154 } | 252 } |
155 | 253 |
| 254 void CopyRGB32Rect(const uint8* source_buffer, |
| 255 int source_stride, |
| 256 const SkIRect& source_buffer_rect, |
| 257 uint8* dest_buffer, |
| 258 int dest_stride, |
| 259 const SkIRect& dest_buffer_rect, |
| 260 const SkIRect& dest_rect) { |
| 261 DCHECK(dest_buffer_rect.contains(dest_rect)); |
| 262 DCHECK(source_buffer_rect.contains(dest_rect)); |
| 263 |
| 264 // Get the address of the starting point. |
| 265 int source_offset = CalculateRGBOffset(dest_rect.x() - source_buffer_rect.x(), |
| 266 dest_rect.y() - source_buffer_rect.y(), |
| 267 source_stride); |
| 268 int dest_offset = CalculateRGBOffset(dest_rect.x() - dest_buffer_rect.x(), |
| 269 dest_rect.y() - dest_buffer_rect.y(), |
| 270 source_stride); |
| 271 |
| 272 // Copy bits. |
| 273 CopyRect(source_buffer + source_offset, |
| 274 source_stride, |
| 275 dest_buffer + dest_offset, |
| 276 dest_stride, |
| 277 GetBytesPerPixel(media::VideoFrame::RGB32), |
| 278 SkIRect::MakeWH(dest_rect.width(), dest_rect.height())); |
| 279 } |
| 280 |
156 } // namespace remoting | 281 } // namespace remoting |
OLD | NEW |