简体   繁体   English

使用 OpenCV 和 gstreamer 显示 RTSP stream

[英]Displaying RTSP stream with OpenCV and gstreamer

I have purchased an IP camera which I am trying to connect to using RTSP.我购买了IP 相机,我正在尝试使用 RTSP 连接它。 The RTSP connection URL is rtsp://admin:@192.168.0.27/channel=1&stream=0.554 . RTSP 连接 URL 是rtsp://admin:@192.168.0.27/channel=1&stream=0.554 I am using OpenCV to open and display the stream:我正在使用OpenCV打开并显示 stream:

#include <opencv2/opencv.hpp>

int main() {
   cv::VideoCapture cap;
   if (!cap.open("rtsp://admin:@192.168.0.27/channel=1&stream=0.554")) {
        std::cout << "Unable to open video capture\n";
        return -1;
    }

    while(true) {
        cv::Mat frame;

        auto ret = cap.grab();
        cap >> frame;

        if (frame.empty()) {
            break; // End of video stream
        }

        cv::resize(frame, frame, cv::Size(640, 480));

        // Do other stuff here with frame

        cv::imshow("frame", frame);

        if (cv::waitKey(10) == 27) {
            break; // stop capturing by pressing ESC
        }
    }

    return 0;
}

When I run the program, it will connect successfully and display a few frames, but then will start to lag badly and usually hang and output some error like this before crashing:当我运行程序时,它会成功连接并显示几帧,但随后会开始严重滞后并且通常会挂起,并且 output 在崩溃之前会出现类似这样的错误:

[h264 @ 0x558ae8e601a0] error while decoding MB 93 40, bytestream -11

I am not sure why I am having issues displaying the stream consistently.我不确定为什么我在始终显示 stream 时遇到问题。 Additionally, when it is able to display the stream, I find that it is quickly become out of sync (note I am doing some heavy processing on the frame which takes quite a lot of time).此外,当它能够显示 stream 时,我发现它很快变得不同步(注意我正在对帧进行一些繁重的处理,这需要相当多的时间)。 As in, it is not displaying the real time frame, but there is a growing lag.例如,它没有显示实时时间范围,但存在越来越大的滞后。

How can I also ensure to use the "latest" frame, and discard all the other ones which may have accumulated in some buffer.我怎样才能确保使用“最新”帧,并丢弃可能在某个缓冲区中累积的所有其他帧。 Also, any ideas why it is crashing and how I can improve the streaming?此外,任何想法为什么它会崩溃以及如何改进流媒体?

I was able to find this SO post which deals with getting the latest frame using gstreamer.我能够找到这篇关于使用 gstreamer 获取最新帧的 SO 帖子。 When I modify my video capture string to utilize gstreamer, it works a bit better.当我修改我的视频捕获字符串以使用 gstreamer 时,它的效果会好一些。

Here is the modified connection string: "rtspsrc location=rtsp://admin:@192.168.0.27/channel=1&stream=0.554 ! decodebin ! videoconvert ! appsink max-buffers=1 drop=true"这是修改后的连接字符串: "rtspsrc location=rtsp://admin:@192.168.0.27/channel=1&stream=0.554 ! decodebin ! videoconvert ! appsink max-buffers=1 drop=true"

I have no experience with gstreamer so I am not sure what it is doing, but it seems to improve things.我没有使用 gstreamer 的经验,所以我不确定它在做什么,但它似乎可以改善一些事情。 However, once it a while, it will all go grey and only display the pixels when there is movement, as shown in the following images.但是,过一会,它就会全部变成灰色,并且只在有运动时才显示像素,如下图所示。 With my experince with codecs, I believe the reference frame is missing, but I am not really sure.根据我对编解码器的经验,我相信缺少参考框架,但我不确定。 Any ideas on how to fix this?有想法该怎么解决这个吗? If I am not using the correct gstreamer parameters, please make a suggestion as to what I should be using for fast streaming (always using the latest frame).如果我没有使用正确的 gstreamer 参数,请就我应该使用什么进行快速流式传输提出建议(始终使用最新帧)。 As I mentioned, I have minimal experience with gstreamer.正如我所提到的,我对 gstreamer 的经验很少。 Thanks for the help!谢谢您的帮助!

在此处输入图像描述 在此处输入图像描述

This may be due to packet loss of the network transmission.这可能是由于网络传输的数据包丢失。 You can give it a try to modify the URL to use the rtspt:// protocol.您可以尝试修改 URL 以使用rtspt://协议。 This will try to establish a TCP transmission which should prevent packet loss on your receiving side.这将尝试建立一个 TCP 传输,这应该可以防止接收端的数据包丢失。

The best approach is to use threads to read frames continuously and assign them on an attribute of a class.最好的方法是使用线程连续读取帧并将它们分配给 class 的属性。 In this way if some thread encounters the packet loss, the other thread buddies compensate for it.这样,如果某个线程遇到丢包,其他线程的小伙伴会进行补偿。

check this out, I hope it helps:看看这个,希望对你有帮助:

from threading import Thread
import cv2

class RTSPVideoWriterObject(object):
    def __init__(self, src=0):
        # Create a VideoCapture object
        self.capture = cv2.VideoCapture(src)
        self.status, self.frame = None, None

        # Default resolutions of the frame are obtained (system dependent)
        self.frame_width = int(self.capture.get(3))
        self.frame_height = int(self.capture.get(4))

        # Set up codec and output video settings
        self.codec = cv2.VideoWriter_fourcc(*'MJPG')
        self.output_video = cv2.VideoWriter('output.avi', self.codec, 30, (self.frame_width, self.frame_height))

        # Start the thread to read frames from the video stream
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()

    def update(self):
        # Read the next frame from the stream in a different thread
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()

    def show_frame(self):
        # Display frames in main program
        # if self.status:
        #     cv2.imshow('frame', self.frame)

        # Press Q on keyboard to stop recording
        key = cv2.waitKey(1)
        if key == ord('q'):
            self.capture.release()
            self.output_video.release()
            cv2.destroyAllWindows()
            exit(1)

    def save_frame(self):
        # Save obtained frame into video output file
        self.output_video.write(self.frame)


if __name__ == '__main__':
    rtsp_link = "rtsp://admin:@192.168.0.27/channel=1&stream=0.554"
    video_stream_widget = RTSPVideoWriterObject(rtsp_stream_link)
    while True:
        try:
            video_stream_widget.show_frame()
            video_stream_widget.save_frame()
        except AttributeError:
            pass

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM