我试图用directshow同时播放多个图表。在做了一些研究后,我在How to play multiple videos in sync over multiple monitors using directshow?
找到了Geraint Davies的绝佳解决方案
- 选择一张图作为主图。
- 确保主人有时钟。这通常在去的时候完成 活跃,但您可以通过调用强制它发生 图上的SetDefaultSyncSource。
- 查询IMediaFilter的图表,从主站获取时钟 使用GetSyncSource的图形并使用它将其传递给其他图形 SetSyncSource。
- 暂停所有图表。
- 等到GetState返回S_OK(暂停完成)。
- 从图表中获取时间并添加10毫秒左右。
- 调用IMediaFilter ::在所有图表上运行,通过此时间(现在+ 10ms) 作为参数。
醇>
结果非常好,视频在视觉上同步显示。 但是,当我使用IMediaFilter :: Run进行测试时,有些事情让我感到困扰。
我试图将一个大的偏移值传入IMediaFilter :: Run,例如(现在+ 1000ms),视频似乎仍然在视觉上立即开始,而不是在开始之前延迟1000ms。
这种行为是正常的还是我做错了什么?
编辑:感谢您的快速回复,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-&gt; GetTime)都给了我一个巨大飞跃的参考时间(可能是由于我给出的巨大偏移)。 这是你在流时间前进的意思吗? 如何检查音频渲染器是否提供时钟?
答案 0 :(得分:1)
这可能是由您的音频渲染器引起的。如果它提供时钟,它可能会立即开始播放,忽略实际的开始时间(我已经看到了一些音频渲染器的这个问题)。然后一旦它运行,时钟上的时间你正在播放的内容。所以你会看到流时间向前跳跃。也许你可以检查一下?