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 "rtc_base/checks.h"
14 #include "third_party/libyuv/include/libyuv/rotate_argb.h"
15
16 namespace webrtc {
17
18 namespace {
19
ToLibyuvRotationMode(Rotation rotation)20 libyuv::RotationMode ToLibyuvRotationMode(Rotation rotation) {
21 switch (rotation) {
22 case Rotation::CLOCK_WISE_0:
23 return libyuv::kRotate0;
24 case Rotation::CLOCK_WISE_90:
25 return libyuv::kRotate90;
26 case Rotation::CLOCK_WISE_180:
27 return libyuv::kRotate180;
28 case Rotation::CLOCK_WISE_270:
29 return libyuv::kRotate270;
30 }
31 RTC_NOTREACHED();
32 return libyuv::kRotate0;
33 }
34
RotateAndOffsetRect(DesktopRect rect,DesktopSize size,Rotation rotation,DesktopVector offset)35 DesktopRect RotateAndOffsetRect(DesktopRect rect,
36 DesktopSize size,
37 Rotation rotation,
38 DesktopVector offset) {
39 DesktopRect result = RotateRect(rect, size, rotation);
40 result.Translate(offset);
41 return result;
42 }
43
44 } // namespace
45
ReverseRotation(Rotation rotation)46 Rotation ReverseRotation(Rotation rotation) {
47 switch (rotation) {
48 case Rotation::CLOCK_WISE_0:
49 return rotation;
50 case Rotation::CLOCK_WISE_90:
51 return Rotation::CLOCK_WISE_270;
52 case Rotation::CLOCK_WISE_180:
53 return Rotation::CLOCK_WISE_180;
54 case Rotation::CLOCK_WISE_270:
55 return Rotation::CLOCK_WISE_90;
56 }
57 RTC_NOTREACHED();
58 return Rotation::CLOCK_WISE_0;
59 }
60
RotateSize(DesktopSize size,Rotation rotation)61 DesktopSize RotateSize(DesktopSize size, Rotation rotation) {
62 switch (rotation) {
63 case Rotation::CLOCK_WISE_0:
64 case Rotation::CLOCK_WISE_180:
65 return size;
66 case Rotation::CLOCK_WISE_90:
67 case Rotation::CLOCK_WISE_270:
68 return DesktopSize(size.height(), size.width());
69 }
70 RTC_NOTREACHED();
71 return DesktopSize();
72 }
73
RotateRect(DesktopRect rect,DesktopSize size,Rotation rotation)74 DesktopRect RotateRect(DesktopRect rect, DesktopSize size, Rotation rotation) {
75 switch (rotation) {
76 case Rotation::CLOCK_WISE_0:
77 return rect;
78 case Rotation::CLOCK_WISE_90:
79 return DesktopRect::MakeXYWH(size.height() - rect.bottom(), rect.left(),
80 rect.height(), rect.width());
81 case Rotation::CLOCK_WISE_180:
82 return DesktopRect::MakeXYWH(size.width() - rect.right(),
83 size.height() - rect.bottom(), rect.width(),
84 rect.height());
85 case Rotation::CLOCK_WISE_270:
86 return DesktopRect::MakeXYWH(rect.top(), size.width() - rect.right(),
87 rect.height(), rect.width());
88 }
89 RTC_NOTREACHED();
90 return DesktopRect();
91 }
92
RotateDesktopFrame(const DesktopFrame & source,const DesktopRect & source_rect,const Rotation & rotation,const DesktopVector & target_offset,DesktopFrame * target)93 void RotateDesktopFrame(const DesktopFrame& source,
94 const DesktopRect& source_rect,
95 const Rotation& rotation,
96 const DesktopVector& target_offset,
97 DesktopFrame* target) {
98 RTC_DCHECK(target);
99 RTC_DCHECK(DesktopRect::MakeSize(source.size()).ContainsRect(source_rect));
100 // The rectangle in |target|.
101 const DesktopRect target_rect =
102 RotateAndOffsetRect(source_rect, source.size(), rotation, target_offset);
103 RTC_DCHECK(DesktopRect::MakeSize(target->size()).ContainsRect(target_rect));
104
105 if (target_rect.is_empty()) {
106 return;
107 }
108
109 int result = libyuv::ARGBRotate(
110 source.GetFrameDataAtPos(source_rect.top_left()), source.stride(),
111 target->GetFrameDataAtPos(target_rect.top_left()), target->stride(),
112 source_rect.width(), source_rect.height(),
113 ToLibyuvRotationMode(rotation));
114 RTC_DCHECK_EQ(result, 0);
115 }
116
117 } // namespace webrtc
118