【问题标题】:DirectShow data copy is TOO slowDirectShow 数据复制太慢了
【发布时间】:2018-06-10 05:23:07
【问题描述】:

有 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)它非常快。

【问题讨论】:

  • 这种内存页的感觉只是捕获设备上的物理缓冲区的链接。在 USB 3.0 线的另一端。并且 memcpy 每次都会在其 USB 连接中复制部分数据,然后将其关闭。
  • 如果您尝试在渲染器之前插入 tee 过滤器?然后,您可以尝试从第二个引脚转储视频数据。
  • 谢谢大家。我在我的图中枚举了过滤器,并看到 capturepraphbuilder2 自己添加了 2 个过滤器。 Smart Tee 和 AVI 解压器。有些奇怪的是,AVI Decompessor 什么都不做。输入和输出格式相同(yuy2)。但是我找到了它的第一个引脚,获取缓冲区并且它不在显存中,所以我通过预定义的 LUT 表非常快(

标签: c performance memory directshow screen-capture


【解决方案1】:

从本质上讲,视频内存(可能)读回速度很慢(例如VMR9 IBasicVideo->GetCurrentImage very slow,您可以找到其他参考资料)。您通常希望在数据实际到达显存之前获取数据。

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

【讨论】:

  • 显存写入速度快,从[到系统内存]读回速度慢。
  • 显存的性质?你的意思是我的视频卡上的内存有很多问题要复制吗?现在它工作正常。我从监视器 1 中获取数据并将其显示在监视器 2 上。现在延迟大约0.5 秒。我只需要每秒一帧来分析它。(可能是异步的)所有其他 59 帧应尽可能快地显示。 (
  • 认为它从 USB 直接写入显存。
  • 似乎唯一的方法是编写自己的过滤器:(
  • 或者您也可以尝试使用本文的memcpy 替代副本:Copying Accelerated Video Decode Frame Buffers。如果我没记错的话,VirtualDub 源代码中也有一些复制实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 2013-03-10
  • 2014-06-07
  • 2016-05-31
  • 2011-07-07
  • 2015-08-23
相关资源
最近更新 更多