我试图用 directshow 同时播放多个图表。在做了一些研究之后,我在如何使用 directshow 在多个显示器上同步播放多个视频?
- 选择一张图作为主图。
- 确保主人有时钟。这通常在激活时完成,但您可以通过在图表上调用 SetDefaultSyncSource 来强制它提前发生。
- 查询 IMediaFilter 的图表,使用 GetSyncSource 从主图表中获取时钟,并使用 SetSyncSource 将其传递给其他图表。
- 暂停所有图表。
- 等到 GetState 返回 S_OK(暂停完成)。
- 从图中获取时间并添加 10ms 左右。
- 在所有图上调用 IMediaFilter::Run,将这个时间(现在 + 10 毫秒)作为参数传递。
结果非常好,视频在视觉上看起来很同步。但是,当我使用 IMediaFilter::Run 进行测试时,确实有一些事情困扰着我。
我试图将一个大的偏移值传递给 IMediaFilter::Run ,例如(现在 + 1000 毫秒),视频似乎仍然在视觉上立即开始,而不是在开始前延迟 1000 毫秒。
这种行为是正常的还是我做错了什么?
编辑:感谢您的快速回复,Roman R。我想当您说“视频时间”时,您的意思是时间戳?我会马上检查他们。
编辑:视频不仅显示第一帧,而且正常播放,没有任何延迟。我还发布了一些我所做的粗略代码。希望有人可以对此有所了解。
CComQIPtr<IMediaFilter>pMasterF(m_pMasterGraphBuilder);
CComQIPtr<IMediaFilter>pSlaveF(m_pSlaveGraphBuilder);
IReferenceClock* pClock;
HRESULT clkHR = pMasterF->GetSyncSource(&pClock); // Get Master Clock
pSlaveF->SetSyncSource(pClock); //Set slave to Master Clock
pMasterF->Pause(); //Pause Master
pSlaveF->Pause(); // Pause slave
FILTER_STATE sFs;
HRESULT hrcue;
hrcue = pMasterF->GetState(0, &sFs);
while(hrcue == VFW_S_STATE_INTERMEDIATE) { // wait for master to cue data
hrcue = pMasterF->GetState(0, &sFs);
if (hrcue == S_OK)
break;
Sleep(5);
}
FILTER_STATE ssFs;
HRESULT hrcues;
hrcues = pSlaveF->GetState(0, &ssFs);
while(hrcues == VFW_S_STATE_INTERMEDIATE) { // wait for slave cue data
hrcue = pSlaveF->GetState(0, &ssFs);
if (hrcues == S_OK)
break;
Sleep(5);
}
REFERENCE_TIME refTime;
HRESULT timeHR = pClock->GetTime(&refTime); // get master ref time
REFERENCE_TIME temp = refTime+100000000000000; // now + offset
pMF->Run(temp); // run master
pSF->Run(temp); // run slave
如您所见,我设置了一些荒谬的偏移量。但是,我仍然看不到任何延迟。也许我弄错了“现在”时间?
编辑:感谢您的回复,Geraint。我确实发现每个 IReferenceClock::GetTime 调用(pClock->GetTime) 都给了我一个巨大飞跃的参考时间(可能是由于我给出了巨大的偏移量)。这就是你所说的流时间向前跳跃的意思吗?如何检查音频渲染器是否提供时钟?