我正在编写一个注册为CLSID_VideoInputDeviceCategory的DirectShow源过滤器,因此可以将其视为视频捕获设备(例如,来自Skype,它被视为另一个WebCam)。 我的源滤波器基于来自here的VCam示例,并且,就目前而言,滤波器产生精确输出,如此示例(具有一个视频输出引脚的随机彩色像素,还没有音频),全部在FillBuffer中实现()方法是唯一的输出引脚。
现在真实情况会有点棘手 - 过滤器使用硬件设备的文件句柄,使用CreateFile()API调用打开(打开设备不受我的控制,由3Party库完成) )。然后它应该从该句柄读取数据块(通常为256-512字节块大小)。 该设备是一个WinUSB设备,3Party框架只是“给我”一个打开的文件句柄来读取块。 过滤器读取的数据是* .mp4文件,从设备流式传输到“句柄”。
此方案相当于从磁盘上的* .mp4文件读取的源过滤器(在“块”中)并将其数据推送到DirectShow图,但无法从头到尾完全读取文件,所以文件大小未知(正确吗?)。
我对DirectShow很新,我觉得好像缺少一些基本概念。如果有人能指导我解决以下问题的解决方案\资源\解释,我会很高兴:
1)从Web上的各种来源和Microsoft SDK(v7.1)示例中,我了解到应用程序(如Skype)构建正确的&有效的DirectShow图形(因此它将成功呈现视频和音频),源过滤器引脚(继承自CSourceStream)应该实现方法“GetMediaType”。根据此实现函数的返回值,应用程序将能够构建正确的图形来呈现数据,从而构建正确的过滤器顺序。如果这是正确的 - 我将如何在我的情况下实现它,以便构建图形以在块中呈现* .mp4输入(我们可以假设常量块大小)?
2)我注意到FillBuffer()方法应该为它获取的IMediaSample对象调用SetTime()(并填充)。我正在从设备上读取原始* .mp4数据。我是否必须解析数据并提取帧和帧?来自流的时间值?如果是的话 - 一个例子会很棒。
3)我是否必须将从文件句柄(“块”)收到的数据拆分为Video& amp;音频,还是可以将数据推送到图形而无需在源过滤器中对其进行操作?如果需要拆分 - 如何完成(数据不连续,并且被分配到块)并且这会影响“GetMediaType”的所需实现吗?
如果我使用的术语不正确,请随时纠正我。
谢谢: - )
答案 0 :(得分:3)
这是一个很好的问题。一方面这是可行的,但有一些特定的涉及。
首先,在CLSID_VideoInputDeviceCategory
类别下注册的过滤器预计会充当实时视频源。通过这样做,您可以通过应用程序(例如您提到的Skype)发现它,并且这些应用程序将尝试配置视频分辨率,他们希望视频以实时速率运行,某些应用程序(例如Skype)不期望压缩视频这样的H.264那里或者只是拒绝这样的设备。您既不能将音频直接附加到此过滤器,因为应用程序甚至不会在那里查找音频(不确定您的过滤器上是否有音频,但是您提到.MP4
文件,因此可能存在音频)。
关于你的问题:
1 - 通过检查应用程序调用过滤器的接口方法,您可以更好地了解应用程序需求。大多数方法由BaseClasses实现,并将调用转换为内部方法,如GetMediaType
。是的,您需要实施它,通过这样做,您将 - 通过尝试您支持的特定媒体类型,使您的过滤器能够连接下游过滤器引脚。
同样,那些不能是我的MP4块,即使这样的方法可以在其他DirectShow图中工作。实现一个视频捕获设备,你应该提供精确的视频帧,最好是解压缩(那些也可以压缩,但你会立即与应用程序兼容)。
您可能正在考虑的解决方案是在内部嵌入一个功能完备的图形,您可以在其中注入MP4块,然后管道解析这些图形,解码并传送到您的自定义渲染器,从而重新曝光它们的帧你的虚拟设备。这可能是一个很好的设计,但假设对过滤器内部如何工作有一定的了解。
2 - 您的设备通常被视为/预期是实时来源,这意味着您实时传送视频,而且帧不一定带有时间戳。因此,您可以将时间放在那里,是的,您肯定需要从原始媒体中提取时间戳(或者通过上面第1项中提到的内部图表完成),但是应该准备应用程序剥离时间戳,尤其是出于预览目的,因为来源是“活的”。
3 - 返回音频,您无法在同一虚拟设备上实现音频。嗯,你可以,这个过滤器甚至可能在自定义构建的图形中工作,但这不适用于应用程序。他们将寻找单独的音频设备,如果你实现这样,他们将分别实例化它。因此,您需要实现虚拟视频和虚拟音频源,并在幕后实现内部同步。这是时间戳非常重要的地方,通过正确提供它们,您将在实时会话中保持唇形同步,使其与您最初流式传输的媒体文件中的内容保持同步。