C++ 在directshow中同步输入引脚

C++ 在directshow中同步输入引脚,c++,directshow,C++,Directshow,我正在创建一个directshow过滤器,其目的是获取3个输入管脚,并创建一个视频,在固定时间内交替显示来自第一个源、第二个源和第三个源的视频 因此,如果我有三个摄像头连接到我的过滤器,我希望最后的视频,例如,显示5秒的第一个摄像头,5秒的第二个摄像头,等等 我尝试了两种方法: 方法一 我使用班级时间管理器。此类有一个函数isItPinsTurn(pinname)。此函数返回关于pin是否应该将样本发送到输出的true或false。为此,TimeManager创建一个新线程,该线程每x秒休眠一次

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

因此,如果我有三个摄像头连接到我的过滤器,我希望最后的视频,例如,显示5秒的第一个摄像头,5秒的第二个摄像头,等等

我尝试了两种方法:

方法一

我使用班级时间管理器。此类有一个函数isItPinsTurn(pinname)。此函数返回关于pin是否应该将样本发送到输出的true或false。为此,TimeManager创建一个新线程,该线程每x秒休眠一次。 休眠后,它会将当前活动的inputpin更改为下一个。 结果是每x秒isItPinSTurn(pinname)函数返回另一个pin。这样,当轮到每个管脚时,每个管脚只需几秒钟就可以输出到outputpin,因此我在输入cam之间通过x间隔获得所需的视频

这种方法的问题

在directshow筛选器中,睡眠似乎不起作用。我得到一个运行时错误:

已调用abort()

方法二

我使用samples 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(由input pins receie函数调用)可根据MediaSample MediaTime的大小调整mediaTimeBUffer。如果此缓冲区高于MEDIATIME(例如,可以是5(秒)),则缓冲区将设置回零,并且下一个引脚将设置为活动

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

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

是的,效果很好,尽管投票是最糟糕的选择

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

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

  • -在源中可用,可从2+流多路传输数据