如何使 rtpjitterbuffer 在没有时间戳的流上工作?

How to make rtpjitterbuffer work on a stream without timestamps?

我正在使用 gstreamer 通过 RTP 发送 H.264 字节流。

# sender
gst-launch-1.0 filesrc location=my_stream.h264 ! h264parse disable-passthrough=true ! rtph264pay config-interval=10 pt=96 ! udpsink host=localhost port=5004

然后我正在接收帧,解码并在其他 gstreamer 实例中显示。

# receiver
gst-launch-1.0 udpsrc port=5004 ! application/x-rtp,payload=96,media="video",encoding-name="H264",clock-rate="90000" ! rtph264depay ! h264parse ! decodebin ! xvimagesink

按原样工作,但我想尝试添加一个 rtpjitterbuffer 以完美平滑播放。

# receiver
gst-launch-1.0 udpsrc port=5004 ! application/x-rtp,payload=96,media="video",encoding-name="H264",clock-rate="90000" ! rtpjitterbuffer ! rtph264depay ! h264parse ! decodebin ! xvimagesink

但是,一旦我这样做,接收器只显示一个帧并冻结。

如果我用 MP4 文件替换 .h264 文件,播放效果很好。

我假设我的 h264 流没有启用抖动缓冲区运行所需的时间戳。

我通过添加 identity datarate=1000000 取得了一些进展。这允许抖动缓冲区播放,但是这与我的帧速率有关,因为 P 帧的数据少于 I 帧。显然,identity 元素添加了正确的时间戳,但只是使用了错误的数字。

是否可以通过在某处正确指定 "framerate" 上限来自动生成发件人的时间戳?到目前为止,我的尝试没有奏效。

您应该尝试将 rtpjitterbuffer 模式设置为默认值以外的其他值:

mode                : Control the buffering algorithm in use
                        flags: readable, writable
                        Enum "RTPJitterBufferMode" Default: 1, "slave"
                           (0): none             - Only use RTP timestamps
                           (1): slave            - Slave receiver to sender clock
                           (2): buffer           - Do low/high watermark buffering
                           (4): synced           - Synchronized sender and receiver clocks

像那样:

... ! rtpjittrbuffer mode=0 ! ...

我遇到了同样的问题,我找到的最佳解决方案是在发送方的流中添加时间戳,方法是向源添加 do-timestamp=1

没有时间戳,我无法让 rtpjitterbuffer 通过超过一帧,无论我给它什么选项。

(我处理的案例是通过 fdsrcraspvid 流式传输,我认为 filesrc 的行为类似)。

gstreamer 如此轻松地发送 gstreamer 本身(和其他工具)无法正确处理的流确实有点糟糕:如果没有时间戳是有效的,那么 rtpjitterbuffer 应该可以应对;如果没有时间戳是无效的,那么 rtph264pay 应该拒绝没有时间戳的发送。我想它从未打算用作用户界面...

您已经部分回答了问题:

If I replace the .h264 file with an MP4 file, the playback works great.

I assume that my h264 stream does not have the required timestamps to enable the jitter buffer to function.

您的发送管道没有协商的帧速率,因为您使用的是 raw h264 流,而您实际上应该使用具有此功能的容器格式(例如 MP4)信息。没有时间戳 udpsink 无法与时钟同步以节流,因此发送方正在以管道可以处理的速度尽可能快地吐出数据包。这不是 live 接收器。

但是添加 rtpjitterbuffer 会使您的接收器充当 实时 源。它冻结是因为它正在尽最大努力应对大量格式错误的时间戳数据包。据我所知,RTP 不会传输 "missing" 时间戳,因此所有数据包都可能具有相同的时间戳。因此它可能会重建第一帧并将其余帧作为副本丢弃。

我必须同意 user1998586,在这种情况下,管道崩溃并显示良好的错误消息应该更好,而不是尽力而为。

Is it possible to automatically generate timestamps on the sender by specifying the "framerate" caps correctly somewhere? So far my attempts have not worked.

没有。你真的应该使用容器。

然而,理论上,au 对齐的 H264 原始流可以通过只知道帧速率来添加时间戳,但是没有 gstreamer 元素(我知道)可以做到这一点并且只指定上限不会'不做。