Skip to content

Commit

Permalink
Add ST2110-30 sender to the gstreamer and demo
Browse files Browse the repository at this point in the history
  • Loading branch information
joaofigueiredobisect committed Sep 25, 2024
1 parent 6a069a4 commit a4859c1
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 18 deletions.
29 changes: 12 additions & 17 deletions cpp/demos/ossrf-nmos-api/config/nmos_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"label": "BISECT OSSRF Node",
"description": "BISECT OSSRF node",
"host_addresses": [
"192.168.1.79"
"192.168.1.15"
],
"interfaces": [
{
Expand All @@ -24,10 +24,10 @@
"locked": true
}
],
"registry_address": "192.168.1.79",
"registry_address": "192.168.1.15",
"registry_version": "v1.3",
"registration_port": 8010,
"system_address": "192.168.1.79",
"system_address": "192.168.1.15",
"system_version": "v1.0",
"system_port": 8010
}
Expand All @@ -44,7 +44,7 @@
"description": "BISECT OSSRF receiver video",
"network": {
"primary": {
"interface_address": "192.168.1.79",
"interface_address": "192.168.1.15",
"interface_name": "wlp1s0"
}
},
Expand All @@ -60,7 +60,7 @@
"description": "BISECT OSSRF sender video 1",
"network": {
"primary": {
"source_address": "192.168.1.79",
"source_address": "192.168.1.15",
"interface_name": "wlp1s0",
"destination_address": "239.10.10.10",
"destination_port": 5004
Expand All @@ -81,27 +81,22 @@
},
{
"id": "f2aa5651-c673-448c-bd02-5e8475898c7f",
"label": "BISECT OSSRF sender video 2",
"description": "BISECT OSSRF sender video 2",
"label": "BISECT OSSRF sender audio",
"description": "BISECT OSSRF sender audio",
"network": {
"primary": {
"source_address": "192.168.1.79",
"source_address": "192.168.1.15",
"interface_name": "wlp1s0",
"destination_address": "239.10.10.11",
"destination_port": 5005
}
},
"payload_type": 97,
"media_type": "video/raw",
"media_type": "audio/L24",
"media": {
"width": 640,
"height": 480,
"frame_rate": {
"num": 50,
"den": 1
},
"sampling": "RGB_444",
"structure": "progressive"
"number_of_channels": 2,
"sampling_rate": 48000,
"packet_time": 1.000
}
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "bisect/expected/match.h"
#include "bisect/json.h"
#include "st2110_20_sender_plugin.h"
#include "st2110_30_sender_plugin.h"
#include <nlohmann/json.hpp>

using namespace bisect;
Expand Down Expand Up @@ -95,7 +96,7 @@ namespace
{
BST_CHECK_ASSIGN(s.format, video_sender_info_from_json(media));
}
else if(media_type == "audio/raw")
else if(media_type == "audio/L24")
{
BST_CHECK_ASSIGN(s.format, audio_l24_sender_info_from_json(media));
}
Expand All @@ -118,6 +119,12 @@ namespace
{
return create_gst_st2110_20_plugin(settings, format, pattern);
}

expected<gst_sender_plugin_uptr> do_create_plugin(const audio_info_t& format, const sender_settings& settings,
int pattern)
{
return create_gst_st2110_30_plugin(settings, format);
}
} // namespace

expected<gst_sender_plugin_uptr> plugins::create_gst_sender_plugin(const std::string& config, int pattern) noexcept
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright (C) 2024 Advanced Media Workflow Association
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "st2110_30_sender_plugin.h"
#include "bisect/expected/macros.h"
#include "bisect/pipeline.h"
#include <gst/gst.h>

using namespace bisect;
using namespace ossrf::gst::sender;
using namespace ossrf::gst::plugins;

namespace
{
constexpr auto queue_max_size_time = 200000;
constexpr auto queue_max_size_buffers = 0;
constexpr auto queue_max_size_bytes = 0;
}; // namespace

struct gst_st2110_30_sender_impl : gst_sender_plugin_t
{
sender_settings s_;
audio_info_t f_;
gst::pipeline pipeline_;

gst_st2110_30_sender_impl(sender_settings settings, audio_info_t format) : s_(settings), f_(format) {}

~gst_st2110_30_sender_impl() { stop(); }

maybe_ok create_gstreamer_pipeline()
{
// Create pipeline and check if all elements are created successfully
BST_CHECK_ASSIGN(pipeline_, bisect::gst::pipeline::create(NULL));
auto* pipeline = pipeline_.get();

// Add pipeline pulsesrc (audio source)
auto* source = gst_element_factory_make("pulsesrc", NULL);
BST_ENFORCE(source != nullptr, "Failed creating GStreamer element pulsesrc");
BST_ENFORCE(gst_bin_add(GST_BIN(pipeline), source), "Failed adding pulsesrc to the pipeline");

// Add pipeline queue1
auto* queue1 = gst_element_factory_make("queue", NULL);
BST_ENFORCE(queue1 != nullptr, "Failed creating GStreamer element queue");
g_object_set(G_OBJECT(queue1), "max-size-time", queue_max_size_time, "max-size-buffers", queue_max_size_buffers,
"max-size-bytes", queue_max_size_bytes, NULL);
BST_ENFORCE(gst_bin_add(GST_BIN(pipeline), queue1), "Failed adding queue to the pipeline");

// Add pipeline audioconvert
auto* audioconvert = gst_element_factory_make("audioconvert", NULL);
BST_ENFORCE(audioconvert != nullptr, "Failed creating GStreamer element audioconvert");
BST_ENFORCE(gst_bin_add(GST_BIN(pipeline), audioconvert), "Failed adding audioconvert to the pipeline");

// Add pipeline queue2
auto* queue2 = gst_element_factory_make("queue", NULL);
BST_ENFORCE(queue2 != nullptr, "Failed creating GStreamer element queue");
g_object_set(G_OBJECT(queue1), "max-size-time", queue_max_size_time, "max-size-buffers", queue_max_size_buffers,
"max-size-bytes", queue_max_size_bytes, NULL);
BST_ENFORCE(gst_bin_add(GST_BIN(pipeline), queue2), "Failed adding queue to the pipeline");

// Add pipeline audioresample
auto* audioresample = gst_element_factory_make("audioresample", NULL);
BST_ENFORCE(audioresample != nullptr, "Failed creating GStreamer element audioresample");
BST_ENFORCE(gst_bin_add(GST_BIN(pipeline), audioresample), "Failed adding audioresample to the pipeline");

// Add pipeline capsfilter
auto* capsfilter = gst_element_factory_make("capsfilter", NULL);
BST_ENFORCE(capsfilter != nullptr, "Failed creating capsfilter");

// Create caps for capsfilter
auto* caps = gst_caps_new_simple("audio/x-raw", "channels", G_TYPE_INT, f_.number_of_channels, "rate",
G_TYPE_INT, f_.sampling_rate, NULL);
BST_ENFORCE(caps != nullptr, "Failed creating GStreamer audio caps");
g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL);
BST_ENFORCE(gst_bin_add(GST_BIN(pipeline), capsfilter), "Failed adding capsfilter to the pipeline");
gst_caps_unref(caps);

// Add pipeline queue1
auto* queue3 = gst_element_factory_make("queue", NULL);
BST_ENFORCE(queue3 != nullptr, "Failed creating GStreamer element queue");
g_object_set(G_OBJECT(queue1), "max-size-time", queue_max_size_time, "max-size-buffers", queue_max_size_buffers,
"max-size-bytes", queue_max_size_bytes, NULL);
BST_ENFORCE(gst_bin_add(GST_BIN(pipeline), queue3), "Failed adding queue to the pipeline");

// Add pipeline rtpL24pay (audio payload)
auto* rtpL24pay = gst_element_factory_make("rtpL24pay", NULL);
BST_ENFORCE(rtpL24pay != nullptr, "Failed creating GStreamer element rtpL24pay");
BST_ENFORCE(gst_bin_add(GST_BIN(pipeline), rtpL24pay), "Failed adding rtpL24pay to the pipeline");

// Add pipeline udpsink
auto* udpsink = gst_element_factory_make("udpsink", NULL);
BST_ENFORCE(udpsink != nullptr, "Failed creating GStreamer element udpsink");
// Set properties
g_object_set(G_OBJECT(udpsink), "host", s_.primary.destination_ip_address.c_str(), NULL);
g_object_set(G_OBJECT(udpsink), "port", s_.primary.destination_port, NULL);
g_object_set(G_OBJECT(udpsink), "auto-multicast", TRUE, NULL);
g_object_set(G_OBJECT(udpsink), "multicast-iface", s_.primary.interface_name.c_str(), NULL);
BST_ENFORCE(gst_bin_add(GST_BIN(pipeline), udpsink), "Failed adding udpsink to the pipeline");

// Link elements
BST_ENFORCE(gst_element_link_many(source, queue1, audioconvert, queue2, audioresample, capsfilter, queue3,
rtpL24pay, udpsink, NULL),
"Failed linking GStreamer audio pipeline");

// Setup runner
pipeline_.run_loop();

return {};
}

void stop() noexcept override
{
pipeline_.stop();
pipeline_ = {};
}
};

expected<gst_sender_plugin_uptr> ossrf::gst::plugins::create_gst_st2110_30_plugin(sender_settings settings,
audio_info_t format) noexcept
{
auto i = std::make_unique<gst_st2110_30_sender_impl>(settings, format);

BST_CHECK(i->create_gstreamer_pipeline());

return i;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (C) 2024 Advanced Media Workflow Association
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once
#include "ossrf/gstreamer/api/sender/sender_plugin.h"
#include "ossrf/gstreamer/api/sender/sender_configuration.h"

namespace ossrf::gst::plugins
{
bisect::expected<gst_sender_plugin_uptr>
create_gst_st2110_30_plugin(ossrf::gst::sender::sender_settings settings,
ossrf::gst::sender::audio_info_t audio_info_t) noexcept;
}

0 comments on commit a4859c1

Please sign in to comment.