我通过以下 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
请注意,
udpsrc
的属性默认设置为true。所以它实际上是在这里为缓冲区添加时间戳的元素。使用 Gstreamer 的 do-timestamp
元素,我提取
appsink
并手动为它们添加 unix 时间戳,并将它们保存在队列中。我所做的时间戳与样本缓冲区的呈现时间戳无关,如GstSample*
所示,它的实现方式如下:GST_BUFFER_PTS(buffer)
在请求特定的unix时间间隔时,我应该提供相应的 通过 Gstreamer 的
struct MyGstSample {
GstSample* sample_;
long unix_time_ns_;
}
通过以下管道(仅用于描述)将队列中的
GstSample*
采样到单独的管道(仅用于描述),并将间隔记录在 appsrc
文件中:.mp4
问题
gst-launch-1.0 appsrc ! application/x-rtp, media=video, clock-rate=90000, encoding-name=H264, payload=96 ! rtph264depay ! h264parse ! mp4mux ! queue ! filesink
。例如,如果用户请求(为了简单起见,从运行时间 5 秒到运行时间 15 秒)我只能得到 10 秒到 15 秒。我想这与关键帧问题或其他问题有关。
有没有一种方法可以在保持帧编码的同时仍确保精确的点播视频录制?
timeoverlay
有关。
调整发送方管道以每 30 帧发送一次关键帧:x264enc
接下来我们需要找出哪些缓冲区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_DELTA_UNIT
来完成在接收器一侧,在探测来自
GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_DELTA_UNIT)
的缓冲区时,您会发现
udpsrc
始终设置为 false,因为数据是 GST_BUFFER_FLAG_DELTA_UNIT
。在这里,您需要使用 application/x-rtp
并检查从中出来的缓冲区。您将开始看到一些关键帧和增量帧。话虽如此,接收方应该如下:rtph264depay
最后,为了让录音管道正常工作,您需要从接收器一侧获取 gst-launch-1.0 -v udpsrc port=5000 ! application/x-rtp,clock-rate=90000,payload=96 ! rtph264depay ! queue ! appsink
的 src pad 的
GstCaps*
,并将其用作录音管道中 rtph264depay
的上限,因为它包含重要的编解码器特定数据。否则解析器appsrc
将无法正常工作。这是管道(仅用于描述,但您仍然需要将上限添加到 appsrc)h264parse
话虽如此,每当我们收到请求的间隔时,实际上都会在队列中搜索最近的关键帧并开始将相应的样本馈送到记录管道。