我有两个过程,一个生产者和一个消费者。IPC是在Win32上使用OpenFileMapping/MapViewOfFile完成的。
生产者从另一个源接收视频,然后将视频传递给使用者,并通过两个事件进行同步。
制片人:
Receive frame
Copy to shared memory using CopyMemory
Trigger DataProduced event
Wait for DataConsumed event为消费者
Indefinitely wait for DataProducedEvent
Copy frame to own memory and send for processing
Signal DataConsumed event如果没有这些,视频平均为5fps。如果我将事件添加到双方,但没有CopyMemory,它仍然在5fps左右,虽然稍微慢一点。当我添加CopyMemory操作时,它会下降到2.5-2.8fps。Memcpy甚至更慢。
我很难相信一个简单的内存拷贝会导致这种减速。有什么补救办法吗?
下面是我创建共享mem的代码:
HANDLE fileMap = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, fileMapSize, L"foomap");
void* mapView = MapViewOfFile(fileMap, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, fileMapSize);大小是1024 * 1024 *3
编辑-添加了实际代码:
关于制片人:
void OnFrameReceived(...)
{
// get buffer
BYTE *buffer = 0;
...
// copy data to shared memory
CopyMemory(((BYTE*)mapView) + 1, buffer, length);
// signal data event
SetEvent(dataProducedEvent);
// wait for it to be signaled back!
WaitForSingleObject(dataConsumedEvent, INFINITE);
}关于消费者:
while(WAIT_OBJECT_0 == WaitForSingleObject(dataProducedEvent, INFINITE))
{
SetEvent(dataConsumedEvent);
}嗯,从DirectShow缓冲区复制到共享内存似乎毕竟是瓶颈。我试着用一个命名管道来传输数据,猜猜是什么-性能恢复了。
,有人知道为什么会这样吗?
为了添加一个我以前认为不相关的细节:生产者被注入并钩子到一个DirectShow图上来检索框架。
发布于 2010-08-24 13:59:17
复制内存涉及到引擎盖下的某些操作,对于视频来说,这可能是非常重要的。
我会尝试另一种方法:为每个帧或几个帧创建一个共享块。因此,将它们命名为block1、block2、block3等,以便收件人知道下一步要读取哪个块。现在直接将帧接收到已分配的blockX,通知使用者新块的可用性,然后立即分配并开始使用另一个块。使用者映射该块而不复制它--该块现在属于使用者,使用者可以在进一步处理时使用原始缓冲区。一旦使用者关闭了块的映射,此映射就被销毁。这样你就可以得到一个块流,并避免阻塞。
如果帧处理不需要花费太多时间,并且创建共享块,则可以创建一个共享块池,其大小足以确保生产者和使用者不会尝试使用同一个块(您可以使用信号量或mutx来保护每个块,从而使方案复杂化)。
希望我的想法是明确的-避免在生产者中使用这个块,而不是在消费者中复制。
发布于 2010-08-24 14:04:37
复制3MB内存所需的时间根本不应该被注意到。在我的旧笔记本电脑上进行了一次快速测试,在大约10秒钟内完成了10,000次memcpy(buf1, buf2, 1024 * 1024 * 3)操作。在1/1000秒,它不应该使你的帧速率减慢一个明显的数量。
无论如何,似乎有一些优化可能会出现,以加快速度。目前,您似乎是双倍或三重处理数据。双重处理,因为你“收到帧”,然后“复制到共享内存”。三重处理如果“复制帧到自己的内存并发送到处理”意味着您真正地复制到本地缓冲区,然后处理而不仅仅是从缓冲区处理。
另一种方法是直接将帧接收到共享缓冲区,并将其直接从缓冲区中处理出来。正如我所怀疑的那样,如果您希望在处理另一个帧时能够接收到另一个帧,则只需增加内存映射的大小,以容纳多个帧,并将其用作循环数组。在消费者方面,情况会是这样的。
char *sharedMemory;
int frameNumber = 0;
...
WaitForSingleObject(...) // Consume data produced event
frame = &sharedMemory[FRAME_SIZE * (frameNumber % FRAMES_IN_ARRAY_COUNT)
processFrame(frame);
ReleaseSemaphore(...) // Generate data consumed event和制片人
char *sharedMemory;
int frameNumber = 0;
...
WaitForSingleObject(...) // Consume data consumed event
frame = &sharedMemory[FRAME_SIZE * (frameNumber % FRAMES_IN_ARRAY_COUNT)
recieveFrame(frame);
ReleaseSemaphore(...) // Generate data produced event只需确保使用的信号量数据初始化为FRAME_IN_ARRAY_COUNT,生成的信号量数据初始化为0。
https://stackoverflow.com/questions/3556953
复制相似问题