Add DesktopFrame rotation functions
This change adds RotateDesktopFrame(), RotateRect(), RotateSize(),
ReverseRotate() functions, so an implementation can use these free functions to
rotate and copy pixels from one DesktopFrame to another at the same time.
This is the first part of the change to support rotation in DirectX capturer. In
a coming change, these functions will be used in DxgiOutputDuplicator to do the
rotation and copying.
Background,
DirectX APIs always return unrotated data buffer, so we need to rotate it to
match the user-selected rotation. What worse is except for the data buffer,
other variables return by these APIs are all rotated, e.g. output size, monitor
position. So we will eventually not be able to capture the rotated monitors,
because we cannot set their position and size correctly. Though
DXGI_OUTDUPL_DESC provides a DXGI_MODE_ROTATION enumeration to indicate the
output rotation, it does not provide a simple way to rotate an IDXGIResource,
which is the only thing we can get from duplication APIs. A typical user case
here is to use a matrix to transform the IDXGIResource and render it to a
surface. But since we do not render the IDXGIResource at all, we need to
manually rotate it.
BUG=314516
Review-Url: https://codereview.webrtc.org/2500883004
Cr-Commit-Position: refs/heads/master@{#15205}
2016-11-22 17:17:09 -08:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "modules/desktop_capture/test_utils.h"
|
Add DesktopFrame rotation functions
This change adds RotateDesktopFrame(), RotateRect(), RotateSize(),
ReverseRotate() functions, so an implementation can use these free functions to
rotate and copy pixels from one DesktopFrame to another at the same time.
This is the first part of the change to support rotation in DirectX capturer. In
a coming change, these functions will be used in DxgiOutputDuplicator to do the
rotation and copying.
Background,
DirectX APIs always return unrotated data buffer, so we need to rotate it to
match the user-selected rotation. What worse is except for the data buffer,
other variables return by these APIs are all rotated, e.g. output size, monitor
position. So we will eventually not be able to capture the rotated monitors,
because we cannot set their position and size correctly. Though
DXGI_OUTDUPL_DESC provides a DXGI_MODE_ROTATION enumeration to indicate the
output rotation, it does not provide a simple way to rotate an IDXGIResource,
which is the only thing we can get from duplication APIs. A typical user case
here is to use a matrix to transform the IDXGIResource and render it to a
surface. But since we do not render the IDXGIResource at all, we need to
manually rotate it.
BUG=314516
Review-Url: https://codereview.webrtc.org/2500883004
Cr-Commit-Position: refs/heads/master@{#15205}
2016-11-22 17:17:09 -08:00
|
|
|
|
2018-11-28 16:47:49 +01:00
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
|
|
#include "modules/desktop_capture/desktop_geometry.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "modules/desktop_capture/rgba_color.h"
|
|
|
|
|
#include "rtc_base/checks.h"
|
|
|
|
|
#include "test/gtest.h"
|
Add DesktopFrame rotation functions
This change adds RotateDesktopFrame(), RotateRect(), RotateSize(),
ReverseRotate() functions, so an implementation can use these free functions to
rotate and copy pixels from one DesktopFrame to another at the same time.
This is the first part of the change to support rotation in DirectX capturer. In
a coming change, these functions will be used in DxgiOutputDuplicator to do the
rotation and copying.
Background,
DirectX APIs always return unrotated data buffer, so we need to rotate it to
match the user-selected rotation. What worse is except for the data buffer,
other variables return by these APIs are all rotated, e.g. output size, monitor
position. So we will eventually not be able to capture the rotated monitors,
because we cannot set their position and size correctly. Though
DXGI_OUTDUPL_DESC provides a DXGI_MODE_ROTATION enumeration to indicate the
output rotation, it does not provide a simple way to rotate an IDXGIResource,
which is the only thing we can get from duplication APIs. A typical user case
here is to use a matrix to transform the IDXGIResource and render it to a
surface. But since we do not render the IDXGIResource at all, we need to
manually rotate it.
BUG=314516
Review-Url: https://codereview.webrtc.org/2500883004
Cr-Commit-Position: refs/heads/master@{#15205}
2016-11-22 17:17:09 -08:00
|
|
|
|
|
|
|
|
namespace webrtc {
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
void PaintDesktopFrame(DesktopFrame* frame,
|
|
|
|
|
DesktopVector pos,
|
|
|
|
|
RgbaColor color) {
|
2019-12-16 07:35:41 +01:00
|
|
|
ASSERT_TRUE(frame);
|
|
|
|
|
ASSERT_TRUE(DesktopRect::MakeSize(frame->size()).Contains(pos));
|
Add DesktopFrame rotation functions
This change adds RotateDesktopFrame(), RotateRect(), RotateSize(),
ReverseRotate() functions, so an implementation can use these free functions to
rotate and copy pixels from one DesktopFrame to another at the same time.
This is the first part of the change to support rotation in DirectX capturer. In
a coming change, these functions will be used in DxgiOutputDuplicator to do the
rotation and copying.
Background,
DirectX APIs always return unrotated data buffer, so we need to rotate it to
match the user-selected rotation. What worse is except for the data buffer,
other variables return by these APIs are all rotated, e.g. output size, monitor
position. So we will eventually not be able to capture the rotated monitors,
because we cannot set their position and size correctly. Though
DXGI_OUTDUPL_DESC provides a DXGI_MODE_ROTATION enumeration to indicate the
output rotation, it does not provide a simple way to rotate an IDXGIResource,
which is the only thing we can get from duplication APIs. A typical user case
here is to use a matrix to transform the IDXGIResource and render it to a
surface. But since we do not render the IDXGIResource at all, we need to
manually rotate it.
BUG=314516
Review-Url: https://codereview.webrtc.org/2500883004
Cr-Commit-Position: refs/heads/master@{#15205}
2016-11-22 17:17:09 -08:00
|
|
|
*reinterpret_cast<uint32_t*>(frame->GetFrameDataAtPos(pos)) =
|
|
|
|
|
color.ToUInt32();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A DesktopFrame implementation to store data in heap, but the stide is
|
|
|
|
|
// doubled.
|
|
|
|
|
class DoubleSizeDesktopFrame : public DesktopFrame {
|
|
|
|
|
public:
|
|
|
|
|
explicit DoubleSizeDesktopFrame(DesktopSize size);
|
|
|
|
|
~DoubleSizeDesktopFrame() override;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
DoubleSizeDesktopFrame::DoubleSizeDesktopFrame(DesktopSize size)
|
|
|
|
|
: DesktopFrame(
|
|
|
|
|
size,
|
|
|
|
|
kBytesPerPixel * size.width() * 2,
|
|
|
|
|
new uint8_t[kBytesPerPixel * size.width() * size.height() * 2],
|
|
|
|
|
nullptr) {}
|
|
|
|
|
|
|
|
|
|
DoubleSizeDesktopFrame::~DoubleSizeDesktopFrame() {
|
|
|
|
|
delete[] data_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
TEST(TestUtilsTest, BasicDataEqualsCases) {
|
|
|
|
|
BasicDesktopFrame frame(DesktopSize(4, 4));
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
for (int j = 0; j < 4; j++) {
|
|
|
|
|
PaintDesktopFrame(&frame, DesktopVector(i, j), RgbaColor(4U * j + i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(DesktopFrameDataEquals(frame, frame));
|
|
|
|
|
BasicDesktopFrame other(DesktopSize(4, 4));
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
for (int j = 0; j < 4; j++) {
|
|
|
|
|
PaintDesktopFrame(&other, DesktopVector(i, j), RgbaColor(4U * j + i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ASSERT_TRUE(DesktopFrameDataEquals(frame, other));
|
|
|
|
|
PaintDesktopFrame(&other, DesktopVector(2, 2), RgbaColor(0U));
|
|
|
|
|
ASSERT_FALSE(DesktopFrameDataEquals(frame, other));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(TestUtilsTest, DifferentSizeShouldNotEqual) {
|
|
|
|
|
BasicDesktopFrame frame(DesktopSize(4, 4));
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
for (int j = 0; j < 4; j++) {
|
|
|
|
|
PaintDesktopFrame(&frame, DesktopVector(i, j), RgbaColor(4U * j + i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BasicDesktopFrame other(DesktopSize(2, 8));
|
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
|
for (int j = 0; j < 8; j++) {
|
|
|
|
|
PaintDesktopFrame(&other, DesktopVector(i, j), RgbaColor(2U * j + i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASSERT_FALSE(DesktopFrameDataEquals(frame, other));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(TestUtilsTest, DifferentStrideShouldBeComparable) {
|
|
|
|
|
BasicDesktopFrame frame(DesktopSize(4, 4));
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
for (int j = 0; j < 4; j++) {
|
|
|
|
|
PaintDesktopFrame(&frame, DesktopVector(i, j), RgbaColor(4U * j + i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(DesktopFrameDataEquals(frame, frame));
|
|
|
|
|
DoubleSizeDesktopFrame other(DesktopSize(4, 4));
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
for (int j = 0; j < 4; j++) {
|
|
|
|
|
PaintDesktopFrame(&other, DesktopVector(i, j), RgbaColor(4U * j + i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ASSERT_TRUE(DesktopFrameDataEquals(frame, other));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace webrtc
|