桌面复制:旋转框架以支持纵向模式

Desktop duplication: Rotating the frames to support portrait mode

我在 windows 8 及更高版本的操作系统上使用 d3d11(桌面复制)捕获屏幕并通过网络发送它们。问题是如果显示器设置为纵向模式且无法正确渲染,帧数 flipped/rotated。

经过分析,我开始知道我必须处理以下轮换模式,但我确实只获得了与此相关的有限资源,

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 获得的用于旋转捕获的图像缓冲区的代码:

参考:desktop_frame_rotation.cc

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 电源旋转屏幕真的很慢。

我还有一个 讨论了通过 directX 本身进行帧旋转但是太不完整了。

如果有人能帮我解决这个问题,我将不胜感激。

Microsoft Media Foundation Video Processor MFT can help with rotation while doing the work on GPU whenever possible. See IMFVideoProcessorControl::SetRotation 方法描述具体。

如果 Media Foundation 听起来很复杂(确实如此)但您通常熟悉 Direct3D 11,则可以改用 Direct3D 11:利用旋转 video processor 或分别旋转渲染纹理四.