DirectShow – 如何从源filter中读取文件

我正在编写一个注册为CLSID_VideoInputDeviceCategory的DirectShow源代码filter,因此可以将其视为一个video捕获设备(例如,将Skype视为另一个WebCam)。 我的源代码filter是基于这里的VCam示例,现在,filter产生如此示例的精确输出(带有一个video输出引脚的随机彩色像素,没有audio),全部在FillBuffer()方法中实现唯一的输出引脚。

现在真实场景会更加棘手 – filter使用文件句柄到硬件设备,使用CreateFile()API调用(打开设备不在我的控制之下,由3Party库完成)打开。 它应该从这个句柄中读取数据块(通常是256-512字节的块大小)。 该设备是一个WinUSB设备,3Party框架只是“给我”一个打开的文件句柄来读取块。 filter读取的数据是* .mp4文件,从设备stream式传输到“句柄”。

这种情况相当于从磁盘上的* .mp4文件(以“块”forms)读取源filter并将其数据推送到DirectShowgraphics,但无法从头到尾完全读取文件,因此文件大小是未知的(正确?)。

我对DirectShow非常陌生,感觉好像缺less一些基本概念。 如果有人能指导我解决以下问题的解决scheme\资源\解释,我会很高兴的。

1)从Web和Microsoft SDK(v7.1)示例中的各种源中,我了解到,为了构build正确和有效的DirectShowgraphics(因此它将成功呈现video和audio)的应用程序(如Skype),源filter引脚(inheritance自CSourceStream)应该实现“GetMediaType”方法。 根据此实现函数的返回值,应用程序将能够构build正确的graphics来呈现数据,从而构build正确的filter顺序。 如果这是正确的 – 我将如何实现它在我的情况下,graphics将build立呈现* .mp4input块(我们可以假定恒定的块大小)?

2)我注意到FillBuffer()方法应该为它获取(和填充)的IMediaSample对象调用SetTime()。 我正在读取来自设备的原始* .mp4数据。 我将不得不parsing数据并从stream中提取帧和时间值吗? 如果是的话 – 一个例子会很棒。

3)是否必须将从文件句柄(“块”)接收的数据拆分为video和audio,还是可以将数据推送到graphics,而无需在源filter中对其进行操作? 如果需要拆分 – 如何完成(数据是不连续的,并分成大块),这将影响所需的“GetMediaType”的实现?

如果我使用不正确的术语,请随时纠正我。

谢谢 :-)

这是一个很好的问题。 一方面这是可行的,但也有一些具体的涉及。

首先, CLSID_VideoInputDeviceCategory类别下注册的过滤器预计将作为一个实时视频源。 通过这样做,您可以通过应用程序(例如Skype提供的应用程序)来发现这些应用程序,这些应用程序将尝试配置视频分辨率,他们希望视频以实时速率播放,而某些应用程序(如Skype)则不期望压缩这样的H.264视频,或只会拒绝这样的设备。 你既不能将音频附加到这个过滤器,因为应用程序甚至不会在那里寻找音频(不知道你的过滤器是否有音频,但你提到.MP4文件,所以音频可能在那里)。

在你的问题上:

1 – 通过检查应用程序在过滤器上调用哪些接口方法,可以更好地了解应用程序需求。 大多数方法都是由BaseClasses实现的,并将调用转换为内部方法,如GetMediaType 。 是的,您需要实现它,通过这样做,除了其他功能之外,您还可以通过尝试支持特定的媒体类型,使您的过滤器与下游的过滤器引脚连接。

再次,那些不能我MP4的块,即使这样的方法可以在其他DirectShow图表工作。 实现一个视频采集设备,你应该提供精确的视频帧,最好是解压缩(以及那些可以压缩,但你会立即与应用程序的兼容issys)。

您可能想到的一个解决方案是在内部嵌入一个功能齐全的图形,将其注入到您的MP4块中,然后流水线将这些块解析出来,解码并传递到您的自定义渲染器,并将帧从虚拟设备上重新曝光。 这可能是一个很好的设计,虽然假设对过滤器如何在内部工作有一定的了解。

2 – 您的设备通常被视为/预计将成为实时来源,这意味着您可以实时传送视频,并且帧不一定是时间标记。 所以你可以把时间放在那里,是的,你肯定需要从你的原始媒体中提取时间戳(或者如上面第1项所述,通过内部图表完成),但是要准备应用程序去掉时间戳,特别是为了预览目的,因为来源是“活”。

3 – 回到音频,您不能在同一个虚拟设备上实现音频。 那么你可以,而且这个过滤器甚至可以在一个定制的图形中工作,但是这不适用于应用程序。 他们将寻找单独的音频设备,如果你实现这样的话,他们会分开实例化它。 因此,您需要实现虚拟视频和虚拟音频源,并在幕后实施内部同步。 这就是时间戳很重要的地方,通过正确提供它们,您可以在实时会话中保持唇形同步,使其与原始流式传输媒体文件上的唇形同步。