使用 OpenCV 将笔记本摄像头推流成 RTSP

7

title: 使用 OpenCV 将笔记本摄像头推流成 RTSP
url: opencv-gstreamer-camera-to-rtsp
date: 2024年03月22日
category: C++
tags:

  • OpenCV
  • RTSP

使用 OpenCV 将笔记本摄像头推流成 RTSP

使用 OpenCV 将笔记本摄像头推流成 RTSP

  1. 下载 Gstreamer
  2. 克隆 OpenCV 源码
  3. 使用 CMake 构建
  4. 代码示例

从 Gstreamer 官网下载安装包,先安装 runtime installer,再安装 development installer。

image-20230909163632285

安装完成后添加环境变量

image-20230909163712456

克隆 opencv 源码,使用 Git 克隆源码,这样再构建中下载是从 Gitcode 下载;如果下载了 zip,会从 GitHub 下载速度很慢。

image-20230909163740673

使用 Git Bash GUI 克隆

image-20230909163810322

然后切换到 4.8.0 的 tag

image-20230909163836637

打开 CMake GUI,填写源码目录和安装目录;

image-20230909164005704

然后点击 Configure,可以看到 Configure 过程中 gitcode 下载

image-20230909164042422

Configure 完成之后搜索 gstreamer,相关的 GStreamer 库路径已经自动识别,默认勾选了 WITH_GSTREAMER

image-20230909190948591

然后再次点击 Configure,查看构建信息,GStreamer 选项已打开

image-20230909191152282

点击 Generate,完成后 Open Project,使用 VS2022 打开项目

image-20230909164232808

生成 ALL_BUILD,再生成 INSTALL。opencv 就安装在了指定的 build 路径下的 install 目录里。目录中包含 include 和 x64\vs17\bin、x64\vs17\lib 就是我们需要的。

使用 VS2022 创建一个 CMake 项目,推流的关键代码如下:

void cvstream::read_rtsp()
{
    do
    {
        cv::VideoCapture vid_capture(videosource);

        if (!vid_capture.isOpened())
        {
            cout << "Error opening video stream or file" << endl;
            return;
        }
        else
        {
            int fps = vid_capture.get(CAP_PROP_FPS);
            cout << "Frames per second :" << fps;
        }

        dWidth = vid_capture.get(cv::CAP_PROP_FRAME_WIDTH);
        dHeight = vid_capture.get(cv::CAP_PROP_FRAME_HEIGHT);

        while (vid_capture.isOpened())
        {
            Mat frame;

            bool isSuccess = vid_capture.read(frame);

            if (isSuccess == true)
            {
                std::lock_guard<std::mutex> guard(mutex);

                bool flag = this->frame.empty();

                this->frame = frame.clone();
                if (flag) {
                    this->streamThread = std::thread(&cvstream::stream_publish, this);
                }

                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }

            if (isSuccess == false)
            {
                cout << "video end" << endl;
                isWorking = false;
                break;
            }
        }

        vid_capture.release();
        return;
    } while (false);

}

void cvstream::stream_publish()
{
    std::string gst = "appsrc ! videoconvert ! video/x-raw, format=I420 ! x264enc speed-preset=veryfast \
        bitrate=4096 key-int-max=40 ! rtspclientsink location=rtsp://127.0.0.1:8554/"+stream_url;
    cv::VideoWriter video(gst, cv::CAP_GSTREAMER, 0, 25, cv::Size (dWidth, dHeight), true);

    if (!video.isOpened()) {
        std::cerr << "Could not open the output video for write\n";
        return;
    }

    while (isWorking)
    {
        cv::Mat frame;
        {
            std::lock_guard<std::mutex> guard(mutex);
            frame = this->frame.clone();
        }

        video.write(frame);
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

代码中的 rtsp://127.0.0.1:8554 是 RTSP 服务器的地址,这里使用 mediamtx 作为 RTSP 服务器。

完整代码下载:opencv_video_stream