7. DirectShow-内部时钟与音画同步

2023-09-04  本文已影响0人  天之彼方_d26a

内部时钟ReferenceTime

Filter Graph 管理器的一个功能是将图形中的所有filter同步到同一时钟(称为 ReferenceTime)。

任何公开 IReferenceClock 接口的对象都可以充当ReferenceTimeReferenceTime可能由 DirectShow filter提供,通常是音频呈现器,它有权访问硬件计时器。 作为回退,Filter Graph 管理器可以使用系统时间。

从名义上说,ReferenceTime以 100 纳秒的间隔测量时间,尽管时钟的实际准确度可能较低。 若要检索时钟的当前时间,请调用 IReferenceClock::GetTime 方法。 时钟的基线(开始计数的时间)取决于实现,因此 GetTime 返回的值本质上没有意义。 重要的是图形开始运行时的增量。

尽管ReferenceTime的准确性可能会有所不同,但 GetTime 方法返回的时间保证单调增加。 换句话说,时钟时间永远不会倒退。 如果ReferenceTime正在从硬件源生成时钟时间,并且硬件时钟向后跳 (例如,如果对时钟) 进行调整, 则 GetTime 方法应继续返回上次报告的时间,直到硬件时钟赶上为止。 有关详细信息,请参阅 CBaseReferenceClock 类。

默认的ReferenceTime来源(不重要)

filter图形管理器在图形运行时自动选择ReferenceTime。 它使用以下算法来选择时钟:

设置ReferenceTime(不重要)

应用程序可以通过在 Filter Graph Manager 上调用 IMediaFilter::SetSyncSource 方法来选择时钟。 仅当有特定原因首选另一个时钟时,才应执行此操作。

可以通过调用值为 NULL 的 SetSyncSource 来指示 Filter Graph 管理器不要使用ReferenceTime。 例如,可以执行此操作以尽快处理MediaSample。 若要还原默认ReferenceTime,请在 Filter Graph 管理器上调用 IFilterGraph::SetDefaultSyncSource 方法。

每当ReferenceTime更改时,Filter Graph 管理器都会通过调用其 IMediaFilter::SetSyncSource 方法通知每个filter。 应用程序绝不应在filter上调用此方法。

引用时间和流时间

DirectShow 定义了两个相关的时钟时间:引用时间和流时间。引用时间 是ReferenceTime返回的绝对时间。 (请参阅 ReferenceTime.)。流时间 相对于图形上次开始运行的时间进行定义。

当应用程序调用 IMediaControl::Run 来运行filter图时,Filter Graph 管理器在每个filter上调用 IMediaFilter::Run 。 为了补偿filter开始运行所花费的轻微时间,Filter Graph 管理器在将来会稍微指定一个启动时间。

时间戳

时间戳采用流时间

时间戳定义MediaSample的开始和完成时间,以流时间度量。 时间戳有时称为 呈现时间。 阅读本文的其余部分时,请务必记住,并非所有格式都以相同的方式使用时间戳。 例如,并非所有 MPEG 样本都带有时间戳。 在 MPEG filter图中,时间戳不会应用于每个帧,直到它们从解码器输出。

当呈现器filter收到MediaSample时,它会根据时间戳计划呈现。 如果样本迟到或没有时间戳,filter将立即呈现样本。 否则,filter将等到MediaSample的开始时间,然后才呈现MediaSample。 (它通过调用 IReferenceClock::AdviseTime 方法等待开始时间。)

filter和分析程序filter负责为其处理的样本设置正确的时间戳。 请遵循以下准则。

MediaTime

(可选)filter还可以指定样本的 媒体时间 。 在视频流中,媒体时间表示帧数。 在音频流中,媒体时间表示数据包中的样本数。 例如,如果每个数据包包含 44.1 千赫 (kHz) 音频的 1 秒,则第一个数据包的媒体开始时间为 0,媒体停止时间为 44100。 在可查找流中,媒体时间始终相对于流的开始时间。 例如,假设你从 15-fps 视频流的开始时间开始 2 秒。 搜寻后的第一个MediaSample的时间戳为零,但媒体时间为 30。

呈现器和复用器filter可以使用媒体时间,通过检查间隙来确定帧或样本是否已丢弃。 但是,不需要filter来设置媒体时间。 若要在MediaSample上设置媒体时间,请调用 IMediaSample::SetMediaTime 方法。

实时源(也称为 推送源)实时接收数据。

MediaSample包括视频捕获和网络广播。 通常,实时源无法控制数据的到达速率。如果存在以下任一情况,则filter被视为实时源:

延迟

filter的延迟是filter处理样本所需的时间。 对于实时源,延迟取决于用于保存样本的缓冲区的大小。 例如,假设filter图的延迟为 33 毫秒 (毫秒的视频源) ,音频源的延迟为 500 毫秒。 在匹配的音频样本到达音频呈现器之前,每个视频帧到达视频呈现器大约 470 毫秒。 除非图形补偿差异,否则音频和视频不会同步。

可以通过 IAMPushSource 接口同步实时源。 Filter Graph 管理器不会同步实时源,除非应用程序通过调用 IAMGraphStreams::SyncUsingStreamOffset 方法启用同步。 如果启用了同步,filter关系图管理器将查询 IAMPushSource 的每个源filter。 如果filter支持 IAMPushSource,filter关系图管理器会调用 IAMLatency::GetLatency 来检索filter的预期延迟。 (IAMPushSource 接口从组合的延迟值继承 IAMLatency.) ,filter关系图管理器确定图中的最大预期延迟。 然后,它调用 IAMPushSource::SetStreamOffset 为每个源filter提供流偏移量,该filter会将该偏移量添加到它生成的时间戳中。

此方法主要用于实时预览版。 但请注意,实时捕获设备上的预览固定 ((如相机) )不会在它提供的MediaSample上设置时间戳。 因此,若要将此方法用于实时捕获设备,必须从捕获引脚预览。 有关详细信息,请参阅 DirectShow 视频捕获filter

目前,VFW 捕获filter和音频捕获filter支持 IAMPushSource 接口。

速率匹配

如果呈现器filter使用一个ReferenceTime计划样本,但源filter使用不同的时钟生成样本,则播放时可能会出现故障。 呈现器运行速度可能比源快,从而导致数据间隙。 或者,它的运行速度可能比源慢,导致样本“堆起来”,直到图在某个时候会丢弃样本。 通常,实时源无法控制其生产速率,因此呈现器应将速率与源匹配。

目前,只有音频呈现器执行速率匹配,因为音频播放中的故障比视频中的故障更明显。 若要执行速率匹配,音频呈现器必须选择与速率匹配的内容。 它使用以下算法:

上一篇 下一篇

猜你喜欢

热点阅读