Skip to content

Commit

Permalink
Add: RxTxApp updated to have ST41 testing possibilities (#983)
Browse files Browse the repository at this point in the history
Co-authored-by: DawidWesierski4 <[email protected]>
Co-authored-by: PanKaker <[email protected]>
Co-authored-by: DawidWesierski4 <[email protected]>
Co-authored-by: Lukas G <[email protected]>
Co-authored-by: GH Action - Upstream Sync <[email protected]>
  • Loading branch information
6 people authored Sep 23, 2024
1 parent 3c98592 commit a0ce526
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 13 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/afxdp_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ jobs:
egress-policy: audit

- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- uses: DoozyX/clang-format-lint-action@a83a8fb7d371f66da7dd1c4f33a193023899494b # v0.16
- uses: DoozyX/clang-format-lint-action@v0.18.2
with:
clangFormatVersion: '14'
source: '.'
extensions: 'hpp,h,cpp,c,cc'

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/centos_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ jobs:
egress-policy: audit

- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- uses: DoozyX/clang-format-lint-action@a83a8fb7d371f66da7dd1c4f33a193023899494b # v0.16
- uses: DoozyX/clang-format-lint-action@v0.18.2
with:
clangFormatVersion: '14'
source: '.'
extensions: 'hpp,h,cpp,c,cc'

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/tools_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ jobs:
egress-policy: audit

- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- uses: DoozyX/clang-format-lint-action@a83a8fb7d371f66da7dd1c4f33a193023899494b # v0.16
- uses: DoozyX/clang-format-lint-action@v0.18.2
with:
clangFormatVersion: '14'
source: '.'
extensions: 'hpp,h,cpp,c,cc'

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/ubuntu_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ jobs:
egress-policy: audit

- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- uses: DoozyX/clang-format-lint-action@a83a8fb7d371f66da7dd1c4f33a193023899494b # v0.16
- uses: DoozyX/clang-format-lint-action@v0.18.2
with:
clangFormatVersion: '14'
source: '.'
extensions: 'hpp,h,cpp,c,cc'

Expand Down
14 changes: 14 additions & 0 deletions app/src/app_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,11 +366,25 @@ struct st_app_rx_anc_session {
struct st_app_rx_fmd_session {
int idx;
st41_rx_handle handle;

/* Reference file handling */
char st41_ref_url[ST_APP_URL_MAX_LEN + 1];
int st41_ref_fd;
uint8_t* st41_ref_begin;
uint8_t* st41_ref_end;
uint8_t* st41_ref_cursor;

pthread_t st41_app_thread;
pthread_cond_t st41_wake_cond;
pthread_mutex_t st41_wake_mutex;
bool st41_app_thread_stop;

/* Expected values */
uint32_t st41_dit;
uint32_t st41_k_bit;

uint32_t errors_count;

/* stat */
int stat_frame_total_received;
uint64_t stat_frame_first_rx_time;
Expand Down
47 changes: 46 additions & 1 deletion app/src/parse_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -1332,8 +1332,16 @@ static int st_json_parse_rx_fmd(int idx, json_object* fmd_obj,
/* parse payload type */
ret = parse_base_payload_type(fmd_obj, &fmd->base);
if (ret < 0) {
err("%s, use default pt %u\n", __func__, ST_APP_PAYLOAD_TYPE_FASTMETADATA);
err("%s, using default expected payload type %u.\n", __func__,
ST_APP_PAYLOAD_TYPE_FASTMETADATA);
fmd->base.payload_type = ST_APP_PAYLOAD_TYPE_FASTMETADATA;
} else {
if (fmd->base.payload_type == 0) {
/* if value = 0, no expected payload type value */
info("%s, No expected payload type.\n", __func__);
} else {
info("%s, using expected payload type %u.\n", __func__, fmd->base.payload_type);
}
}

/* parse fmd interlaced */
Expand All @@ -1346,6 +1354,43 @@ static int st_json_parse_rx_fmd(int idx, json_object* fmd_obj,
fmd->enable_rtcp =
json_object_get_boolean(st_json_object_object_get(fmd_obj, "enable_rtcp"));

/* parse fmd data item type */
json_object* fmd_dit_obj =
st_json_object_object_get(fmd_obj, "fastmetadata_data_item_type");
if (fmd_dit_obj) {
uint32_t fmd_dit = json_object_get_int(fmd_dit_obj);
if (fmd_dit > 0x3fffff) {
err("%s, invalid fastmetadata_data_item_type 0x%x.\n", __func__, fmd_dit);
return -ST_JSON_NOT_VALID;
}
fmd->info.fmd_dit = fmd_dit;
info("%s, expected fastmetadata_data_item_type = 0x%x.\n", __func__, fmd_dit);
} else {
info("%s, No expected fastmetadata_data_item_type set.\n", __func__);
fmd->info.fmd_dit = 0xffffffff; /* No expected fmd data item type */
}

/* parse fmd data item K-bit */
json_object* fmd_k_bit_obj = st_json_object_object_get(fmd_obj, "fastmetadata_k_bit");
if (fmd_k_bit_obj) {
uint8_t fmd_k_bit = json_object_get_int(fmd_k_bit_obj);
if (fmd_k_bit > 1) {
err("%s, invalid fastmetadata_k_bit 0x%x.\n", __func__, fmd_k_bit);
return -ST_JSON_NOT_VALID;
}
fmd->info.fmd_k_bit = fmd_k_bit;
info("%s, expected fastmetadata_k_bit = 0x%x.\n", __func__, fmd_k_bit);
} else {
info("%s, No expected fastmetadata_k_bit set.\n", __func__);
fmd->info.fmd_k_bit = 0xff; /* No expected fmd K-bit */
}

/* parse fmd url */
ret = parse_url(fmd_obj, "fastmetadata_url", fmd->info.fmd_url);
if (ret < 0) {
info("%s, no fastmetadata reference file.\n", __func__);
}

return ST_JSON_SUCCESS;
}

Expand Down
175 changes: 169 additions & 6 deletions app/src/rx_fastmetadata_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,155 @@

#include "rx_fastmetadata_app.h"

static void app_rx_fmd_handle_rtp(struct st_app_rx_fmd_session* s) {
dbg("%s(%d).\n", __func__, s->idx);
static void app_rx_fmd_close_source(struct st_app_rx_fmd_session* session) {
if (session->st41_ref_fd >= 0) {
munmap(session->st41_ref_begin, session->st41_ref_end - session->st41_ref_begin);
close(session->st41_ref_fd);
session->st41_ref_fd = -1;
}
}

static int app_rx_fmd_open_ref(struct st_app_rx_fmd_session* session) {
int fd, idx = session->idx;
struct stat i;
session->st41_ref_fd = -1;

fd = st_open(session->st41_ref_url, O_RDONLY);
if (fd < 0) {
info("%s(%d), open file '%s' fail.\n", __func__, idx, session->st41_ref_url);
return -EIO;
}

if (fstat(fd, &i) < 0) {
err("%s, fstat '%s' fail.\n", __func__, session->st41_ref_url);
close(fd);
return -EIO;
}

uint8_t* m = mmap(NULL, i.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (MAP_FAILED == m) {
err("%s(%d), mmap '%s' fail.\n", __func__, idx, session->st41_ref_url);
close(fd);
return -EIO;
}

session->st41_ref_begin = m;
session->st41_ref_cursor = m;
session->st41_ref_end = m + i.st_size;
session->st41_ref_fd = fd;

info("%s, opening file '%s' success.\n", __func__, session->st41_ref_url);
return 0;
}

static int app_rx_fmd_compare_with_ref(struct st_app_rx_fmd_session* session, void* frame,
int frame_size) {
int ret = -1;
uint32_t last_zeros = 0; /* 4 bytes with 0 */
uint32_t st41_ref_remaining_length =
session ? session->st41_ref_end - session->st41_ref_cursor : 0;

if (frame_size <= st41_ref_remaining_length) {
ret = memcmp(frame, session->st41_ref_cursor, frame_size);
if (ret) {
session->errors_count++;
err("%s() FAIL: reference file comparison with frame.\n", __func__);
} else {
dbg("%s() PASS: reference file comparison with frame.\n", __func__);
}
} else {
if (frame_size - st41_ref_remaining_length > 3) {
ret = -1;
session->errors_count++;
err("%s() FAIL: frame_size > ref_remaining_length by %d.\n", __func__,
frame_size - st41_ref_remaining_length);
} else {
ret = memcmp(frame, session->st41_ref_cursor, st41_ref_remaining_length);
if (ret) {
session->errors_count++;
err("%s() FAIL: reference file comparison with ending frame.\n", __func__);
} else {
dbg("%s() PASS: reference file comparison with ending frame.\n", __func__);

/* Verify last 0-3 bytes of frame (filled with zero's) */
ret = memcmp(&(((uint8_t*)frame)[st41_ref_remaining_length]), (void*)&last_zeros,
frame_size - st41_ref_remaining_length);
if (ret) {
session->errors_count++;
err("%s() FAIL: frame comparison with ending zeros.\n", __func__);
} else {
dbg("%s() PASS: frame comparison with ending zeros.\n", __func__);
}
}
}
}

#ifdef DEBUG /* print out of frame and reference file if error */
if (ret) {
err("%s() FRAME START>>", __func__);
for (int i = 0; i < frame_size; i++) {
err("%c", ((char*)frame)[i]);
}
err("<<END FRAME.\n\n");

err("%s() REFERENCE START>>", __func__);
for (int i = 0; i < frame_size; i++) {
err("%c", ((char*)(session->st41_ref_cursor))[i]);
}
err("<<END REFERENCE.\n\n");
}
#endif /* DEBUG */

/* calculate new reference frame */
session->st41_ref_cursor += frame_size;
if (session->st41_ref_cursor >= session->st41_ref_end)
session->st41_ref_cursor = session->st41_ref_begin;

return ret;
}

static void app_rx_fmd_handle_rtp(struct st_app_rx_fmd_session* s, void* usrptr) {
struct st41_rtp_hdr* hdr = (struct st41_rtp_hdr*)usrptr;
void* payload = (void*)(&hdr[1]);

hdr->swaped_st41_hdr_chunk = ntohl(hdr->swaped_st41_hdr_chunk);

/* Testing data_item_type */
if (s->st41_dit != 0xffffffff) {
if (hdr->st41_hdr_chunk.data_item_type != s->st41_dit) {
s->errors_count++;
err("%s(%d) FAIL: hdr->st41_hdr_chunk.data_item_type=%u, expected to be %u.\n",
__func__, s->idx, hdr->st41_hdr_chunk.data_item_type, s->st41_dit);
} else {
dbg("%s(%d) PASS: hdr->st41_hdr_chunk.data_item_type=%u, expected to be %u.\n",
__func__, s->idx, hdr->st41_hdr_chunk.data_item_type, s->st41_dit);
}
}

/* Testing data_item K-bit */
if (s->st41_k_bit != 0xff) {
if (hdr->st41_hdr_chunk.data_item_k_bit != s->st41_k_bit) {
s->errors_count++;
err("%s(%d) FAIL: hdr->st41_hdr_chunk.data_item_k_bit=%u, expected to be %u.\n",
__func__, s->idx, hdr->st41_hdr_chunk.data_item_k_bit, s->st41_k_bit);
} else {
dbg("%s(%d) PASS: hdr->st41_hdr_chunk.data_item_k_bit=%u, expected to be %u.\n",
__func__, s->idx, hdr->st41_hdr_chunk.data_item_k_bit, s->st41_k_bit);
}
}

s->stat_frame_total_received++;
if (!s->stat_frame_first_rx_time)
s->stat_frame_first_rx_time = st_app_get_monotonic_time();

/* Compare each packet with reference (part by part) */
if (s->st41_ref_fd > 0) {
app_rx_fmd_compare_with_ref(s, payload, hdr->st41_hdr_chunk.data_item_length * 4);
/* (field hdr->st41_hdr_chunk.data_item_length is expressed in 4-byte words, thus
* multiplying by 4) */
}

hdr->swaped_st41_hdr_chunk = htonl(hdr->swaped_st41_hdr_chunk);
}

static void* app_rx_fmd_read_thread(void* arg) {
Expand All @@ -31,7 +174,7 @@ static void* app_rx_fmd_read_thread(void* arg) {
continue;
}
/* parse the packet */
app_rx_fmd_handle_rtp(s);
app_rx_fmd_handle_rtp(s, usrptr);
st41_rx_put_mbuf(s->handle, mbuf);
}
info("%s(%d), stop\n", __func__, idx);
Expand Down Expand Up @@ -67,6 +210,8 @@ static int app_rx_fmd_uinit(struct st_app_rx_fmd_session* s) {
st_pthread_mutex_destroy(&s->st41_wake_mutex);
st_pthread_cond_destroy(&s->st41_wake_cond);

app_rx_fmd_close_source(s);

return 0;
}

Expand Down Expand Up @@ -107,12 +252,30 @@ static int app_rx_fmd_init(struct st_app_context* ctx,
}
ops.rtp_ring_size = 1024;
ops.payload_type = fmd ? fmd->base.payload_type : ST_APP_PAYLOAD_TYPE_FASTMETADATA;
s->st41_dit = fmd ? fmd->info.fmd_dit : 0xffffffff;
s->st41_k_bit = fmd ? fmd->info.fmd_k_bit : 0xff;
ops.interlaced = fmd ? fmd->info.interlaced : false;
ops.notify_rtp_ready = app_rx_fmd_rtp_ready;
if (fmd && fmd->enable_rtcp) ops.flags |= ST41_RX_FLAG_ENABLE_RTCP;
st_pthread_mutex_init(&s->st41_wake_mutex, NULL);
st_pthread_cond_init(&s->st41_wake_cond, NULL);

s->errors_count = 0;
s->st41_ref_fd = -1;
if (fmd) {
if (strcmp(fmd->info.fmd_url, "")) {
snprintf(s->st41_ref_url, sizeof(s->st41_ref_url), "%s",
fmd ? fmd->info.fmd_url : "null");

ret = app_rx_fmd_open_ref(s);
if (ret < 0) {
err("%s(%d), app_rx_fmd_open_ref fail %d.\n", __func__, idx, ret);
app_rx_fmd_uinit(s);
return -EIO;
}
}
}

handle = st41_rx_create(ctx->st, &ops);
if (!handle) {
err("%s(%d), st41_rx_create fail\n", __func__, idx);
Expand Down Expand Up @@ -152,9 +315,9 @@ static int app_rx_fmd_result(struct st_app_rx_fmd_session* s) {

if (!s->stat_frame_total_received) return -EINVAL;

critical("%s(%d), %s, fps %f, %d frame received\n", __func__, idx,
app_rx_fmd_fps_check(framerate) ? "OK" : "FAILED", framerate,
s->stat_frame_total_received);
critical("%s(%d), %s, fps %f, %d frame received, %d counted errors.\n", __func__, idx,
(app_rx_fmd_fps_check(framerate) && (s->errors_count == 0)) ? "OK" : "FAILED",
framerate, s->stat_frame_total_received, s->errors_count);
return 0;
}

Expand Down
11 changes: 11 additions & 0 deletions format-coding.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@

# Based on clang-format
# For ubuntu, pls "apt-get install clang-format"
# When updating clang format version, remeber to update also GHA clang lister version:
# - uses: DoozyX/[email protected]
# with:
# clangFormatVersion: '14'
# source: '.'
# extensions: 'hpp,h,cpp,c,cc'
# in
# .github/workflows/afxdp_build.yml
# .github/workflows/centos_build.yml
# .github/workflows/tools_build.yml
# .github/workflows/ubuntu_build.yml

set -e

Expand Down
10 changes: 8 additions & 2 deletions include/st41_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,15 @@ struct st41_rx_ops {
/** Mandatory. UDP dest port number */
uint16_t udp_port[MTL_SESSION_PORT_MAX];

/** Mandatory. 7 bits payload type define in RFC3550. Zero means disable the
* payload_type check on the RX pkt path */
/** Mandatory. 7 bits payload type define in RFC3550. Value zero (0) means disable the
* payload_type check on the RX pkt path */
uint8_t payload_type;
/** Optional. Expected 22 bits data item type. Value 0xffffffff means disable the
* data item type check on the RX pkt path */
uint32_t fmd_dit;
/** Optional. Expected 1 bit K-bit. Value 0xff means disable the
* K-bit check on the RX pkt path */
uint8_t fmd_k_bit;
/** Mandatory. interlaced or not */
bool interlaced;

Expand Down

0 comments on commit a0ce526

Please sign in to comment.