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