Browse Source

添加rtmp节点

leon 3 weeks ago
parent
commit
fe3ecfda6b

+ 6 - 0
src/graph/graph.cpp

@@ -177,6 +177,12 @@ void Graph::create_from_json(const std::string& json_path)
                             }
                             new_node = record_node;
                         } 
+                        else if (node_type == "Rtmp") 
+                        {
+                            std::string gst_pipeline = params.at("gst_pipeline").get<std::string>();
+                            int fps = params.value("fps", 25);
+                            new_node = std::make_shared<GNode::RtmpNode>(node_id, gst_pipeline, fps);
+                        } 
                         else 
                         {
                             throw std::runtime_error("Unknown node type '" + node_type + "' for node ID '" + node_id + "'");

+ 1 - 0
src/graph/graph.hpp

@@ -14,6 +14,7 @@
 #include "nodes/analyze/analyzeNode.hpp"
 #include "nodes/draw/drawNode.hpp"
 #include "nodes/record/recordNode.hpp"
+#include "nodes/rtmp/rtmpNode.hpp"
 #include "nodes/httpPush/httpPush.hpp"
 
 

+ 6 - 4
src/infer/trt/classfier/classifier.cu

@@ -119,21 +119,23 @@ void ClassifierModelImpl::preprocess(int ibatch, const tensor::Image &image, aff
     checkRuntime(cudaStreamSynchronize(stream_));
 }
 
-virtual Result ClassifierModelImpl::forward(const tensor::Image &image, void *stream)
+Result ClassifierModelImpl::forward(const tensor::Image &image, void *stream)
 {
     return std::monostate{};
 }
-virtual Result ClassifierModelImpl::forward(const tensor::Image &image, int slice_width, int slice_height, float overlap_width_ratio, float overlap_height_ratio, void *stream)
+
+Result ClassifierModelImpl::forward(const tensor::Image &image, int slice_width, int slice_height, float overlap_width_ratio, float overlap_height_ratio, void *stream)
 {
     return std::monostate{};
 }
-virtual Result ClassifierModelImpl::forward(const tensor::Image &image, data::BoxArray& boxes, void *stream)
+
+Result ClassifierModelImpl::forward(const tensor::Image &image, data::BoxArray& boxes, void *stream)
 {
     std::lock_guard<std::mutex> lock(mutex_);
     std::vector<data::Box*> classfier_boxes_ptr;
     for (auto& box : boxes)
     {
-        if (std::find(box.label, class_names_.begin(), class_names_.end()) != class_names_.end())
+        if (std::find(class_names_.begin(), class_names_.end(), box.label) != class_names_.end())
         {
             classfier_boxes_ptr.push_back(&box);
         }

+ 1 - 1
src/nodes/record/recordNode.hpp

@@ -1,7 +1,7 @@
 #ifndef RECORDNODE_HPP__
 #define RECORDNODE_HPP__
 #include "nodes/base/base.hpp"
-#include <opencv2/opencv.hpp>
+#include "opencv2/opencv.hpp"
 
 // 日志库
 #include "plog/Log.h"

+ 25 - 0
src/nodes/rtmp/rtmpNode.cpp

@@ -0,0 +1,25 @@
+#include "common/data.hpp"
+#include "common/meta.hpp"
+#include "nodes/rtmp/rtmpNode.hpp"
+
+namespace GNode
+{
+
+void RtmpNode::handle_data(std::shared_ptr<meta::MetaData>& meta_data)
+{
+    cv::Mat image = meta_data->draw_image;
+    int width = image.cols;
+    int height = image.rows;
+    if (!writer_.isOpened())
+    {
+        writer_.open(gst_pipeline_, cv::CAP_GSTREAMER, 0, fps_, cv::Size(width, height), true);
+        if (!writer_.isOpened())
+        {
+            PLOGE.printf("RtmpNode : [%s] cannot open video writer", name_.c_str());
+            stop();
+        }
+    }
+    writer_ << image;
+}
+
+}   // namespace GNode

+ 73 - 0
src/nodes/rtmp/rtmpNode.hpp

@@ -0,0 +1,73 @@
+#ifndef RTMPNODE_HPP__
+#define RTMPNODE_HPP__
+
+#include "nodes/base/base.hpp"
+#include "opencv2/opencv.hpp"
+#include "opencv2/videoio.hpp"
+
+// 日志库
+#include "plog/Log.h"
+#include "plog/Initializers/RollingFileInitializer.h"
+
+namespace GNode
+{
+
+class RtmpNode : public BaseNode
+{
+public:
+    RtmpNode() = delete;
+    RtmpNode(const std::string& name, const std::string& gst_pipeline, int fps = 25) 
+        : BaseNode(name, NODE_TYPE::DES_NODE) 
+    {
+        fps_ = fps;
+        gst_pipeline_ = gst_pipeline;
+    }
+    virtual ~RtmpNode() 
+    { 
+        stop(); 
+        if (writer_.isOpened())
+        {
+            writer_.release();
+        }
+    }
+
+    void handle_data(std::shared_ptr<meta::MetaData>& meta_data) override;
+private:
+    int fps_ = 35;
+    std::string gst_pipeline_;
+    cv::VideoWriter writer_;
+};
+
+}
+
+#endif // RTMPNODE_HPP__
+
+
+/*
+cmake -D CMAKE_BUILD_TYPE=RELEASE \
+-D BUILD_TESTS=OFF \
+-D BUILD_PERF_TESTS=OFF \
+-D BUILD_EXAMPLES=OFF \
+-D BUILD_opencv_apps=OFF \
+-D BUILD_PNG=ON \
+-D BUILD_JPEG=ON \
+-D BUILD_TIFF=ON \
+-D BUILD_WEBP=ON \
+-D OpenJPEG=ON \
+-D BUILD_OPENEXR=ON \
+-D OPENCV_GENERATE_PKGCONFIG=ON \
+-D OPENCV_EXTRA_MODULES_PATH=/workspace/compile/opencv490/opencv_contrib-4.9.0/modules \
+-D WITH_CUDA=OFF \
+-D WITH_CUDNN=OFF \
+-D BUILD_PROTOBUF=ON \
+-D OPENCV_DNN_CUDA=OFF \
+-D CUDA_FAST_MATH=OFF \
+-D WITH_CUBLAS=OFF \
+-D WITH_GSTREAMER=ON \
+-D WITH_FFMPEG=ON \
+-D WITH_QT=OFF \
+-D WITH_GTK=OFF \
+-D BUILD_JAVA=OFF \
+-D WITH_1394=OFF \
+-D CMAKE_INSTALL_PREFIX=/workspace/compile/__install/opencv490-gst ..
+*/

+ 4 - 52
workspace/demo.json

@@ -132,59 +132,11 @@
                     "params": {}
                 },
                 {
-                    "node_id": "record_0",
-                    "node_type": "Recorder",
+                    "node_id": "rtmp_0",
+                    "node_type": "Rtmp",
                     "params": {
-                        "record_path": "result/result_pipeline0.mp4"
-                    }
-                }
-            ]
-        },
-        {
-            "pipeline_id": "pipeline_1",
-            "description": "处理摄像头1的视频流",
-            "nodes": [
-                {
-                    "node_id": "src_1",
-                    "node_type": "Source",
-                    "params": {
-                        "stream_url": "rtsp://admin:lww123456@172.16.22.16:554/Streaming/Channels/101",
-                        "gpu_id": 1,
-                        "decode_type": "GPU",
-                        "skip_frame": 1
-                    }
-                },
-                {
-                    "node_id": "infer_1",
-                    "node_type": "Inference",
-                    "params": {
-                        "model_id": "yolo_model_main"
-                    }
-                },
-                {
-                    "node_id": "track_1",
-                    "node_type": "Tracker",
-                    "params": {
-                        "track_name": "person",
-                        "track_frame": 30,
-                        "track_distance": 30
-                    }
-                },
-                {
-                    "node_id": "analyze_1",
-                    "node_type": "Analyzer",
-                    "params": {}
-                },
-                {
-                    "node_id": "draw_1",
-                    "node_type": "Drawer",
-                    "params": {}
-                },
-                {
-                    "node_id": "record_1",
-                    "node_type": "Recorder",
-                    "params": {
-                        "record_path": "result/result_pipeline1.mp4"
+                        "gst_pipeline": "appsrc ! videoconvert ! x264enc tune=zerolatency bitrate=500 speed-preset=ultrafast ! video/x-h264, stream-format=byte-stream ! flvmux streamable=true ! rtmpsink location='rtmpUrl sync=false async=false'",
+                        "fps": 25
                     }
                 }
             ]