-
Notifications
You must be signed in to change notification settings - Fork 21
Add ST2110 bridge classes derived from Connection #261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
tszumski
merged 27 commits into
OpenVisualCloud:main
from
tszumski:tszumski-st2110-covvection-impl
Dec 3, 2024
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
01373b0
Add error code "error_shutdown",
tszumski ba5c36a
Add ST2110 Rx/Tx 20/22/30 connections with basic UT
tszumski 030c4ef
Adjust clang-format and apply it to st2110 files
tszumski 8f3aa39
Call shutdown() in destructor
tszumski ae8e31d
CI/CD quick fix. Disable MTL tests as hugepages are not set
tszumski 2954106
Replace std::function, with virtual fn in ST2110 derrived classes
tszumski 974051f
Fix mutex
tszumski 2db96fc
1. Free memory allocated by "strdup()"
tszumski cfdbb20
1. Remove prefix "_*" from class members name
tszumski 0afaf08
1. Move empty constructor to header
tszumski e25952d
Rework functions to return an error if the format is unknown.
tszumski d194ef1
1. Initialze _ctx with context::WithCancel(context::Background());
tszumski 1f0e0da
Set sent variable only when data is actually sent.
tszumski 3bf6fce
Set state Result::configured only if Result::success
tszumski 2bfc5b4
Rename variable "_sent" to "to_be_sent"
tszumski b29cdf8
Format-coding applied based on updated clang-format
tszumski db06c5a
Fix log message
tszumski 2dd4cd3
Use only atomic for synchronization
tszumski 8d01718
Rename error message
tszumski 80abcb0
Move varaibles to default initializers
tszumski 565e3fe
Adjust code formatting
tszumski e8a44f5
Fix synchronization based on std::atomic
tszumski c628077
Fix setting state prematurely
tszumski fa712dc
Reorder loop
tszumski ee85085
Remove redundant mesh:: namespace
tszumski b154f4b
Add test scenarios for ST2110 transmit and receive following Concept.…
tszumski 2e7b582
Move common implementation from ST2110Tx/ST2110Rx to ST2110
tszumski File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| #ifndef ST2110_H | ||
| #define ST2110_H | ||
|
|
||
| #include <thread> | ||
| #include <bsd/string.h> | ||
| #include <arpa/inet.h> | ||
| #include <mtl/st_pipeline_api.h> | ||
| #include <mtl/st30_pipeline_api.h> | ||
|
|
||
| #include "conn.h" | ||
| #include "mesh_dp.h" | ||
| #include "logger.h" | ||
|
|
||
| namespace mesh::connection { | ||
|
|
||
| #define ST_APP_PAYLOAD_TYPE_ST30 (111) | ||
| #define ST_APP_PAYLOAD_TYPE_ST20 (112) | ||
| #define ST_APP_PAYLOAD_TYPE_ST22 (114) | ||
|
|
||
| int mesh_video_format_to_st_format(int fmt, st_frame_fmt& st_fmt); | ||
| int mesh_audio_format_to_st_format(int fmt, st30_fmt& st_fmt); | ||
| int mesh_audio_sampling_to_st_sampling(int sampling, st30_sampling& st_sampling); | ||
| int mesh_audio_ptime_to_st_ptime(int ptime, st30_ptime& st_ptime); | ||
|
|
||
| void *get_frame_data_ptr(st_frame *src); | ||
| void *get_frame_data_ptr(st30_frame *src); | ||
|
|
||
| void get_mtl_dev_params(mtl_init_params& st_param, const std::string& dev_port, | ||
| mtl_log_level log_level, const char local_ip_addr[MESH_IP_ADDRESS_SIZE]); | ||
| mtl_handle get_mtl_device(const std::string& dev_port, mtl_log_level log_level, | ||
| const char local_ip_addr[MESH_IP_ADDRESS_SIZE], int& session_id); | ||
|
|
||
| /** | ||
| * ST2110 | ||
| * | ||
| * Base abstract class of SPMTE ST2110-xx bridge. ST2110Rx/ST2110Tx | ||
| * inherit this class. | ||
| */ | ||
| template <typename FRAME, typename HANDLE, typename OPS> class ST2110 : public Connection { | ||
| public: | ||
| virtual ~ST2110() { | ||
| shutdown(_ctx); | ||
| if (ops.name) | ||
| free((void *)ops.name); | ||
| }; | ||
|
|
||
| protected: | ||
| mtl_handle mtl_device = nullptr; | ||
| HANDLE mtl_session = nullptr; | ||
| OPS ops = {0}; | ||
| size_t transfer_size = 0; | ||
| std::atomic<bool> frame_available; | ||
| context::Context _ctx = context::WithCancel(context::Background()); | ||
|
|
||
| virtual FRAME *get_frame(HANDLE) = 0; | ||
| virtual int put_frame(HANDLE, FRAME *) = 0; | ||
| virtual HANDLE create_session(mtl_handle, OPS *) = 0; | ||
| virtual int close_session(HANDLE) = 0; | ||
|
|
||
| static int frame_available_cb(void *ptr) { | ||
| auto _this = static_cast<ST2110 *>(ptr); | ||
| if (!_this) { | ||
| return -1; | ||
| } | ||
|
|
||
| _this->notify_frame_available(); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| void notify_frame_available() { | ||
| frame_available.store(true, std::memory_order_release); | ||
| frame_available.notify_one(); | ||
| } | ||
|
|
||
| void wait_frame_available() { | ||
| frame_available.wait(false, std::memory_order_acquire); | ||
| frame_available = false; | ||
| } | ||
|
|
||
| virtual int configure_common(context::Context& ctx, const std::string& dev_port, | ||
| const MeshConfig_ST2110& cfg_st2110) { | ||
| int session_id = 0; | ||
| mtl_device = get_mtl_device(dev_port, MTL_LOG_LEVEL_CRIT, cfg_st2110.local_ip_addr, session_id); | ||
| if (!mtl_device) { | ||
| log::error("Failed to get MTL device"); | ||
| return -1; | ||
| } | ||
|
|
||
| strlcpy(ops.port.port[MTL_PORT_P], dev_port.c_str(), MTL_PORT_MAX_LEN); | ||
| ops.port.num_port = 1; | ||
|
|
||
| char session_name[NAME_MAX] = ""; | ||
| snprintf(session_name, NAME_MAX, "mcm_mtl_%d", session_id); | ||
| if (ops.name) | ||
| free((void *)ops.name); | ||
| ops.name = strdup(session_name); | ||
| ops.framebuff_cnt = 4; | ||
|
|
||
| ops.priv = this; // app handle register to lib | ||
| ops.notify_frame_available = frame_available_cb; | ||
|
|
||
| log::info("ST2110: configure") | ||
| ("port", ops.port.port[MTL_PORT_P]) | ||
| ("num_port", (int)ops.port.num_port) | ||
| ("name", ops.name) | ||
| ("framebuff_cnt", ops.framebuff_cnt); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| Result on_establish(context::Context& ctx) override { | ||
| _ctx = context::WithCancel(ctx); | ||
| frame_available = false; | ||
|
|
||
| mtl_session = create_session(mtl_device, &ops); | ||
| if (!mtl_session) { | ||
| log::error("Failed to create session"); | ||
| set_state(ctx, State::closed); | ||
| return set_result(Result::error_general_failure); | ||
| } | ||
|
|
||
| set_state(ctx, State::active); | ||
| return set_result(Result::success); | ||
| } | ||
|
|
||
| Result on_shutdown(context::Context& ctx) override { | ||
| _ctx.cancel(); | ||
| notify_frame_available(); | ||
|
|
||
| if (mtl_session) { | ||
| close_session(mtl_session); | ||
| mtl_session = nullptr; | ||
| } | ||
| set_state(ctx, State::closed); | ||
| return set_result(Result::success); | ||
| }; | ||
| }; | ||
|
|
||
| } // namespace mesh::connection | ||
|
|
||
| #endif // ST2110_H | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| #ifndef ST2110RX_H | ||
| #define ST2110RX_H | ||
|
|
||
| #include "st2110.h" | ||
|
|
||
| namespace mesh::connection { | ||
|
|
||
| /** | ||
| * ST2110Rx | ||
| * | ||
| * Base abstract class of ST2110Rx. ST2110_20Rx/ST2110_22Rx/ST2110_30Rx | ||
| * inherit this class. | ||
| */ | ||
| template <typename FRAME, typename HANDLE, typename OPS> | ||
| class ST2110Rx : public ST2110<FRAME, HANDLE, OPS> { | ||
| public: | ||
| ST2110Rx() { this->_kind = Kind::receiver; } | ||
|
|
||
| protected: | ||
| std::jthread frame_thread_handle; | ||
|
|
||
| int configure_common(context::Context& ctx, const std::string& dev_port, | ||
Sakoram marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const MeshConfig_ST2110& cfg_st2110) override{ | ||
| ST2110<FRAME, HANDLE, OPS>::configure_common(ctx, dev_port, cfg_st2110); | ||
|
|
||
| inet_pton(AF_INET, cfg_st2110.remote_ip_addr, this->ops.port.ip_addr[MTL_PORT_P]); | ||
| inet_pton(AF_INET, cfg_st2110.local_ip_addr, this->ops.port.mcast_sip_addr[MTL_PORT_P]); | ||
| this->ops.port.udp_port[MTL_PORT_P] = cfg_st2110.local_port; | ||
|
|
||
| log::info("ST2110Rx: configure") | ||
| ("ip_addr", std::to_string(this->ops.port.ip_addr[MTL_PORT_P][0]) + " " + | ||
| std::to_string(this->ops.port.ip_addr[MTL_PORT_P][1]) + " " + | ||
| std::to_string(this->ops.port.ip_addr[MTL_PORT_P][2]) + " " + | ||
| std::to_string(this->ops.port.ip_addr[MTL_PORT_P][3])) | ||
| ("mcast_sip_addr", std::to_string(this->ops.port.mcast_sip_addr[MTL_PORT_P][0]) + " " + | ||
| std::to_string(this->ops.port.mcast_sip_addr[MTL_PORT_P][1]) + " " + | ||
| std::to_string(this->ops.port.mcast_sip_addr[MTL_PORT_P][2]) + " " + | ||
| std::to_string(this->ops.port.mcast_sip_addr[MTL_PORT_P][3])) | ||
| ("udp_port", this->ops.port.udp_port[MTL_PORT_P]); | ||
| return 0; | ||
| } | ||
|
|
||
| Result on_establish(context::Context& ctx) override { | ||
ko80 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Result res = ST2110<FRAME, HANDLE, OPS>::on_establish(ctx); | ||
| if (res != Result::success) { | ||
| return res; | ||
| } | ||
|
|
||
| /* Start MTL session thread. */ | ||
| try { | ||
| frame_thread_handle = std::jthread(&ST2110Rx::frame_thread, this); | ||
| } catch (const std::system_error& e) { | ||
| log::error("Failed to create thread"); | ||
| this->set_state(ctx, State::closed); | ||
| return this->set_result(Result::error_out_of_memory); | ||
| } | ||
|
|
||
| this->set_state(ctx, State::active); | ||
| return this->set_result(Result::success); | ||
| } | ||
|
|
||
| Result on_shutdown(context::Context& ctx) override { | ||
| Result res = ST2110<FRAME, HANDLE, OPS>::on_shutdown(ctx); | ||
| if (res != Result::success) { | ||
| return res; | ||
| } | ||
|
|
||
| frame_thread_handle.join(); | ||
|
|
||
| this->set_state(ctx, State::closed); | ||
| return this->set_result(Result::success); | ||
| }; | ||
|
|
||
| private: | ||
| void frame_thread() { | ||
| while (!this->_ctx.cancelled()) { | ||
| // Get full buffer from MTL | ||
| FRAME *frame_ptr = this->get_frame(this->mtl_session); | ||
| if (frame_ptr) { | ||
| // Forward buffer to emulated receiver | ||
| this->transmit(this->_ctx, get_frame_data_ptr(frame_ptr), this->transfer_size); | ||
| // Return used buffer to MTL | ||
| this->put_frame(this->mtl_session, frame_ptr); | ||
| } else { | ||
| this->wait_frame_available(); | ||
| } | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| class ST2110_20Rx : public ST2110Rx<st_frame, st20p_rx_handle, st20p_rx_ops> { | ||
| public: | ||
| Result configure(context::Context& ctx, const std::string& dev_port, | ||
| const MeshConfig_ST2110& cfg_st2110, const MeshConfig_Video& cfg_video); | ||
|
|
||
| protected: | ||
| st_frame *get_frame(st20p_rx_handle h) override; | ||
| int put_frame(st20p_rx_handle h, st_frame *f) override; | ||
| st20p_rx_handle create_session(mtl_handle h, st20p_rx_ops *o) override; | ||
| int close_session(st20p_rx_handle h) override; | ||
| }; | ||
|
|
||
| class ST2110_22Rx : public ST2110Rx<st_frame, st22p_rx_handle, st22p_rx_ops> { | ||
| public: | ||
| Result configure(context::Context& ctx, const std::string& dev_port, | ||
| const MeshConfig_ST2110& cfg_st2110, const MeshConfig_Video& cfg_video); | ||
|
|
||
| protected: | ||
| st_frame *get_frame(st22p_rx_handle h) override; | ||
| int put_frame(st22p_rx_handle h, st_frame *f) override; | ||
| st22p_rx_handle create_session(mtl_handle h, st22p_rx_ops *o) override; | ||
| int close_session(st22p_rx_handle h) override; | ||
| }; | ||
|
|
||
| class ST2110_30Rx : public ST2110Rx<st30_frame, st30p_rx_handle, st30p_rx_ops> { | ||
| public: | ||
| Result configure(context::Context& ctx, const std::string& dev_port, | ||
| const MeshConfig_ST2110& cfg_st2110, const MeshConfig_Audio& cfg_audio); | ||
|
|
||
| protected: | ||
| st30_frame *get_frame(st30p_rx_handle h) override; | ||
| int put_frame(st30p_rx_handle h, st30_frame *f) override; | ||
| st30p_rx_handle create_session(mtl_handle h, st30p_rx_ops *o) override; | ||
| int close_session(st30p_rx_handle h) override; | ||
| }; | ||
|
|
||
| } // namespace mesh::connection | ||
|
|
||
| #endif // ST2110RX_H | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.