diff --git a/CMakeLists.txt b/CMakeLists.txt index 7306c81..d60f78b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,9 +49,10 @@ link_directories(/usr/local/cuda/targets/x86_64-linux/lib/) include_directories(${PROJECT_SOURCE_DIR}/camera_manager.hpp) include_directories(${PROJECT_SOURCE_DIR}/pipeline_manager.hpp) include_directories(${PROJECT_SOURCE_DIR}/streammux_manager.hpp) +include_directories(${PROJECT_SOURCE_DIR}/source_bin.hpp) -set(SOURCES src/main.cpp src/camera_manager.cpp src/pipeline_manager.cpp src/streammux_manager.cpp) +set(SOURCES src/main.cpp src/camera_manager.cpp src/pipeline_manager.cpp src/streammux_manager.cpp src/source_bin.cpp) # Create the executable add_executable(${PROJECT_NAME} ${SOURCES}) diff --git a/src/main.cpp b/src/main.cpp index 60e055d..d0449bc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,7 @@ gboolean *g_eos_list = NULL; gboolean *check_finished_streams = NULL; gboolean *g_source_enabled = NULL; guint num_sources; // number of input cameras +GstElement **g_source_bin_list = NULL; void allocate_memory_variables_cameras(const int MAX_NUM_SOURCES) { g_source_id_list = (gint *)g_malloc0(sizeof(gint) * MAX_NUM_SOURCES); @@ -22,6 +23,8 @@ void allocate_memory_variables_cameras(const int MAX_NUM_SOURCES) { (gboolean *)g_malloc0(sizeof(gboolean) * MAX_NUM_SOURCES); g_source_enabled = (gboolean *)g_malloc0(sizeof(gboolean) * MAX_NUM_SOURCES); + g_source_bin_list = + (GstElement **)g_malloc0(sizeof(GstElement *) * MAX_NUM_SOURCES); } int load_rtsp_address(CameraManager *camera_manager, fs::path file_path) { @@ -77,7 +80,7 @@ int main(int argc, char *argv[]) { PipelineManager *pipeline_manager = new PipelineManager(num_sources, url_camera); pipeline_manager->create_pipeline(); - pipeline_manager->create_pipeline_elements(num_sources); + pipeline_manager->create_pipeline_elements(num_sources, url_camera); return 0; } \ No newline at end of file diff --git a/src/pipeline_manager.cpp b/src/pipeline_manager.cpp index 46ef99c..dc08632 100644 --- a/src/pipeline_manager.cpp +++ b/src/pipeline_manager.cpp @@ -32,7 +32,29 @@ void PipelineManager::set_cuda_device() { << std::endl; } -void PipelineManager::create_pipeline_elements(int num_sources) { +bool PipelineManager::create_pipeline_elements(int num_sources, + char** url_camera) { streammux_manager->create_streammux(num_sources); set_cuda_device(); + gst_bin_add(GST_BIN(pipeline), streammux_manager->streammux); + // for each source generate a pad for the source, generate another pad for + // streammux, then connect the source pad to the pad of streammux + + for (guint i = 0; i < (guint)num_sources; i++) { + GstElement* source_bin; + // GstElement *source_bin = create_uridecode_bin (i, + // const_cast(first_video.c_str())); + g_print("Trying to create uridecode_bin for %s \n", url_camera[i + 1]); + + source_bin = SourceBin::create_uridecode_bin( + i, url_camera[i + 1], streammux_manager->streammux, prop); + if (!source_bin) { + g_printerr("Failed to create source bin for %s. Exiting.\n", + url_camera[i + 1]); + return false; + } + // g_source_bin_list[i] = source_bin; + gst_bin_add(GST_BIN(pipeline), source_bin); + } + return true; } \ No newline at end of file diff --git a/src/pipeline_manager.hpp b/src/pipeline_manager.hpp index 01a115a..c8a9509 100644 --- a/src/pipeline_manager.hpp +++ b/src/pipeline_manager.hpp @@ -2,6 +2,7 @@ #include #include "cuda_runtime_api.h" +#include "source_bin.hpp" #include "streammux_manager.hpp" class PipelineManager { @@ -18,7 +19,7 @@ class PipelineManager { PipelineManager(); PipelineManager(int, char **); int create_pipeline(); - void create_pipeline_elements(int); + bool create_pipeline_elements(int, char **); void set_cuda_device(); ~PipelineManager(); }; \ No newline at end of file diff --git a/src/source_bin.cpp b/src/source_bin.cpp new file mode 100644 index 0000000..946c161 --- /dev/null +++ b/src/source_bin.cpp @@ -0,0 +1,114 @@ +#include "source_bin.hpp" + +// Initialize static member (required for non-const static members) +// int MyClass::staticCounter = 0; + +// Definition of static function +void SourceBin::decodebin_child_added(GstChildProxy *child_proxy, + GObject *object, gchar *name, + gpointer user_data) { + (void)child_proxy; // This explicitly marks it as unused + std::cout << "decodebin_child_added" << std::endl; + + StreamData *data = static_cast(user_data); + gint source_id = data->source_id; + // gint source_id = (*(gint *) user_data); + + g_print( + "Decodebin child added %s for stream_id %d" + "\n", + name, source_id); + if (g_strrstr(name, "decodebin") == name) { + g_signal_connect(G_OBJECT(object), "child-added", + G_CALLBACK(decodebin_child_added), user_data); + } + + if (g_strrstr(name, "nvv4l2decoder") == name) { + if (data->prop.integrated) { + g_object_set(object, "enable-max-performance", TRUE, NULL); + g_object_set(object, "bufapi-version", TRUE, NULL); + g_object_set(object, "drop-frame-interval", 0, NULL); + g_object_set(object, "num-extra-surfaces", 0, NULL); + } else { + g_object_set(object, "gpu-id", GPU_ID, NULL); + } + } +} + +// Definition of static function +void SourceBin::cb_newpad(GstElement *decodebin, GstPad *pad, + gpointer user_data, gboolean *flag) { + (void)decodebin; // This explicitly marks it as unused + (void)flag; // This explicitly marks it as unused + std::cout << "cb_newpad" << std::endl; + StreamData *data = static_cast(user_data); + gint source_id = data->source_id; + GstElement *streammux = data->streammux; + // gint source_id = (*(gint *) data); + g_print( + "In cb_newpad for stream_id %d" + "\n", + source_id); + GstCaps *caps = gst_pad_query_caps(pad, NULL); + const GstStructure *str = gst_caps_get_structure(caps, 0); + const gchar *name = gst_structure_get_name(str); + + // g_print ("decodebin new pad %s\n", name); + g_print( + "decodebin new pad %s for stream_id %d" + "\n", + name, source_id); + if (!strncmp(name, "video", 5)) { + gchar pad_name[16] = {0}; + GstPad *sinkpad = NULL; + g_snprintf(pad_name, 15, "sink_%u", source_id); + sinkpad = gst_element_request_pad_simple( + streammux, pad_name); // gst_element_get_request_pad + + if (!sinkpad) { + g_printerr( + "Streammux request sink pad failed for stream_id %d or " + ". Exiting. \n", + source_id); + } + if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) { + g_printerr( + "Failed to link decodebin bin to pipeline for stream_id %d or " + ". Exiting.\n", + source_id); + } else { + // g_print ("Decodebin linked to pipeline\n"); + g_print( + "Decodebin linked to pipeline for stream_id %d" + "\n", + source_id); + } + gst_object_unref(sinkpad); + } +} + +// Definition of static function +GstElement *SourceBin::create_uridecode_bin(guint index, gchar *filename, + GstElement *streammux, + cudaDeviceProp prop) { + GstElement *decodebin = NULL; + gchar decodebin_name[16] = {}; + // Create data structure for callbacks + StreamData *stream_data = new StreamData{(int)index, streammux, prop}; + + // g_print ("creating uridecodebin for [%s]\n", filename); + g_print("Creating uridecodebin for stream_id %d or stream %s \n", index, + filename); + // g_source_id_list[index] = index; + g_snprintf(decodebin_name, 15, "source-bin-%02d", index); + decodebin = gst_element_factory_make("uridecodebin", decodebin_name); + g_object_set(G_OBJECT(decodebin), "uri", filename, NULL); + g_signal_connect(G_OBJECT(decodebin), "pad-added", G_CALLBACK(cb_newpad), + stream_data); //&g_source_id_list[index] + g_signal_connect( + G_OBJECT(decodebin), "child-added", G_CALLBACK(decodebin_child_added), + stream_data); //&g_source_id_list[index] //&stream_data->source_id + // g_source_enabled[index] = TRUE; + + return decodebin; +} \ No newline at end of file diff --git a/src/source_bin.hpp b/src/source_bin.hpp new file mode 100644 index 0000000..76876b0 --- /dev/null +++ b/src/source_bin.hpp @@ -0,0 +1,32 @@ +// #ifndef MYCLASS_H +// #define MYCLASS_H +#include +#include + +#include +#include + +#include "cuda_runtime_api.h" +#define GPU_ID 0 + +class SourceBin { + public: + typedef struct { + gint source_id; + GstElement *streammux; + struct cudaDeviceProp prop; + } StreamData; + + // Static function declaration + static void decodebin_child_added(GstChildProxy *, GObject *, gchar *, + gpointer); + static void cb_newpad(GstElement *, GstPad *, gpointer, gboolean *); + static GstElement *create_uridecode_bin(guint, gchar *, GstElement *, + cudaDeviceProp prop); + + private: + // Static data member (if needed) + // static int staticCounter; +}; + +// #endif // MYCLASS_H \ No newline at end of file diff --git a/src/streammux_manager.hpp b/src/streammux_manager.hpp index 0ab6573..bcdb456 100644 --- a/src/streammux_manager.hpp +++ b/src/streammux_manager.hpp @@ -8,9 +8,9 @@ class StreammuxManager { private: - GstElement *streammux = NULL; public: + GstElement *streammux = NULL; int MUXER_OUTPUT_WIDTH; int MUXER_OUTPUT_HEIGHT; StreammuxManager();