在directshow中同步输入引脚

Synchronizing input pins in directshow

本文关键字:输入 引脚 同步 directshow      更新时间:2023-10-16

我正在创建一个directshow过滤器,其目的是取3个输入引脚并创建一个视频,该视频交替显示来自第一个源,第二个源和第三个源的视频,在固定时间内。

如果我有三个网络摄像头连接到我的滤镜,我希望最后的视频显示第一个摄像头的5秒,第二个摄像头的5秒,以此类推…

我试过两种方法:

方法一个

我使用了一个类TimeManager。这个类有一个函数isItPinsTurn(pinname)。这个函数根据引脚是否应该将样本发送到输出返回真或假。为此,TimeManager会创建一个每x秒休眠一次的新线程。在它休眠后,它将当前的活动输入引脚转换为下一个。结果是,每隔x秒,isItPinSTurn(pinname)函数返回另一个引脚。这样一来,每个引脚只有秒输出到输出引脚,当它轮到,因此我得到所需的视频与输入凸轮之间的x间隔。

这个方法的问题

Sleep在directshow过滤器中似乎不起作用。我得到一个运行时错误:

abort()被调用

方法两个

我使用样本GetMediaTime方法和一个缓冲区,它可以跟踪多少视频样本在其mediatime方面,已经被发送到输出引脚。下面的代码可以很好地说明这一点:

void MyFilter::acceptFilterInput(LPCWSTR pinname, IMediaSample* sample)
{
    mylogger->LogDebug("In acceptFIlterInput", L"D:\TEMP\yc.log");
    if (wcscmp(pinname, this->currentInputPin) == 0)
    {
        outpin->Deliver(sample);
        LONGLONG timestart;
        LONGLONG timeend;
        sample->GetTime(&timestart, &timeend);
        *mediaTimeBuffer += timeend - timestart;
        if (*mediaTimeBuffer > this->MEDIATIME)
        {
            this->SetNextPinActive(pinname);
            *mediaTimeBuffer = 0;
        }
    }
}

当过滤器启动时,currentInputPin被设置为pin0(第一个)。调用acceptFilterInput(由输入引脚接收函数调用)根据mediassample - mediatime的大小调整mediaTimeBUffer。如果该缓冲区高于MEDIATIME(例如,可以是5(秒)),则缓冲区被设置回零,下一个引脚被设置为活动。

此方法存在的问题我甚至不确定CMediaSample->GetMediaTime是否返回我需要的数据,因为它似乎返回负数,这似乎没有多大意义。我没有找到关于GetMediaTime的返回值在web上的有用信息。

您应该阻止输入流上的执行(对IPin::Receive的传入调用),以便其他流可以赶上自己的流线程。您通常通过使用等待/同步api和函数来实现这一点,或者通过保持对媒体样本的引用,以便输入对等体将阻塞在空分配器上,等待媒体样本(缓冲区)可用。

是的,Sleep工作得很好,尽管轮询是最糟糕的选项。

方法二对我来说没有意义,因为我没有看到任何真正的同步:没有执行阻塞,也没有使引脚活动。您不能强制输入引脚上的数据,您只能等待调用新的媒体样本。所以你应该阻止在一个输入流/引脚上接受数据,直到你在另一个输入流/引脚上获得数据。

关于多路复用的一些有用的相关信息:

  • 如何制作DirectShow混频器滤波器-第1部分
  • 如何制作DirectShow多路滤波器-第2部分
  • GDCL MPEG-4多路复用器-可从源,并可以复用数据从2+流