(痛苦地)学习如何使用拓扑和会话来呈现捕获的视频。没什么特别的——只需选择一个网络摄像头,列出它的模式,选择一种视频格式,然后点击“开始”。一般来说,这些是我呈现视频捕获的步骤:
- 列出具有
MFEnumDeviceSources()
过滤条件的可用设备MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
并让用户选择一个 GetStreamDescriptorCount()
在激活源并创建 Presentation Descriptors 之后列出流CreatePresentationDescriptor()
并让用户选择一个流(如果有多个流可用)- 根据
IMFMediaType
可用的列表显示所有支持的视频格式,GetMediaTypeByIndex()
并让用户选择一种
一旦选择了确切的格式,我就会以这种方式构建拓扑:
- 调用
MFCreateTopology()
创建一个新IMFTopology
对象 - 创建媒体接收器激活
MFCreateVideoRendererActivate()
- 确保调用当前选择
SetCurrentMediaType()
的对象IMFMediaTypeHandler
IMFStreamDescriptor
- 确保调用当前选择
- 创建源节点
MFCreateTopologyNode()
,通过调用设置其表示和流描述符SetUnknown()
并将该节点添加到拓扑- 确保将其电流设置
IMFMediaType
为用户选择的SetCurrentMediaType()
- 确保将其电流设置
- 创建一个输出节点并调用
SetObject()
它,提供先前创建的媒体接收器激活对象(来自上面的步骤 5) - 将源连接到输出并
ConnectOutput()
为其提供节点 ID0
单击“预览”按钮时,会IMFMediaSession
使用新拓扑设置会话对象(在应用程序启动时创建)
m_session->SetTopology(MFSESSION_SETTOPOLOGY_IMMEDIATE, pTopo);
这就是我看到一些奇怪的地方。我根据用户选择的帧尺寸设置预览视频的大小,IMFMediaType
并且源似乎正在以该格式生成视频。然而,渲染器错误地处理了像素纵横比,并且在将图片呈现为垂直或水平拉伸的同时对视频进行了信箱/邮筒处理。
对于我的一生,我无法找到告诉渲染器调整正确像素纵横比的方法(在上面的步骤 5.1 中设置为正确的值)
MS 的 SDK 示例仅显示如何为未压缩格式呈现捕获的视频 - 它不使用IMFMediaSession
对象并且适用于YUV2
格式但不适用于MJPG
. 事实上,它工作得很好,我认为继续使用会话会很容易:)
使用IMFMediaSession
似乎是支持压缩视频格式的最简单的方式,尤其是H.264
在较新的UVC 1.5
标准中以及H.265
将来出现的任何新 (?) 格式中。