From 93ed240a0a2a79c373877649e3580aad8539e2f6 Mon Sep 17 00:00:00 2001 From: Barzan Hayati Date: Tue, 1 Jul 2025 13:49:25 +0000 Subject: [PATCH] Create rtsp streaming --- CMakeLists.txt | 9 ++-- data/configuration.json | 11 ++++- src/pipeline_manager.cpp | 19 ++++---- src/pipeline_manager.hpp | 4 +- src/rtsp_streaming_manager.cpp | 88 ++++++++++++++++++++++++++++++++++ src/rtsp_streaming_manager.hpp | 31 ++++++++++++ 6 files changed, 147 insertions(+), 15 deletions(-) create mode 100644 src/rtsp_streaming_manager.cpp create mode 100644 src/rtsp_streaming_manager.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ec9a7b7..ef13dd4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,8 @@ endif() find_package(PkgConfig REQUIRED) find_package(CUDA REQUIRED) -pkg_check_modules(GLIB REQUIRED glib-2.0 gobject-2.0 nlohmann_json gstreamer-base-1.0 gstreamer-1.0 gstreamer-video-1.0) +pkg_check_modules(GLIB REQUIRED glib-2.0 gobject-2.0 nlohmann_json gstreamer-base-1.0 + gstreamer-rtsp-server-1.0 gstreamer-rtsp-1.0 gstreamer-1.0 gstreamer-video-1.0) if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") message("embed_platform on") @@ -61,11 +62,13 @@ include_directories(${PROJECT_SOURCE_DIR}/queue_manager.hpp) include_directories(${PROJECT_SOURCE_DIR}/nv_ds_logger_manager.hpp) include_directories(${PROJECT_SOURCE_DIR}/sink_manager.hpp) include_directories(${PROJECT_SOURCE_DIR}/message_handling.hpp) +include_directories(${PROJECT_SOURCE_DIR}/rtsp_streaming_manager.hpp) set(SOURCES src/main.cpp src/camera_manager.cpp src/pipeline_manager.cpp src/streammux_manager.cpp src/source_bin.cpp src/gstds_example_manager.cpp src/tiler_manager.cpp src/nv_video_convert_manager.cpp src/nv_osd_manager.cpp src/queue_manager.cpp - src/nv_ds_logger_manager.cpp src/sink_manager.cpp src/message_handling.cpp) + src/nv_ds_logger_manager.cpp src/sink_manager.cpp src/message_handling.cpp + src/rtsp_streaming_manager.cpp) # Create the executable add_executable(${PROJECT_NAME} ${SOURCES}) @@ -88,7 +91,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(${PROJECT_NAME} PRIVATE ${GLIB_INCLUDE_DIRS}) target_link_libraries(${PROJECT_NAME} ${GLIB_LIBRARIES}) -target_link_libraries(${PROJECT_NAME} gstbase-1.0 gstreamer-1.0 gstrtp-1.0 gstvideo-1.0) +target_link_libraries(${PROJECT_NAME} gstbase-1.0 gstreamer-1.0 gstrtp-1.0 gstvideo-1.0 gstrtspserver-1.0) target_link_libraries(${PROJECT_NAME} cudart cuda) target_link_libraries(${PROJECT_NAME} nvdsgst_infer nvds_meta nvds_inferutils nvds_utils nvdsgst_helper)#nvdsgst_metnvdsa \ No newline at end of file diff --git a/data/configuration.json b/data/configuration.json index 0c1383a..5b1a7c6 100644 --- a/data/configuration.json +++ b/data/configuration.json @@ -2,5 +2,14 @@ "MUXER_OUTPUT_HEIGHT": 1080, "MUXER_OUTPUT_WIDTH": 1920, "output_video_path": "test.mkv", - "display_output": 1 + "display_output": 1, + "codec_rtsp_out": "H264", + "mount_address": "/rtsp-output", + "udp_buffer_size": 524288, + "clock_rate": 90000, + "bitrate":4000000, + "payload": 96, + "rtsp_port": 8554, + "updsink_port_num": 5400, + "host": "224.224.255.255" } diff --git a/src/pipeline_manager.cpp b/src/pipeline_manager.cpp index 0834ebf..9a204f0 100644 --- a/src/pipeline_manager.cpp +++ b/src/pipeline_manager.cpp @@ -48,21 +48,19 @@ char* createName(const char* str, int num) { return result; } -void PipelineManager::playing_pipeline(int num_sources, - char** url_camera){ +void PipelineManager::playing_pipeline(int num_sources, char** url_camera) { /* Set the pipeline to "playing" state */ - g_print ("Now playing... \n"); - for (int i = 0; i < num_sources; i++) - { - g_print ("\033[1;35m %s,", url_camera[i + 1]); + g_print("Now playing... \n"); + for (int i = 0; i < num_sources; i++) { + g_print("%s, \n", url_camera[i + 1]); } - GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), - GST_DEBUG_GRAPH_SHOW_ALL, sink_manager->output_sink.c_str()); - - gst_element_set_state (pipeline, GST_STATE_PLAYING); + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(pipeline), + GST_DEBUG_GRAPH_SHOW_ALL, + sink_manager->output_sink.c_str()); + gst_element_set_state(pipeline, GST_STATE_PLAYING); } bool PipelineManager::setup_pipeline() { @@ -168,6 +166,7 @@ bool PipelineManager::create_pipeline_elements(int num_sources, setup_pipeline(); playing_pipeline(num_sources, url_camera); + rtsp_streaming_manager->start_rtsp_streaming(); return true; } \ No newline at end of file diff --git a/src/pipeline_manager.hpp b/src/pipeline_manager.hpp index 6a8b4fb..0151141 100644 --- a/src/pipeline_manager.hpp +++ b/src/pipeline_manager.hpp @@ -8,6 +8,7 @@ #include "nv_osd_manager.hpp" #include "nv_video_convert_manager.hpp" #include "queue_manager.hpp" +#include "rtsp_streaming_manager.hpp" #include "sink_manager.hpp" #include "source_bin.hpp" #include "streammux_manager.hpp" @@ -28,6 +29,7 @@ class PipelineManager { NvDsLoggerManager *nv_ds_logger_manager = new NvDsLoggerManager(); SinkManager *sink_manager = new SinkManager(); MessageHandling *message_handling = new MessageHandling(); + RtspStreamingManager *rtsp_streaming_manager = new RtspStreamingManager(); public: int current_device = -1; @@ -38,7 +40,7 @@ class PipelineManager { int create_pipeline(); bool create_pipeline_elements(int, char **); bool setup_pipeline(); - void playing_pipeline(int , char** ); + void playing_pipeline(int, char **); void set_cuda_device(); ~PipelineManager(); }; \ No newline at end of file diff --git a/src/rtsp_streaming_manager.cpp b/src/rtsp_streaming_manager.cpp new file mode 100644 index 0000000..c6c5ae7 --- /dev/null +++ b/src/rtsp_streaming_manager.cpp @@ -0,0 +1,88 @@ +#include "rtsp_streaming_manager.hpp" + +#define SET_GPU_ID(object, gpu_id) \ + g_object_set(G_OBJECT(object), "gpu-id", gpu_id, NULL); +#define GPU_ID 0 + +using json = nlohmann::json; + +GstRTSPServer *RtspStreamingManager::server; +std::string RtspStreamingManager::codec_rtsp_out = ""; +std::string RtspStreamingManager::mount_address = ""; +guint RtspStreamingManager::udp_buffer_size = 1; +guint RtspStreamingManager::clock_rate = 1; +guint RtspStreamingManager::rtsp_port = 1; +guint RtspStreamingManager::updsink_port_num = 1; +guint RtspStreamingManager::payload = 1; + +RtspStreamingManager::RtspStreamingManager() { + json j; + std::ifstream i("../data/configuration.json"); + i >> j; + + j.at("codec_rtsp_out").get_to(codec_rtsp_out); + j.at("mount_address").get_to(mount_address); + j.at("udp_buffer_size").get_to(udp_buffer_size); + j.at("clock_rate").get_to(clock_rate); + j.at("bitrate").get_to(bitrate); + j.at("rtsp_port").get_to(rtsp_port); + j.at("updsink_port_num").get_to(updsink_port_num); + j.at("payload").get_to(payload); + j.at("host").get_to(host); +} + +gboolean RtspStreamingManager::start_rtsp_streaming() { + GstRTSPMountPoints *mounts; + GstRTSPMediaFactory *factory; + char udpsrc_pipeline[512]; + char port_num_Str[64] = {0}; + // char *encoder_name; + + // if (udp_buffer_size == 0) + // udp_buffer_size = 512 * 1024;//524288 + + server = gst_rtsp_server_new(); + sprintf(port_num_Str, "%d", rtsp_port); + sprintf(udpsrc_pipeline, + "( udpsrc name=pay0 port=%d buffer-size=%u " + "caps=\"application/x-rtp, media=video, " + "clock-rate=%d, encoding-name=%s, payload=%d \" )", + updsink_port_num, udp_buffer_size, clock_rate, + codec_rtsp_out.c_str(), payload); // H264 + // g_print(udpsrc_pipeline); + g_print("%s\n", udpsrc_pipeline); + g_object_set(server, "service", port_num_Str, NULL); + mounts = gst_rtsp_server_get_mount_points(server); + factory = gst_rtsp_media_factory_new(); + gst_rtsp_media_factory_set_launch(factory, udpsrc_pipeline); + gst_rtsp_mount_points_add_factory(mounts, mount_address.c_str(), factory); + g_object_unref(mounts); + gst_rtsp_server_attach(server, NULL); + g_print( + "\n *** DeepStream: Launched RTSP Streaming at rtsp://localhost:%d%s " + "***\n\n", + rtsp_port, mount_address.c_str()); + return TRUE; +} + +GstRTSPFilterResult RtspStreamingManager::client_filter(GstRTSPServer *server, + GstRTSPClient *client, + gpointer user_data) { + (void)server; // This explicitly marks it as unused + (void)client; // This explicitly marks it as unused + (void)user_data; // This explicitly marks it as unused + return GST_RTSP_FILTER_REMOVE; +} + +void RtspStreamingManager::destroy_sink_bin() { + GstRTSPMountPoints *mounts; + GstRTSPSessionPool *pool; + + mounts = gst_rtsp_server_get_mount_points(server); + gst_rtsp_mount_points_remove_factory(mounts, mount_address.c_str()); + g_object_unref(mounts); + gst_rtsp_server_client_filter(server, client_filter, NULL); + pool = gst_rtsp_server_get_session_pool(server); + gst_rtsp_session_pool_cleanup(pool); + g_object_unref(pool); +} \ No newline at end of file diff --git a/src/rtsp_streaming_manager.hpp b/src/rtsp_streaming_manager.hpp new file mode 100644 index 0000000..c4aa809 --- /dev/null +++ b/src/rtsp_streaming_manager.hpp @@ -0,0 +1,31 @@ +#include +#include +#include + +#include +#include + +#include "cuda_runtime_api.h" +#include "json.hpp" + +class RtspStreamingManager { + private: + public: + static gboolean start_rtsp_streaming(); + static GstRTSPFilterResult client_filter(GstRTSPServer *, GstRTSPClient *, + gpointer); + static void destroy_sink_bin(); + + static GstRTSPServer *server; + static guint rtsp_port; + static guint updsink_port_num; + int bitrate; + static std::string codec_rtsp_out; + static guint udp_buffer_size; + static guint clock_rate; + static guint payload; + static std::string mount_address; + std::string host; + RtspStreamingManager(); + ~RtspStreamingManager(); +}; \ No newline at end of file