From e78fbc5e1b32964e5cafc29794ca0eef0c0e789f Mon Sep 17 00:00:00 2001 From: LufeBisect Date: Fri, 24 Jan 2025 18:36:21 +0000 Subject: [PATCH] WIP: master_enable --- .../src/gst_nmos_audio_receiver_plugin.cpp | 104 +++++++++++------- .../src/gst_nmos_sender_plugin.cpp | 95 +++++++++------- .../src/gst_nmos_video_receiver_plugin.cpp | 102 ++++++++++------- cpp/libs/gst_nmos_plugins/src/utils.cpp | 9 +- 4 files changed, 187 insertions(+), 123 deletions(-) diff --git a/cpp/libs/gst_nmos_plugins/src/gst_nmos_audio_receiver_plugin.cpp b/cpp/libs/gst_nmos_plugins/src/gst_nmos_audio_receiver_plugin.cpp index ed2d2b5..0fbc25b 100644 --- a/cpp/libs/gst_nmos_plugins/src/gst_nmos_audio_receiver_plugin.cpp +++ b/cpp/libs/gst_nmos_plugins/src/gst_nmos_audio_receiver_plugin.cpp @@ -331,53 +331,79 @@ void construct_pipeline(GstNmosaudioreceiver* self) fmt::print("Invalid format sent for current receiver.\n"); } } - void create_nmos(GstNmosaudioreceiver* self) { - const auto node_config_json = create_node_config(self->config); - if(node_config_json == nullptr) - { - GST_ERROR_OBJECT(self, "Failed to initialize NMOS client. No valid node JSON location given."); - return; - } - const auto device_config_json = create_device_config(self->config); - nlohmann::json_abi_v3_11_3::json receiver_config_json = nullptr; - - receiver_config_json = create_receiver_config(self->config); - - auto receiver_callback = [self](const std::optional& sdp, bool master_enabled) { - fmt::print("Receiver Activation Callback: SDP={}, Master Enabled={}\n", sdp.has_value() ? sdp.value() : "None", - master_enabled); - - if(sdp) + auto initialize_nmos = [&]() -> bool { + const auto node_config_json = create_node_config(self->config); + if(node_config_json == nullptr) { - fmt::print("Received SDP: {}\n", sdp.value()); - auto sdp_settings = parse_sdp(sdp.value()); - if(sdp_settings.has_value() && sdp.value() != self->sdp_string) - { - self->sdp_settings = sdp_settings.value(); - self->sdp_string = sdp.value(); - remove_old_bin(self); - construct_pipeline(self); - gst_element_set_state(GST_ELEMENT(self), GST_STATE_PLAYING); - } + GST_ERROR_OBJECT(self, "Failed to initialize NMOS client. No valid node JSON location given."); + return false; } - else + + auto result = ossrf::nmos_client_t::create(self->config.node.id, node_config_json.dump()); + if(!result.has_value()) { - fmt::print("No SDP provided.\n"); + GST_ERROR_OBJECT(self, "Failed to initialize NMOS client."); + return false; } - fmt::print("Master enabled: {}\n", master_enabled); + + self->client = std::move(result.value()); + return true; }; - auto result = ossrf::nmos_client_t::create(self->config.node.id, node_config_json.dump()); - if(!result.has_value()) - { - GST_ERROR_OBJECT(self, "Failed to initialize NMOS client."); - return; - } - self->client = std::move(result.value()); - self->client->add_device(device_config_json.dump()); - self->client->add_receiver(self->config.device.id, receiver_config_json.dump(), receiver_callback); + if(!initialize_nmos()) return; + + // Add device and receiver configurations + self->client->add_device(create_device_config(self->config).dump()); + self->client->add_receiver( + self->config.device.id, create_receiver_config(self->config).dump(), + [self](const std::optional& sdp, bool master_enabled) { + fmt::print("Receiver Activation Callback: SDP={}, Master Enabled={}\n", + sdp.has_value() ? sdp.value() : "None", master_enabled); + + if(master_enabled) + { + if(sdp) + { + fmt::print("Received SDP: {}\n", sdp.value()); + auto sdp_settings = parse_sdp(sdp.value()); + if(sdp_settings.has_value() && sdp.value() != self->sdp_string) + { + self->sdp_settings = sdp_settings.value(); + self->sdp_string = sdp.value(); + remove_old_bin(self); + construct_pipeline(self); + auto time = gst_element_get_base_time(GST_ELEMENT(self)); + gst_element_set_state(GST_ELEMENT(self), GST_STATE_PLAYING); + gst_pad_set_offset(self->bin_pad, static_cast(gst_clock_get_time(self->clock) - time)); + } + } + else if(!sdp && self->sdp_string != "") + { + fmt::print("No new SDP provided, enabling master pipeline.\n"); + remove_old_bin(self); + construct_pipeline(self); + auto time = gst_element_get_base_time(GST_ELEMENT(self)); + gst_element_set_state(GST_ELEMENT(self), GST_STATE_PLAYING); + gst_pad_set_offset(self->bin_pad, static_cast(gst_clock_get_time(self->clock) - time)); + } + } + else + { + if(sdp) + { + fmt::print("Disabling master: SDP received but master is not enabled.\n"); + remove_old_bin(self); + } + else + { + fmt::print("Master not enabled and no SDP provided.\n"); + } + } + fmt::print("Master enabled: {}\n", master_enabled); + }); + GST_INFO_OBJECT(self, "NMOS client initialized successfully."); } diff --git a/cpp/libs/gst_nmos_plugins/src/gst_nmos_sender_plugin.cpp b/cpp/libs/gst_nmos_plugins/src/gst_nmos_sender_plugin.cpp index ee453d9..dd06ff2 100644 --- a/cpp/libs/gst_nmos_plugins/src/gst_nmos_sender_plugin.cpp +++ b/cpp/libs/gst_nmos_plugins/src/gst_nmos_sender_plugin.cpp @@ -47,6 +47,7 @@ typedef struct _GstNmossender ossrf::nmos_client_uptr client; GstCaps* caps; config_fields_t config; + bool nmos_active; } GstNmossender; typedef struct _GstNmossenderClass @@ -276,57 +277,73 @@ static gboolean gst_nmossender_sink_event(GstPad* pad, GstObject* parent, GstEve return gst_pad_event_default(pad, parent, event); } -/* State Change so it doesn't boot NMOS without pipeline being set to playing */ -static GstStateChangeReturn gst_nmossender_change_state(GstElement* element, GstStateChange transition) +void create_nmos(GstNmossender* self) { - GstStateChangeReturn ret; - GstNmossender* self = GST_NMOSSENDER(element); - - auto sender_activation_callback = [](bool master_enabled, const nlohmann::json& transport_params) { + auto sender_activation_callback = [self](bool master_enabled, const nlohmann::json& transport_params) { fmt::print("nmos_sender_callback: master_enabled={}, transport_params={}\n", master_enabled, transport_params.dump()); + + // if (master_enabled) { + // fmt::print("Master enabled, keeping the pipeline in PLAYING state.\n"); + // gst_element_set_state(GST_ELEMENT(self), GST_STATE_PLAYING); + // } else { + // fmt::print("Master disabled, setting the pipeline to PAUSED state.\n"); + // gst_element_set_state(GST_ELEMENT(self), GST_STATE_PAUSED); + // } }; - switch(transition) + const auto node_config_json = create_node_config(self->config); + if(node_config_json == nullptr) { - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: { + GST_ERROR_OBJECT(self, "Failed to initialize NMOS client. No valid node JSON location given."); + return; + } + const auto device_config_json = create_device_config(self->config); + nlohmann::json_abi_v3_11_3::json sender_config_json = nullptr; - const auto node_config_json = create_node_config(self->config); - if(node_config_json == nullptr) - { - GST_ERROR_OBJECT(self, "Failed to initialize NMOS client. No valid node JSON location given."); - return GST_STATE_CHANGE_FAILURE; - } - const auto device_config_json = create_device_config(self->config); - nlohmann::json_abi_v3_11_3::json sender_config_json = nullptr; + if(self->config.is_audio) + { + sender_config_json = create_audio_sender_config(self->config); + } + else + { + sender_config_json = create_video_sender_config(self->config); + } - if(self->config.is_audio) - { - sender_config_json = create_audio_sender_config(self->config); - } - else - { - sender_config_json = create_video_sender_config(self->config); - } + auto result = ossrf::nmos_client_t::create(self->config.node.id, node_config_json.dump()); + if(result.has_value() == false) + { + GST_ERROR_OBJECT(self, "Failed to initialize NMOS client. Node ID: %s", self->config.node.id.c_str()); + return; + } - auto result = ossrf::nmos_client_t::create(self->config.node.id, node_config_json.dump()); - if(result.has_value() == false) - { - GST_ERROR_OBJECT(self, "Failed to initialize NMOS client. Node ID: %s", self->config.node.id.c_str()); - return GST_STATE_CHANGE_FAILURE; - } + self->client = std::move(result.value()); + if(!self->client->add_device(device_config_json.dump())) + { + GST_ERROR_OBJECT(self, "Failed to add device to NMOS client"); + return; + } - self->client = std::move(result.value()); - if(!self->client->add_device(device_config_json.dump())) - { - GST_ERROR_OBJECT(self, "Failed to add device to NMOS client"); - return GST_STATE_CHANGE_FAILURE; - } + if(!self->client->add_sender(self->config.device.id, sender_config_json.dump(), sender_activation_callback)) + { + GST_ERROR_OBJECT(self, "Failed to add sender to NMOS client"); + return; + } +} - if(!self->client->add_sender(self->config.device.id, sender_config_json.dump(), sender_activation_callback)) +/* State Change so it doesn't boot NMOS without pipeline being set to playing */ +static GstStateChangeReturn gst_nmossender_change_state(GstElement* element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstNmossender* self = GST_NMOSSENDER(element); + + switch(transition) + { + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: { + if(self->nmos_active != true) { - GST_ERROR_OBJECT(self, "Failed to add sender to NMOS client"); - return GST_STATE_CHANGE_FAILURE; + create_nmos(self); + self->nmos_active = true; } } break; diff --git a/cpp/libs/gst_nmos_plugins/src/gst_nmos_video_receiver_plugin.cpp b/cpp/libs/gst_nmos_plugins/src/gst_nmos_video_receiver_plugin.cpp index e0a2ccd..13c8cdb 100644 --- a/cpp/libs/gst_nmos_plugins/src/gst_nmos_video_receiver_plugin.cpp +++ b/cpp/libs/gst_nmos_plugins/src/gst_nmos_video_receiver_plugin.cpp @@ -316,52 +316,74 @@ void construct_pipeline(GstNmosvideoreceiver* self) void create_nmos(GstNmosvideoreceiver* self) { - const auto node_config_json = create_node_config(self->config); - if(node_config_json == nullptr) - { - GST_ERROR_OBJECT(self, "Failed to initialize NMOS client. No valid node JSON location given."); - return; - } - const auto device_config_json = create_device_config(self->config); - nlohmann::json_abi_v3_11_3::json receiver_config_json = nullptr; - - receiver_config_json = create_receiver_config(self->config); - - auto receiver_callback = [self](const std::optional& sdp, bool master_enabled) { - fmt::print("Receiver Activation Callback: SDP={}, Master Enabled={}\n", sdp.has_value() ? sdp.value() : "None", - master_enabled); - - if(sdp) + auto initialize_nmos = [&]() -> bool { + const auto node_config_json = create_node_config(self->config); + if(node_config_json == nullptr) { - fmt::print("Received SDP: {}\n", sdp.value()); - auto sdp_settings = parse_sdp(sdp.value()); - if(sdp_settings.has_value() && sdp.value() != self->sdp_string) - { - self->sdp_settings = sdp_settings.value(); - self->sdp_string = sdp.value(); - remove_old_bin(self); - construct_pipeline(self); - auto time = gst_element_get_base_time(GST_ELEMENT(self)); - gst_element_set_state(GST_ELEMENT(self), GST_STATE_PLAYING); - gst_pad_set_offset(self->bin_pad, (long)(gst_clock_get_time(self->clock) - time)); - } + GST_ERROR_OBJECT(self, "Failed to initialize NMOS client. No valid node JSON location given."); + return false; } - else + + auto result = ossrf::nmos_client_t::create(self->config.node.id, node_config_json.dump()); + if(!result.has_value()) { - fmt::print("No SDP provided.\n"); + GST_ERROR_OBJECT(self, "Failed to initialize NMOS client."); + return false; } - fmt::print("Master enabled: {}\n", master_enabled); + + self->client = std::move(result.value()); + return true; }; - auto result = ossrf::nmos_client_t::create(self->config.node.id, node_config_json.dump()); - if(!result.has_value()) - { - GST_ERROR_OBJECT(self, "Failed to initialize NMOS client."); - return; - } - self->client = std::move(result.value()); - self->client->add_device(device_config_json.dump()); - self->client->add_receiver(self->config.device.id, receiver_config_json.dump(), receiver_callback); + if(!initialize_nmos()) return; + + // Add device and receiver configurations + self->client->add_device(create_device_config(self->config).dump()); + self->client->add_receiver( + self->config.device.id, create_receiver_config(self->config).dump(), + [self](const std::optional& sdp, bool master_enabled) { + fmt::print("Receiver Activation Callback: SDP={}, Master Enabled={}\n", + sdp.has_value() ? sdp.value() : "None", master_enabled); + + if(master_enabled) + { + if(sdp) + { + fmt::print("Received SDP: {}\n", sdp.value()); + auto sdp_settings = parse_sdp(sdp.value()); + if(sdp_settings.has_value() && sdp.value() != self->sdp_string) + { + self->sdp_settings = sdp_settings.value(); + self->sdp_string = sdp.value(); + remove_old_bin(self); + construct_pipeline(self); + auto time = gst_element_get_base_time(GST_ELEMENT(self)); + gst_element_set_state(GST_ELEMENT(self), GST_STATE_PLAYING); + gst_pad_set_offset(self->bin_pad, static_cast(gst_clock_get_time(self->clock) - time)); + } + } + else if(!sdp && self->sdp_string != "") + { + construct_pipeline(self); + auto time = gst_element_get_base_time(GST_ELEMENT(self)); + gst_element_set_state(GST_ELEMENT(self), GST_STATE_PLAYING); + gst_pad_set_offset(self->bin_pad, static_cast(gst_clock_get_time(self->clock) - time)); + } + } + else if(!master_enabled) + { + if(sdp) + { + remove_old_bin(self); + } + else + { + fmt::print("No SDP provided.\n"); + } + } + fmt::print("Master enabled: {}\n", master_enabled); + }); + GST_INFO_OBJECT(self, "NMOS client initialized successfully."); } diff --git a/cpp/libs/gst_nmos_plugins/src/utils.cpp b/cpp/libs/gst_nmos_plugins/src/utils.cpp index d8a9b0b..6e3f300 100644 --- a/cpp/libs/gst_nmos_plugins/src/utils.cpp +++ b/cpp/libs/gst_nmos_plugins/src/utils.cpp @@ -11,7 +11,6 @@ using namespace bisect; using json = nlohmann::json; - void create_default_config_fields_sender(config_fields_t* config) { if(!config) @@ -80,7 +79,7 @@ void create_default_config_fields_video_receiver(config_fields_t* config) config->description = "BISECT OSSRF Video Receiver"; config->interface_name = "wlp1s0"; config->address = "192.168.1.36"; - config->is_audio = false; + config->is_audio = false; } void create_default_config_fields_audio_receiver(config_fields_t* config) @@ -107,7 +106,7 @@ void create_default_config_fields_audio_receiver(config_fields_t* config) config->description = "BISECT OSSRF Audio Receiver"; config->interface_name = "wlp1s0"; config->address = "192.168.1.36"; - config->is_audio = true; + config->is_audio = true; } json create_node_config(config_fields_t& config) @@ -136,7 +135,8 @@ json create_device_config(config_fields_t& config) json create_receiver_config(config_fields_t& config) { std::string caps = "video/raw"; - if(config.is_audio == true){ + if(config.is_audio == true) + { caps = "audio/L24"; } json sender = { @@ -276,7 +276,6 @@ std::string get_sender_config(char* sender_configuration_location) return sender_config.value().dump(); } - json create_video_sender_config(config_fields_t& config) { json sender = {