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

时间:2018-03-13 15:17:15

标签: visual-c++ directx directx-11 direct3d desktop-duplication

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

参考: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电源旋转屏幕会非常慢。

我还得到了一个stackoverflow thread来讨论通过directX本身进行的帧旋转,但是它太不完整了。

如果有人可以帮助我解决这个问题,那将是非常明显的。

1 个答案:

答案 0 :(得分:1)

Microsoft Media Foundation Video Processor MFT可以在尽可能在GPU上完成工作时帮助轮换。具体请参见IMFVideoProcessorControl::SetRotation方法说明。

如果Media Foundation听起来很复杂(确实如此),但你一般熟悉Direct3D 11,你可以使用Direct3D 11代替:通过使用旋转video processor或使用分别旋转的四边形渲染纹理。