0

我有两个 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),但无济于事。

有什么建议么?

4

1 回答 1

0

我认为您也应该重新启动接收器管道。您可以将-e开关添加到发送方管道,当您停止管道时,它应该通过 GDP 元素将 EOS 正确传播到接收方管道。否则我猜你可以向接收者发送一个新的段或不连续性。某些事件必须发出信号以使管道知道该更改,否则它有些是伪造的数据。我会说重新启动接收器是最简单的方法。

于 2021-10-15T10:59:25.000 回答