我试图找出是否有一种方法可以在gstreamer管道中指定我只希望RTSP流中的关键帧。
在ffmpeg中,您可以使用-skip_frame nokey
标志来实现。例如:
ffmpeg -skip_frame nokey -i rtsp://184.72.239.149/vod/mp4:BigBuckBunny_175k.mov -qscale 0 -r 1/1 frame%03d.jpg
用于读取RTSP提要的相应gstreamer命令如下:
gst-launch-1.0 rtspsrc location=rtsp://184.72.239.149/vod/mp4:BigBuckBunny_175k.mov ! decodebin ! videorate ! "video/x-raw,framerate=1/1" ! videoconvert ! autovideosink
有人知道是否可以要求gstreamer仅返回关键帧吗?
答案 0 :(得分:2)
在花了几天时间寻找这个问题的完整答案之后,我最终找到了一个解决方案,该解决方案为我提供了所希望的rtsp处理能力。
这是Python中管道的差异,从处理每个RTSP帧过渡到仅处理关键帧。
https://github.com/ambianic/ambianic-edge/pull/171/files#diff-f89415777c559bba294250e788230c5e
流启动总线事件的第一个寄存器:
Gst.MessageType.STREAM_START
在流处理开始时触发。发生此事件时,请求查找下一个关键帧。
请求完成后,管道触发我们需要监听的下一个总线事件:
Gst.MessageType.ASYNC_DONE
最后,这是关键帧查找请求本身:
def _gst_seek_next_keyframe(self):
found, pos_int = self.gst_pipeline.query_position(Gst.Format.TIME)
if not found:
log.warning('Gst current pipeline position not found.')
return
rate = 1.0 # keep rate close to real time
flags = \
Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT | \
Gst.SeekFlags.TRICKMODE | Gst.SeekFlags.SNAP_AFTER | \
Gst.SeekFlags.TRICKMODE_KEY_UNITS | \
Gst.SeekFlags.TRICKMODE_NO_AUDIO
is_event_handled = self.gst_pipeline.seek(
rate,
Gst.Format.TIME,
flags,
Gst.SeekType.SET, pos_int,
Gst.SeekType.END, 0)
答案 1 :(得分:1)
我认为您可以尝试添加GST_PAD_PROBE_TYPE_BUFFER
填充探针,并在设置了GST_PAD_PROBE_DROP
标志的缓冲区上返回GST_BUFFER_FLAG_DELTA_UNIT
。
答案 2 :(得分:1)
对于特技模式func sendPing() {
guard let socket = socket, socket.isConnected
else { return }
socket.write(ping: "PING")
}
,可以将带有标志gst_event_new_seek
的新搜索事件GstSeekFlags
用于特技模式GST_SEEK_FLAG_TRICKMODE
,仅跳过帧GST_SEEK_FLAG_SKIP
和关键帧GST_SEEK_FLAG_TRICKMODE_KEY_UNITS
。
您还可以使用identity
及其属性drop-buffer-flags
来过滤GST_BUFFER_FLAG_DELTA_UNIT
,甚至可以过滤GST_BUFFER_FLAG_DROPPABLE
。
有关搜索的信息,请参见文档中的trickmodes,seeking和GstSeekFlags,有关身份的信息请参见identity:drop-buffer-flags和GstBufferFlags。