拥有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
答案 0 :(得分:1)
视频内存(可能)的性质很慢(例如VMR9 IBasicVideo->GetCurrentImage very slow,您可以找到其他引用)。您通常希望在数据实际到达视频内存之前获取数据。
此外,您读取数据的方式也不太可靠。你不知道你实际上正在复制什么帧,你甚至可能会读到黑暗或垃圾,反之亦然,你获得缓冲区的访问会冻结主视频流。这是因为您从可用缓冲池中获取未使用的缓冲区,而不是与特定视频帧对应的缓冲区。从这样的缓冲区中获取图像是在一个脆弱的假设中发生的,即先前流式帧中未使用的数据已初始化,但尚未被其他任何内容覆盖。