Skip to content

Commit 9e305dc

Browse files
committed
Add ST2110 Rx/Tx 20/22/30 connections with basic UT
Signed-off-by: Tomasz Szumski <tomasz.szumski@intel.com>
1 parent cfb75fb commit 9e305dc

File tree

11 files changed

+1575
-0
lines changed

11 files changed

+1575
-0
lines changed

media-proxy/include/mesh/st2110.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#ifndef ST2110_H
2+
#define ST2110_H
3+
4+
#include <thread>
5+
#include <bsd/string.h>
6+
#include <arpa/inet.h>
7+
#include <mtl/st_pipeline_api.h>
8+
#include <mtl/st30_pipeline_api.h>
9+
10+
#include "conn.h"
11+
#include "mesh_dp.h"
12+
#include "logger.h"
13+
14+
namespace mesh
15+
{
16+
17+
namespace connection
18+
{
19+
20+
#define ST_APP_PAYLOAD_TYPE_ST30 (111)
21+
#define ST_APP_PAYLOAD_TYPE_ST20 (112)
22+
#define ST_APP_PAYLOAD_TYPE_ST22 (114)
23+
24+
/**
25+
* ST2110
26+
*
27+
* Base abstract class of ST2110. ST2110Rx/ST2110Tx
28+
* inherit this class.
29+
*/
30+
class ST2110 : public Connection
31+
{
32+
public:
33+
static st_frame_fmt mesh_video_format_to_st_format(int fmt);
34+
static st30_fmt mesh_audio_format_to_st_format(int fmt);
35+
static st30_sampling mesh_audio_sampling_to_st_sampling(int sampling);
36+
static st30_ptime mesh_audio_ptime_to_st_ptime(int ptime);
37+
static void *get_frame_data_ptr(st_frame *src);
38+
static void *get_frame_data_ptr(st30_frame *src);
39+
40+
static void get_mtl_dev_params(mtl_init_params &st_param, const std::string &dev_port,
41+
mtl_log_level log_level,
42+
const char local_ip_addr[MESH_IP_ADDRESS_SIZE]);
43+
static mtl_handle get_mtl_handle(const std::string &dev_port, mtl_log_level log_level,
44+
const char local_ip_addr[MESH_IP_ADDRESS_SIZE]);
45+
46+
ST2110() : _st(0){};
47+
virtual ~ST2110(){};
48+
49+
protected:
50+
static int frame_available_cb(void *ptr);
51+
52+
mtl_handle _st;
53+
std::atomic<bool> _stop;
54+
std::condition_variable_any _cv;
55+
56+
private:
57+
};
58+
59+
} // namespace connection
60+
61+
} // namespace mesh
62+
63+
#endif // ST2110_H
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#ifndef ST2110RX_H
2+
#define ST2110RX_H
3+
4+
#include "st2110.h"
5+
6+
namespace mesh
7+
{
8+
9+
namespace connection
10+
{
11+
12+
/**
13+
* ST2110Rx
14+
*
15+
* Base abstract class of ST2110Rx. ST2110_20Rx/ST2110_22Rx/ST2110_30Rx
16+
* inherit this class.
17+
*/
18+
template <typename FRAME, typename HANDLE, typename OPS> class ST2110Rx : public ST2110
19+
{
20+
public:
21+
ST2110Rx()
22+
{
23+
_kind = Kind::receiver;
24+
25+
_handle = nullptr;
26+
_ops = {0};
27+
_transfer_size = 0;
28+
}
29+
~ST2110Rx() {}
30+
31+
protected:
32+
HANDLE _handle;
33+
OPS _ops;
34+
size_t _transfer_size;
35+
std::jthread _frame_thread_handle;
36+
context::Context _ctx;
37+
38+
std::function<FRAME *(HANDLE)> _get_frame_fn;
39+
std::function<int(HANDLE, FRAME *)> _put_frame_fn;
40+
std::function<HANDLE(mtl_handle, OPS *)> _create_session_fn;
41+
std::function<int(HANDLE)> _close_session_fn;
42+
43+
Result on_establish(context::Context &ctx) override
44+
{
45+
_ctx = context::WithCancel(ctx);
46+
_stop = false;
47+
48+
_handle = _create_session_fn(_st, &_ops);
49+
if (!_handle) {
50+
log::error("Failed to create session");
51+
set_state(ctx, State::closed);
52+
return set_result(Result::error_general_failure);
53+
}
54+
55+
/* Start MTL session thread. */
56+
try {
57+
_frame_thread_handle = std::jthread(&ST2110Rx::frame_thread, this);
58+
} catch (const std::system_error &e) {
59+
log::error("Failed to create thread");
60+
set_state(ctx, State::closed);
61+
return set_result(Result::error_out_of_memory);
62+
}
63+
64+
set_state(ctx, State::active);
65+
return set_result(Result::success);
66+
}
67+
68+
Result on_shutdown(context::Context &ctx) override
69+
{
70+
_ctx.cancel();
71+
72+
_frame_thread_handle.join();
73+
74+
if (_handle) {
75+
_close_session_fn(_handle);
76+
_handle = nullptr;
77+
}
78+
set_state(ctx, State::closed);
79+
return set_result(Result::success);
80+
};
81+
82+
virtual void on_delete(context::Context &ctx) override {}
83+
84+
private:
85+
void frame_thread()
86+
{
87+
while (!_ctx.cancelled()) {
88+
// Get full buffer from MTL
89+
FRAME *frame_ptr = _get_frame_fn(_handle);
90+
if (!frame_ptr) { /* no frame */
91+
std::mutex mx;
92+
std::unique_lock lk(mx);
93+
_cv.wait(lk, _ctx.stop_token(), [this] { return _stop.load(); });
94+
_stop = false;
95+
if (_ctx.cancelled()) {
96+
return;
97+
}
98+
continue;
99+
}
100+
// Forward buffer to emulated receiver
101+
transmit(_ctx, get_frame_data_ptr(frame_ptr), _transfer_size);
102+
// Return used buffer to MTL
103+
_put_frame_fn(_handle, frame_ptr);
104+
}
105+
}
106+
};
107+
108+
class ST2110_20Rx : public ST2110Rx<st_frame, st20p_rx_handle, st20p_rx_ops>
109+
{
110+
public:
111+
ST2110_20Rx();
112+
~ST2110_20Rx();
113+
114+
Result configure(context::Context &ctx, const std::string &dev_port,
115+
const MeshConfig_ST2110 &cfg_st2110, const MeshConfig_Video &cfg_video);
116+
117+
private:
118+
};
119+
120+
class ST2110_22Rx : public ST2110Rx<st_frame, st22p_rx_handle, st22p_rx_ops>
121+
{
122+
public:
123+
ST2110_22Rx();
124+
~ST2110_22Rx();
125+
126+
Result configure(context::Context &ctx, const std::string &dev_port,
127+
const MeshConfig_ST2110 &cfg_st2110, const MeshConfig_Video &cfg_video);
128+
129+
private:
130+
};
131+
132+
class ST2110_30Rx : public ST2110Rx<st30_frame, st30p_rx_handle, st30p_rx_ops>
133+
{
134+
public:
135+
ST2110_30Rx();
136+
~ST2110_30Rx();
137+
138+
Result configure(context::Context &ctx, const std::string &dev_port,
139+
const MeshConfig_ST2110 &cfg_st2110, const MeshConfig_Audio &cfg_audio);
140+
141+
private:
142+
};
143+
144+
} // namespace connection
145+
146+
} // namespace mesh
147+
148+
#endif // ST2110RX_H
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#ifndef ST2110TX_H
2+
#define ST2110TX_H
3+
4+
#include "st2110.h"
5+
#include <algorithm>
6+
7+
namespace mesh
8+
{
9+
10+
namespace connection
11+
{
12+
13+
/**
14+
* ST2110
15+
*
16+
* Base abstract class of ST2110. ST2110_20Tx/ST2110_22Tx/ST2110_30Tx
17+
* inherit this class.
18+
*/
19+
template <typename FRAME, typename HANDLE, typename OPS> class ST2110Tx : public ST2110
20+
{
21+
public:
22+
ST2110Tx()
23+
{
24+
_kind = Kind::transmitter;
25+
26+
_handle = nullptr;
27+
_ops = {0};
28+
_transfer_size = 0;
29+
};
30+
~ST2110Tx(){};
31+
32+
protected:
33+
HANDLE _handle;
34+
OPS _ops;
35+
uint32_t _transfer_size;
36+
context::Context _ctx;
37+
38+
std::function<FRAME *(HANDLE)> _get_frame_fn;
39+
std::function<int(HANDLE, FRAME *)> _put_frame_fn;
40+
std::function<HANDLE(mtl_handle, OPS *)> _create_session_fn;
41+
std::function<int(HANDLE)> _close_session_fn;
42+
43+
Result on_establish(context::Context &ctx) override
44+
{
45+
_ctx = context::WithCancel(ctx);
46+
_stop = false;
47+
48+
_handle = _create_session_fn(_st, &_ops);
49+
if (!_handle) {
50+
log::error("Failed to create session");
51+
set_state(ctx, State::closed);
52+
return set_result(Result::error_general_failure);
53+
}
54+
55+
set_state(ctx, State::active);
56+
return set_result(Result::success);
57+
};
58+
59+
Result on_shutdown(context::Context &ctx) override
60+
{
61+
_ctx.cancel();
62+
63+
if (_handle) {
64+
_close_session_fn(_handle);
65+
_handle = nullptr;
66+
}
67+
set_state(ctx, State::closed);
68+
return set_result(Result::success);
69+
};
70+
71+
Result on_receive(context::Context &ctx, void *ptr, uint32_t sz, uint32_t &sent) override
72+
{
73+
sent = std::min(_transfer_size, sz);
74+
// TODO: add error/warning if sent is different than _transfer_size
75+
76+
FRAME *frame = NULL;
77+
do {
78+
// Get empty buffer from MTL
79+
frame = _get_frame_fn(_handle);
80+
if (!frame) {
81+
std::mutex mx;
82+
std::unique_lock lk(mx);
83+
_cv.wait(lk, _ctx.stop_token(), [this] { return _stop.load(); });
84+
_stop = false;
85+
if (_ctx.cancelled()) {
86+
return set_result(Result::error_shutdown);
87+
}
88+
}
89+
} while (!frame);
90+
91+
if (frame) {
92+
// Copy data from emulated transmitter to MTL empty buffer
93+
mtl_memcpy(get_frame_data_ptr(frame), ptr, sent);
94+
// Return full buffer to MTL
95+
_put_frame_fn(_handle, frame);
96+
} else {
97+
sent = 0;
98+
// TODO: add Result that indicate shutdown
99+
}
100+
return set_result(Result::success);
101+
};
102+
103+
private:
104+
};
105+
106+
class ST2110_20Tx : public ST2110Tx<st_frame, st20p_tx_handle, st20p_tx_ops>
107+
{
108+
public:
109+
ST2110_20Tx();
110+
~ST2110_20Tx();
111+
112+
Result configure(context::Context &ctx, const std::string &dev_port,
113+
const MeshConfig_ST2110 &cfg_st2110, const MeshConfig_Video &cfg_video);
114+
115+
private:
116+
};
117+
118+
class ST2110_22Tx : public ST2110Tx<st_frame, st22p_tx_handle, st22p_tx_ops>
119+
{
120+
public:
121+
ST2110_22Tx();
122+
~ST2110_22Tx();
123+
124+
Result configure(context::Context &ctx, const std::string &dev_port,
125+
const MeshConfig_ST2110 &cfg_st2110, const MeshConfig_Video &cfg_video);
126+
127+
private:
128+
};
129+
130+
class ST2110_30Tx : public ST2110Tx<st30_frame, st30p_tx_handle, st30p_tx_ops>
131+
{
132+
public:
133+
ST2110_30Tx();
134+
~ST2110_30Tx();
135+
136+
Result configure(context::Context &ctx, const std::string &dev_port,
137+
const MeshConfig_ST2110 &cfg_st2110, const MeshConfig_Audio &cfg_audio);
138+
139+
private:
140+
};
141+
142+
} // namespace connection
143+
144+
} // namespace mesh
145+
146+
#endif // ST2110TX_H

0 commit comments

Comments
 (0)