Create source bin

This commit is contained in:
Barzan Hayati 2025-06-30 18:24:27 +00:00
parent bdbb067489
commit 9360f4130e
7 changed files with 178 additions and 5 deletions

View File

@ -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})

View File

@ -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;
}

View File

@ -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<char*>(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;
}

View File

@ -2,6 +2,7 @@
#include <gst/gst.h>
#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();
};

114
src/source_bin.cpp Normal file
View File

@ -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<StreamData *>(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<StreamData *>(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;
}

32
src/source_bin.hpp Normal file
View File

@ -0,0 +1,32 @@
// #ifndef MYCLASS_H
// #define MYCLASS_H
#include <glib.h>
#include <gst/gst.h>
#include <fstream>
#include <iostream>
#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

View File

@ -8,9 +8,9 @@
class StreammuxManager {
private:
GstElement *streammux = NULL;
public:
GstElement *streammux = NULL;
int MUXER_OUTPUT_WIDTH;
int MUXER_OUTPUT_HEIGHT;
StreammuxManager();