| Index: remoting/base/util.cc
|
| diff --git a/remoting/base/util.cc b/remoting/base/util.cc
|
| index 486b6a3510e6f42efa1680d449d7363628aa4b14..30691ea065531f9300883092de8dc55d5316b65b 100644
|
| --- a/remoting/base/util.cc
|
| +++ b/remoting/base/util.cc
|
| @@ -11,6 +11,7 @@
|
| #include "base/time.h"
|
| #include "media/base/video_frame.h"
|
| #include "media/base/yuv_convert.h"
|
| +#include "third_party/skia/include/core/SkRegion.h"
|
|
|
| using media::VideoFrame;
|
|
|
| @@ -48,38 +49,15 @@ static int CalculateRGBOffset(int x, int y, int stride) {
|
| }
|
|
|
| static int CalculateYOffset(int x, int y, int stride) {
|
| + DCHECK(((x & 1) == 0) && ((y & 1) == 0));
|
| return stride * y + x;
|
| }
|
|
|
| static int CalculateUVOffset(int x, int y, int stride) {
|
| + DCHECK(((x & 1) == 0) && ((y & 1) == 0));
|
| return stride * y / 2 + x / 2;
|
| }
|
|
|
| -void ConvertYUVToRGB32WithRect(const uint8* y_plane,
|
| - const uint8* u_plane,
|
| - const uint8* v_plane,
|
| - uint8* rgb_plane,
|
| - const SkIRect& rect,
|
| - int y_stride,
|
| - int uv_stride,
|
| - int rgb_stride) {
|
| - DCHECK((rect.x() & 1) == 0 && (rect.y() & 1) == 0);
|
| - int rgb_offset = CalculateRGBOffset(rect.left(), rect.top(), rgb_stride);
|
| - int y_offset = CalculateYOffset(rect.left(), rect.top(), y_stride);
|
| - int uv_offset = CalculateUVOffset(rect.left(), rect.top(), uv_stride);
|
| -
|
| - media::ConvertYUVToRGB32(y_plane + y_offset,
|
| - u_plane + uv_offset,
|
| - v_plane + uv_offset,
|
| - rgb_plane + rgb_offset,
|
| - rect.width(),
|
| - rect.height(),
|
| - y_stride,
|
| - uv_stride,
|
| - rgb_stride,
|
| - media::YV12);
|
| -}
|
| -
|
| void ConvertRGB32ToYUVWithRect(const uint8* rgb_plane,
|
| uint8* y_plane,
|
| uint8* u_plane,
|
| @@ -106,6 +84,126 @@ void ConvertRGB32ToYUVWithRect(const uint8* rgb_plane,
|
| uv_stride);
|
| }
|
|
|
| +void ConvertAndScaleYUVToRGB32Rect(const uint8* source_yplane,
|
| + const uint8* source_uplane,
|
| + const uint8* source_vplane,
|
| + int source_ystride,
|
| + int source_uvstride,
|
| + const SkISize& source_size,
|
| + const SkIRect& source_buffer_rect,
|
| + uint8* dest_buffer,
|
| + int dest_stride,
|
| + const SkISize& dest_size,
|
| + const SkIRect& dest_buffer_rect,
|
| + const SkIRect& dest_rect) {
|
| + // N.B. It is caller's responsibility to check if strides are large enough. We
|
| + // cannot do it here anyway.
|
| + DCHECK(SkIRect::MakeSize(source_size).contains(source_buffer_rect));
|
| + DCHECK(SkIRect::MakeSize(dest_size).contains(dest_buffer_rect));
|
| + DCHECK(dest_buffer_rect.contains(dest_rect));
|
| + DCHECK(ScaleRect(source_buffer_rect, source_size, dest_size).
|
| + contains(dest_rect));
|
| +
|
| + // If the source and/or destination buffers don't start at (0, 0)
|
| + // offset the pointers to pretend we have complete buffers.
|
| + int y_offset = - CalculateYOffset(source_buffer_rect.x(),
|
| + source_buffer_rect.y(),
|
| + source_ystride);
|
| + int uv_offset = - CalculateUVOffset(source_buffer_rect.x(),
|
| + source_buffer_rect.y(),
|
| + source_uvstride);
|
| + int rgb_offset = - CalculateRGBOffset(dest_buffer_rect.x(),
|
| + dest_buffer_rect.y(),
|
| + dest_stride);
|
| +
|
| + // See if scaling is needed.
|
| + if (source_size == dest_size) {
|
| + // Calculate the inner rectangle that can be copied by the optimized
|
| + // ConvertYUVToRGB32().
|
| + SkIRect inner_rect =
|
| + SkIRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left() + 1),
|
| + RoundToTwosMultiple(dest_rect.top() + 1),
|
| + dest_rect.right(),
|
| + dest_rect.bottom());
|
| +
|
| + // Offset pointers to point to the top left corner of the inner rectangle.
|
| + y_offset += CalculateYOffset(inner_rect.x(), inner_rect.y(),
|
| + source_ystride);
|
| + uv_offset += CalculateUVOffset(inner_rect.x(), inner_rect.y(),
|
| + source_uvstride);
|
| + rgb_offset += CalculateRGBOffset(inner_rect.x(), inner_rect.y(),
|
| + dest_stride);
|
| +
|
| + media::ConvertYUVToRGB32(source_yplane + y_offset,
|
| + source_uplane + uv_offset,
|
| + source_vplane + uv_offset,
|
| + dest_buffer + rgb_offset,
|
| + inner_rect.width(),
|
| + inner_rect.height(),
|
| + source_ystride,
|
| + source_uvstride,
|
| + dest_stride,
|
| + media::YV12);
|
| +
|
| + // Now see if some pixels weren't copied due to alignment.
|
| + if (dest_rect != inner_rect) {
|
| + SkIRect outer_rect =
|
| + SkIRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left()),
|
| + RoundToTwosMultiple(dest_rect.top()),
|
| + dest_rect.right(),
|
| + dest_rect.bottom());
|
| +
|
| + SkIPoint offset = SkIPoint::Make(outer_rect.x() - inner_rect.x(),
|
| + outer_rect.y() - inner_rect.y());
|
| +
|
| + // Offset the pointers to point to the top left corner of the outer
|
| + // rectangle.
|
| + y_offset += CalculateYOffset(offset.x(), offset.y(), source_ystride);
|
| + uv_offset += CalculateUVOffset(offset.x(), offset.y(), source_uvstride);
|
| + rgb_offset += CalculateRGBOffset(offset.x(), offset.y(), dest_stride);
|
| +
|
| + // Draw unaligned edges.
|
| + SkRegion edges(dest_rect);
|
| + edges.op(inner_rect, SkRegion::kDifference_Op);
|
| + for (SkRegion::Iterator i(edges); !i.done(); i.next()) {
|
| + SkIRect rect(i.rect());
|
| + rect.offset(- outer_rect.left(), - outer_rect.top());
|
| + media::ScaleYUVToRGB32WithRect(source_yplane + y_offset,
|
| + source_uplane + uv_offset,
|
| + source_vplane + uv_offset,
|
| + dest_buffer + rgb_offset,
|
| + source_size.width(),
|
| + source_size.height(),
|
| + dest_size.width(),
|
| + dest_size.height(),
|
| + rect.left(),
|
| + rect.top(),
|
| + rect.right(),
|
| + rect.bottom(),
|
| + source_ystride,
|
| + source_uvstride,
|
| + dest_stride);
|
| + }
|
| + }
|
| + } else {
|
| + media::ScaleYUVToRGB32WithRect(source_yplane + y_offset,
|
| + source_uplane + uv_offset,
|
| + source_vplane + uv_offset,
|
| + dest_buffer + rgb_offset,
|
| + source_size.width(),
|
| + source_size.height(),
|
| + dest_size.width(),
|
| + dest_size.height(),
|
| + dest_rect.left(),
|
| + dest_rect.top(),
|
| + dest_rect.right(),
|
| + dest_rect.bottom(),
|
| + source_ystride,
|
| + source_uvstride,
|
| + dest_stride);
|
| + }
|
| +}
|
| +
|
| int RoundToTwosMultiple(int x) {
|
| return x & (~1);
|
| }
|
| @@ -153,4 +251,31 @@ void CopyRect(const uint8* src_plane,
|
| }
|
| }
|
|
|
| +void CopyRGB32Rect(const uint8* source_buffer,
|
| + int source_stride,
|
| + const SkIRect& source_buffer_rect,
|
| + uint8* dest_buffer,
|
| + int dest_stride,
|
| + const SkIRect& dest_buffer_rect,
|
| + const SkIRect& dest_rect) {
|
| + DCHECK(dest_buffer_rect.contains(dest_rect));
|
| + DCHECK(source_buffer_rect.contains(dest_rect));
|
| +
|
| + // Get the address of the starting point.
|
| + int source_offset = CalculateRGBOffset(dest_rect.x() - source_buffer_rect.x(),
|
| + dest_rect.y() - source_buffer_rect.y(),
|
| + source_stride);
|
| + int dest_offset = CalculateRGBOffset(dest_rect.x() - dest_buffer_rect.x(),
|
| + dest_rect.y() - dest_buffer_rect.y(),
|
| + source_stride);
|
| +
|
| + // Copy bits.
|
| + CopyRect(source_buffer + source_offset,
|
| + source_stride,
|
| + dest_buffer + dest_offset,
|
| + dest_stride,
|
| + GetBytesPerPixel(media::VideoFrame::RGB32),
|
| + SkIRect::MakeWH(dest_rect.width(), dest_rect.height()));
|
| +}
|
| +
|
| } // namespace remoting
|
|
|