首页 > 解决方案 > 将视频数据捕获到屏幕和文件

问题描述

我正在编写一个尽可能简单的演示应用程序,它从网络摄像头读取传入数据并将其显示到屏幕上,并且(可选地在按钮的切换处)将视频流记录到磁盘。为此,我实现了一个标准的 WMF 管道架构,从充当媒体源的 WebCam 到充当媒体接收器的 EVR。为了实现文件捕获功能,我修改了一个简单的 MFT(FrameCounter MFT),如果 Sink Writer 对象可用,也将传入的样本写入 Sink Writer。因此,所有数据都通过 MFT 从源传输到接收器,如果 MFT 可以使用接收器写入器,它也会将样本数据写入接收器写入器。

MFT 在从其输出处理循环返回之前进行就地处理并释放样本。在释放发生之前,对 sink writer 的写入只是在其 WriteSample() 调用中使用相同的输入样本。

问题是这段代码有效。我预计必须在 MFT 中复制样本并将其提供给 Sink Writer 以便它可以发布它。这提出了以下问题..

  1. Sink Writer 是否制作自己的样本副本或添加自己对样本的引用?它会释放给它的样本吗?据我了解,Sink Writer 可以在编写这些样本之前将它们排队一段时间(如果它愿意的话)。Sink Writers WriteSample() 调用中对样本的一般处理是什么。

  2. 这只是一个侥幸,现在正在工作,我是在为以后或在较慢的机器上制造问题吗?上述技术是否有效?如果没有,推荐的方法是什么。我没有遇到任何奇怪的运行时错误。

  3. 我的印象是,在从网络摄像头捕获数据时,样本上的时间戳需要在写出之前重新设置基准。换句话说,写入的第一个样本的时间戳必须为​​ 0,并且每个后续样本的时间戳都以此为基础进行调整。在这种情况下,这似乎没有必要。这个时基重置是一个要求吗(曾经有过)吗?我注意到 FileCapture 演示中的示例代码会注意做到这一点。微软是否在最近的版本中改进了 Sink Writer 来应对这个问题?

我正在使用 WMF.Net 在 C# 中使用 Windows 10。我意识到这可能是 CLR 及其垃圾收集的一个特殊情况——但是,我希望您能提供任何 WMF 见解(任何语言)。Sink Writer 输出格式是 H.264——如果这很重要的话。

标签: ms-media-foundation

解决方案


1- Sink Writer 并没有真正记录它对样本的作用。为了提高效率,我想它只是样本上的“AddRef”。如果您在每次视频捕获后创建一个新样本,您只需在 WriteSample 之后发布它。Sink Writer 不会有问题。

2-对于较慢的机器,它的工作原理相同。也许您将不得不放弃样品以提高效率,但这与发布样品无关。

3- IMFSinkWriter 文档中的 WriteSample 方法没有明确说明是否需要采样时间/持续时间。所以我会说,如有必要,请设置它们。

编辑

我上面的解释是关于 C++ 的。C# COM 互操作是另一回事。

我阅读了有关 interop com 的文章。看来C#开发者在调用Marshal.ReleaseComObject之后并没有将对象设置为nullptr,而是复用了。他们收到 InvalidComObjectException。如果你 AddRef,Release ans 设置为 NULL,就像在 C++ 中一样,我认为你不会有问题(RCW 也在做引用计数)。

对于用托管代码重写 COM 对象的情况:

据我所知,MediaFoundation 组件是本机代码。我怀疑他们将它们更改为托管代码。即使发生这种情况,您也只需要抑制 Marshal.ReleaseComObject,或者现在使用 IsComObject。


推荐阅读