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