使用 Gstreamer 通过 RTSP 流式传输视频/另一台摄像机

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

我对 Gstreamer 还很陌生,我正在尝试创建一个管道来获取视频或另一个 RTSP 摄像机流并将其作为 RTSP 进行流式传输。 我设法创建了此代码,并且可以使用以下链接使用 VLC 打开流:rtsp://localhost:8554/stream,但它仅向我显示视频的第一帧。我应该更改什么才能使其正常工作?

import cv2
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstRtspServer', '1.0')
from gi.repository import Gst, GstRtspServer, GLib
Gst.init(None)


class Camera:
    def __init__(self):

        self.camera_url = 'RTSP link/video path'

        self.number_frames = 0
        self.fps = 12
        self.duration = 1 / self.fps * Gst.SECOND
        self.pipe = "appsrc name=source is-live=true block=true format=GST_FORMAT_TIME " \
            " caps=video/x-raw,format=BGR,width=1280,height=720,framerate={}/1 " \
            "! videoconvert ! video/x-raw,format=I420 ! x264enc speed-preset=ultrafast tune=zerolatency " \
            "! rtph264pay config-interval=1 name=pay0 pt=96 " \
            "! udpsink host=127.0.0.1 port=5400 sync=true async=false".format(self.fps)
        self.pipeline = Gst.parse_launch(self.pipe)
        self.loop = None
        appsrc=self.pipeline.get_by_name('source')
        appsrc.connect('need-data', self.start_camera)


    
    def create_rtsp_server(self):
        server = GstRtspServer.RTSPServer.new()
        server.set_property("service", "8554")
        server.attach(None)

        factory = GstRtspServer.RTSPMediaFactory.new()

        pipeline = "( udpsrc port=5400 name=pay0 caps=\"application/x-rtp, media=video, clock-rate=90000, encoding-name=(string)H264, payload=96 \" )"
        factory.set_launch(pipeline)
        factory.set_shared(True)
        server.get_mount_points().add_factory("/stream", factory)
    
    def run(self):
        
        self.pipeline.set_state(Gst.State.READY)
        self.pipeline.set_state(Gst.State.PLAYING)

        self.create_rtsp_server()

        self.loop = GLib.MainLoop()
        self.loop.run()



    def start_camera(
        self, src, lenght
    ):

        cap = cv2.VideoCapture(self.camera_url)  

        try:

            while cap.isOpened():
                ret, frame = cap.read()

                if not ret:
                    break
                
                data = frame.tobytes()
                
                buf = Gst.Buffer.new_allocate(None, len(data), None)
                buf.fill(0, data)
                buf.duration = self.duration
                timestamp = self.number_frames * self.duration
                buf.pts = buf.dts = int(timestamp)
                buf.offset = timestamp
                self.number_frames += 1

                retval = src.emit('push-buffer', buf)
                print('pushed buffer, frame {}, duration {} ns, durations {} s'.format(self.number_frames, self.duration, self.duration / Gst.SECOND))                                                                                  
                if retval != Gst.FlowReturn.OK:
                    print(retval)
                

                return True
                

        finally:
            cap.release()
            cv2.destroyAllWindows()

我尝试搜索类似的 Gstreamer 管道,但找不到类似的东西

opencv gstreamer rtsp
1个回答
0
投票

令我惊讶的是,rtsp 工厂能够使用

name
元素上设置的
udpsrc
属性创建流。虽然有可能,但我认为
udpsrc
元素卡在接收数据包和通过 rtsp 发送数据包之间。因为它是单线程,所以它可能会达到竞争条件。

通常最好在

queue
元素之后、
src
等重处理元素之前添加
x264enc
元素。
queue
为帧添加缓冲区,并模拟
GStreamer
中的多线程。

所以我建议按如下方式更改两个管道并尝试一下

源管道

self.pipe = "appsrc name=source is-live=true block=true format=GST_FORMAT_TIME " \
        " caps=video/x-raw,format=BGR,width=1280,height=720,framerate={}/1 " \
        "! queue ! videoconvert ! video/x-raw,format=I420 ! queue ! x264enc speed-preset=ultrafast tune=zerolatency " \
        "! rtph264pay config-interval=1 name=pay0 pt=96 " \
        "! queue ! udpsink host=127.0.0.1 port=5400 sync=true async=false".format(self.fps)

工厂流水线

pipeline = "( udpsrc port=5400 caps=\"application/x-rtp, media=video, clock-rate=90000, encoding-name=(string)H264\" ! queue ! rtph264depay ! h264parse ! rtph264pay name=pay0 pt=96 )"
© www.soinside.com 2019 - 2024. All rights reserved.