DirectShow数据拷贝太慢了

时间:2017-12-29 20:40:33

标签: c performance memory directshow screen-capture

拥有USB 3.0 HDMI Capture设备。它使用YUY2格式(每像素2个字节)和1920x1080分辨率。

视频捕获输出引脚直接连接到视频渲染输入引脚。 一切都很好。它显示我1920x1080没有任何冻结。 但我需要每秒制作一次屏幕截图。所以这就是我的工作:

void CaptureInterface::ScreenShoot() {

    IMemInputPin* p_MemoryInputPin = nullptr;
    hr = p_RenderInputPin->QueryInterface(IID_IMemInputPin, (void**)&p_MemoryInputPin);
    IMemAllocator* p_MemoryAllocator = nullptr;
    hr = p_MemoryInputPin->GetAllocator(&p_MemoryAllocator);

    IMediaSample* p_MediaSample = nullptr;
    hr = p_MemoryAllocator->GetBuffer(&p_MediaSample, 0, 0, 0);

    long buff_size = p_MediaSample->GetSize(); //buff_size = 4147200 Bytes
    BYTE* buff = nullptr;
    hr = p_MediaSample->GetPointer(&buff);

    //BYTE CaptureInterface::ScreenBuff[1920*1080*2]; defined in header

    //--------- TOO SLOW (1.5 seconds for 4 MBytes) ----------
    std::memcpy(ScreenBuff, buff, buff_size);
    //--------------------------------------------

    p_MediaSample->Release();
    p_MemoryAllocator->Release();
    p_MemoryInputPin->Release();

    return;
}

使用此缓冲区的任何其他操作也非常慢。

但是如果我在其他数据上使用memcpy(我的班级中的2个数组,例如相同大小的4MB),速度非常快。 < 0.01sec

1 个答案:

答案 0 :(得分:1)

视频内存(可能)的性质很慢(例如VMR9 IBasicVideo->GetCurrentImage very slow,您可以找到其他引用)。您通常希望在数据实际到达视频内存之前获取数据。

此外,您读取数据的方式也不太可靠。你不知道你实际上正在复制什么帧,你甚至可能会读到黑暗或垃圾,反之亦然,你获得缓冲区的访问会冻结主视频流。这是因为您从可用缓冲池中获取未使用的缓冲区,而不是与特定视频帧对应的缓冲区。从这样的缓冲区中获取图像是在一个脆弱的假设中发生的,即先前流式帧中未使用的数据已初始化,但尚未被其他任何内容覆盖。