流媒体RTP/RTSP: 同步/时间戳问题

13

我在使用RTSP流传输H.264视频时遇到了问题。目标是将摄像头图像实时流式传输到RTSP客户端(最终最好是浏览器插件)。到目前为止,这种方式一直运行得非常好,除了一个问题:视频会在启动时出现卡顿,每几秒钟就会卡顿一次,并且有约4秒的延迟。这很糟糕。

我们的设置是使用x264进行编码(带有零延迟和超快速度),并使用来自ffmpeg 0.6.5的libavformat打包成RTSP / RTP。测试时,我使用gst-launch连接到RTSP服务器接收流。

但是,当直接从另一个GStreamer实例进行RTP流传输时,我已经能够复制相同的问题。

发送机器:

gst-launch videotestsrc ! x264enc tune=zerolatency ! rtph264pay ! udpsink host=10.89.6.3

接收机:

gst-launch udpsrc ! application/x-rtp,payload=96 ! rtph264depay ! decodebin ! xvimagesink

你也可以在同一台机器上运行这两个程序,只需要在发送端将主机更改为127.0.0.1。在接收端,你应该会注意到视频有卡顿和表现不佳的现象,同时控制台会反复发出警告:

WARNING: from element /GstPipeline:pipeline0/GstXvImageSink:xvimagesink0: A lot of buffers are being dropped.
Additional debug info:
gstbasesink.c(2875): gst_base_sink_is_too_late (): /GstPipeline:pipeline0/GstXvImageSink:xvimagesink0:
There may be a timestamping problem, or this computer is too slow.

在互联网上广泛建议的一种“修复”方式是在xvimagesink中使用sync=false

gst-launch udpsrc ! application/x-rtp,payload=96 ! rtph264depay ! decodebin ! xvimagesink sync=false
视频将以几乎零延迟的方式播放,即使经过我们的相机软件测试也是如此。这对于测试很有用,但对于部署来说并不是很有用,因为它不能与Totem、VLC或它们的浏览器插件嵌入一起使用。
我想尝试从源头解决这个问题;我怀疑x264在H.264流上缺少某种时间戳信息,或者可能是RTP负载上。有没有办法修改源gst管道,以便我不需要在接收端使用"sync=false"?
如果不可能,我该如何告诉客户端(通过SDP或其他方式)流不应该同步?最终,我们会使用某种VLC插件将其嵌入到浏览器中,因此适用于那里的解决方案甚至更好。
3个回答

11

正如root.ctrlc发布的那样,您可以使用sync=FALSE。然而,您可能会注意到发送端的CPU使用率大幅增加。原因是sync=FALSE告诉接收器在收到缓冲区后立即将其推出。 接收器驱动整个管道。 因此,sync=FALSE将导致管道尽可能快地对视频进行编码并将其推送到UDP; 它将使用100%的CPU。

您需要的是gstrtpjitterbuffer。它还会处理这里已经损坏的时间戳。

示例发送方:

gst-launch-0.10 -v videotestsrc ! videorate ! video/x-raw-yuv, framerate=30/1 ! ffmpegcolorspace ! x264enc ! rtph264pay ! udpsink port=50000 host=<sender IP>

示例接收器:

gst-launch-0.10 udpsrc port=50000 caps="application/x-rtp, media=(string)video, clock-rate=(int)90000 , encoding-name=(string)H264 , payload=(int)96" ! gstrtpjitterbuffer ! rtph264depay ! ffdec_h264 ! ffmpegcolorspace ! videoscale ! "video/x-raw-yuv, width=320, height=240" ! xvimagesink

+1 但是当我们使用 gst-launch-0.10 -v gstrtpbin name=rtpbin latency=40 udpsrc caps=".." port=50000 时,如何使用 gstrtpjitterbuffer?您能否分享在使用 gstrtpbin 时的接收器部分? - user285594
gsrtpbin已经包含gstrtpjitterbuffer。至于命令行,我会尝试回复你。由于我这里没有安装GStreamer 0.10,目前无法尝试。顺便说一句,你真的应该升级到1.0版本,这是强烈推荐的。 - dv_
@dv_ 感谢你指出gstrtpjitterbuffer并解释了sink=false的含义。你能否解释一下当sync=true时,管道是如何驱动的? - joanpau
这里的时间戳为什么出了问题? - nirvanaswap

9
您可以在源Gst管道中添加“sync=false”选项。在Ubuntu 12.04上,这似乎可以消除延迟和错误消息。
以下是我在源上使用的命令:
gst-launch videotestsrc ! x264enc tune=zerolatency ! rtph264pay ! udpsink host=127.0.0.1 sync=false

这是我在接收端使用的:

gst-launch udpsrc ! application/x-rtp,payload=96 ! rtph264depay ! decodebin ! xvimagesink

很遗憾,我不知道为什么它能起作用,甚至不知道“sync=false”属性属于哪个组件(在源管道上)。


谢谢。我遇到了同样的问题,但在接收端加上了“sync=false”,这对我有用。 - Embedded_User

0

我不知道这是否属实,但当我在未将电池充电器连接到笔记本电脑的情况下运行我的管道时,它曾经向我发出相同的警告,而当我插入电源时,相信我它可以工作。我认为这可能是因为旧的CMOS电池没有按照应有的方式工作,因为它负责时钟生成。


3
在这种情况下,我会怀疑你的笔记本电脑有一个电源配置选项,当使用电池时可以降低最大可用CPU功率。当您使用充电器运行时,您可以获得100%的CPU,但是当您使用电池时,CPU性能会降低。因此就会出现“或者这台电脑太慢”的情况。 - KevinM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接