我有许多模块必须实时处理视频流。简单的方法是有一个帧缓冲区,模块从那里获取视频图像、处理,然后删除它们。
问题 #1:并非所有模块都以相同的速度工作。有些能够处理所有帧,有些则不能。因此,某些模块不会处理所有帧。如果我在删除缓冲区之前等待所有模块完成工作,则较快的模块将无故停止(图 A)。
图 B 是一个简单的解决方案。每个模块一个单独的缓冲区。如果缓冲区已满,则不会将帧放在那里。但是问题 #2 出现了:内存被浪费:一些帧将在不同的缓冲区中有多个拷贝。
更聪明的解决方案是一个物理缓冲区,附加更多逻辑缓冲区,如图 C 所示。当至少一个逻辑缓冲区可以容纳一帧时,该帧被添加到实际缓冲区中,当链接到它的所有逻辑缓冲区都被删除时,该实际缓冲区被删除。 (智能指针给出了一个简单的实现方案——给所有可以容纳它的逻辑缓冲区添加一个指向缓冲区的智能指针)问题#3:可能发生,在最坏的情况下,每一帧都被分配给一个模块,而不是共享,这将是解决方案 B 的一个困惑的缺点。
问题
有没有更好的方法来处理这个问题?标准答案?实现它的模板库?
编辑 这种使用缓冲区但在缓冲区已满时删除帧的复杂机制在不同平台上提供了一种可扩展的解决方案:我处理尽可能多的帧,而不管模块或硬件性能如何。
最佳答案
以下是我在生产实时视频系统中看到的两种方法:
与选项 A 类似,存储单个缓冲区列表,但向每个缓冲区添加两组标志。第一组标志指定缓冲区需要执行哪些任务,第二组标志指定已经执行了哪些任务。当每个模块准备就绪时,它将扫描缓冲区列表,直到找到它可以提供帮助的缓冲区。
与选项 C 类似,使用包含指向实际帧数据的指针的多个 fifos。使用 reference counting跟踪哪些帧仍然有效。这意味着每次你创建一个指向帧的新指针时,你都会调用一个函数来增加它的引用计数,而每次你完成指针的操作时,你都会调用一个函数来减少引用计数。一旦它们的引用计数达到零,就可以重复使用帧。
在我看来,第一种方法实现起来更简单,如果你有少量未完成的帧和少量处理任务就可以了,但第二种方法更通用,应该更容易扩展到更复杂的系统系统。
关于c++ - 一个真实帧缓冲区中的多个逻辑缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9938432/