15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/util.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_frame.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/yuv_convert.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/libyuv/include/libyuv/convert.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkRegion.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_POSIX) 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <pwd.h> 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <sys/types.h> 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <unistd.h> 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // defined(OS_POSIX) 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::VideoFrame; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum { kBytesPerPixelRGB32 = 4 }; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Do not write LOG messages in this routine since it is called from within 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// our LOG message handler. Bad things will happen. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetTimestampString() { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time t = base::Time::NowFromSystemTime(); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time::Exploded tex; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t.LocalExplode(&tex); 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::StringPrintf("%02d%02d/%02d%02d%02d:", 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tex.month, tex.day_of_month, 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tex.hour, tex.minute, tex.second); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CalculateRGBOffset(int x, int y, int stride) { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stride * y + kBytesPerPixelRGB32 * x; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CalculateYOffset(int x, int y, int stride) { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(((x & 1) == 0) && ((y & 1) == 0)); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stride * y + x; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CalculateUVOffset(int x, int y, int stride) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(((x & 1) == 0) && ((y & 1) == 0)); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stride * y / 2 + x / 2; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConvertRGB32ToYUVWithRect(const uint8* rgb_plane, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* y_plane, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* u_plane, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* v_plane, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int height, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rgb_stride, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y_stride, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int uv_stride) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rgb_offset = CalculateRGBOffset(x, y, rgb_stride); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y_offset = CalculateYOffset(x, y, y_stride); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int uv_offset = CalculateUVOffset(x, y, uv_stride);; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) libyuv::ARGBToI420(rgb_plane + rgb_offset, rgb_stride, 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) y_plane + y_offset, y_stride, 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) u_plane + uv_offset, uv_stride, 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) v_plane + uv_offset, uv_stride, 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) width, height); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConvertAndScaleYUVToRGB32Rect(const uint8* source_yplane, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* source_uplane, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* source_vplane, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int source_ystride, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int source_uvstride, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkISize& source_size, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkIRect& source_buffer_rect, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* dest_buffer, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dest_stride, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkISize& dest_size, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkIRect& dest_buffer_rect, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkIRect& dest_rect) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // N.B. It is caller's responsibility to check if strides are large enough. We 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cannot do it here anyway. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(SkIRect::MakeSize(source_size).contains(source_buffer_rect)); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(SkIRect::MakeSize(dest_size).contains(dest_buffer_rect)); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(dest_buffer_rect.contains(dest_rect)); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ScaleRect(source_buffer_rect, source_size, dest_size). 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contains(dest_rect)); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the source and/or destination buffers don't start at (0, 0) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // offset the pointers to pretend we have complete buffers. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y_offset = - CalculateYOffset(source_buffer_rect.x(), 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_buffer_rect.y(), 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_ystride); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int uv_offset = - CalculateUVOffset(source_buffer_rect.x(), 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_buffer_rect.y(), 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_uvstride); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rgb_offset = - CalculateRGBOffset(dest_buffer_rect.x(), 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_buffer_rect.y(), 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_stride); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if scaling is needed. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source_size == dest_size) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calculate the inner rectangle that can be copied by the optimized 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // libyuv::I420ToARGB(). 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkIRect inner_rect = 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkIRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left() + 1), 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RoundToTwosMultiple(dest_rect.top() + 1), 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_rect.right(), 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_rect.bottom()); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Offset pointers to point to the top left corner of the inner rectangle. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y_offset += CalculateYOffset(inner_rect.x(), inner_rect.y(), 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_ystride); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uv_offset += CalculateUVOffset(inner_rect.x(), inner_rect.y(), 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_uvstride); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rgb_offset += CalculateRGBOffset(inner_rect.x(), inner_rect.y(), 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_stride); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) libyuv::I420ToARGB(source_yplane + y_offset, source_ystride, 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) source_uplane + uv_offset, source_uvstride, 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) source_vplane + uv_offset, source_uvstride, 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dest_buffer + rgb_offset, dest_stride, 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inner_rect.width(), inner_rect.height()); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now see if some pixels weren't copied due to alignment. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dest_rect != inner_rect) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkIRect outer_rect = 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkIRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left()), 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RoundToTwosMultiple(dest_rect.top()), 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_rect.right(), 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_rect.bottom()); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkIPoint offset = SkIPoint::Make(outer_rect.x() - inner_rect.x(), 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outer_rect.y() - inner_rect.y()); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Offset the pointers to point to the top left corner of the outer 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rectangle. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y_offset += CalculateYOffset(offset.x(), offset.y(), source_ystride); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uv_offset += CalculateUVOffset(offset.x(), offset.y(), source_uvstride); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rgb_offset += CalculateRGBOffset(offset.x(), offset.y(), dest_stride); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw unaligned edges. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkRegion edges(dest_rect); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) edges.op(inner_rect, SkRegion::kDifference_Op); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SkRegion::Iterator i(edges); !i.done(); i.next()) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkIRect rect(i.rect()); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.offset(- outer_rect.left(), - outer_rect.top()); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::ScaleYUVToRGB32WithRect(source_yplane + y_offset, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_uplane + uv_offset, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_vplane + uv_offset, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_buffer + rgb_offset, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_size.width(), 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_size.height(), 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_size.width(), 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_size.height(), 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.left(), 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.top(), 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.right(), 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.bottom(), 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_ystride, 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_uvstride, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_stride); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::ScaleYUVToRGB32WithRect(source_yplane + y_offset, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_uplane + uv_offset, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_vplane + uv_offset, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_buffer + rgb_offset, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_size.width(), 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_size.height(), 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_size.width(), 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_size.height(), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_rect.left(), 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_rect.top(), 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_rect.right(), 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_rect.bottom(), 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_ystride, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_uvstride, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_stride); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int RoundToTwosMultiple(int x) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return x & (~1); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkIRect AlignRect(const SkIRect& rect) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = RoundToTwosMultiple(rect.left()); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y = RoundToTwosMultiple(rect.top()); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int right = RoundToTwosMultiple(rect.right() + 1); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bottom = RoundToTwosMultiple(rect.bottom() + 1); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkIRect::MakeLTRB(x, y, right, bottom); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkIRect ScaleRect(const SkIRect& rect, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkISize& in_size, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkISize& out_size) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int left = (rect.left() * out_size.width()) / in_size.width(); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int top = (rect.top() * out_size.height()) / in_size.height(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int right = (rect.right() * out_size.width() + in_size.width() - 1) / 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_size.width(); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bottom = (rect.bottom() * out_size.height() + in_size.height() - 1) / 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_size.height(); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkIRect::MakeLTRB(left, top, right, bottom); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyRGB32Rect(const uint8* source_buffer, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int source_stride, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkIRect& source_buffer_rect, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* dest_buffer, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dest_stride, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkIRect& dest_buffer_rect, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkIRect& dest_rect) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(dest_buffer_rect.contains(dest_rect)); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(source_buffer_rect.contains(dest_rect)); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the address of the starting point. 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_buffer += CalculateRGBOffset(dest_rect.x() - source_buffer_rect.x(), 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dest_rect.y() - source_buffer_rect.y(), 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_stride); 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dest_buffer += CalculateRGBOffset(dest_rect.x() - dest_buffer_rect.x(), 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dest_rect.y() - dest_buffer_rect.y(), 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_stride); 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy pixels in the rectangle line by line. 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int bytes_per_line = kBytesPerPixelRGB32 * dest_rect.width(); 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0 ; i < dest_rect.height(); ++i) { 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(dest_buffer, source_buffer, bytes_per_line); 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_buffer += source_stride; 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dest_buffer += dest_stride; 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReplaceLfByCrLf(const std::string& in) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string out; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.resize(2 * in.size()); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* out_p_begin = &out[0]; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* out_p = out_p_begin; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* in_p_begin = &in[0]; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* in_p_end = &in[in.size()]; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (const char* in_p = in_p_begin; in_p < in_p_end; ++in_p) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char c = *in_p; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (c == '\n') { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out_p++ = '\r'; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out_p++ = c; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.resize(out_p - out_p_begin); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return out; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReplaceCrLfByLf(const std::string& in) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string out; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.resize(in.size()); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* out_p_begin = &out[0]; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* out_p = out_p_begin; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* in_p_begin = &in[0]; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* in_p_end = &in[in.size()]; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (const char* in_p = in_p_begin; in_p < in_p_end; ++in_p) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char c = *in_p; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((c == '\r') && (in_p + 1 < in_p_end) && (*(in_p + 1) == '\n')) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out_p++ = '\n'; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++in_p; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out_p++ = c; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.resize(out_p - out_p_begin); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return out; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool StringIsUtf8(const char* data, size_t length) { 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* ptr = data; 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* ptr_end = data + length; 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (ptr != ptr_end) { 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*ptr & 0x80) == 0) { 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Single-byte symbol. 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++ptr; 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if ((*ptr & 0xc0) == 0x80 || (*ptr & 0xfe) == 0xfe) { 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Invalid first byte. 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // First byte of a multi-byte symbol. The bits from 2 to 6 are the count 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // of continuation bytes (up to 5 of them). 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (char first = *ptr << 1; first & 0x80; first <<= 1) { 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++ptr; 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Missing continuation byte. 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ptr == ptr_end) 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Invalid continuation byte. 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*ptr & 0xc0) != 0x80) 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++ptr; 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string GetUsername() { 3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if defined(OS_ANDROID) 3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch struct passwd* passwd = getpwuid(getuid()); 3157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return passwd ? passwd->pw_name : std::string(); 3167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#elif defined(OS_POSIX) 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) long buf_size = sysconf(_SC_GETPW_R_SIZE_MAX); 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (buf_size <= 0) 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 3207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<char[]> buf(new char[buf_size]); 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct passwd passwd; 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct passwd* passwd_result = NULL; 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) getpwuid_r(getuid(), &passwd, buf.get(), buf_size, &passwd_result); 3257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return passwd_result ? passwd_result->pw_name : std::string(); 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else // !defined(OS_POSIX) 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // defined(OS_POSIX) 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 332