| // 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 <math.h> |
| |
| #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 |