DirectShow解码器丢弃媒体时间

时间:2010-12-29 16:03:05

标签: c++ com filter directshow

在DirectShow中,媒体样本有两个与时间相关的属性:时间戳和媒体时间。我的应用程序需要寻找视频中的特定帧,因此需要媒体时间。但是,看起来大多数解码器过滤器都没有传递这些信息。

我有一个看起来像这样的DirectShow图:

[File Source (Async.)] -> [AVI Splitter] -> [<Video decoder>] -> [My filter]

我尝试过以下视频解码器:

  • 带有Mpeg4s解码器DMO的DMO包装滤波器(这是我机器上MPEG-4的默认设置)
  • Xvid MPEG-4视频解码器
  • MainConcept(演示)MPEG-4视频解码器
  • ffdshow视频解码器(ffdshow试用版)

在这四个中,只有ffdshow解码器生成具有媒体时间的样本。其他三个只设置时间戳,但将媒体时间留空。这看起来很奇怪,因为他们从AVI分离器获得的每个样本都正确设置了媒体时间。

有人知道为什么会这样吗?即使应用程序不断跳过视频,是否有一种解决方法可以使媒体时间可靠地工作?

编辑(回应kidjan):

我们假设我想阅读视频帧#100。使用25fps文件,此帧距视频4秒。使用过滤器图形的IMediaSeeking界面,我寻求到那个位置。在内部,该搜索请求被转发到分离器滤波器(示例中的AVI分离器)。但是,有两个潜在的问题:

  • 根据视频格式,我无法确定分割器是否能够精确地搜索帧#100。它可能会到达帧#95而我必须在获得正确的帧之前读取5帧。
  • 分离器可以是帧精确的,但是由于DirectShow的异步性质,解码器滤波器产生的下一帧可能是搜索之前的残留物。如果解码器过滤器使用线程,它可以在搜索操作之后传递该帧。

在这些情况下,如果解码器过滤器设置样本的媒体时间,将会很有帮助。这样,我就知道我收到了哪一帧。

我的问题归结为基本上:
如何在DirectShow图中获取特定的视频帧(按编号)?

2 个答案:

答案 0 :(得分:0)

我很困惑 - 你需要媒体时间来“......寻找视频中的特定帧”。为什么不用时间戳去寻求?此外,搜索通常由源过滤器处理,下游过滤器实际上不必做太多。我有一个看起来像的过滤器图:

[实施IMediaSeeking的自定义源过滤器] - &gt; [解码器滤波器] - &gt; [渲染]

......并且所有的搜寻都是用时间戳而不是媒体时间进行的。所以我不确定你为什么要使用媒体时间而不是时间戳。

您使用的是IMediaSeeking吗?

答案 1 :(得分:0)

并非所有解码器都遵循DirectShow的所有规则,因此丢失媒体时间是您必须承担的事情之一。如果你只使用AVI文件,那么在使用IMediaSeeking时只需要依赖分割器的准确性,并适当地使用IMediaControl的Stop()和Pause()来确保任何缓存的帧被解除,你就拥有了所需的帧。使用AVI文件,您可以从其标题中获得真实的帧速率,并在使用媒体时间失败时计算正确的搜索时间。

但对于非AVI文件,可能没有恒定的帧速率,并且使用媒体时间进行搜索在那里没有意义。