2

我正在使用 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线程,讨论了通过directX本身的帧旋转,但这太不完整了。

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

4

1 回答 1

1

Microsoft Media Foundation Video Processor MFT可以帮助旋转,同时尽可能在 GPU 上进行工作。具体见IMFVideoProcessorControl::SetRotation方法说明。

如果 Media Foundation 听起来很复杂(确实如此),但您通常熟悉 Direct3D 11,则可以使用 Direct3D 11 代替:通过使用旋转视频处理器或使用分别旋转的四边形渲染纹理。

于 2018-03-25T23:23:28.097 回答