如何编写 GstSamples 的特定时间间隔(RTP over UDP H264 数据包)?

How to write specific time interval of GstSamples (RTP over UDP H264 packets)?

设置

我正在通过以下 Gstreamer CLI 管道通过 RTP UDP 发送 H.264 编码数据包:

gst-launch-1.0 videotestsrc is-live=true ! video/x-raw,framerate=30/1 ! timeoverlay ! videoconvert ! x264enc ! h264parse ! rtph264pay pt=96 ! udpsink host=127.0.0.1 port=5000

请注意,timeoverlay 元素稍后会派上用场!

在接收端,仅用于描述(这不是从 CLI 启动的),我使用以下管道:

gst-launch-1.0 -v udpsrc port=5000 ! application/x-rtp,clock-rate=90000,payload=96 ! queue ! appsink

请注意,udpsrcdo-timestamp 的 属性 默认设置为 true。所以实际上是在此处为缓冲区添加时间戳的元素。

使用 Gstreamer 的 appsink 元素,我提取 GstSample* 并手动为它们添加 unix 时间戳,并将它们保存在队列中。我所做的时间戳与示例缓冲区的显示时间戳无关,因为 GST_BUFFER_PTS(buffer) 它的实现方式如下:

struct MyGstSample {
  GstSample* sample_;
  long unix_time_ns_;
}

在请求特定的 unix 时间间隔时,我应该提供相应的 通过 Gstreamer 的 appsrc 从队列采样 GstSample* 通过以下管道(仅供描述)并在 .mp4 文件中记录间隔:

gst-launch-1.0 appsrc ! application/x-rtp, media=video, clock-rate=90000, encoding-name=H264, payload=96 ! rtph264depay ! h264parse ! mp4mux ! queue ! filesink

问题

我好像不能准确地写出所需的时间间隔,你可以根据录制视频中显示的时间来判断,感谢timeoverlay。例如,如果用户请求(为简单起见,从 运行 时间 5s 到 运行 时间 15s)我只得到 10s 到 15s。我想这与关键帧问题或其他问题有关。

有没有一种方法可以在保持帧编码的同时确保精确的点播视频录制?

所以问题实际上与关键帧有关,因为录制管道只会从它找到的第一个关键帧开始写入视频,所有增量帧都会被丢弃。而我在请求的间隔中错过了很多秒的原因是因为发送管道每 300 帧发送一个关键帧的配置,这个 属性 与 x264enc.

正在调整发送管道以每 30 帧发送一次关键帧:

gst-launch-1.0 videotestsrc is-live=true ! video/x-raw,framerate=30/1 ! timeoverlay ! videoconvert ! x264enc key-int-max=30 ! h264parse ! rtph264pay pt=96 ! udpsink host=127.0.0.1 port=5000

接下来我们需要找出哪些缓冲区GstBuffer *对应于关键帧。这可以通过检查缓冲区是否具有 GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_DELTA_UNIT)

设置的 GST_BUFFER_FLAG_DELTA_UNIT 来完成

在接收端,在探测来自 udpsrc 的缓冲区时,您会发现 GST_BUFFER_FLAG_DELTA_UNIT 始终设置为 false,因为数据是 application/x-rtp。在这里您需要使用 rtph264depay 并检查从中产生的缓冲区。您将开始看到一些关键帧和增量帧。话虽如此,接收方应如下所示:

gst-launch-1.0 -v udpsrc port=5000 ! application/x-rtp,clock-rate=90000,payload=96 ! rtph264depay ! queue ! appsink

最后,为了让录音管道正常工作,您需要从接收端获取 rtph264depay 的 src pad 的 GstCaps*,并将其用作 appsrc 在记录管道中,因为它包含重要的特定于编解码器的数据。否则解析器 h264parse 将无法正常运行。这是管道(仅供描述,您仍然需要将上限添加到 appsrc)

gst-launch-1.0 appsrc ! h264parse ! mp4mux ! queue ! filesink

话虽如此,每当我们收到请求的间隔时,实际上都会在队列中搜索最近的关键帧,并开始将相应的样本提供给记录管道。