使用 gstreamer 和 python 对原始视频进行按需编码

问题描述 投票:0回答:1

我正在开发一个基于gstreamer和python的视频处理和分发服务器。我有几个传入的压缩视频流,我通过使用 mpegtsmux 添加 multifdsink 元素在管道之间传递。因此,当我看到特定流不再使用时,我可以将 EOS 事件发送到特定管道。这是我如何保持按需提供的主要想法。然而,在处理原始视频时,事情会变得非常快。

在理想的世界中,我希望有 1 个解码器管道,它可以为其他解码器管道提供各种检测器和编码器的原始视频。所以到目前为止我已经尝试了 3 个选项:

  1. Multifdsink /原始视频

主解码器:

fdsrc! tsdemux!解码器!视频转换!视频率!多裂水槽

编码器示例(独立管道):

fdsrc! rawvideoparse use-sink-caps=1 ! “此处插入了来自 multifdsink 的盖子”!视频转换!视频率!视频尺度! x264enc 调整=零延迟 key-int-max=5 ! mpegtsmux!多fdsink

这样我就可以轻松启动/停止编码器,但无论 multifdsink 提供什么上限,我都会得到图片颜色混乱的

  1. Multiudpsink / 原始视频

主解码器:

fdsrc! tsdemux!解码器!视频转换!视频率! rtpvraw支付!多udpsink

编码器示例(独立管道):

udpsrc caps="此处插入来自 multiudpsink 的 caps"! rtpvrawdepay !视频转换!视频率!视频尺度! x264enc 调整=零延迟 key-int-max=5 ! mpegtsmux!多fdsink

这样我就可以轻松启动/停止编码器。当场景中几乎没有运动时,我什至能得到一张漂亮的照片,但当引入运动时,我会得到很多伪像,例如行走的人的缺失部分。更不用说我在 lo 上获得单个 320X240 流的 50Mbit 网络流量

  1. 动态管道使用

(主要灵感来自https://github.com/MaZderMind/dynamic-gstreamer-pipelines-cookbook/blob/master/05-add-and-remove-network-sink.py

主解码器:

fdsrc! tsdemux!解码器!视频转换!视频率!三通

编码器示例(Gst.Bin):

排队!视频转换!视频率!视频尺度! x264enc 调整=零延迟 key-int-max=5 ! mpegtsmux!多fdsink

    # code to add encoder to running pipeline 
    self.motion_debug = self.create_encoder_pipeline('motion', encoder='h264')
    self.pipeline.add(self.motion_debug)
    tee = self.pipeline.get_by_name('motion_tee')
    print(tee.link(self.motion_debug))
    self.motion_debug.set_state(Gst.State.PLAYING)

    #code to remove encoder from running pipeline   
    ghostpad = self.motion_debug.get_static_pad("sink")
    teepad = ghostpad.get_peer()
    teepad.add_probe(Gst.PadProbeType.BLOCK, self.blocking_pad_probe)
   
    def blocking_pad_probe(self,pad, info):
        print("Stopping Bin")
        self.motion_debug.set_state(Gst.State.NULL)


        tee = self.pipeline.get_by_name('motion_tee')
        ghostpad = self.motion_debug.get_static_pad("sink")
        teepad = ghostpad.get_peer()

        print('Removing encoder bin')
        print(self.pipeline.remove(self.motion_debug))

        print("Releasing Tee-Pad")
        tee.release_request_pad(teepad)

        self.motion_debug = None
        return Gst.PadProbeReturn.REMOVE

在这里,我启动主解码器并根据需要添加包含示例编码器的 Gst.Bin。第一次(尚未请求编码器)我可以获得可见延迟为 1-2 秒的流。但是,当编码器根据下一个需求停止并与管道分离时,我会得到一个静止帧,其中播放器实际上指示时间滴答(编码器再次推送同一帧)。因此,对于观看者来说,看起来就像在播放视频时一次又一次地收到冻结的图片。

我相信解决我的问题最正确的方法是第三种方法。但我欢迎任何解决方案或想法。

提前致谢!

python video-streaming gstreamer video-processing
1个回答
0
投票

解决方案很简单:videorate 元素有时可以推送同一帧以达到所需的 fps。使用 viderate.set_property('drop-only',True) 来避免这种行为。

© www.soinside.com 2019 - 2024. All rights reserved.