从可在多个客户端识别的实时流制作视频帧

时间:2015-04-29 09:32:07

标签: video ffmpeg video-streaming live-streaming

我需要将视频流从实时源分发到多个客户端,并要求所有客户端都能识别每个帧。

我已经对这个主题进行了研究,并且我已经找到了一个可以分享的可能解决方案。我的解决方案似乎不是最理想的,这是我第一次使用视频流,所以我想知道是否有人知道更好的方式。

我需要能够识别视频流中的特定帧的原因是,流媒体客户端需要能够讨论每个事件在其视频流中识别的事件之间的时间差异。

一个澄清的例子

我想启用以下互动:

  • 两个客户端应用程序Dewey和Stevie连接到流媒体服务器
  • Dewey显示流,Stevie将其保存到磁盘
  • Dewey确定了Stevie感兴趣的特定视频帧,因此他想告诉Stevie它
  • 杜威从视频帧中提取一些识别信息并将其发送给Stevie
  • Stevie使用识别信息从他当前正在保存的直播的副本中提取相同的框架

杜威不能直接将框架发送给Stevie,因为Malcolm和Reese也想告诉他特定的视频帧,Stevie对他们的发现之间的时差感兴趣。

建议的解决方案

我找到的解决方案是使用ffserver来广播RTP流,并使用RTCP数据包中的时间戳来识别帧。这些时间戳通常用于同步音频和视频,而不是为多个客户端提供共享时间线,这就是为什么我怀疑这是解决问题的最佳方法。

拥有帧数似乎也是有益的,比如增加帧的计数器而不是任意时间戳增加一些可能变化的偏移量,因为我的应用程序我也必须引用相邻帧,并且似乎更容易计算帧的时间差数字,而不是相反。

2 个答案:

答案 0 :(得分:1)

我们最终没有完成项目的完成,遗憾的是我无法提供任何源代码,但我们在概念上开发了两种解决方案,这些解决方案可能对解决同一问题的其他人有用。 第一个解决方案是实现预期目标的最小努力解决方案,而第二个解决方案是更灵活的设计,利用RTCP支持各种视频格式。

快速而肮脏

您从MJPEG流的现有实现开始,或者从具有源代码的自包含帧的类似相当简单的视频编解码器开始,并在该格式下放置无损传输层(如TCP或HTTP)。

1)您可以在视频编解码器实现中添加单个函数,该函数可以从帧的图像数据中生成散列,如SHA1。

2)你向你的服务器实现添加一个(持久的)Map,让我们把它称为 framemap ,它将你的哈希作为键,并返回一个整数作为它的值。

3)当您将视频编码为服务器上的输出格式时,计算每个帧的哈希值并将其放入 framemap 中,并使用递增整数来标识帧。

4)您向服务器添加了一些额外的API,客户端可以在其中为您提供哈希值,然后在 framemap 中查找并返回相应的增加帧编号。

5)在客户端上,如果你想知道递增的帧号,你计算帧的哈希值,向服务器API询问帧哈希值,然后它会发回增加的帧号。

在此设计中,您只需在视频编解码器的某处添加散列功能,并在其他位置添加其他内容。

清洁设计

这取决于RTP协议及其RTCP控制流。 每个RTP数据包都有一个时间戳,表示所包含帧的预期显示时间,但它的起始值是随机的,因此您需要查看RTCP控制流,它为您提供服务器的NTP时间戳以及相应的显示时间。从这里你应该能够根据服务器的NTP时钟计算相当精确的时间戳。我们尝试将支持此功能的功能添加到VLC,结果证明相当困难,因为VLC具有相当复杂的代码库,可以将来自不同位置的大量代码汇集在一起​​。因此,您可能希望在此处扩展更简单的实现,具体取决于您的要求。

请看一下RFC 2326 - 第3.6章正常播放时间和第3.7章绝对播放时间。

答案 1 :(得分:0)

取决于格式。例如,MPEG传输流使用Program Clock Reference(PCR)。为了帮助您入门,使用ffplay,您可以获得一帧的Presentation Time Stamp(PTS)和帧数。我不确定帧数是否有用,因为它取决于播放开始时间。

ffplay -i <input stream> -vf showinfo

PCR值将在某个时刻回合,因此您也必须考虑到这一点。