在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只返回关键帧吗?
在花了几天时间寻找这个问题的完整答案后,我最终找到了一个解决方案,它提高了我想要的rtsp处理能力。
以下是Python中从处理每个RTSP帧过渡到只处理关键帧的管道的差异。
https://github.com/ambianic/ambianic-edge/pull/171/files#diff-f89415777C59bba294250e788230c5e
流启动总线事件的第一个寄存器:
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)
我认为您可以尝试添加GST_PAD_PROBE_TYPE_BUFFER
焊盘探针,并在设置了GST_BUFFER_FLAG_DELTA_UNIT
标志的缓冲区上返回GST_PAD_PROBE_DROP
。
对于特技模式GST_SEEK_FLAG_TRICKMODE
、跳过帧GST_SEEK_FLAG_SKIP
和仅关键帧GST_SEEK_FLAG_TRICKMODE_KEY_UNITS
,可以使用带有标志GstSeekFlags
的新搜索事件gst_event_new_seek
。
您也可以使用identity
及其属性drop-buffer-flags
来筛选GST_BUFFER_FLAG_DELTA_UNIT
,可能还有GST_BUFFER_FLAG_DROPPABLE
。
请参阅文档中的trickmode、seeking和GstSeekFlags以获取查找和标识:drop-buffer flags和GstBufferFlags用于标识。