简体   繁体   English

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

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

Learning (painfully) how to use the Topology and Session to present a captured video. 学习(痛苦地)如何使用拓扑和会话来呈现捕获的视频。 Nothing fancy - just select a web cam, list its modes, choose a video format and hit "go". 没什么-只需选择一个网络摄像头,列出其模式,选择一种视频格式,然后点击“开始”即可。 In general these are the steps I'm taking to present the video capture: 通常,这些是我要呈现的视频捕获步骤:

  1. List the available devices with MFEnumDeviceSources() filtered by MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID and let user select one 列出具有MFEnumDeviceSources()的可用设备,该设备由MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID过滤,然后让用户选择一个
  2. List the streams based on GetStreamDescriptorCount() after activating the source and creating Presentation Descriptors with CreatePresentationDescriptor() and let the user select a stream (if multiple streams are available) 在激活源并使用CreatePresentationDescriptor()创建Presentation Descriptor之后,基于GetStreamDescriptorCount()列出流,并让用户选择一个流(如果有多个流可用)
  3. Display all the supported video formats based on the list of IMFMediaType s available through GetMediaTypeByIndex() and let the user choose one 根据可通过GetMediaTypeByIndex()获得的IMFMediaType列表显示所有受支持的视频格式,并让用户选择一种

Once the exact format is selected I build the Topology this way: 选择了确切的格式后,我将以这种方式构建拓扑:

  1. call MFCreateTopology() to create a new IMFTopology object 调用MFCreateTopology()创建一个新的IMFTopology对象
  2. create media sink activation with MFCreateVideoRendererActivate() 使用MFCreateVideoRendererActivate()创建媒体接收器激活
    1. making sure to call SetCurrentMediaType() on the IMFMediaTypeHandler object of the currently selected IMFStreamDescriptor 确保在当前选定的IMFStreamDescriptorIMFMediaTypeHandler对象上调用SetCurrentMediaType()
  3. create the source node with MFCreateTopologyNode() , setting its presentation and stream descriptors with the call to SetUnknown() and adding that node to the Topology 创建与源节点MFCreateTopologyNode()与该呼叫到设置其呈现和流描述符SetUnknown()和添加该节点到拓扑
    1. made sure to set its current IMFMediaType to the one chosen by user with SetCurrentMediaType() 确保将其当前IMFMediaType设置为用户使用SetCurrentMediaType()选择的那个
  4. create an output node and call SetObject() of it providing the previously created media sink activation object (from step 5 above) 创建一个输出节点并调用它的SetObject()以提供先前创建的媒体接收器激活对象(来自上面的步骤5)
  5. connect the source to output with ConnectOutput() providing it with the node ID 0 使用ConnectOutput()将源连接到输出,并ConnectOutput()提供节点ID 0

When the "preview" button is clicked a session IMFMediaSession object (created at the app's startup) is set with the new Topology 单击“预览”按钮时,将使用新的拓扑设置会话IMFMediaSession对象(在应用程序启动时创建)

m_session->SetTopology(MFSESSION_SETTOPOLOGY_IMMEDIATE, pTopo);

And this is where I see something strange. 这就是我看到奇怪的地方的地方。 I set the size of the preview video based on the frame dimensions provided by the IMFMediaType that the user chose and the source seems to be producing the video in that format. 我根据用户选择的IMFMediaType提供的帧尺寸来设置预览视频的大小,并且源似乎正在以该格式生成视频。 However the renderer is handling the pixel aspect ratio incorrectly and is letterboxing/pillarboxing the video while presenting the picture as being stretched either vertically of horizontally. 但是 ,渲染器错误地处理了像素的长宽比,并且在将图片呈现为垂直或水平拉伸时,正在对视频进行信箱/竖箱显示。

For the life of me I am unable to find the way to tell the renderer to adjust for the proper pixel aspect ratio (which was set to the proper value in step 5.1 above) 为了我的一生,我无法找到方法告诉渲染器调整适当的像素长宽比(已在上面的步骤5.1中将其设置为适当的值)


The MS's SDK example only shows how to present captured video for uncompressed formats - it doesn't use the IMFMediaSession object and works fine for the YUV2 format but not for the MJPG . MS的SDK示例仅显示了如何以未压缩的格式显示捕获的视频-它不使用IMFMediaSession对象,并且对于YUV2格式可以正常工作,而对于MJPGMJPG In fact it worked so well that I thought moving onto using the session would be easy :) 实际上,它运行得很好,以至于我认为继续使用该会话很容易:)

Using the IMFMediaSession seems to be the least cumbersome way of supporting compressed video formats, especially the H.264 that's in the newer UVC 1.5 standard and any new ( H.265 ?) formats that are coming up in the future. 使用IMFMediaSession似乎是支持压缩视频格式的最简单的方法,尤其是更新的UVC 1.5标准中的H.264和将来出现的任何新的( H.265 ?)格式。

Further research has shown that one can access the renderer object by querying the session to get the service and then use that service to get the video display control . 进一步的研究表明,可以通过查询会话来访问渲染器对象以获取服务,然后使用该服务获取视频显示控件 That IMFVideoDisplayControl is the object that lets you control various aspects of the rendered video, including the aspect ratio of the image. IMFVideoDisplayControl是使您可以控制渲染视频的各个方面(包括图像的纵横比)的对象。

Here's how to get to that IMFVideoDisplayControl object: 以下是获取该IMFVideoDisplayControl对象的方法:

  1. get the IMFGetService : 获取IMFGetService

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

  2. get the IMFVideoDisplayControl : 得到IMFVideoDisplayControl

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

Once you have the display control object you can achieve the rest. 一旦有了显示控件对象,就可以完成其余工作。 In my case (since I knew the actual true geometry of the expected video) the solution was to set the aspect ratio mode to MFVideoARMode_None 就我而言(因为我知道期望视频的实际真实几何形状),解决方案是将纵横比模式设置为MFVideoARMode_None

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM