Skip to content

Fix: improve timestamp calculation for st20 st40 st41 #1224

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 0 additions & 4 deletions lib/src/st2110/st_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -1054,8 +1054,6 @@ struct st_tx_ancillary_session_pacing {
uint64_t cur_epochs; /* epoch of current frame */
/* timestamp for rtp header */
uint32_t rtp_time_stamp;
/* timestamp for pacing */
uint32_t pacing_time_stamp;
uint64_t cur_epoch_time;
double tsc_time_cursor; /* in ns, tsc time cursor for packet pacing */
/* ptp time may onward */
Expand Down Expand Up @@ -1224,8 +1222,6 @@ struct st_tx_fastmetadata_session_pacing {
uint64_t cur_epochs; /* epoch of current frame */
/* timestamp for rtp header */
uint32_t rtp_time_stamp;
/* timestamp for pacing */
uint32_t pacing_time_stamp;
uint64_t cur_epoch_time;
double tsc_time_cursor; /* in ns, tsc time cursor for packet pacing */
/* ptp time may onward */
Expand Down
18 changes: 13 additions & 5 deletions lib/src/st2110/st_tx_ancillary_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ static int tx_ancillary_session_sync_pacing(struct mtl_main_impl* impl,
bool sync, uint64_t required_tai,
bool second_field) {
struct st_tx_ancillary_session_pacing* pacing = &s->pacing;
double frame_time = pacing->frame_time;
long double frame_time = pacing->frame_time;
/* always use MTL_PORT_P for ptp now */
uint64_t ptp_time = mt_get_ptp_time(impl, MTL_PORT_P);
uint64_t next_epochs = pacing->cur_epochs + 1;
Expand Down Expand Up @@ -309,12 +309,20 @@ static int tx_ancillary_session_sync_pacing(struct mtl_main_impl* impl,
if (epochs < next_epochs) s->stat_epoch_onward += (next_epochs - epochs);

pacing->cur_epochs = epochs;
pacing->cur_epoch_time = tx_ancillary_pacing_time(pacing, epochs);
pacing->pacing_time_stamp = tx_ancillary_pacing_time_stamp(pacing, epochs);
pacing->rtp_time_stamp = pacing->pacing_time_stamp;

if (required_tai) {
pacing->cur_epoch_time = required_tai + frame_time;
pacing->rtp_time_stamp =
((uint64_t)((required_tai / frame_time) * pacing->frame_time_sampling) &
0xffffffff);
} else {
pacing->cur_epoch_time = tx_ancillary_pacing_time(pacing, epochs);
pacing->rtp_time_stamp = tx_ancillary_pacing_time_stamp(pacing, epochs);
}

pacing->tsc_time_cursor = (double)mt_get_tsc(impl) + to_epoch;
dbg("%s(%d), epochs %" PRIu64 " time_stamp %u time_cursor %f to_epoch %f\n", __func__,
s->idx, pacing->cur_epochs, pacing->pacing_time_stamp, pacing->tsc_time_cursor,
s->idx, pacing->cur_epochs, pacing->rtp_time_stamp, pacing->tsc_time_cursor,
to_epoch);

if (sync) {
Expand Down
18 changes: 13 additions & 5 deletions lib/src/st2110/st_tx_fastmetadata_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ static int tx_fastmetadata_session_sync_pacing(struct mtl_main_impl* impl,
bool sync, uint64_t required_tai,
bool second_field) {
struct st_tx_fastmetadata_session_pacing* pacing = &s->pacing;
double frame_time = pacing->frame_time;
long double frame_time = pacing->frame_time;
/* always use MTL_PORT_P for ptp now */
uint64_t ptp_time = mt_get_ptp_time(impl, MTL_PORT_P);
uint64_t next_epochs = pacing->cur_epochs + 1;
Expand Down Expand Up @@ -309,12 +309,20 @@ static int tx_fastmetadata_session_sync_pacing(struct mtl_main_impl* impl,
if (epochs < next_epochs) s->stat_epoch_onward += (next_epochs - epochs);

pacing->cur_epochs = epochs;
pacing->cur_epoch_time = tx_fastmetadata_pacing_time(pacing, epochs);
pacing->pacing_time_stamp = tx_fastmetadata_pacing_time_stamp(pacing, epochs);
pacing->rtp_time_stamp = pacing->pacing_time_stamp;

if (required_tai) {
pacing->cur_epoch_time = required_tai + frame_time;
pacing->rtp_time_stamp =
((uint64_t)((required_tai / frame_time) * pacing->frame_time_sampling) &
0xffffffff);
} else {
pacing->cur_epoch_time = tx_fastmetadata_pacing_time(pacing, epochs);
pacing->rtp_time_stamp = tx_fastmetadata_pacing_time_stamp(pacing, epochs);
}

pacing->tsc_time_cursor = (double)mt_get_tsc(impl) + to_epoch;
dbg("%s(%d), epochs %" PRIu64 " time_stamp %u time_cursor %f to_epoch %f\n", __func__,
s->idx, pacing->cur_epochs, pacing->pacing_time_stamp, pacing->tsc_time_cursor,
s->idx, pacing->cur_epochs, pacing->rtp_time_stamp, pacing->tsc_time_cursor,
to_epoch);

if (sync) {
Expand Down
66 changes: 44 additions & 22 deletions lib/src/st2110/st_tx_video_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ static inline double pacing_time(struct st_tx_video_pacing* pacing, uint64_t epo
return epochs * pacing->frame_time;
}

static inline double pacing_first_pkt_time(struct st_tx_video_pacing* pacing,
uint64_t epochs) {
return pacing_time(pacing, epochs) + pacing->tr_offset - (pacing->vrx * pacing->trs);
static inline double pacing_first_pkt_time(struct st_tx_video_pacing* pacing) {
return pacing->tr_offset - (pacing->vrx * pacing->trs);
}

/* pacing start time(warmup pkt if has warmup stage) of the frame */
Expand All @@ -33,25 +32,26 @@ static inline double pacing_start_time(struct st_tx_video_pacing* pacing,
/* time stamp on the first pkt video pkt(not the warmup) */
static inline uint32_t pacing_time_stamp(struct st_tx_video_session_impl* s,
struct st_tx_video_pacing* pacing,
uint64_t epochs) {
uint64_t epochs, uint64_t tai) {
uint64_t tmstamp64;
double time;
if (s->ops.flags & ST20_TX_FLAG_RTP_TIMESTAMP_EPOCH) {
/* the start of epoch */
time = pacing_first_pkt_time(pacing, epochs);
} else if (s->ops.flags & ST20_TX_FLAG_RTP_TIMESTAMP_FIRST_PKT) {
long double frame_time = pacing->frame_time;
double time = pacing_time(pacing, epochs);

if (s->ops.flags & ST20_TX_FLAG_USER_TIMESTAMP) {
time = tai;
} else if (s->ops.flags & ST20_TX_FLAG_RTP_TIMESTAMP_EPOCH) {
time += pacing_first_pkt_time(pacing);
} else { // if (s->ops.flags & ST20_TX_FLAG_RTP_TIMESTAMP_FIRST_PKT) {
/* the start of first pkt */
time = pacing_first_pkt_time(pacing, epochs);
if (pacing->warm_pkts) time -= 3 * pacing->trs; /* deviation for VRX */
} else if (s->ops.rtp_timestamp_delta_us) {
int32_t rtp_timestamp_delta_us = s->ops.rtp_timestamp_delta_us;
time = pacing_time(pacing, epochs) + (rtp_timestamp_delta_us * NS_PER_US);
} else {
/* default to the start of first pkt */
time = pacing_first_pkt_time(pacing, epochs);
time += pacing_first_pkt_time(pacing);
if (pacing->warm_pkts) time -= 3 * pacing->trs; /* deviation for VRX */
}
tmstamp64 = (time / pacing->frame_time) * pacing->frame_time_sampling;

if (s->ops.rtp_timestamp_delta_us) {
time += (s->ops.rtp_timestamp_delta_us * NS_PER_US);
}

tmstamp64 = (time / frame_time) * pacing->frame_time_sampling;
uint32_t tmstamp32 = tmstamp64;

return tmstamp32;
Expand Down Expand Up @@ -600,14 +600,16 @@ static int tv_sync_pacing(struct mtl_main_impl* impl, struct st_tx_video_session
int idx = s->idx;
struct st_tx_video_pacing* pacing = &s->pacing;
double frame_time = pacing->frame_time;
double to_epoch;
/* always use MTL_PORT_P for ptp now */
uint64_t ptp_time = mt_get_ptp_time(impl, MTL_PORT_P);
uint64_t next_epochs = pacing->cur_epochs + 1;
uint64_t epochs;
uint64_t ptp_epochs;
bool interlaced = s->ops.interlaced;

if (required_tai) {
uint64_t ptp_epochs = ptp_time / frame_time;
ptp_epochs = ptp_time / frame_time;
epochs = required_tai / frame_time;
dbg("%s(%d), required tai %" PRIu64 " ptp_epochs %" PRIu64 " epochs %" PRIu64 "\n",
__func__, idx, required_tai, ptp_epochs, epochs);
Expand Down Expand Up @@ -638,7 +640,22 @@ static int tv_sync_pacing(struct mtl_main_impl* impl, struct st_tx_video_session

/* epoch resolved */
double start_time_ptp = pacing_start_time(pacing, epochs);
double to_epoch = start_time_ptp - ptp_time;
if (required_tai) {
to_epoch = (double)required_tai - ptp_time;
if (to_epoch > NS_PER_S) {
dbg("%s(%d), required tai %" PRIu64 " ptp_epochs %" PRIu64 " epochs %" PRIu64 "\n",
__func__, s->idx, required_tai, ptp_epochs, epochs);
s->stat_error_user_timestamp++;
to_epoch = NS_PER_S; // do our best to slow down
}
if (to_epoch < 0) {
/* time bigger than the assigned epoch time */
to_epoch = 0; /* send asap */
}
} else {
to_epoch = start_time_ptp - ptp_time;
}

if (to_epoch < 0) {
/* time larger than the next assigned epoch time */
dbg("%s(%d), to_epoch %f, ptp epochs %" PRIu64 " cur_epochs %" PRIu64
Expand All @@ -665,8 +682,13 @@ static int tv_sync_pacing(struct mtl_main_impl* impl, struct st_tx_video_session
}
if (epochs < next_epochs) s->stat_epoch_onward += (next_epochs - epochs);
pacing->cur_epochs = epochs;
pacing->cur_epoch_time = pacing_time(pacing, epochs);
pacing->rtp_time_stamp = pacing_time_stamp(s, pacing, epochs);
if (s->ops.flags & ST20_TX_FLAG_USER_TIMESTAMP) {
pacing->cur_epoch_time = required_tai;
} else {
pacing->cur_epoch_time = pacing_time(pacing, epochs);
}

pacing->rtp_time_stamp = pacing_time_stamp(s, pacing, epochs, required_tai);
dbg("%s(%d), old time_cursor %fms\n", __func__, idx,
pacing->tsc_time_cursor / 1000 / 1000);
pacing->tsc_time_cursor = (double)mt_get_tsc(impl) + to_epoch;
Expand Down