将视频数据捕获到屏幕和文件
Posted
技术标签:
【中文标题】将视频数据捕获到屏幕和文件【英文标题】:Capturing Video Data to Screen and File 【发布时间】:2018-09-08 16:33:04 【问题描述】:我正在编写一个尽可能简单的演示应用程序,它从网络摄像头读取传入数据并将其显示到屏幕上,并且(可选地在按钮的切换处)将视频流记录到磁盘。为此,我实现了一个标准的 WMF 管道架构,从充当媒体源的 WebCam 到充当媒体接收器的 EVR。为了实现文件捕获功能,我修改了一个简单的 MFT(FrameCounter MFT),如果 Sink Writer 对象可用,也将传入的样本写入 Sink Writer。因此,所有数据都通过 MFT 从源传输到接收器,如果 MFT 可以使用 Sink Writer,它也会将样本数据写入 Sink Writer。
MFT 在从其输出处理循环返回之前进行就地处理并释放样本。在释放发生之前,对 sink writer 的写入只是在其 WriteSample() 调用中使用相同的输入样本。
问题是这段代码有效。我预计必须在 MFT 中复制样本并将其提供给 Sink Writer 以便它可以发布它。这引发了以下问题..
Sink Writer 是否制作自己的样本副本或添加自己对样本的引用?它会释放给它的样本吗?据我了解,Sink Writer 可以在编写这些样本之前将它们排队一段时间(如果它愿意的话)。 Sink Writers WriteSample() 调用中样本的一般处理方式是什么。
现在可以正常工作只是侥幸吗?我是在为以后或在较慢的机器上制造问题吗?上述技术是否有效?如果没有,推荐的方法是什么。我没有遇到任何奇怪的运行时错误。
我的印象是,在从网络摄像头捕获数据时,样本上的时间戳需要在写出之前重新设置基准。换句话说,写入的第一个样本的时间戳必须为 0,并且每个后续样本的时间戳都以此为基础进行调整。在这种情况下,这似乎没有必要。这个时基重置是一个要求吗(曾经有过)吗?我注意到 FileCapture 演示中的示例代码会注意做到这一点。微软是否在最近的版本中改进了 Sink Writer 来应对这个问题?
我正在使用 WMF.Net 在 C# 中开发 Windows 10。我意识到这可能是 CLR 及其垃圾收集的一个特殊情况——但是,我希望您能提供任何 WMF 见解(任何语言)。 Sink Writer 输出格式是 H.264——如果这很重要的话。
【问题讨论】:
【参考方案1】: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。
【讨论】:
谢谢。这几乎就是我的想法。关于该主题的可用信息似乎很少,当您稍微研究一下该主题时,您会遇到像这样的文章(blogs.msdn.microsoft.com/visualstudio/2010/03/01/… 这似乎是说 COM 对象可能不需要释放。这种情况更加复杂因为我是用 C# 编写的,它使用 Run Time Callable Wrappers 来封装 COM 对象,例如示例,而 RCW 似乎使用 C# 垃圾收集器进行引用和发布管理。以上是关于将视频数据捕获到屏幕和文件的主要内容,如果未能解决你的问题,请参考以下文章