wangrong
2025-03-19 291afb9c81aae1d15d9e3edcea618d0a2e1fc5a6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
 
 
#include "vp_rtsp_des_node.h"
 
 
namespace vp_nodes {
        
    vp_rtsp_des_node::vp_rtsp_des_node(std::string node_name, 
                        int channel_index, 
                        int rtsp_port, 
                        std::string rtsp_name, 
                        vp_objects::vp_size resolution_w_h, 
                        int bitrate,
                        bool osd,
                        std::string gst_encoder_name):
                        vp_des_node(node_name, channel_index),
                        rtsp_port(rtsp_port),
                        rtsp_name(rtsp_name),
                        resolution_w_h(resolution_w_h),
                        bitrate(bitrate),
                        osd(osd),
                        gst_encoder_name(gst_encoder_name) {
        if (rtsp_name.empty()) {
            // use channel index as rtsp name
            this->rtsp_name = std::to_string(channel_index);
        }
        gst_template = vp_utils::string_format(gst_template, gst_encoder_name.c_str(), bitrate, base_udp_port + channel_index);
        VP_INFO(vp_utils::string_format("[%s] [%s]", node_name.c_str(), gst_template.c_str()));
 
        // start rtsp server asynchronously
        start_rtsp_streaming();
 
        this->initialized();
    }
    
    vp_rtsp_des_node::~vp_rtsp_des_node() { 
        deinitialized();
    }
    GstRTSPServer* vp_rtsp_des_node::rtsp_server = NULL;
    std::shared_ptr<vp_objects::vp_meta> vp_rtsp_des_node::handle_frame_meta(std::shared_ptr<vp_objects::vp_frame_meta> meta) {
        VP_DEBUG(vp_utils::string_format("[%s] received frame meta, channel_index=>%d, frame_index=>%d", node_name.c_str(), meta->channel_index, meta->frame_index));
        
        cv::Mat resize_frame;
        if (this->resolution_w_h.width != 0 && this->resolution_w_h.height != 0) {                 
            cv::resize((osd && !meta->osd_frame.empty()) ? meta->osd_frame : meta->frame, resize_frame, cv::Size(resolution_w_h.width, resolution_w_h.height));
        }
        else {
            resize_frame = (osd && !meta->osd_frame.empty()) ? meta->osd_frame : meta->frame;
        }
 
        if (!rtsp_writer.isOpened()) {
            assert(rtsp_writer.open(this->gst_template, cv::CAP_GSTREAMER, 0, meta->fps, {resize_frame.cols, resize_frame.rows}));
        }
 
        rtsp_writer.write(resize_frame);
 
        // for general works defined in base class
        return vp_des_node::handle_frame_meta(meta);
    }
 
    void vp_rtsp_des_node::start_rtsp_streaming () {
        // create a rtsp server using gst-rtsp-server
        if (rtsp_server == NULL) {
            char port_num_Str[64] = { 0 };
            sprintf (port_num_Str, "%d", rtsp_port);
            rtsp_server = gst_rtsp_server_new ();
            g_object_set (rtsp_server, "service", port_num_Str, NULL);
            gst_rtsp_server_attach (rtsp_server, NULL);
        }
 
        char udpsrc_pipeline[512];
        if (udp_buffer_size == 0)
            udp_buffer_size = 512 * 1024;
        
        // receive stream data from udpsrc internally and push it via rtsp
        sprintf (udpsrc_pipeline,
                "( udpsrc name=pay0 port=%d buffer-size=%lu caps=\"application/x-rtp, media=video, "
                "clock-rate=90000, encoding-name=H264, payload=96 \" )",
                base_udp_port + channel_index, udp_buffer_size);
            
        auto mounts = gst_rtsp_server_get_mount_points (rtsp_server);
 
        auto factory = gst_rtsp_media_factory_new ();
        gst_rtsp_media_factory_set_launch (factory, udpsrc_pipeline);
        gst_rtsp_media_factory_set_shared (factory, TRUE);
        gst_rtsp_mount_points_add_factory (mounts, ("/" + rtsp_name).c_str(), factory);
        g_object_unref (mounts);
 
        VP_INFO(vp_utils::string_format("[%s] is going to push rtsp stream, please visit:[%s]", node_name.c_str(), to_string().c_str()));
    }
 
    std::string vp_rtsp_des_node::to_string() {
        return "rtsp://localhost:" + std::to_string(rtsp_port) + "/" + rtsp_name;
    }
}