(痛苦地)学习如何使用拓扑和会话来呈现捕获的视频。没什么特别的——只需选择一个网络摄像头,列出它的模式,选择一种视频格式,然后点击“开始”。一般来说,这些是我呈现视频捕获的步骤:
- 列出具有
MFEnumDeviceSources()过滤条件的可用设备MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID并让用户选择一个 GetStreamDescriptorCount()在激活源并创建 Presentation Descriptors 之后列出流CreatePresentationDescriptor()并让用户选择一个流(如果有多个流可用)- 根据
IMFMediaType可用的列表显示所有支持的视频格式,GetMediaTypeByIndex()并让用户选择一种
一旦选择了确切的格式,我就会以这种方式构建拓扑:
- 调用
MFCreateTopology()创建一个新IMFTopology对象 - 创建媒体接收器激活
MFCreateVideoRendererActivate()- 确保调用当前选择
SetCurrentMediaType()的对象IMFMediaTypeHandlerIMFStreamDescriptor
- 确保调用当前选择
- 创建源节点
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将来出现的任何新 (?) 格式中。