| Index: webrtc/modules/desktop_capture/desktop_frame_rotator.cc
|
| diff --git a/webrtc/modules/desktop_capture/desktop_frame_rotator.cc b/webrtc/modules/desktop_capture/desktop_frame_rotator.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b397195edcf45da28b70f1a7974dabe6f9d3c858
|
| --- /dev/null
|
| +++ b/webrtc/modules/desktop_capture/desktop_frame_rotator.cc
|
| @@ -0,0 +1,199 @@
|
| +/*
|
| + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license
|
| + * that can be found in the LICENSE file in the root of the source
|
| + * tree. An additional intellectual property rights grant can be found
|
| + * in the file PATENTS. All contributing project authors may
|
| + * be found in the AUTHORS file in the root of the source tree.
|
| + */
|
| +
|
| +#include "webrtc/modules/desktop_capture/desktop_frame_rotator.h"
|
| +
|
| +#include <string.h>
|
| +
|
| +#include "webrtc/base/checks.h"
|
| +
|
| +namespace webrtc {
|
| +
|
| +namespace {
|
| +
|
| +// The count of bytes to jump per pixel if a DesktopFrame |frame| has been
|
| +// rotated by |rotation|.
|
| +int StepPerPixel(const DesktopFrame& frame, Rotation rotation) {
|
| + switch (rotation) {
|
| + case Rotation::CLOCK_WISE_0:
|
| + return DesktopFrame::kBytesPerPixel;
|
| + case Rotation::CLOCK_WISE_90:
|
| + return frame.stride();
|
| + case Rotation::CLOCK_WISE_180:
|
| + return -DesktopFrame::kBytesPerPixel;
|
| + case Rotation::CLOCK_WISE_270:
|
| + return -frame.stride();
|
| + default:
|
| + RTC_NOTREACHED();
|
| + return 0;
|
| + }
|
| +}
|
| +
|
| +// The count of bytes to jump per line if a DesktopFrame |frame| has been
|
| +// rotated by |rotation|.
|
| +int StepPerLine(const DesktopFrame& frame, Rotation rotation) {
|
| + switch (rotation) {
|
| + case Rotation::CLOCK_WISE_0:
|
| + return frame.stride();
|
| + case Rotation::CLOCK_WISE_90:
|
| + return -DesktopFrame::kBytesPerPixel;
|
| + case Rotation::CLOCK_WISE_180:
|
| + return -frame.stride();
|
| + case Rotation::CLOCK_WISE_270:
|
| + return DesktopFrame::kBytesPerPixel;
|
| + default:
|
| + RTC_NOTREACHED();
|
| + return 0;
|
| + }
|
| +}
|
| +
|
| +// Returns a rotated DesktopRect of |rect|. The |size| represents the size of
|
| +// the DesktopFrame which |rect| belongs in.
|
| +DesktopRect Rotate(DesktopRect rect, DesktopSize size, Rotation rotation) {
|
| + switch (rotation) {
|
| + case Rotation::CLOCK_WISE_0:
|
| + return rect;
|
| + case Rotation::CLOCK_WISE_90:
|
| + return DesktopRect::MakeLTRB(size.height() - rect.bottom(),
|
| + rect.left(),
|
| + size.height() - rect.top(),
|
| + rect.right());
|
| + case Rotation::CLOCK_WISE_180:
|
| + return DesktopRect::MakeLTRB(size.width() - rect.right(),
|
| + size.height() - rect.bottom(),
|
| + size.width() - rect.left(),
|
| + size.height() - rect.top());
|
| + case Rotation::CLOCK_WISE_270:
|
| + return DesktopRect::MakeLTRB(rect.top(),
|
| + size.width() - rect.right(),
|
| + rect.bottom(),
|
| + size.width() - rect.left());
|
| + default:
|
| + RTC_NOTREACHED();
|
| + return DesktopRect();
|
| + }
|
| +}
|
| +
|
| +// Returns a reverse-rotated Rotation of |rotation|.
|
| +Rotation Reverse(Rotation rotation) {
|
| + switch (rotation) {
|
| + case Rotation::CLOCK_WISE_0:
|
| + return rotation;
|
| + case Rotation::CLOCK_WISE_90:
|
| + return Rotation::CLOCK_WISE_270;
|
| + case Rotation::CLOCK_WISE_180:
|
| + return Rotation::CLOCK_WISE_180;
|
| + case Rotation::CLOCK_WISE_270:
|
| + return Rotation::CLOCK_WISE_90;
|
| + default:
|
| + RTC_NOTREACHED();
|
| + return Rotation::CLOCK_WISE_0;
|
| + }
|
| +}
|
| +
|
| +// Returns a reverse-rotated DesktopRect of |rect|. The |size| represents the
|
| +// size of the DesktopFrame which |rect| belongs in.
|
| +DesktopRect Derotate(DesktopRect rect, DesktopSize size, Rotation rotation) {
|
| + return Rotate(rect, size, Reverse(rotation));
|
| +}
|
| +
|
| +// The new position of Derotate(|rect|, |rotation|).top_left() after rotated.
|
| +DesktopVector RotatedTopLeft(DesktopRect rect, Rotation rotation) {
|
| + switch (rotation) {
|
| + case Rotation::CLOCK_WISE_0:
|
| + return rect.top_left();
|
| + case Rotation::CLOCK_WISE_90:
|
| + return DesktopVector(rect.right() - 1, rect.top());
|
| + case Rotation::CLOCK_WISE_180:
|
| + return DesktopVector(rect.right() - 1, rect.bottom() - 1);
|
| + case Rotation::CLOCK_WISE_270:
|
| + return DesktopVector(rect.left(), rect.bottom() - 1);
|
| + default:
|
| + RTC_NOTREACHED();
|
| + return DesktopVector();
|
| + }
|
| +}
|
| +
|
| +// Returns a reverse-rotated DesktopSize of |size|.
|
| +DesktopSize Derotate(DesktopSize size, Rotation rotation) {
|
| + switch (rotation) {
|
| + case Rotation::CLOCK_WISE_0:
|
| + case Rotation::CLOCK_WISE_180:
|
| + return size;
|
| + case Rotation::CLOCK_WISE_90:
|
| + case Rotation::CLOCK_WISE_270:
|
| + return DesktopSize(size.height(), size.width());
|
| + default:
|
| + RTC_NOTREACHED();
|
| + return DesktopSize();
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +bool CopyRotatedRectTo(const DesktopFrame& src,
|
| + DesktopRect rect,
|
| + Rotation rotation,
|
| + DesktopFrame* target) {
|
| + if (!target) {
|
| + return false;
|
| + }
|
| + if (!DesktopRect::MakeSize(target->size()).ContainsRect(rect)) {
|
| + return false;
|
| + }
|
| + if (rect.is_empty()) {
|
| + return true;
|
| + }
|
| +
|
| + target->mutable_updated_region()->AddRect(rect);
|
| + if (rotation == Rotation::CLOCK_WISE_0) {
|
| + // A shortcut: if |rotation| is 0, this function uses
|
| + // DesktopFrame::CopyPixelsFrom() for a better performance.
|
| + target->CopyPixelsFrom(src, rect.top_left(), rect);
|
| + return true;
|
| + }
|
| +
|
| + // The rectangle in |src|.
|
| + const DesktopRect src_rect =
|
| + Derotate(rect, Derotate(src.size(), rotation), rotation);
|
| + const uint8_t* src_array = src.GetFrameDataAtPos(src_rect.top_left());
|
| + // The stride without the area which needs to be copied. i.e. The byte
|
| + // count between the end of last line and the start of next line in the
|
| + // |src_rect|.
|
| + const int src_exclusive_stride =
|
| + src.stride() - src_rect.width() * DesktopFrame::kBytesPerPixel;
|
| + uint8_t* dest_array =
|
| + target->GetFrameDataAtPos(RotatedTopLeft(rect, rotation));
|
| + const int dest_step_per_pixel = StepPerPixel(*target, rotation);
|
| + const int dest_exclusive_stride =
|
| + StepPerLine(*target, rotation) -
|
| + dest_step_per_pixel * src_rect.width();
|
| +
|
| + for (int i = 0; i < src_rect.height(); i++) {
|
| + for (int j = 0; j < src_rect.width(); j++) {
|
| + memcpy(dest_array, src_array, DesktopFrame::kBytesPerPixel);
|
| + src_array += DesktopFrame::kBytesPerPixel;
|
| + dest_array += dest_step_per_pixel;
|
| + }
|
| + src_array += src_exclusive_stride;
|
| + dest_array += dest_exclusive_stride;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool CopyUnrotatedRectTo(const DesktopFrame& src,
|
| + DesktopRect rect,
|
| + Rotation rotation,
|
| + DesktopFrame* target) {
|
| + return CopyRotatedRectTo(
|
| + src, Rotate(rect, src.size(), rotation), rotation, target);
|
| +}
|
| +
|
| +} // namespace webrtc
|
|
|