Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions control-plane-agent/internal/model/sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ type SDKConfigRDMA struct {
MaxLatencyNs uint32 `json:"maxLatencyNs"`
}

type SDKConnectionOptionsRDMA struct {
Provider string `json:"provider,omitempty"`
NumEndpoints uint8 `json:"numEndpoints,omitempty"`
}

type SDKConfigVideo struct {
Width uint32 `json:"width"`
Height uint32 `json:"height"`
Expand Down Expand Up @@ -74,6 +79,10 @@ type SDKConnectionConfig struct {
RDMA *SDKConfigRDMA `json:"rdma,omitempty"`
} `json:"conn"`

Options struct {
RDMA SDKConnectionOptionsRDMA `json:"rdma"`
} `json:"options"`

Payload struct {
Video *SDKConfigVideo `json:"video,omitempty"`
Audio *SDKConfigAudio `json:"audio,omitempty"`
Expand Down Expand Up @@ -178,6 +187,11 @@ func (s *SDKConnectionConfig) AssignFromPb(cfg *sdk.ConnectionConfig) error {
return errors.New("unknown sdk conn cfg type")
}

if cfg.Options != nil && cfg.Options.Rdma != nil {
s.Options.RDMA.Provider = cfg.Options.Rdma.Provider
s.Options.RDMA.NumEndpoints = uint8(cfg.Options.Rdma.NumEndpoints)
}

switch payload := cfg.Payload.(type) {
case *sdk.ConnectionConfig_Video:
s.Payload.Video = &SDKConfigVideo{
Expand Down Expand Up @@ -251,6 +265,13 @@ func (s *SDKConnectionConfig) AssignToPb(cfg *sdk.ConnectionConfig) {
}
}

cfg.Options = &sdk.ConnectionOptions{
Rdma: &sdk.ConnectionOptionsRDMA{
Provider: s.Options.RDMA.Provider,
NumEndpoints: uint32(s.Options.RDMA.NumEndpoints),
},
}

switch {
case s.Payload.Video != nil:
cfg.Payload = &sdk.ConnectionConfig_Video{
Expand Down Expand Up @@ -311,6 +332,13 @@ func (s *SDKConnectionConfig) CheckPayloadCompatibility(c *SDKConnectionConfig)
}
}

if s.Options.RDMA.Provider != c.Options.RDMA.Provider {
return fmt.Errorf("incompatible rdma provider: %v vs. %v", s.Options.RDMA.Provider, c.Options.RDMA.Provider)
}
if s.Options.RDMA.NumEndpoints != c.Options.RDMA.NumEndpoints {
return fmt.Errorf("incompatible rdma number of endpoints: %v vs. %v", s.Options.RDMA.NumEndpoints, c.Options.RDMA.NumEndpoints)
}

switch {
case s.Payload.Video != nil:
if c.Payload.Video == nil {
Expand Down
7 changes: 7 additions & 0 deletions docs/FFmpegPlugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ Refer to the [SDK API Definition](SDK_API_Definition.md) for the options of conf
|----------|------------------------------------------------------------------------|---------------------|
| `-urn` | Multipoint group Uniform Resource Name, or URN. Default "192.168.97.1" | `-urn 192.168.97.1` |

### Connection options – RDMA ingress/egress bridge related parameters

| Argument | Description | Example |
|-----------------------|-------------------------------------------|-------------------------|
| `-rdma_provider` | RDMA provider type. Default "tcp" | `-rdma_provider verbs` |
| `-rdma_num_endpoints` | Number of RDMA endpoints, 1..8. Default 1 | `-rdma_num_endpoints 4` |

### Video payload parameters

| Argument | Description | Example |
Expand Down
22 changes: 22 additions & 0 deletions docs/SDK_API_Definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ Creates a transmitter connection with the provided JSON configuration.
"transportPixelFormat": "yuv422p10rfc4175"
},
},
"options": {
"rdma": {
"provider": "tcp",
"numEndpoints": 2,
}
},
"payload": {
"video": {
"width": 1920,
Expand Down Expand Up @@ -120,6 +126,16 @@ to setup various connection and payload options. The examples correspond to the
}
```

### Configure connection options
```json
"options": {
"rdma": {
"provider": "tcp",
"numEndpoints": 2,
}
},
```

### Configure payload – Video
```json
"payload": {
Expand Down Expand Up @@ -181,6 +197,12 @@ The above `maxPayloadSize` is set explicitly to define the buffer size for the B
* `"transportPixelFormat"` – Required only for the `"st2110-20"` transport type, default "yuv422p10rfc4175".
1. `"multipointGroup"` – Multipoint Group connection.
* `"urn"` – Uniform Resource Name (URN) of the multipoint group, e.g. "ipv4:224.0.0.1:9003".
* `"options"` – Connection options
* `"rdma"` – RDMA bridge related parameters
* `"provider"` – Default "tcp".
* `"tcp"`
* `"verbs"`
* `"numEndpoints"` – Integer number of RDMA endpoints between 1-8, default 1.
* `"payload"` – Payload type, options 1-3 are the following:
1. `"video"` – Video payload.
* `"width"` – Integer frame width, e.g. 1920.
Expand Down
9 changes: 8 additions & 1 deletion ffmpeg-plugin/mcm_audio_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ typedef struct McmAudioDemuxerContext {
int sample_rate;
char* ptime;

char *rdma_provider;
int rdma_num_endpoints;

MeshClient *mc;
MeshConnection *conn;
bool first_frame;
Expand All @@ -58,14 +61,16 @@ static int mcm_audio_read_header(AVFormatContext* avctx, enum AVCodecID codec_id
n = snprintf(json_config, sizeof(json_config),
mcm_json_config_multipoint_group_audio_format,
s->buf_queue_cap, s->conn_delay,
s->urn, s->channels, s->sample_rate,
s->urn, s->rdma_provider, s->rdma_num_endpoints,
s->channels, s->sample_rate,
avcodec_get_name(codec_id), s->ptime);

} else if (!strcmp(s->conn_type, "st2110")) {
n = snprintf(json_config, sizeof(json_config),
mcm_json_config_st2110_audio_format,
s->buf_queue_cap, s->conn_delay,
s->ip_addr, s->port, s->mcast_sip_addr, s->payload_type,
s->rdma_provider, s->rdma_num_endpoints,
s->channels, s->sample_rate,
avcodec_get_name(codec_id), s->ptime);
} else {
Expand Down Expand Up @@ -219,6 +224,8 @@ static const AVOption mcm_audio_rx_options[] = {
{ "channels", "number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, DEC },
{ "sample_rate", "audio sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, DEC },
{ "ptime", "audio packet time", OFFSET(ptime), AV_OPT_TYPE_STRING, {.str = "1ms"}, .flags = DEC },
{ "rdma_provider", "optional: set RDMA provider type ('tcp' or 'verbs')", OFFSET(rdma_provider), AV_OPT_TYPE_STRING, {.str = "tcp"}, .flags = DEC },
{ "rdma_num_endpoints", "optional: set number of RDMA endpoints, range 1..8", OFFSET(rdma_num_endpoints), AV_OPT_TYPE_INT, {.i64 = 1}, 1, 8, DEC },
{ NULL },
};

Expand Down
9 changes: 8 additions & 1 deletion ffmpeg-plugin/mcm_audio_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ typedef struct McmAudioMuxerContext {
int sample_rate;
char* ptime;

char *rdma_provider;
int rdma_num_endpoints;

MeshClient *mc;
MeshConnection *conn;
MeshBuffer *unsent_buf;
Expand Down Expand Up @@ -69,14 +72,16 @@ static int mcm_audio_write_header(AVFormatContext* avctx)
n = snprintf(json_config, sizeof(json_config),
mcm_json_config_multipoint_group_audio_format,
s->buf_queue_cap, s->conn_delay,
s->urn, s->channels, s->sample_rate,
s->urn, s->rdma_provider, s->rdma_num_endpoints,
s->channels, s->sample_rate,
avcodec_get_name(codecpar->codec_id), s->ptime);

} else if (!strcmp(s->conn_type, "st2110")) {
n = snprintf(json_config, sizeof(json_config),
mcm_json_config_st2110_audio_format,
s->buf_queue_cap, s->conn_delay,
s->ip_addr, s->port, "", s->payload_type,
s->rdma_provider, s->rdma_num_endpoints,
s->channels, s->sample_rate,
avcodec_get_name(codecpar->codec_id), s->ptime);
} else {
Expand Down Expand Up @@ -213,6 +218,8 @@ static const AVOption mcm_audio_tx_options[] = {
{ "channels", "number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, ENC },
{ "sample_rate", "audio sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, ENC },
{ "ptime", "audio packet time", OFFSET(ptime), AV_OPT_TYPE_STRING, {.str = "1ms"}, .flags = ENC },
{ "rdma_provider", "optional: set RDMA provider type ('tcp' or 'verbs')", OFFSET(rdma_provider), AV_OPT_TYPE_STRING, {.str = "tcp"}, .flags = ENC },
{ "rdma_num_endpoints", "optional: set number of RDMA endpoints, range 1..8", OFFSET(rdma_num_endpoints), AV_OPT_TYPE_INT, {.i64 = 1}, 1, 8, ENC },
{ NULL },
};

Expand Down
24 changes: 24 additions & 0 deletions ffmpeg-plugin/mcm_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ const char mcm_json_config_multipoint_group_video_format[] =
"`urn`: `%s`"
"}"
"},"
"`options`: {"
"`rdma`: {"
"`provider`: `%s`,"
"`num_endpoints`: %d"
"}"
"},"
"`payload`: {"
"`video`: {"
"`width`: %d,"
Expand All @@ -163,6 +169,12 @@ const char mcm_json_config_st2110_video_format[] =
"`transportPixelFormat`: `%s`"
"}"
"},"
"`options`: {"
"`rdma`: {"
"`provider`: `%s`,"
"`num_endpoints`: %d"
"}"
"},"
"`payload`: {"
"`video`: {"
"`width`: %d,"
Expand All @@ -182,6 +194,12 @@ const char mcm_json_config_multipoint_group_audio_format[] =
"`urn`: `%s`"
"}"
"},"
"`options`: {"
"`rdma`: {"
"`provider`: `%s`,"
"`num_endpoints`: %d"
"}"
"},"
"`payload`: {"
"`audio`: {"
"`channels`: %d,"
Expand All @@ -205,6 +223,12 @@ const char mcm_json_config_st2110_audio_format[] =
"`payloadType`: %d"
"}"
"},"
"`options`: {"
"`rdma`: {"
"`provider`: `%s`,"
"`num_endpoints`: %d"
"}"
"},"
"`payload`: {"
"`audio`: {"
"`channels`: %d,"
Expand Down
9 changes: 8 additions & 1 deletion ffmpeg-plugin/mcm_video_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ typedef struct McmVideoDemuxerContext {
enum AVPixelFormat pixel_format;
AVRational frame_rate;

char *rdma_provider;
int rdma_num_endpoints;

MeshClient *mc;
MeshConnection *conn;
bool first_frame;
Expand All @@ -61,7 +64,8 @@ static int mcm_video_read_header(AVFormatContext* avctx)
n = snprintf(json_config, sizeof(json_config),
mcm_json_config_multipoint_group_video_format,
s->buf_queue_cap, s->conn_delay,
s->urn, s->width, s->height, av_q2d(s->frame_rate),
s->urn, s->rdma_provider, s->rdma_num_endpoints,
s->width, s->height, av_q2d(s->frame_rate),
av_get_pix_fmt_name(s->pixel_format));
} else if (!strcmp(s->conn_type, "st2110")) {
n = snprintf(json_config, sizeof(json_config),
Expand All @@ -70,6 +74,7 @@ static int mcm_video_read_header(AVFormatContext* avctx)
s->ip_addr, s->port, s->mcast_sip_addr,
s->transport, s->payload_type,
s->transport_pixel_format,
s->rdma_provider, s->rdma_num_endpoints,
s->width, s->height, av_q2d(s->frame_rate),
av_get_pix_fmt_name(s->pixel_format));
} else {
Expand Down Expand Up @@ -213,6 +218,8 @@ static const AVOption mcm_video_rx_options[] = {
{ "video_size", "set video frame size given a string such as 640x480 or hd720", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = "1920x1080"}, 0, 0, DEC },
{ "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_YUV422P10LE}, AV_PIX_FMT_NONE, INT_MAX, DEC },
{ "frame_rate", "set video frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC },
{ "rdma_provider", "optional: set RDMA provider type ('tcp' or 'verbs')", OFFSET(rdma_provider), AV_OPT_TYPE_STRING, {.str = "tcp"}, .flags = DEC },
{ "rdma_num_endpoints", "optional: set number of RDMA endpoints, range 1..8", OFFSET(rdma_num_endpoints), AV_OPT_TYPE_INT, {.i64 = 1}, 1, 8, DEC },
{ NULL },
};

Expand Down
9 changes: 8 additions & 1 deletion ffmpeg-plugin/mcm_video_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ typedef struct McmVideoMuxerContext {
enum AVPixelFormat pixel_format;
AVRational frame_rate;

char *rdma_provider;
int rdma_num_endpoints;

MeshClient *mc;
MeshConnection *conn;
} McmVideoMuxerContext;
Expand All @@ -54,7 +57,8 @@ static int mcm_video_write_header(AVFormatContext* avctx)
n = snprintf(json_config, sizeof(json_config),
mcm_json_config_multipoint_group_video_format,
s->buf_queue_cap, s->conn_delay,
s->urn, s->width, s->height, av_q2d(s->frame_rate),
s->urn, s->rdma_provider, s->rdma_num_endpoints,
s->width, s->height, av_q2d(s->frame_rate),
av_get_pix_fmt_name(s->pixel_format));
} else if (!strcmp(s->conn_type, "st2110")) {
n = snprintf(json_config, sizeof(json_config),
Expand All @@ -63,6 +67,7 @@ static int mcm_video_write_header(AVFormatContext* avctx)
s->ip_addr, s->port, "",
s->transport, s->payload_type,
s->transport_pixel_format,
s->rdma_provider, s->rdma_num_endpoints,
s->width, s->height, av_q2d(s->frame_rate),
av_get_pix_fmt_name(s->pixel_format));
} else {
Expand Down Expand Up @@ -162,6 +167,8 @@ static const AVOption mcm_video_tx_options[] = {
{ "video_size", "set video frame size given a string such as 640x480 or hd720", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = "1920x1080"}, 0, 0, ENC },
{ "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_YUV422P10LE}, AV_PIX_FMT_NONE, INT_MAX, ENC },
{ "frame_rate", "set video frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, ENC },
{ "rdma_provider", "optional: set RDMA provider type ('tcp' or 'verbs')", OFFSET(rdma_provider), AV_OPT_TYPE_STRING, {.str = "tcp"}, .flags = ENC },
{ "rdma_num_endpoints", "optional: set number of RDMA endpoints, range 1..8", OFFSET(rdma_num_endpoints), AV_OPT_TYPE_INT, {.i64 = 1}, 1, 8, ENC },
{ NULL },
};

Expand Down
68 changes: 68 additions & 0 deletions media-proxy/include/mesh/SDK_BRIDGE_PARAMS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# SDK Bridge-related Parameter Propagation — Developer's Guide

SDK allows passing some parameters to be applied when Egress or Ingress Bridge is created in Media Proxy.

When adding or modifying any of the RDMA or SMPTE ST 2110 SDK parameters, many parts of code should be adjusted accordingly. The affected software components are SDK, Media Proxy, and Agent.

The following diagram shows the propagation flow of SDK parameters from the JSON configuration to the bridge's `configure()` method. RDMA classes are taken as an example.

> Note: Each function AND each data structure mentioned in the diagram should be revised and adjusted appropriately.

```mermaid
flowchart
a1(["mesh_create_tx_connection()
mesh_create_rx_connection()"])

subgraph sdk [SDK]
direction TB
a2("parse_from_json()")
a3("CreateConnectionJson()")
end

subgraph proxy [Media Proxy]
direction TB
a4("connection::Config.assign_from_pb()")
a5("connection::Config.assign_to_pb()")
a8("StartCommandQueue()")
a9("create_bridge()")
a10("RdmaTx::configure()
RdmaRx::configure()")
end

subgraph agent [Agent]
direction TB
a6("SDKConnectionConfig.AssignFromPb()")
a6-1("CheckPayloadCompatibility()")
a7("SDKConnectionConfig.AssignToPb()")
end

a1 -- JSON config --> a2 -- mesh::ConnectionConfig --> a3
a3 -- Protobuf sdk::ConnectionConfig --> a4 -- connection::Config --> a5
a5 -- Protobuf sdk.ConnectionConfig --> a6 -- SDKConnectionConfig --> a6-1
a6-1 -- SDKConnectionConfig --> a7
a7 -- Protobuf sdk.ConnectionConfig --> a8 -- BridgeConfig --> a9
a9 -- Rdma class config struct --> a10
```

## Checklist: What to adjust to enable passing SDK parameters to the recipient class configuration?

1. Adjust the SDK code
* Structure `mesh::ConnectionConfig`.
* Method `parse_from_json()`
* Proto file `conn-config.proto` – Add/Modify/Remove fields.
* Method `CreateConnectionJson()`.
1. Adjust the Media Proxy code
* Structure `connection::Config`.
* Method `connection::Config.assign_from_pb()`.
* Method `connection::Config.assign_to_pb()`.
1. Adjust the Agent code
* Structure `SDKConnectionConfig`.
* Function `SDKConnectionConfig.AssignFromPb()`.
* Function `CheckPayloadCompatibility()`.
* Function `SDKConnectionConfig.AssignToPb()`.
1. Adjust the Media Proxy code
* Structure `BridgeConfig`.
* Method `StartCommandQueue()`.
* Recipient class config struct, e.g. RDMA.
* Method `create_bridge()`.
1. Update documentation.
Loading
Loading