Windows DirectShow-如何从源筛选器读取文件

Windows DirectShow-如何从源筛选器读取文件,windows,sdk,directshow,Windows,Sdk,Directshow,我正在编写一个DirectShow源过滤器,该过滤器注册为CLSID_VideoInputDeviceCategory,因此可以将其视为视频捕获设备(例如,从Skype,可以将其视为另一个网络摄像头)。 我的源过滤器基于的VCam示例,目前,该过滤器生成与此示例相同的精确输出(带有一个视频输出管脚的随机彩色像素,还没有音频),所有这些都是在唯一输出管脚的FillBuffer()方法中实现的 现在,真正的场景会有点棘手-过滤器使用硬件设备的文件句柄,使用CreateFile()API调用打开(打开

我正在编写一个DirectShow源过滤器,该过滤器注册为CLSID_VideoInputDeviceCategory,因此可以将其视为视频捕获设备(例如,从Skype,可以将其视为另一个网络摄像头)。 我的源过滤器基于的VCam示例,目前,该过滤器生成与此示例相同的精确输出(带有一个视频输出管脚的随机彩色像素,还没有音频),所有这些都是在唯一输出管脚的FillBuffer()方法中实现的

现在,真正的场景会有点棘手-过滤器使用硬件设备的文件句柄,使用CreateFile()API调用打开(打开设备超出我的控制,由3Party库完成)。然后它应该从这个句柄读取数据块(通常是256-512字节的块大小)。 该设备是一个WinUSB设备,3Party框架只是“给”了我一个打开的文件句柄来读取数据块。 过滤器读取的数据是一个*.mp4文件,从设备传输到“句柄”

此场景相当于源筛选器从磁盘上的*.mp4文件(以“块”形式)读取数据并将其数据推送到DirectShow图形,但无法从开始到结束完全读取文件,因此文件大小未知(正确吗?)

我对DirectShow还很陌生,我觉得自己好像缺少了一些基本概念。如果有人能告诉我以下问题的解决方案\资源\解释,我将非常高兴:

1) 从web上的各种来源和Microsoft SDK(v7.1)示例中,我了解到,对于应用程序(如Skype)来说,要构建正确有效的DirectShow图形(以便成功呈现视频和音频),源筛选器pin(继承自CSourceStream)应实现方法“GetMediaType”。根据此实现函数的返回值,应用程序将能够构建正确的图形来呈现数据,从而构建正确的过滤器顺序。如果这是正确的-我将如何在我的案例中实现它,以便构建图形以呈现区块中的*.mp4输入(我们可以假设恒定区块大小)

2) 我注意到FillBuffer()方法应该为它获取(并填充)的IMediaSample对象调用SetTime()。我正在从设备读取原始的*.mp4数据。我必须解析数据并从流中提取帧和时间值吗?如果是,举个例子就好了

3) 我是否必须将从文件句柄(“块”)接收的数据拆分为视频和音频,或者是否可以将数据推送到图形,而无需在源过滤器中对其进行操作?如果需要分割-如何进行分割(数据不是连续的,并且被分割成块),这会影响“GetMediaType”的预期实现吗

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


谢谢:-)

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

首先,在
CLSID\u VideoInputDeviceCategory
类别下注册的过滤器应作为实时视频源。通过这样做,您可以让应用程序(如您提到的Skype)发现它,并且这些应用程序将尝试配置视频分辨率,他们希望视频以实时速率传输,一些应用程序(如Skype)不希望压缩视频(如H.264)出现,或者只会拒绝此类设备。您既不能将音频权限附加到此过滤器,因为应用程序甚至不会在那里查找音频(不确定您的过滤器上是否有音频,但您提到了
.MP4
文件,因此音频可能在那里)

关于你的问题:

1-通过检查应用程序在过滤器上调用的接口方法,可以更好地了解应用程序需求。大多数方法由基类实现,并将调用转换为内部方法,如
GetMediaType
。是的,您需要实现它,通过这样做,您将通过尝试您支持的特定介质类型,使您的过滤器能够与下游过滤器引脚连接

同样,即使这种方法可以在其他DirectShow图形中使用,也不能使用MP4块。实现一个视频捕获设备,你应该提供准确的视频帧,最好是解压缩的(这些也可以被压缩,但你将立即与应用程序兼容)

您可能正在考虑的一个解决方案是在内部嵌入一个功能齐全的图形,将MP4块注入其中,然后管道解析这些图形,解码并将其传递到自定义渲染器,从虚拟设备上获取重新公开它们的帧。这可能是一个很好的设计,但前提是对过滤器内部工作方式有一定的了解

2-您的设备通常被视为/预期为实时视频源,这意味着您可以实时发送视频,并且帧不一定带有时间戳。因此,您可以将时间放在那里,是的,您肯定需要从原始媒体中提取时间戳(或通过上面第1项中提到的内部图表进行提取),但是,请准备好应用程序剥离时间戳,特别是用于预览目的,因为源是“实时的”

3-回到音频,您无法在同一虚拟设备上实现音频。当然可以,这个过滤器甚至可以在自定义构建的图中工作,但这不适用于应用程序。他们将寻找单独的音频设备,如果您实现了这样的设备,他们将单独实例化它。因此,您需要实现虚拟视频和虚拟音频源,并在后台实现内部同步。这就是时间戳的重要性所在,通过正确地提供时间戳,您可以在直播会话中保持唇形同步,与您流媒体文件中的原始内容保持同步