Skip to content

Commit

Permalink
video: add user meta support
Browse files Browse the repository at this point in the history
use the highest bit of rfc4175 Length field for the user meta pkt

Signed-off-by: Frank Du <frank.du@intel.com>
  • Loading branch information
frankdjx committed Jul 20, 2023
1 parent 3b7b3e9 commit 78f07e4
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 21 deletions.
8 changes: 8 additions & 0 deletions app/sample/legacy/rx_video_sample.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ static int rx_video_frame_ready(void* priv, void* frame,

if (!s->handle) return -EIO;

if (meta->user_meta) {
const struct st_frame_user_meta* user_meta = meta->user_meta;
if (meta->user_meta_size != sizeof(*user_meta)) {
err("%s(%d), user_meta_size wrong\n", __func__, s->idx);
}
info("%s(%d), user_meta %d %s\n", __func__, s->idx, user_meta->idx, user_meta->dummy);
}

/* incomplete frame */
if (!st_is_frame_complete(meta->status)) {
st20_rx_put_framebuff(s->handle, frame);
Expand Down
12 changes: 12 additions & 0 deletions app/sample/legacy/tx_video_sample.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ struct tv_sample_context {
struct st_tx_frame* framebuffs;

mtl_dma_mem_handle dma_mem;

struct st_frame_user_meta meta;
bool has_user_meta;
};

static int tx_video_next_frame(void* priv, uint16_t* next_frame_idx,
Expand All @@ -43,6 +46,11 @@ static int tx_video_next_frame(void* priv, uint16_t* next_frame_idx,
consumer_idx++;
if (consumer_idx >= s->framebuff_cnt) consumer_idx = 0;
s->framebuff_consumer_idx = consumer_idx;
if (s->has_user_meta) {
s->meta.idx = s->fb_send;
meta->user_meta = &s->meta;
meta->user_meta_size = sizeof(s->meta);
}
} else {
/* not ready */
ret = -EIO;
Expand Down Expand Up @@ -160,6 +168,10 @@ int main(int argc, char** argv) {
st_pthread_mutex_init(&app[i]->wake_mutex, NULL);
st_pthread_cond_init(&app[i]->wake_cond, NULL);
app[i]->idx = i;
if (ctx.has_user_meta) {
snprintf(app[i]->meta.dummy, sizeof(app[i]->meta.dummy), "st20_tx_%d", i);
app[i]->has_user_meta = true;
}
app[i]->framebuff_cnt = ctx.framebuff_cnt;
app[i]->framebuffs =
(struct st_tx_frame*)malloc(sizeof(*app[i]->framebuffs) * app[i]->framebuff_cnt);
Expand Down
5 changes: 5 additions & 0 deletions app/sample/sample_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ enum sample_args_cmd {
SAMPLE_ARG_GDDR_PA,
SAMPLE_ARG_RX_DUMP,
SAMPLE_ARG_USE_CPU_COPY,
SAMPLE_ARG_USER_META,

SAMPLE_ARG_UDP_MODE = 0x300,
SAMPLE_ARG_UDP_LEN,
Expand Down Expand Up @@ -110,6 +111,7 @@ static struct option sample_args_options[] = {
{"gddr_pa", required_argument, 0, SAMPLE_ARG_GDDR_PA},
{"use_cpu_copy", no_argument, 0, SAMPLE_ARG_USE_CPU_COPY},
{"rx_dump", no_argument, 0, SAMPLE_ARG_RX_DUMP},
{"user_meta", no_argument, 0, SAMPLE_ARG_USER_META},

{0, 0, 0, 0}};

Expand Down Expand Up @@ -326,6 +328,9 @@ static int _sample_parse_args(struct st_sample_context* ctx, int argc, char** ar
case SAMPLE_ARG_RX_DUMP:
ctx->rx_dump = true;
break;
case SAMPLE_ARG_USER_META:
ctx->has_user_meta = true;
break;
case SAMPLE_ARG_USE_CPU_COPY:
ctx->use_cpu_copy = true;
break;
Expand Down
7 changes: 7 additions & 0 deletions app/sample/sample_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ struct st_sample_context {
off_t gddr_pa;
off_t gddr_offset;
bool use_cpu_copy;

bool has_user_meta; /* if provide user meta data with the st2110-20 frame */
};

struct st_frame_user_meta {
int idx; /* frame index */
char dummy[512];
};

int sample_parse_args(struct st_sample_context* ctx, int argc, char** argv, bool tx,
Expand Down
20 changes: 17 additions & 3 deletions include/st20_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,14 @@ struct st20_tx_frame_meta {
uint64_t timestamp;
/** epoch */
uint64_t epoch;
/**
* The user meta data buffer for current frame, the size must smaller than
* MTL_PKT_MAX_RTP_BYTES. This data will be transported to RX with video data and passed
* to user by user_meta in st20_rx_frame_meta.
*/
const void* user_meta;
/** size for meta data buffer */
size_t user_meta_size;
};

/**
Expand Down Expand Up @@ -376,6 +384,12 @@ struct st20_rx_frame_meta {
uint64_t timestamp_last_pkt;
/** first packet time in ns to the start of current epoch */
int64_t fpt;
/**
* The received user meta data buffer for current frame.
*/
const void* user_meta;
/** size for meta data buffer */
size_t user_meta_size;
};

/**
Expand Down Expand Up @@ -471,15 +485,15 @@ struct st22_rx_frame_meta {
};

/**
* The Continuation bit shall be set to 1 if an additional Sample Row Data.
* The Continuation bit shall in row_offset be set to 1 if an additional Sample Row Data.
* Header follows the current Sample Row Data Header in the RTP Payload
* Header, which signals that the RTP packet is carrying data for more than one
* sample row. The Continuation bit shall be set to 0 otherwise.
*/
#define ST20_SRD_OFFSET_CONTINUATION (0x1 << 15)
/**
* The field identification bit shall be set to 1 if the payload comes from second
* field.The field identification bit shall be set to 0 otherwise.
* The field identification bit in row_number shall be set to 1 if the payload comes from
* second field.The field identification bit shall be set to 0 otherwise.
*/
#define ST20_SECOND_FIELD (0x1 << 15)

Expand Down
6 changes: 6 additions & 0 deletions lib/src/mt_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,12 @@ int st_frame_trans_uinit(struct st_frame_trans* frame) {
frame->page_table_len = 0;
}

if (frame->user_meta) {
mt_rte_free(frame->user_meta);
frame->user_meta = NULL;
frame->user_meta_buffer_size = 0;
}

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions lib/src/st2110/st_err.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum sti_ret_code {
STI_FRAME_INFLIGHT_R_ENQUEUE_FAIL,
STI_FRAME_APP_GET_FRAME_BUSY,
STI_FRAME_APP_ERR_TX_FRAME,
STI_FRAME_APP_ERR_USER_META,
STI_FRAME_APP_SLICE_NOT_READY,
STI_FRAME_PKT_ALLOC_FAIL,
STI_FRAME_PKT_ENQUEUE_FAIL,
Expand Down
9 changes: 8 additions & 1 deletion lib/src/st2110/st_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ struct st_page_info {

/* describe the frame used in transport(both tx and rx) */
struct st_frame_trans {
/* todo: use struct st_frame as base */
int idx;
void* addr; /* virtual address */
rte_iova_t iova; /* iova for hw */
Expand All @@ -130,6 +129,10 @@ struct st_frame_trans {
uint32_t flags; /* ST_FT_FLAG_* */
struct rte_mbuf_ext_shared_info sh_info; /* for st20 tx ext shared */

void* user_meta; /* the meta data from user */
size_t user_meta_buffer_size;
size_t user_meta_data_size;

/* metadata */
union {
struct st20_tx_frame_meta tv_meta;
Expand Down Expand Up @@ -367,6 +370,8 @@ struct st_tx_video_session_impl {
uint32_t stat_vsync_mismatch;
uint32_t stat_tx_done_cleanup;
uint64_t stat_bytes_build;
uint32_t stat_user_meta_cnt;
uint32_t stat_user_meta_pkt_cnt;
};

struct st_tx_video_sessions_mgr {
Expand Down Expand Up @@ -688,6 +693,8 @@ struct st_rx_video_session_impl {
int stat_slices_received;
int stat_pkts_slice_fail;
int stat_pkts_slice_merged;
int stat_pkts_user_meta;
int stat_pkts_user_meta_err;
uint64_t stat_last_time;
uint32_t stat_vsync_mismatch;
uint32_t stat_slot_get_frame_fail;
Expand Down
3 changes: 3 additions & 0 deletions lib/src/st2110/st_pkt.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ struct st_rfc3550_hdr {
struct st_rfc3550_rtp_hdr rtp; /* size: 12 */
} __attribute__((__packed__)) __rte_aligned(2);

/* if this rfc4175 rtp carry a user meta data */
#define ST20_LEN_USER_META (0x1 << 15)

/* total size: 62 */
struct st_rfc4175_video_hdr {
struct rte_ether_hdr eth; /* size: 14 */
Expand Down
39 changes: 39 additions & 0 deletions lib/src/st2110/st_rx_video_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,17 @@ static int rv_alloc_frames(struct mtl_main_impl* impl,
}
}
}

/* init user meta */
st20_frame->user_meta_buffer_size =
impl->pkt_udp_suggest_max_size - sizeof(struct st20_rfc4175_rtp_hdr);
st20_frame->user_meta =
mt_rte_zmalloc_socket(st20_frame->user_meta_buffer_size, soc_id);
if (!st20_frame->user_meta) {
err("%s(%d), user_meta malloc %" PRIu64 " fail at %d\n", __func__, idx,
st20_frame->user_meta_buffer_size, i);
return -ENOMEM;
}
}

dbg("%s(%d), succ\n", __func__, idx);
Expand Down Expand Up @@ -1074,6 +1085,13 @@ static void rv_frame_notify(struct st_rx_video_session_impl* s,
meta->frame_total_size = s->st20_frame_size;
meta->uframe_total_size = s->st20_uframe_size;
meta->frame_recv_size = rv_slot_get_frame_size(s, slot);
if (slot->frame->user_meta_data_size) {
meta->user_meta_size = slot->frame->user_meta_data_size;
meta->user_meta = slot->frame->user_meta;
} else {
meta->user_meta_size = 0;
meta->user_meta = NULL;
}
if (meta->frame_recv_size >= s->st20_frame_size) {
meta->status = ST_FRAME_STATUS_COMPLETE;
if (ops->num_port > 1) {
Expand Down Expand Up @@ -1328,6 +1346,7 @@ static struct st_rx_video_slot_impl* rv_slot_by_tmstamp(
frame_info->flags |= ST_FT_FLAG_EXT;
meta->opaque = ext_frame.opaque;
}
frame_info->user_meta_data_size = 0;
slot->frame = frame_info;
slot->timestamp_first_pkt = mtl_ptp_read_time(s->parent->parent);

Expand Down Expand Up @@ -1690,6 +1709,20 @@ static int rv_handle_frame_pkt(struct st_rx_video_session_impl* s, struct rte_mb
s->stat_pkts_no_slot++;
return -EIO;
}

if (line1_length & ST20_LEN_USER_META) {
line1_length &= ~ST20_LEN_USER_META;
dbg("%s(%d,%d): ST20_LEN_USER_META %u\n", __func__, s->idx, s_port, line1_length);
if (line1_length <= slot->frame->user_meta_buffer_size) {
rte_memcpy(slot->frame->user_meta, payload, line1_length);
slot->frame->user_meta_data_size = line1_length;
} else {
s->stat_pkts_user_meta_err++;
}
s->stat_pkts_user_meta++;
return 0;
}

uint8_t* bitmap = slot->frame_bitmap;
slot->second_field = (line1_number & ST20_SECOND_FIELD) ? true : false;
line1_number &= ~ST20_SECOND_FIELD;
Expand Down Expand Up @@ -3361,6 +3394,12 @@ static void rv_stat(struct st_rx_video_sessions_mgr* mgr,
s->stat_pkts_simulate_loss);
s->stat_pkts_simulate_loss = 0;
}
if (s->stat_pkts_user_meta) {
notice("RX_VIDEO_SESSION(%d,%d): user meta pkts %d invalid %d\n", m_idx, idx,
s->stat_pkts_user_meta, s->stat_pkts_user_meta_err);
s->stat_pkts_user_meta = 0;
s->stat_pkts_user_meta_err = 0;
}
}

static int rvs_ctl_tasklet_start(void* priv) {
Expand Down
89 changes: 87 additions & 2 deletions lib/src/st2110/st_tx_video_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,17 @@ static int tv_alloc_frames(struct mtl_main_impl* impl,
tv_frame_create_page_table(impl, s, frame_info);
}
frame_info->priv = s;

/* init user meta */
frame_info->user_meta_buffer_size =
impl->pkt_udp_suggest_max_size - sizeof(struct st20_rfc4175_rtp_hdr);
frame_info->user_meta =
mt_rte_zmalloc_socket(frame_info->user_meta_buffer_size, soc_id);
if (!frame_info->user_meta) {
err("%s(%d), user_meta malloc %" PRIu64 " fail at %d\n", __func__, idx,
frame_info->user_meta_buffer_size, i);
return -ENOMEM;
}
}

dbg("%s(%d), succ\n", __func__, idx);
Expand Down Expand Up @@ -1583,6 +1594,20 @@ static int tv_tasklet_frame(struct mtl_main_impl* impl,
}
frame->tv_meta = meta;

frame->user_meta_data_size = 0;
if (meta.user_meta) {
if (meta.user_meta_size > frame->user_meta_buffer_size) {
err("%s(%d), frame %u user meta size %" PRId64 " too large\n", __func__, idx,
next_frame_idx, meta.user_meta_size);
s->stat_build_ret_code = -STI_FRAME_APP_ERR_USER_META;
return MT_TASKLET_ALL_DONE;
}
s->stat_user_meta_cnt++;
/* copy user meta to frame meta */
rte_memcpy(frame->user_meta, meta.user_meta, meta.user_meta_size);
frame->user_meta_data_size = meta.user_meta_size;
}

s->stat_user_busy_first = true;
/* all check fine */
rte_atomic32_inc(&frame->refcnt);
Expand Down Expand Up @@ -3000,6 +3025,12 @@ static void tv_stat(struct st_tx_video_sessions_mgr* mgr,
s->ops_name, s->stat_build_ret_code, s->stat_trs_ret_code[MTL_SESSION_PORT_P],
s->stat_trs_ret_code[MTL_SESSION_PORT_R]);
}
if (s->stat_user_meta_cnt || s->stat_user_meta_pkt_cnt) {
notice("TX_VIDEO_SESSION(%d,%d): user meta %u pkt %u\n", m_idx, idx,
s->stat_user_meta_cnt, s->stat_user_meta_pkt_cnt);
s->stat_user_meta_cnt = 0;
s->stat_user_meta_pkt_cnt = 0;
}

/* check frame busy stat */
if (s->st20_frames) {
Expand Down Expand Up @@ -3414,9 +3445,63 @@ static int tv_st22_ops_check(struct st22_tx_ops* ops) {
}

/* only st20 frame mode has this callback */
int st20_frame_tx_start(struct st_tx_video_session_impl* s, enum mtl_session_port port,
struct st_frame_trans* frame) {
int st20_frame_tx_start(struct mtl_main_impl* impl, struct st_tx_video_session_impl* s,
enum mtl_session_port s_port, struct st_frame_trans* frame) {
dbg("%s(%d,%d), start trans for frame %p\n", __func__, s->idx, port, frame);
if (!frame->user_meta_data_size) return 0;

enum mtl_port port = mt_port_logic2phy(s->port_maps, s_port);
/* tx the user meta */
struct rte_mbuf* pkt;
struct st_rfc4175_video_hdr* hdr;
struct rte_ipv4_hdr* ipv4;
struct st20_rfc4175_rtp_hdr* rtp;
struct rte_udp_hdr* udp;

pkt = rte_pktmbuf_alloc(mt_get_tx_mempool(impl, port));
if (!pkt) {
err("%s(%d), pkt alloc fail\n", __func__, port);
return -ENOMEM;
}

hdr = rte_pktmbuf_mtod(pkt, struct st_rfc4175_video_hdr*);
ipv4 = &hdr->ipv4;
rtp = &hdr->rtp;
udp = &hdr->udp;

/* copy the basic hdrs: eth, ip, udp, rtp */
rte_memcpy(hdr, &s->s_hdr[s_port], sizeof(*hdr));

/* update ipv4 hdr */
ipv4->packet_id = htons(s->st20_ipv4_packet_id);
s->st20_ipv4_packet_id++;
/* set timestamp */
rtp->base.tmstamp = htonl(s->pacing.rtp_time_stamp);
/* indicate it's user meta pkt */
rtp->row_length = htons(frame->user_meta_data_size | ST20_LEN_USER_META);

/* copy user meta */
void* payload = &rtp[1];
mtl_memcpy(payload, frame->user_meta, frame->user_meta_data_size);

pkt->data_len = sizeof(struct st_rfc4175_video_hdr) + frame->user_meta_data_size;
pkt->pkt_len = pkt->data_len;

udp->dgram_len = htons(pkt->pkt_len - pkt->l2_len - pkt->l3_len);
ipv4->total_length = htons(pkt->pkt_len - pkt->l2_len);
if (!s->eth_ipv4_cksum_offload[s_port]) {
/* generate cksum if no offload */
ipv4->hdr_checksum = rte_ipv4_cksum(ipv4);
}

uint16_t send = mt_dev_tx_sys_queue_burst(impl, port, &pkt, 1);
if (send < 1) {
err("%s(%d), tx fail\n", __func__, port);
rte_pktmbuf_free(pkt);
return -EIO;
}
s->stat_user_meta_pkt_cnt++;

return 0;
}

Expand Down
Loading

0 comments on commit 78f07e4

Please sign in to comment.