MS Media Foundation Session 默认演示者 - 视频宽高比错误

MS Media Foundation Session default presenter - video aspect ratio is wrong

学习(痛苦地)如何使用 Topology 和 Session 来呈现捕获的视频。没什么特别的 - 只是 select 一个网络摄像头,列出其模式,选择视频格式并点击 "go"。总的来说,这些是我为呈现视频捕获而采取的步骤:

  1. 列出 MFEnumDeviceSources() 的可用设备 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID 并让用户 select 一个
  2. 在激活源并使用 CreatePresentationDescriptor() 创建演示描述符后,列出基于 GetStreamDescriptorCount() 的流,并让用户 select 一个流(如果有多个流可用)
  3. 根据 GetMediaTypeByIndex() 可用的 IMFMediaType 列表显示所有支持的视频格式,并让用户选择一个

一旦 select 确定了确切的格式,我就这样构建拓扑:

  1. 调用MFCreateTopology()创建一个新的IMFTopology对象
  2. 使用 MFCreateVideoRendererActivate() 创建媒体接收器激活
    1. 确保在当前 select 编辑的 IMFStreamDescriptor
    2. IMFMediaTypeHandler 对象上调用 SetCurrentMediaType()
  3. 使用 MFCreateTopologyNode() 创建源节点,通过调用 SetUnknown() 设置其表示和流描述符并将该节点添加到拓扑
    1. 确保将其当前 IMFMediaType 设置为用户使用 SetCurrentMediaType()
    2. 选择的那个
  4. 创建一个输出节点并调用 SetObject() 它提供先前创建的媒体接收器激活对象(来自上面的第 5 步)
  5. 使用 ConnectOutput() 将源连接到输出并为其提供节点 ID 0

单击 "preview" 按钮后,会话 IMFMediaSession 对象(在应用程序启动时创建)将设置为新拓扑

m_session->SetTopology(MFSESSION_SETTOPOLOGY_IMMEDIATE, pTopo);

这就是我看到一些奇怪的地方。我根据用户选择的 IMFMediaType 提供的帧尺寸设置预览视频的大小,并且来源似乎正在以该格式制作视频。 但是 渲染器处理 像素长宽比 不正确,并且 letterboxing/pillarboxing 视频在呈现图片时被垂直或水平拉伸.

对于我来说,我无法找到告诉渲染器调整适当像素纵横比的方法(在上面的步骤 5.1 中设置为适当的值)


MS 的 SDK 示例仅展示了如何呈现未压缩格式的捕获视频 - 它不使用 IMFMediaSession 对象并且适用于 YUV2 格式但不适用于 MJPG.事实上,它运行得非常好,我认为继续使用会话会很容易:)

使用 IMFMediaSession 似乎是支持压缩视频格式最简单的方法,尤其是较新的 UVC 1.5 标准中的 H.264 和任何新的(H.265?) 将来会出现的格式。

进一步的研究表明,可以通过查询会话获取服务来访问渲染器对象,然后使用该服务获取视频显示控件IMFVideoDisplayControl 是一个对象,可让您控制渲染视频的各个方面,包括图像的纵横比。

这是到达 IMFVideoDisplayControl 对象的方法:

  1. 得到 IMFGetService:

    hr = m_session->QueryInterface<IMFGetService>(&service);

  2. 得到 IMFVideoDisplayControl:

    hr = service->GetService(MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl, (void**)&control);

一旦你有了显示控制对象,你就可以实现剩下的了。在我的例子中(因为我知道预期视频的实际真实几何形状)解决方案是将 纵横比模式 设置为 MFVideoARMode_None