/* * 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 "modules/desktop_capture/desktop_frame_rotation.h" #include "rtc_base/checks.h" #include "third_party/libyuv/include/libyuv/rotate_argb.h" namespace webrtc { namespace { libyuv::RotationMode ToLibyuvRotationMode(Rotation rotation) { switch (rotation) { case Rotation::CLOCK_WISE_0: return libyuv::kRotate0; case Rotation::CLOCK_WISE_90: return libyuv::kRotate90; case Rotation::CLOCK_WISE_180: return libyuv::kRotate180; case Rotation::CLOCK_WISE_270: return libyuv::kRotate270; } RTC_DCHECK_NOTREACHED(); return libyuv::kRotate0; } DesktopRect RotateAndOffsetRect(DesktopRect rect, DesktopSize size, Rotation rotation, DesktopVector offset) { DesktopRect result = RotateRect(rect, size, rotation); result.Translate(offset); return result; } } // namespace Rotation ReverseRotation(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; } RTC_DCHECK_NOTREACHED(); return Rotation::CLOCK_WISE_0; } DesktopSize RotateSize(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()); } RTC_DCHECK_NOTREACHED(); return DesktopSize(); } DesktopRect RotateRect(DesktopRect rect, DesktopSize size, Rotation rotation) { switch (rotation) { case Rotation::CLOCK_WISE_0: return rect; case Rotation::CLOCK_WISE_90: return DesktopRect::MakeXYWH(size.height() - rect.bottom(), rect.left(), rect.height(), rect.width()); case Rotation::CLOCK_WISE_180: return DesktopRect::MakeXYWH(size.width() - rect.right(), size.height() - rect.bottom(), rect.width(), rect.height()); case Rotation::CLOCK_WISE_270: return DesktopRect::MakeXYWH(rect.top(), size.width() - rect.right(), rect.height(), rect.width()); } RTC_DCHECK_NOTREACHED(); return DesktopRect(); } void RotateDesktopFrame(const DesktopFrame& source, const DesktopRect& source_rect, const Rotation& rotation, const DesktopVector& target_offset, DesktopFrame* target) { RTC_DCHECK(target); RTC_DCHECK(DesktopRect::MakeSize(source.size()).ContainsRect(source_rect)); // The rectangle in `target`. const DesktopRect target_rect = RotateAndOffsetRect(source_rect, source.size(), rotation, target_offset); RTC_DCHECK(DesktopRect::MakeSize(target->size()).ContainsRect(target_rect)); if (target_rect.is_empty()) { return; } int result = libyuv::ARGBRotate( source.GetFrameDataAtPos(source_rect.top_left()), source.stride(), target->GetFrameDataAtPos(target_rect.top_left()), target->stride(), source_rect.width(), source_rect.height(), ToLibyuvRotationMode(rotation)); RTC_DCHECK_EQ(result, 0); } } // namespace webrtc