desktop_frame_rotation.cc (4142B)
1 /* 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/desktop_capture/desktop_frame_rotation.h" 12 13 #include "modules/desktop_capture/desktop_frame.h" 14 #include "modules/desktop_capture/desktop_geometry.h" 15 #include "rtc_base/checks.h" 16 #include "third_party/libyuv/include/libyuv/rotate.h" 17 #include "third_party/libyuv/include/libyuv/rotate_argb.h" 18 19 namespace webrtc { 20 21 namespace { 22 23 libyuv::RotationMode ToLibyuvRotationMode(Rotation rotation) { 24 switch (rotation) { 25 case Rotation::CLOCK_WISE_0: 26 return libyuv::kRotate0; 27 case Rotation::CLOCK_WISE_90: 28 return libyuv::kRotate90; 29 case Rotation::CLOCK_WISE_180: 30 return libyuv::kRotate180; 31 case Rotation::CLOCK_WISE_270: 32 return libyuv::kRotate270; 33 } 34 RTC_DCHECK_NOTREACHED(); 35 return libyuv::kRotate0; 36 } 37 38 DesktopRect RotateAndOffsetRect(DesktopRect rect, 39 DesktopSize size, 40 Rotation rotation, 41 DesktopVector offset) { 42 DesktopRect result = RotateRect(rect, size, rotation); 43 result.Translate(offset); 44 return result; 45 } 46 47 } // namespace 48 49 Rotation ReverseRotation(Rotation rotation) { 50 switch (rotation) { 51 case Rotation::CLOCK_WISE_0: 52 return rotation; 53 case Rotation::CLOCK_WISE_90: 54 return Rotation::CLOCK_WISE_270; 55 case Rotation::CLOCK_WISE_180: 56 return Rotation::CLOCK_WISE_180; 57 case Rotation::CLOCK_WISE_270: 58 return Rotation::CLOCK_WISE_90; 59 } 60 RTC_DCHECK_NOTREACHED(); 61 return Rotation::CLOCK_WISE_0; 62 } 63 64 DesktopSize RotateSize(DesktopSize size, Rotation rotation) { 65 switch (rotation) { 66 case Rotation::CLOCK_WISE_0: 67 case Rotation::CLOCK_WISE_180: 68 return size; 69 case Rotation::CLOCK_WISE_90: 70 case Rotation::CLOCK_WISE_270: 71 return DesktopSize(size.height(), size.width()); 72 } 73 RTC_DCHECK_NOTREACHED(); 74 return DesktopSize(); 75 } 76 77 DesktopRect RotateRect(DesktopRect rect, DesktopSize size, Rotation rotation) { 78 switch (rotation) { 79 case Rotation::CLOCK_WISE_0: 80 return rect; 81 case Rotation::CLOCK_WISE_90: 82 return DesktopRect::MakeXYWH(size.height() - rect.bottom(), rect.left(), 83 rect.height(), rect.width()); 84 case Rotation::CLOCK_WISE_180: 85 return DesktopRect::MakeXYWH(size.width() - rect.right(), 86 size.height() - rect.bottom(), rect.width(), 87 rect.height()); 88 case Rotation::CLOCK_WISE_270: 89 return DesktopRect::MakeXYWH(rect.top(), size.width() - rect.right(), 90 rect.height(), rect.width()); 91 } 92 RTC_DCHECK_NOTREACHED(); 93 return DesktopRect(); 94 } 95 96 void RotateDesktopFrame(const DesktopFrame& source, 97 const DesktopRect& source_rect, 98 const Rotation& rotation, 99 const DesktopVector& target_offset, 100 DesktopFrame* target) { 101 RTC_DCHECK(target); 102 RTC_DCHECK(DesktopRect::MakeSize(source.size()).ContainsRect(source_rect)); 103 // TODO(bugs.webrtc.org/436974448): Support other pixel formats. 104 RTC_CHECK_EQ(FOURCC_ARGB, source.pixel_format()); 105 // The rectangle in `target`. 106 const DesktopRect target_rect = 107 RotateAndOffsetRect(source_rect, source.size(), rotation, target_offset); 108 RTC_DCHECK(DesktopRect::MakeSize(target->size()).ContainsRect(target_rect)); 109 110 if (target_rect.is_empty()) { 111 return; 112 } 113 114 int result = libyuv::ARGBRotate( 115 source.GetFrameDataAtPos(source_rect.top_left()), source.stride(), 116 target->GetFrameDataAtPos(target_rect.top_left()), target->stride(), 117 source_rect.width(), source_rect.height(), 118 ToLibyuvRotationMode(rotation)); 119 RTC_DCHECK_EQ(result, 0); 120 } 121 122 } // namespace webrtc