我有两个 GStreamer 管道,一个就像一个“源”管道,将实时摄像头馈送到外部通道,第二个管道就像一个“接收器”管道,从该通道的另一端读取并输出实时视频到某种形式的水槽。
[videotestsrc] -> [appsink] ----- Serial Channel ------> [appsrc] -> [autovideosink]
First Pipeline Second Pipeline
第一个管道从 a 开始videotestsrc
,对视频进行编码并将其包装在gdppay
有效负载中,然后将管道接收到串行通道中(但为了这个问题,任何可以读取的接收器都可以启动另一个管道,如写入文件接收器串行端口或 udpsink),它由下一个管道的源读取并通过 a 显示autovideosrc
:
“源”管道
gst-launch-1.0 -v videotestsrc ! videoconvert ! video/x-raw,format=I420 ! x265enc ! gdppay ! udpsink host=127.0.0.1 port=5004
“下沉”管道
gst-launch-1.0 -v udpsrc uri=udp://127.0.0.1:5004 ! gdpdepay ! h265parse ! avdec_h265 ! autovideosink
注意:鉴于使用 udpsink/udpsrc 引起的延迟,该管道会抱怨时间戳问题。如果您将 udpsrc/udpsink 替换为 filesrc/filesink 到串行端口,您会看到我将要描述的问题。
问题:
既然我已经描述了管道,问题就来了:如果我启动两个管道,一切都会按预期工作。但是,如果在 30 秒后,我停止“源”管道并重新启动管道,运行时间将重置为零,导致所有缓冲区的时间戳被发送到接收器管道视为旧缓冲区,因为它已经接收到时间戳为 0 到 30 秒的缓冲区,因此另一端的播放要到 30 秒后才会恢复:
Source Pipeline: [28][29][30][0 ][1 ][2 ][3 ]...[29][30][31]
Sink Pipeline: [28][29][30][30][30][30][30]...[30][30][31]
________________________^
Source pipeline restarted
^^^^^^^^^^^^^^^^...^^^^^^^^
Sink pipeline will continue
to only show the "frame"
received at 30s until a
"newer" frame is sent, when
in reality each sent frame
is newer and should be shown
immediately.
解决方案
我发现添加确实sync=false
可以autovideosink
解决问题,但是我希望找到一个解决方案,其中源将根据该页面上的图像中看到的时钟时间发送其时间戳(DTS 和 PTS)。
我已经看过这篇文章is-live
并在我的视频源上进行了实验do-timestamp
,但他们似乎没有做我想做的事。我还尝试根据系统时间手动设置缓冲区中的时间戳(DTS、PTS),但无济于事。
有什么建议么?