// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "remoting/base/util.h" #include #include "base/logging.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" #include "third_party/libyuv/include/libyuv/convert.h" #include "third_party/webrtc/modules/desktop_capture/desktop_region.h" namespace remoting { enum { kBytesPerPixelRGB32 = 4 }; static int CalculateRGBOffset(int x, int y, int stride) { return stride * y + kBytesPerPixelRGB32 * x; } // Do not write LOG messages in this routine since it is called from within // our LOG message handler. Bad things will happen. std::string GetTimestampString() { base::Time t = base::Time::NowFromSystemTime(); base::Time::Exploded tex; t.LocalExplode(&tex); return base::StringPrintf("%02d%02d/%02d%02d%02d:", tex.month, tex.day_of_month, tex.hour, tex.minute, tex.second); } int RoundToTwosMultiple(int x) { return x & (~1); } webrtc::DesktopRect AlignRect(const webrtc::DesktopRect& rect) { int x = RoundToTwosMultiple(rect.left()); int y = RoundToTwosMultiple(rect.top()); int right = RoundToTwosMultiple(rect.right() + 1); int bottom = RoundToTwosMultiple(rect.bottom() + 1); return webrtc::DesktopRect::MakeLTRB(x, y, right, bottom); } void CopyRGB32Rect(const uint8_t* source_buffer, int source_stride, const webrtc::DesktopRect& source_buffer_rect, uint8_t* dest_buffer, int dest_stride, const webrtc::DesktopRect& dest_buffer_rect, const webrtc::DesktopRect& dest_rect) { DCHECK(DoesRectContain(dest_buffer_rect, dest_rect)); DCHECK(DoesRectContain(source_buffer_rect, dest_rect)); // Get the address of the starting point. source_buffer += CalculateRGBOffset( dest_rect.left() - source_buffer_rect.left(), dest_rect.top() - source_buffer_rect.top(), source_stride); dest_buffer += CalculateRGBOffset( dest_rect.left() - dest_buffer_rect.left(), dest_rect.top() - dest_buffer_rect.top(), source_stride); // Copy pixels in the rectangle line by line. const int bytes_per_line = kBytesPerPixelRGB32 * dest_rect.width(); for (int i = 0 ; i < dest_rect.height(); ++i) { memcpy(dest_buffer, source_buffer, bytes_per_line); source_buffer += source_stride; dest_buffer += dest_stride; } } std::string ReplaceLfByCrLf(const std::string& in) { std::string out; out.resize(2 * in.size()); char* out_p_begin = &out[0]; char* out_p = out_p_begin; const char* in_p_begin = &in[0]; const char* in_p_end = &in[in.size()]; for (const char* in_p = in_p_begin; in_p < in_p_end; ++in_p) { char c = *in_p; if (c == '\n') { *out_p++ = '\r'; } *out_p++ = c; } out.resize(out_p - out_p_begin); return out; } std::string ReplaceCrLfByLf(const std::string& in) { std::string out; out.resize(in.size()); char* out_p_begin = &out[0]; char* out_p = out_p_begin; const char* in_p_begin = &in[0]; const char* in_p_end = &in[in.size()]; for (const char* in_p = in_p_begin; in_p < in_p_end; ++in_p) { char c = *in_p; if ((c == '\r') && (in_p + 1 < in_p_end) && (*(in_p + 1) == '\n')) { *out_p++ = '\n'; ++in_p; } else { *out_p++ = c; } } out.resize(out_p - out_p_begin); return out; } bool StringIsUtf8(const char* data, size_t length) { const char* ptr = data; const char* ptr_end = data + length; while (ptr != ptr_end) { if ((*ptr & 0x80) == 0) { // Single-byte symbol. ++ptr; } else if ((*ptr & 0xc0) == 0x80 || (*ptr & 0xfe) == 0xfe) { // Invalid first byte. return false; } else { // First byte of a multi-byte symbol. The bits from 2 to 6 are the count // of continuation bytes (up to 5 of them). for (char first = *ptr << 1; first & 0x80; first <<= 1) { ++ptr; // Missing continuation byte. if (ptr == ptr_end) return false; // Invalid continuation byte. if ((*ptr & 0xc0) != 0x80) return false; } ++ptr; } } return true; } bool DoesRectContain(const webrtc::DesktopRect& a, const webrtc::DesktopRect& b) { webrtc::DesktopRect intersection(a); intersection.IntersectWith(b); return intersection.equals(b); } } // namespace remoting