MS Media Foundation Session 默认演示者 - 视频宽高比错误
MS Media Foundation Session default presenter - video aspect ratio is wrong
学习(痛苦地)如何使用 Topology 和 Session 来呈现捕获的视频。没什么特别的 - 只是 select 一个网络摄像头,列出其模式,选择视频格式并点击 "go"。总的来说,这些是我为呈现视频捕获而采取的步骤:
- 列出
MFEnumDeviceSources()
的可用设备 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
并让用户 select 一个
- 在激活源并使用
CreatePresentationDescriptor()
创建演示描述符后,列出基于 GetStreamDescriptorCount()
的流,并让用户 select 一个流(如果有多个流可用)
- 根据
GetMediaTypeByIndex()
可用的 IMFMediaType
列表显示所有支持的视频格式,并让用户选择一个
一旦 select 确定了确切的格式,我就这样构建拓扑:
- 调用
MFCreateTopology()
创建一个新的IMFTopology
对象
- 使用
MFCreateVideoRendererActivate()
创建媒体接收器激活
- 确保在当前 select 编辑的
IMFStreamDescriptor
的 IMFMediaTypeHandler
对象上调用 SetCurrentMediaType()
- 使用
MFCreateTopologyNode()
创建源节点,通过调用 SetUnknown()
设置其表示和流描述符并将该节点添加到拓扑
- 确保将其当前
IMFMediaType
设置为用户使用 SetCurrentMediaType()
选择的那个
- 创建一个输出节点并调用
SetObject()
它提供先前创建的媒体接收器激活对象(来自上面的第 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
对象的方法:
得到 IMFGetService
:
hr = m_session->QueryInterface<IMFGetService>(&service);
得到 IMFVideoDisplayControl
:
hr = service->GetService(MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl, (void**)&control);
一旦你有了显示控制对象,你就可以实现剩下的了。在我的例子中(因为我知道预期视频的实际真实几何形状)解决方案是将 纵横比模式 设置为 MFVideoARMode_None
学习(痛苦地)如何使用 Topology 和 Session 来呈现捕获的视频。没什么特别的 - 只是 select 一个网络摄像头,列出其模式,选择视频格式并点击 "go"。总的来说,这些是我为呈现视频捕获而采取的步骤:
- 列出
MFEnumDeviceSources()
的可用设备MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
并让用户 select 一个 - 在激活源并使用
CreatePresentationDescriptor()
创建演示描述符后,列出基于GetStreamDescriptorCount()
的流,并让用户 select 一个流(如果有多个流可用) - 根据
GetMediaTypeByIndex()
可用的IMFMediaType
列表显示所有支持的视频格式,并让用户选择一个
一旦 select 确定了确切的格式,我就这样构建拓扑:
- 调用
MFCreateTopology()
创建一个新的IMFTopology
对象 - 使用
MFCreateVideoRendererActivate()
创建媒体接收器激活- 确保在当前 select 编辑的
IMFStreamDescriptor
的
IMFMediaTypeHandler
对象上调用SetCurrentMediaType()
- 确保在当前 select 编辑的
- 使用
MFCreateTopologyNode()
创建源节点,通过调用SetUnknown()
设置其表示和流描述符并将该节点添加到拓扑- 确保将其当前
IMFMediaType
设置为用户使用SetCurrentMediaType()
选择的那个
- 确保将其当前
- 创建一个输出节点并调用
SetObject()
它提供先前创建的媒体接收器激活对象(来自上面的第 5 步) - 使用
ConnectOutput()
将源连接到输出并为其提供节点 ID0
单击 "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
对象的方法:
得到
IMFGetService
:hr = m_session->QueryInterface<IMFGetService>(&service);
得到
IMFVideoDisplayControl
:hr = service->GetService(MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl, (void**)&control);
一旦你有了显示控制对象,你就可以实现剩下的了。在我的例子中(因为我知道预期视频的实际真实几何形状)解决方案是将 纵横比模式 设置为 MFVideoARMode_None