Skip to content
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

rx/timing_parser: add -7 support #697

Merged
merged 3 commits into from
Jan 10, 2024
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
9 changes: 8 additions & 1 deletion app/sample/rx_st20_pipeline_sample.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,19 @@ int main(int argc, char** argv) {
memset(&ops_rx, 0, sizeof(ops_rx));
ops_rx.name = "st20p_test";
ops_rx.priv = app[i]; // app handle register to lib
ops_rx.port.num_port = 1;
ops_rx.port.num_port = ctx.param.num_ports;
memcpy(ops_rx.port.sip_addr[MTL_SESSION_PORT_P], ctx.rx_sip_addr[MTL_PORT_P],
MTL_IP_ADDR_LEN);
snprintf(ops_rx.port.port[MTL_SESSION_PORT_P], MTL_PORT_MAX_LEN, "%s",
ctx.param.port[MTL_PORT_P]);
ops_rx.port.udp_port[MTL_SESSION_PORT_P] = ctx.udp_port + i * 2;
if (ops_rx.port.num_port > 1) {
memcpy(ops_rx.port.sip_addr[MTL_SESSION_PORT_R], ctx.rx_sip_addr[MTL_PORT_R],
MTL_IP_ADDR_LEN);
snprintf(ops_rx.port.port[MTL_SESSION_PORT_R], MTL_PORT_MAX_LEN, "%s",
ctx.param.port[MTL_PORT_R]);
ops_rx.port.udp_port[MTL_SESSION_PORT_R] = ctx.udp_port + i * 2;
}
ops_rx.port.payload_type = ctx.payload_type;
ops_rx.width = ctx.width;
ops_rx.height = ctx.height;
Expand Down
43 changes: 33 additions & 10 deletions app/sample/rx_st20p_timing_parser_sample.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ struct rx_timing_parser_sample_ctx {
bool pass_get; /* pass critical is only available */

/* stat report */
struct rx_tp_stat stat;
struct rx_tp_stat stat[MTL_SESSION_PORT_MAX];
uint8_t num_port;
};

static void rx_st20p_tp_stat_init(struct rx_tp_stat* stat) {
Expand All @@ -62,9 +63,9 @@ static void rx_st20p_tp_stat_init(struct rx_tp_stat* stat) {
}

static void rx_st20p_tp_stat_print(struct rx_timing_parser_sample_ctx* s,
struct rx_tp_stat* stat) {
enum mtl_session_port port, struct rx_tp_stat* stat) {
int idx = s->idx;
info("%s(%d), COMPLIANT NARROW %d WIDE %d FAILED %d!\n", __func__, idx,
info("%s(%d,%d), COMPLIANT NARROW %d WIDE %d FAILED %d!\n", __func__, idx, port,
stat->compliant_result[ST_RX_TP_COMPLIANT_NARROW],
stat->compliant_result[ST_RX_TP_COMPLIANT_WIDE],
stat->compliant_result[ST_RX_TP_COMPLIANT_FAILED]);
Expand All @@ -81,14 +82,14 @@ static void rx_st20p_tp_stat_print(struct rx_timing_parser_sample_ctx* s,
}

static int rx_st20p_tp_consume(struct rx_timing_parser_sample_ctx* s,
struct st20_rx_tp_meta* tp) {
enum mtl_session_port port, struct st20_rx_tp_meta* tp) {
if (tp->compliant != ST_RX_TP_COMPLIANT_NARROW) {
dbg("%s(%d), compliant failed %d cause: %s, frame idx %d\n", __func__, s->idx,
tp->compliant, tp->failed_cause, s->fb_recv);
}

/* update stat */
struct rx_tp_stat* stat = &s->stat;
struct rx_tp_stat* stat = &s->stat[port];
stat->vrx_min = ST_MIN(tp->vrx_min, stat->vrx_min);
stat->vrx_max = ST_MAX(tp->vrx_max, stat->vrx_max);
stat->cinst_min = ST_MIN(tp->cinst_min, stat->cinst_min);
Expand Down Expand Up @@ -132,7 +133,9 @@ static void* rx_st20p_tp_thread(void* arg) {
s->pass.vrx_max_narrow, s->pass.vrx_max_wide);
}
}
rx_st20p_tp_consume(s, frame->tp);
rx_st20p_tp_consume(s, MTL_SESSION_PORT_P, frame->tp[MTL_SESSION_PORT_P]);
if (s->num_port > 1)
rx_st20p_tp_consume(s, MTL_SESSION_PORT_R, frame->tp[MTL_SESSION_PORT_R]);

s->fb_recv++;
st20p_rx_put_frame(handle, frame);
Expand All @@ -151,6 +154,9 @@ int main(int argc, char** argv) {
ret = rx_sample_parse_args(&ctx, argc, argv);
if (ret < 0) return ret;

/* enable hw offload timestamp */
ctx.param.flags |= MTL_FLAG_ENABLE_HW_TIMESTAMP;

ctx.st = mtl_init(&ctx.param);
if (!ctx.st) {
err("%s: mtl_init fail\n", __func__);
Expand All @@ -172,18 +178,28 @@ int main(int argc, char** argv) {
app[i]->idx = i;
app[i]->stop = false;
app[i]->fb_cnt = ctx.framebuff_cnt;
rx_st20p_tp_stat_init(&app[i]->stat);
app[i]->num_port = ctx.param.num_ports;

rx_st20p_tp_stat_init(&app[i]->stat[MTL_SESSION_PORT_P]);
rx_st20p_tp_stat_init(&app[i]->stat[MTL_SESSION_PORT_R]);

struct st20p_rx_ops ops_rx;
memset(&ops_rx, 0, sizeof(ops_rx));
ops_rx.name = "st20p_test";
ops_rx.priv = app[i]; // app handle register to lib
ops_rx.port.num_port = 1;
ops_rx.port.num_port = app[i]->num_port;
memcpy(ops_rx.port.sip_addr[MTL_SESSION_PORT_P], ctx.rx_sip_addr[MTL_PORT_P],
MTL_IP_ADDR_LEN);
snprintf(ops_rx.port.port[MTL_SESSION_PORT_P], MTL_PORT_MAX_LEN, "%s",
ctx.param.port[MTL_PORT_P]);
ops_rx.port.udp_port[MTL_SESSION_PORT_P] = ctx.udp_port + i * 2;
if (ops_rx.port.num_port > 1) {
memcpy(ops_rx.port.sip_addr[MTL_SESSION_PORT_R], ctx.rx_sip_addr[MTL_PORT_R],
MTL_IP_ADDR_LEN);
snprintf(ops_rx.port.port[MTL_SESSION_PORT_R], MTL_PORT_MAX_LEN, "%s",
ctx.param.port[MTL_PORT_R]);
ops_rx.port.udp_port[MTL_SESSION_PORT_R] = ctx.udp_port + i * 2;
}
ops_rx.port.payload_type = ctx.payload_type;
ops_rx.width = ctx.width;
ops_rx.height = ctx.height;
Expand Down Expand Up @@ -221,15 +237,22 @@ int main(int argc, char** argv) {
cnt++;
if ((cnt % 10) == 0) {
for (int i = 0; i < session_num; i++) {
rx_st20p_tp_stat_print(app[i], &app[i]->stat);
rx_st20p_tp_stat_init(&app[i]->stat);
rx_st20p_tp_stat_print(app[i], MTL_SESSION_PORT_P,
&app[i]->stat[MTL_SESSION_PORT_P]);
rx_st20p_tp_stat_init(&app[i]->stat[MTL_SESSION_PORT_P]);
if (app[i]->num_port > 1) {
rx_st20p_tp_stat_print(app[i], MTL_SESSION_PORT_R,
&app[i]->stat[MTL_SESSION_PORT_R]);
rx_st20p_tp_stat_init(&app[i]->stat[MTL_SESSION_PORT_R]);
}
}
}
}

// stop app thread
for (int i = 0; i < session_num; i++) {
app[i]->stop = true;
if (app[i]->handle) st20p_rx_wake_block(app[i]->handle);
pthread_join(app[i]->frame_thread, NULL);
info("%s(%d), received frames %d\n", __func__, i, app[i]->fb_recv);
}
Expand Down
9 changes: 8 additions & 1 deletion app/sample/tx_st22_pipeline_sample.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,19 @@ int main(int argc, char** argv) {
memset(&ops_tx, 0, sizeof(ops_tx));
ops_tx.name = "st22p_sample";
ops_tx.priv = app[i]; // app handle register to lib
ops_tx.port.num_port = 1;
ops_tx.port.num_port = ctx.param.num_ports;
memcpy(ops_tx.port.dip_addr[MTL_SESSION_PORT_P], ctx.tx_dip_addr[MTL_PORT_P],
MTL_IP_ADDR_LEN);
snprintf(ops_tx.port.port[MTL_SESSION_PORT_P], MTL_PORT_MAX_LEN, "%s",
ctx.param.port[MTL_PORT_P]);
ops_tx.port.udp_port[MTL_SESSION_PORT_P] = ctx.udp_port + i * 2;
if (ops_tx.port.num_port > 1) {
memcpy(ops_tx.port.dip_addr[MTL_SESSION_PORT_R], ctx.tx_dip_addr[MTL_PORT_R],
MTL_IP_ADDR_LEN);
snprintf(ops_tx.port.port[MTL_SESSION_PORT_R], MTL_PORT_MAX_LEN, "%s",
ctx.param.port[MTL_PORT_R]);
ops_tx.port.udp_port[MTL_SESSION_PORT_R] = ctx.udp_port + i * 2;
}
ops_tx.port.payload_type = ctx.payload_type;
ops_tx.width = ctx.width;
ops_tx.height = ctx.height;
Expand Down
4 changes: 3 additions & 1 deletion doc/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,9 @@ In addition to the built-in RxTxApp, IMTL also provides numerous sample codes th

### 6.16 RX Timing Parser

To verify the compliance of incoming ST2110-20 RX streams with the ST2110 standard, IMTL provides several utilities for analysis. To support this functionality, if the Network Interface Card (NIC) supports the hardware time synchronization feature, IMTL will read the RX timestamp directly from the NIC's hardware to obtain accurate timing.
To verify the compliance of incoming ST2110-20 RX streams with the ST2110 standard, IMTL provides several utilities for analysis.
To support this functionality, if the Network Interface Card (NIC) supports the hardware time synchronization feature, IMTL will read the RX timestamp directly from the NIC's hardware to obtain accurate timing. And please set `MTL_FLAG_ENABLE_HW_TIMESTAMP` flag to enable HW offload timestamp for all RX packets.

The fallback method is to read the time when IMTL processes the packet. However, it's important to note that this fallback method cannot guarantee timing accuracy, potentially rendering the parsed results unreliable.

The simplest method is to enable the built-in status report. An application can activate the feature by setting the flag `ST20_RX_FLAG_TIMING_PARSER_STAT` or `ST20P_RX_FLAG_TIMING_PARSER_STAT`. Subsequently, IMTL will engage the Timing Parser module and include the results in the status log.
Expand Down
2 changes: 1 addition & 1 deletion include/st20_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ struct st20_rx_frame_meta {
* 'pkts_total,' which serves as an indicator of signal quality. */
uint32_t pkts_recv[MTL_SESSION_PORT_MAX];
/** st20 rx timing parser meta, only active if ST20_RX_FLAG_TIMING_PARSER_META */
struct st20_rx_tp_meta* tp;
struct st20_rx_tp_meta* tp[MTL_SESSION_PORT_MAX];
};

/**
Expand Down
2 changes: 1 addition & 1 deletion include/st_pipeline_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ struct st_frame {
void* opaque;
/** timing parser meta for st20p_rx_get_frame, only active if
* ST20P_RX_FLAG_TIMING_PARSER_META */
struct st20_rx_tp_meta* tp;
struct st20_rx_tp_meta* tp[MTL_SESSION_PORT_MAX];
};

/** Device type of st plugin */
Expand Down
17 changes: 10 additions & 7 deletions lib/src/st2110/pipeline/st20_pipeline_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,17 +204,20 @@ static int rx_st20p_frame_ready(void* priv, void* frame,
framebuff->src.status = framebuff->dst.status = meta->status;

framebuff->src.pkts_total = framebuff->dst.pkts_total = meta->pkts_total;
for (enum mtl_session_port s_port = MTL_SESSION_PORT_P; s_port < MTL_SESSION_PORT_MAX;
s_port++) {
for (enum mtl_session_port s_port = 0; s_port < MTL_SESSION_PORT_MAX; s_port++) {
framebuff->src.pkts_recv[s_port] = framebuff->dst.pkts_recv[s_port] =
meta->pkts_recv[s_port];
}

if (meta->tp) {
mtl_memcpy(&framebuff->tp, meta->tp, sizeof(framebuff->tp));
framebuff->src.tp = framebuff->dst.tp = &framebuff->tp;
} else {
framebuff->src.tp = framebuff->dst.tp = NULL;
/* copy timing parser meta */
for (enum mtl_session_port s_port = 0; s_port < MTL_SESSION_PORT_MAX; s_port++) {
framebuff->src.tp[s_port] = framebuff->dst.tp[s_port] = NULL;
}

for (enum mtl_session_port s_port = 0; s_port < ctx->ops.port.num_port; s_port++) {
if (!meta->tp[s_port]) continue;
mtl_memcpy(&framebuff->tp[s_port], meta->tp[s_port], sizeof(framebuff->tp[s_port]));
framebuff->src.tp[s_port] = framebuff->dst.tp[s_port] = &framebuff->tp[s_port];
}

/* check user meta */
Expand Down
2 changes: 1 addition & 1 deletion lib/src/st2110/pipeline/st20_pipeline_rx.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct st20p_rx_frame {
void* user_meta; /* the user meta data */
size_t user_meta_buffer_size;
size_t user_meta_data_size;
struct st20_rx_tp_meta tp;
struct st20_rx_tp_meta tp[MTL_SESSION_PORT_MAX];
};

struct st20p_rx_ctx {
Expand Down
6 changes: 3 additions & 3 deletions lib/src/st2110/st_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -544,11 +544,11 @@ struct st_rx_video_tp {
struct st20_rx_tp_pass pass;

/* timing info for each slot */
struct st_rv_tp_slot slots[ST_VIDEO_RX_REC_NUM_OFO];
uint32_t pre_rtp_tmstamp;
struct st_rv_tp_slot slots[ST_VIDEO_RX_REC_NUM_OFO][MTL_SESSION_PORT_MAX];
uint32_t pre_rtp_tmstamp[MTL_SESSION_PORT_MAX];

/* for the status */
struct st_rv_tp_stat stat;
struct st_rv_tp_stat stat[MTL_SESSION_PORT_MAX];
};

struct st_rx_video_session_impl {
Expand Down
Loading