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" 15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/desktop_region.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::VideoFrame; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum { kBytesPerPixelRGB32 = 4 }; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Do not write LOG messages in this routine since it is called from within 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// our LOG message handler. Bad things will happen. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetTimestampString() { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time t = base::Time::NowFromSystemTime(); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time::Exploded tex; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t.LocalExplode(&tex); 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::StringPrintf("%02d%02d/%02d%02d%02d:", 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tex.month, tex.day_of_month, 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tex.hour, tex.minute, tex.second); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CalculateRGBOffset(int x, int y, int stride) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stride * y + kBytesPerPixelRGB32 * x; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CalculateYOffset(int x, int y, int stride) { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(((x & 1) == 0) && ((y & 1) == 0)); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stride * y + x; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CalculateUVOffset(int x, int y, int stride) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(((x & 1) == 0) && ((y & 1) == 0)); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stride * y / 2 + x / 2; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ConvertAndScaleYUVToRGB32Rect( 49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const uint8* source_yplane, 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const uint8* source_uplane, 51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const uint8* source_vplane, 52d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int source_ystride, 53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int source_uvstride, 54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopSize& source_size, 55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRect& source_buffer_rect, 56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uint8* dest_buffer, 57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int dest_stride, 58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopSize& dest_size, 59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRect& dest_buffer_rect, 60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRect& dest_rect) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // N.B. It is caller's responsibility to check if strides are large enough. We 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cannot do it here anyway. 63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(DoesRectContain(webrtc::DesktopRect::MakeSize(source_size), 64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) source_buffer_rect)); 65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(DoesRectContain(webrtc::DesktopRect::MakeSize(dest_size), 66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest_buffer_rect)); 67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(DoesRectContain(dest_buffer_rect, dest_rect)); 68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(DoesRectContain(ScaleRect(source_buffer_rect, source_size, dest_size), 69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest_rect)); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the source and/or destination buffers don't start at (0, 0) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // offset the pointers to pretend we have complete buffers. 73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int y_offset = - CalculateYOffset(source_buffer_rect.left(), 74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) source_buffer_rect.top(), 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_ystride); 76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int uv_offset = - CalculateUVOffset(source_buffer_rect.left(), 77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) source_buffer_rect.top(), 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_uvstride); 79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int rgb_offset = - CalculateRGBOffset(dest_buffer_rect.left(), 80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest_buffer_rect.top(), 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_stride); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if scaling is needed. 84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (source_size.equals(dest_size)) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calculate the inner rectangle that can be copied by the optimized 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // libyuv::I420ToARGB(). 87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect inner_rect = 88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left() + 1), 89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) RoundToTwosMultiple(dest_rect.top() + 1), 90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest_rect.right(), dest_rect.bottom()); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Offset pointers to point to the top left corner of the inner rectangle. 93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) y_offset += CalculateYOffset(inner_rect.left(), inner_rect.top(), 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_ystride); 95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uv_offset += CalculateUVOffset(inner_rect.left(), inner_rect.top(), 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_uvstride); 97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rgb_offset += CalculateRGBOffset(inner_rect.left(), inner_rect.top(), 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_stride); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) libyuv::I420ToARGB(source_yplane + y_offset, source_ystride, 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) source_uplane + uv_offset, source_uvstride, 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) source_vplane + uv_offset, source_uvstride, 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dest_buffer + rgb_offset, dest_stride, 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inner_rect.width(), inner_rect.height()); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now see if some pixels weren't copied due to alignment. 107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!dest_rect.equals(inner_rect)) { 108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect outer_rect = 109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect::MakeLTRB(RoundToTwosMultiple(dest_rect.left()), 110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) RoundToTwosMultiple(dest_rect.top()), 111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest_rect.right(), dest_rect.bottom()); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopVector offset(outer_rect.left() - inner_rect.left(), 114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) outer_rect.top() - inner_rect.top()); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Offset the pointers to point to the top left corner of the outer 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rectangle. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y_offset += CalculateYOffset(offset.x(), offset.y(), source_ystride); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uv_offset += CalculateUVOffset(offset.x(), offset.y(), source_uvstride); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rgb_offset += CalculateRGBOffset(offset.x(), offset.y(), dest_stride); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw unaligned edges. 123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion edges(dest_rect); 124d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) edges.Subtract(inner_rect); 125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (webrtc::DesktopRegion::Iterator i(edges); !i.IsAtEnd(); 126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) i.Advance()) { 127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect rect = i.rect(); 128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rect.Translate(-outer_rect.left(), -outer_rect.top()); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::ScaleYUVToRGB32WithRect(source_yplane + y_offset, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_uplane + uv_offset, 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_vplane + uv_offset, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_buffer + rgb_offset, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_size.width(), 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_size.height(), 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_size.width(), 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_size.height(), 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.left(), 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.top(), 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.right(), 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect.bottom(), 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_ystride, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_uvstride, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_stride); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::ScaleYUVToRGB32WithRect(source_yplane + y_offset, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_uplane + uv_offset, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_vplane + uv_offset, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_buffer + rgb_offset, 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_size.width(), 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_size.height(), 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_size.width(), 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_size.height(), 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_rect.left(), 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_rect.top(), 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_rect.right(), 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_rect.bottom(), 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_ystride, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_uvstride, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_stride); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int RoundToTwosMultiple(int x) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return x & (~1); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 169d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)webrtc::DesktopRect AlignRect(const webrtc::DesktopRect& rect) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = RoundToTwosMultiple(rect.left()); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y = RoundToTwosMultiple(rect.top()); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int right = RoundToTwosMultiple(rect.right() + 1); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bottom = RoundToTwosMultiple(rect.bottom() + 1); 174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return webrtc::DesktopRect::MakeLTRB(x, y, right, bottom); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)webrtc::DesktopRect ScaleRect(const webrtc::DesktopRect& rect, 178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopSize& in_size, 179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopSize& out_size) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int left = (rect.left() * out_size.width()) / in_size.width(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int top = (rect.top() * out_size.height()) / in_size.height(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int right = (rect.right() * out_size.width() + in_size.width() - 1) / 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_size.width(); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bottom = (rect.bottom() * out_size.height() + in_size.height() - 1) / 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_size.height(); 186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return webrtc::DesktopRect::MakeLTRB(left, top, right, bottom); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyRGB32Rect(const uint8* source_buffer, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int source_stride, 191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRect& source_buffer_rect, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* dest_buffer, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dest_stride, 194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRect& dest_buffer_rect, 195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRect& dest_rect) { 196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(DoesRectContain(dest_buffer_rect, dest_rect)); 197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(DoesRectContain(source_buffer_rect, dest_rect)); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the address of the starting point. 200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) source_buffer += CalculateRGBOffset( 201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest_rect.left() - source_buffer_rect.left(), 202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest_rect.top() - source_buffer_rect.top(), 203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) source_stride); 204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest_buffer += CalculateRGBOffset( 205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest_rect.left() - dest_buffer_rect.left(), 206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest_rect.top() - dest_buffer_rect.top(), 207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) source_stride); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy pixels in the rectangle line by line. 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int bytes_per_line = kBytesPerPixelRGB32 * dest_rect.width(); 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0 ; i < dest_rect.height(); ++i) { 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(dest_buffer, source_buffer, bytes_per_line); 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_buffer += source_stride; 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dest_buffer += dest_stride; 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReplaceLfByCrLf(const std::string& in) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string out; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.resize(2 * in.size()); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* out_p_begin = &out[0]; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* out_p = out_p_begin; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* in_p_begin = &in[0]; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* in_p_end = &in[in.size()]; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (const char* in_p = in_p_begin; in_p < in_p_end; ++in_p) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char c = *in_p; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (c == '\n') { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out_p++ = '\r'; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out_p++ = c; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.resize(out_p - out_p_begin); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return out; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReplaceCrLfByLf(const std::string& in) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string out; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.resize(in.size()); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* out_p_begin = &out[0]; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* out_p = out_p_begin; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* in_p_begin = &in[0]; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* in_p_end = &in[in.size()]; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (const char* in_p = in_p_begin; in_p < in_p_end; ++in_p) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char c = *in_p; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((c == '\r') && (in_p + 1 < in_p_end) && (*(in_p + 1) == '\n')) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out_p++ = '\n'; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++in_p; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out_p++ = c; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.resize(out_p - out_p_begin); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return out; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool StringIsUtf8(const char* data, size_t length) { 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* ptr = data; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* ptr_end = data + length; 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (ptr != ptr_end) { 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*ptr & 0x80) == 0) { 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Single-byte symbol. 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++ptr; 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if ((*ptr & 0xc0) == 0x80 || (*ptr & 0xfe) == 0xfe) { 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Invalid first byte. 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // First byte of a multi-byte symbol. The bits from 2 to 6 are the count 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // of continuation bytes (up to 5 of them). 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (char first = *ptr << 1; first & 0x80; first <<= 1) { 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++ptr; 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Missing continuation byte. 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ptr == ptr_end) 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Invalid continuation byte. 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*ptr & 0xc0) != 0x80) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++ptr; 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 288d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool DoesRectContain(const webrtc::DesktopRect& a, 289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRect& b) { 290d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRect intersection(a); 291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) intersection.IntersectWith(b); 292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return intersection.equals(b); 293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 296