| OLD | NEW |
| (Empty) | |
| 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 "webrtc/modules/desktop_capture/desktop_frame_rotator.h" |
| 12 |
| 13 #include <string.h> |
| 14 |
| 15 #include "webrtc/base/checks.h" |
| 16 |
| 17 namespace webrtc { |
| 18 |
| 19 namespace { |
| 20 |
| 21 // The count of bytes to jump per pixel if a DesktopFrame |frame| has been |
| 22 // rotated by |rotation|. |
| 23 int StepPerPixel(const DesktopFrame& frame, Rotation rotation) { |
| 24 switch (rotation) { |
| 25 case Rotation::CLOCK_WISE_0: |
| 26 return DesktopFrame::kBytesPerPixel; |
| 27 case Rotation::CLOCK_WISE_90: |
| 28 return frame.stride(); |
| 29 case Rotation::CLOCK_WISE_180: |
| 30 return -DesktopFrame::kBytesPerPixel; |
| 31 case Rotation::CLOCK_WISE_270: |
| 32 return -frame.stride(); |
| 33 default: |
| 34 RTC_NOTREACHED(); |
| 35 return 0; |
| 36 } |
| 37 } |
| 38 |
| 39 // The count of bytes to jump per line if a DesktopFrame |frame| has been |
| 40 // rotated by |rotation|. |
| 41 int StepPerLine(const DesktopFrame& frame, Rotation rotation) { |
| 42 switch (rotation) { |
| 43 case Rotation::CLOCK_WISE_0: |
| 44 return frame.stride(); |
| 45 case Rotation::CLOCK_WISE_90: |
| 46 return -DesktopFrame::kBytesPerPixel; |
| 47 case Rotation::CLOCK_WISE_180: |
| 48 return -frame.stride(); |
| 49 case Rotation::CLOCK_WISE_270: |
| 50 return DesktopFrame::kBytesPerPixel; |
| 51 default: |
| 52 RTC_NOTREACHED(); |
| 53 return 0; |
| 54 } |
| 55 } |
| 56 |
| 57 // Returns a rotated DesktopRect of |rect|. The |size| represents the size of |
| 58 // the DesktopFrame which |rect| belongs in. |
| 59 DesktopRect Rotate(DesktopRect rect, DesktopSize size, Rotation rotation) { |
| 60 switch (rotation) { |
| 61 case Rotation::CLOCK_WISE_0: |
| 62 return rect; |
| 63 case Rotation::CLOCK_WISE_90: |
| 64 return DesktopRect::MakeLTRB(size.height() - rect.bottom(), |
| 65 rect.left(), |
| 66 size.height() - rect.top(), |
| 67 rect.right()); |
| 68 case Rotation::CLOCK_WISE_180: |
| 69 return DesktopRect::MakeLTRB(size.width() - rect.right(), |
| 70 size.height() - rect.bottom(), |
| 71 size.width() - rect.left(), |
| 72 size.height() - rect.top()); |
| 73 case Rotation::CLOCK_WISE_270: |
| 74 return DesktopRect::MakeLTRB(rect.top(), |
| 75 size.width() - rect.right(), |
| 76 rect.bottom(), |
| 77 size.width() - rect.left()); |
| 78 default: |
| 79 RTC_NOTREACHED(); |
| 80 return DesktopRect(); |
| 81 } |
| 82 } |
| 83 |
| 84 // Returns a reverse-rotated Rotation of |rotation|. |
| 85 Rotation Reverse(Rotation rotation) { |
| 86 switch (rotation) { |
| 87 case Rotation::CLOCK_WISE_0: |
| 88 return rotation; |
| 89 case Rotation::CLOCK_WISE_90: |
| 90 return Rotation::CLOCK_WISE_270; |
| 91 case Rotation::CLOCK_WISE_180: |
| 92 return Rotation::CLOCK_WISE_180; |
| 93 case Rotation::CLOCK_WISE_270: |
| 94 return Rotation::CLOCK_WISE_90; |
| 95 default: |
| 96 RTC_NOTREACHED(); |
| 97 return Rotation::CLOCK_WISE_0; |
| 98 } |
| 99 } |
| 100 |
| 101 // Returns a reverse-rotated DesktopRect of |rect|. The |size| represents the |
| 102 // size of the DesktopFrame which |rect| belongs in. |
| 103 DesktopRect Derotate(DesktopRect rect, DesktopSize size, Rotation rotation) { |
| 104 return Rotate(rect, size, Reverse(rotation)); |
| 105 } |
| 106 |
| 107 // The new position of Derotate(|rect|, |rotation|).top_left() after rotated. |
| 108 DesktopVector RotatedTopLeft(DesktopRect rect, Rotation rotation) { |
| 109 switch (rotation) { |
| 110 case Rotation::CLOCK_WISE_0: |
| 111 return rect.top_left(); |
| 112 case Rotation::CLOCK_WISE_90: |
| 113 return DesktopVector(rect.right() - 1, rect.top()); |
| 114 case Rotation::CLOCK_WISE_180: |
| 115 return DesktopVector(rect.right() - 1, rect.bottom() - 1); |
| 116 case Rotation::CLOCK_WISE_270: |
| 117 return DesktopVector(rect.left(), rect.bottom() - 1); |
| 118 default: |
| 119 RTC_NOTREACHED(); |
| 120 return DesktopVector(); |
| 121 } |
| 122 } |
| 123 |
| 124 // Returns a reverse-rotated DesktopSize of |size|. |
| 125 DesktopSize Derotate(DesktopSize size, Rotation rotation) { |
| 126 switch (rotation) { |
| 127 case Rotation::CLOCK_WISE_0: |
| 128 case Rotation::CLOCK_WISE_180: |
| 129 return size; |
| 130 case Rotation::CLOCK_WISE_90: |
| 131 case Rotation::CLOCK_WISE_270: |
| 132 return DesktopSize(size.height(), size.width()); |
| 133 default: |
| 134 RTC_NOTREACHED(); |
| 135 return DesktopSize(); |
| 136 } |
| 137 } |
| 138 |
| 139 } // namespace |
| 140 |
| 141 bool CopyRotatedRectTo(const DesktopFrame& src, |
| 142 DesktopRect rect, |
| 143 Rotation rotation, |
| 144 DesktopFrame* target) { |
| 145 if (!target) { |
| 146 return false; |
| 147 } |
| 148 if (!DesktopRect::MakeSize(target->size()).ContainsRect(rect)) { |
| 149 return false; |
| 150 } |
| 151 if (rect.is_empty()) { |
| 152 return true; |
| 153 } |
| 154 |
| 155 target->mutable_updated_region()->AddRect(rect); |
| 156 if (rotation == Rotation::CLOCK_WISE_0) { |
| 157 // A shortcut: if |rotation| is 0, this function uses |
| 158 // DesktopFrame::CopyPixelsFrom() for a better performance. |
| 159 target->CopyPixelsFrom(src, rect.top_left(), rect); |
| 160 return true; |
| 161 } |
| 162 |
| 163 // The rectangle in |src|. |
| 164 const DesktopRect src_rect = |
| 165 Derotate(rect, Derotate(src.size(), rotation), rotation); |
| 166 const uint8_t* src_array = src.GetFrameDataAtPos(src_rect.top_left()); |
| 167 // The stride without the area which needs to be copied. i.e. The byte |
| 168 // count between the end of last line and the start of next line in the |
| 169 // |src_rect|. |
| 170 const int src_exclusive_stride = |
| 171 src.stride() - src_rect.width() * DesktopFrame::kBytesPerPixel; |
| 172 uint8_t* dest_array = |
| 173 target->GetFrameDataAtPos(RotatedTopLeft(rect, rotation)); |
| 174 const int dest_step_per_pixel = StepPerPixel(*target, rotation); |
| 175 const int dest_exclusive_stride = |
| 176 StepPerLine(*target, rotation) - |
| 177 dest_step_per_pixel * src_rect.width(); |
| 178 |
| 179 for (int i = 0; i < src_rect.height(); i++) { |
| 180 for (int j = 0; j < src_rect.width(); j++) { |
| 181 memcpy(dest_array, src_array, DesktopFrame::kBytesPerPixel); |
| 182 src_array += DesktopFrame::kBytesPerPixel; |
| 183 dest_array += dest_step_per_pixel; |
| 184 } |
| 185 src_array += src_exclusive_stride; |
| 186 dest_array += dest_exclusive_stride; |
| 187 } |
| 188 return true; |
| 189 } |
| 190 |
| 191 bool CopyUnrotatedRectTo(const DesktopFrame& src, |
| 192 DesktopRect rect, |
| 193 Rotation rotation, |
| 194 DesktopFrame* target) { |
| 195 return CopyRotatedRectTo( |
| 196 src, Rotate(rect, src.size(), rotation), rotation, target); |
| 197 } |
| 198 |
| 199 } // namespace webrtc |
| OLD | NEW |