【问题标题】:DirectShow - How to read a file from a source filterDirectShow - 如何从源过滤器中读取文件
【发布时间】:2012-03-19 21:19:22
【问题描述】:

我正在编写一个注册为 CLSID_VideoInputDeviceCategory 的 DirectShow 源过滤器,因此可以将其视为视频捕获设备(例如,来自 Skype,它被视为另一个 WebCam)。 我的源过滤器基于来自here 的 VCam 示例,并且,目前,过滤器产生与此示例相同的输出(带有一个视频输出引脚的随机彩色像素,还没有音频),全部在 FillBuffer() 中实现唯一的输出引脚的方法。

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

这种情况相当于源过滤器从磁盘上的 *.mp4 文件(以“块”形式)读取并将其数据推送到 DirectShow 图形,但无法从头到尾完全读取文件,所以文件大小是未知的(对吗?)。

我对 DirectShow 还很陌生,感觉好像缺少一些基本概念。如果有人可以指导我解决以下问题的解决方案\资源\解释,我会很高兴:

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

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

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

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

谢谢:-)

【问题讨论】:

    标签: windows sdk directshow


    【解决方案1】:

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

    首先,您在CLSID_VideoInputDeviceCategory 类别下注册的过滤器应充当实时视频源。通过这样做,您可以使其被应用程序(例如您提到的 Skype)发现,并且这些应用程序将尝试配置视频分辨率,它们希望视频以实时速率传输,某些应用程序(例如 Skype)不希望压缩那里有 H.264 之类的视频,或者会拒绝此类设备。您既不能将音频直接附加到此过滤器,因为应用程序甚至不会在那里寻找音频(不确定您的过滤器上是否有音频,但您提到了 .MP4 文件,因此音频可能在那里)。

    关于你的问题:

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

    再一次,那些不能我 MP4 块,即使这种方法可以在其他 DirectShow 图表中工作。实现视频捕获设备时,您应该准确地传送视频帧,最好是解压缩的(当然也可以压缩这些帧,但您将立即遇到与应用程序的兼容性问题)。

    您可能正在考虑的一个解决方案是在内部嵌入一个功能齐全的图表,您可以在其中注入您的 MP4 块,然后管道解析这些、解码并交付给您的自定义渲染器,获取您重新暴露它们的帧你的虚拟设备。这可能是一个不错的设计,但前提是您对过滤器内部的工作方式有一定的了解。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 2021-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多