我使用d3d11(桌面复制)捕获屏幕并通过网络在Windows 8及以上操作系统上发送。问题是如果显示器设置为纵向模式并且无法正确渲染,则会翻转/旋转框架。
经过分析后我才知道我必须处理以下轮换模式,但我确实只获得了与此相关的有限资源,
typedef enum DXGI_MODE_ROTATION {
DXGI_MODE_ROTATION_UNSPECIFIED = 0,
DXGI_MODE_ROTATION_IDENTITY = 1,
DXGI_MODE_ROTATION_ROTATE90 = 2,
DXGI_MODE_ROTATION_ROTATE180 = 3,
DXGI_MODE_ROTATION_ROTATE270 = 4
} DXGI_MODE_ROTATION;
在花了很多时间浏览资源之后,我遇到了webrtc中的代码,它使用libyuv旋转捕获的缓冲区。
以下是我从Webrtc获取的用于旋转捕获的图像缓冲区的代码:
void RotateDesktopFrame(const DesktopFrame& source,
const DesktopRect& source_rect,
const Rotation& rotation,
const DesktopVector& target_offset,
DesktopFrame* target) {
RTC_DCHECK(target);
RTC_DCHECK(DesktopRect::MakeSize(source.size()).ContainsRect(source_rect));
// The rectangle in |target|.
const DesktopRect target_rect =
RotateAndOffsetRect(source_rect, source.size(), rotation, target_offset);
RTC_DCHECK(DesktopRect::MakeSize(target->size()).ContainsRect(target_rect));
if (target_rect.is_empty()) {
return;
}
int result = libyuv::ARGBRotate(
source.GetFrameDataAtPos(source_rect.top_left()), source.stride(),
target->GetFrameDataAtPos(target_rect.top_left()), target->stride(),
source_rect.width(), source_rect.height(),
ToLibyuvRotationMode(rotation));
RTC_DCHECK_EQ(result, 0);
}
}
没关系,但libYuv没有GPU支持,使用CPU电源旋转屏幕会非常慢。
我还得到了一个stackoverflow thread来讨论通过directX本身进行的帧旋转,但是它太不完整了。
如果有人可以帮助我解决这个问题,那将是非常明显的。
答案 0 :(得分:1)
Microsoft Media Foundation Video Processor MFT可以在尽可能在GPU上完成工作时帮助轮换。具体请参见IMFVideoProcessorControl::SetRotation
方法说明。
如果Media Foundation听起来很复杂(确实如此),但你一般熟悉Direct3D 11,你可以使用Direct3D 11代替:通过使用旋转video processor或使用分别旋转的四边形渲染纹理。