如何让 Gstreamer return 只有关键帧?
How to make Gstreamer return only keyframes?
在 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 仅 return 个关键帧?
我认为您可以尝试在设置了 GST_BUFFER_FLAG_DELTA_UNIT
标志的缓冲区上添加 GST_PAD_PROBE_TYPE_BUFFER
填充探针和 return GST_PAD_PROBE_DROP
。
您可以使用带有标记 GstSeekFlags
的新搜索事件 gst_event_new_seek
来实现特技模式 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 and GstSeekFlags in the documentation for the seeking and identity:drop-buffer-flags and GstBufferFlags 了解身份。
在花了几天时间寻找这个问题的完整答案后,我最终得到了一个解决方案,它为我提供了我一直在寻找的 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)
在 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 仅 return 个关键帧?
我认为您可以尝试在设置了 GST_BUFFER_FLAG_DELTA_UNIT
标志的缓冲区上添加 GST_PAD_PROBE_TYPE_BUFFER
填充探针和 return GST_PAD_PROBE_DROP
。
您可以使用带有标记 GstSeekFlags
的新搜索事件 gst_event_new_seek
来实现特技模式 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 and GstSeekFlags in the documentation for the seeking and identity:drop-buffer-flags and GstBufferFlags 了解身份。
在花了几天时间寻找这个问题的完整答案后,我最终得到了一个解决方案,它为我提供了我一直在寻找的 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)