Replaced chrono clocks with integer nanoseconds

Ref 84861d6

It was perhaps rather a workaround for low-resolution Windows timeval
compat. On the other hand it enforced C++ API and makes things a bit
complicated. It had also broken some invariants, namely that the timeval
values had been wallclock time.
This commit is contained in:
Martin Pulec
2022-03-16 11:09:15 +01:00
parent 571813689f
commit b5f1fd3735
14 changed files with 79 additions and 72 deletions

View File

@@ -158,7 +158,7 @@ struct state_audio {
enum audio_transport_device sender = NET_NATIVE;
enum audio_transport_device receiver = NET_NATIVE;
std::chrono::steady_clock::time_point start_time;
time_ns_t start_time;
struct timeval t0; // for statistics
audio_frame2 captured;
@@ -242,7 +242,7 @@ struct state_audio * audio_cfg_init(struct module *parent,
const char *encryption,
int force_ip_version, const char *mcast_iface,
long long int bitrate, volatile int *audio_delay,
const std::chrono::steady_clock::time_point *start_time,
time_ns_t start_time,
int mtu, int ttl, struct exporter *exporter)
{
struct state_audio *s = NULL;
@@ -269,7 +269,7 @@ struct state_audio * audio_cfg_init(struct module *parent,
}
s = new state_audio(parent);
s->start_time = *start_time;
s->start_time = start_time;
s->audio_channel_map = opt->channel_map;
s->audio_scale = opt->scale;
@@ -634,8 +634,6 @@ static void *audio_receiver_thread(void *arg)
set_thread_name(__func__);
struct state_audio *s = (struct state_audio *) arg;
// rtp variables
struct timeval timeout, curr_time;
uint32_t ts;
struct pdb_e *cp;
struct audio_desc device_desc{};
bool playback_supports_multiple_streams;
@@ -664,11 +662,13 @@ static void *audio_receiver_thread(void *arg)
bool decoded = false;
if (s->receiver == NET_NATIVE || s->receiver == NET_STANDARD) {
time_ns_t time_ns = get_time_in_ns();
uint32_t ts = (time_ns - s->start_time) / 100'000 * 9; // at 90000 Hz
struct timeval curr_time;
gettimeofday(&curr_time, NULL);
auto curr_time_hr = std::chrono::high_resolution_clock::now();
ts = std::chrono::duration_cast<std::chrono::duration<double>>(s->start_time - std::chrono::steady_clock::now()).count() * 90000;
rtp_update(s->audio_network_device, curr_time);
rtp_send_ctrl(s->audio_network_device, ts, 0, curr_time);
struct timeval timeout;
timeout.tv_sec = 0;
// timeout.tv_usec = 999999 / 59.94; // audio goes almost always at the same rate
// as video frames
@@ -713,14 +713,14 @@ static void *audio_receiver_thread(void *arg)
// We iterate in loop since there can be more than one frmae present in
// the playout buffer and it would be discarded by following pbuf_remove()
// call.
while (pbuf_decode(cp->playout_buffer, curr_time_hr, s->receiver == NET_NATIVE ? decode_audio_frame : decode_audio_frame_mulaw, &dec_state->pbuf_data)) {
while (pbuf_decode(cp->playout_buffer, time_ns, s->receiver == NET_NATIVE ? decode_audio_frame : decode_audio_frame_mulaw, &dec_state->pbuf_data)) {
current_pbuf = &dec_state->pbuf_data;
decoded = true;
}
}
pbuf_remove(cp->playout_buffer, curr_time_hr);
pbuf_remove(cp->playout_buffer, time_ns);
cp = pdb_iter_next(&it);
if (decoded && !playback_supports_multiple_streams)
@@ -1002,10 +1002,9 @@ static void *audio_sender_thread(void *arg)
}
if ((s->audio_tx_mode & MODE_RECEIVER) == 0) { // otherwise receiver thread does the stuff...
uint32_t ts = (get_time_in_ns() - s->start_time) / 10'0000 * 9; // at 90000 Hz
struct timeval curr_time;
uint32_t ts;
gettimeofday(&curr_time, NULL);
ts = std::chrono::duration_cast<std::chrono::duration<double>>(s->start_time - std::chrono::steady_clock::now()).count() * 90000;
rtp_update(s->audio_network_device, curr_time);
rtp_send_ctrl(s->audio_network_device, ts, 0, curr_time);

View File

@@ -53,6 +53,7 @@
#define PORT_AUDIO 5006
#include "audio/types.h"
#include "tv.h"
struct module;
struct state_audio;
@@ -80,7 +81,7 @@ struct state_audio * audio_cfg_init(struct module *parent,
const char *encryption,
int force_ip_version, const char *mcast_iface,
long long int bitrate, volatile int *audio_delay,
const std::chrono::steady_clock::time_point *start_time,
time_ns_t start_time,
int mtu, int ttl, struct exporter *exporter);
#endif

View File

@@ -61,7 +61,7 @@
#include "debug.h"
#include "host.h"
#include "rtp/rtp.h"
#include "tv.h"
#include "video.h"
#include "video_display.h"
#include "video_display/pipe.hpp"
@@ -171,7 +171,6 @@ void *hd_rum_decompress_init(struct module *parent, struct hd_rum_output_conf co
int force_ip_version = 0;
s = new state_transcoder_decompress();
chrono::steady_clock::time_point start_time(chrono::steady_clock::now());
s->recompress = recompress;
@@ -215,7 +214,7 @@ void *hd_rum_decompress_init(struct module *parent, struct hd_rum_output_conf co
params["fec"].str = "none";
params["encryption"].str = NULL;
params["bitrate"].ll = 0;
params["start_time"].ptr = (void *) &start_time;
params["start_time"].ll = get_time_in_ns();
params["video_delay"].vptr = 0;
// UltraGrid RTP

View File

@@ -57,7 +57,7 @@
#include "debug.h"
#include "host.h"
#include "rtp/rtp.h"
#include "tv.h"
#include "video_compress.h"
#include "video_rxtx/ultragrid_rtp.h"
@@ -113,7 +113,6 @@ recompress_output_port::recompress_output_port(struct module *parent,
active(true)
{
int force_ip_version = 0;
auto start_time = std::chrono::steady_clock::now();
std::map<std::string, param_u> params;
@@ -134,7 +133,7 @@ recompress_output_port::recompress_output_port(struct module *parent,
params["fec"].str = fec;
params["encryption"].str = NULL;
params["bitrate"].ll = bitrate;
params["start_time"].cptr = (const void *) &start_time;
params["start_time"].ll = get_time_in_ns();
params["video_delay"].vptr = 0;
// UltraGrid RTP

View File

@@ -90,6 +90,7 @@
#include "playback.h"
#include "rtp/rtp.h"
#include "rtsp/rtsp_utils.h"
#include "tv.h"
#include "ug_runtime_error.hpp"
#include "utils/color_out.h"
#include "utils/misc.h"
@@ -1331,7 +1332,7 @@ int main(int argc, char *argv[])
struct exporter *exporter = NULL;
int ret;
const chrono::steady_clock::time_point start_time(chrono::steady_clock::now());
time_ns_t start_time = get_time_in_ns();
struct ug_nat_traverse *nat_traverse = nullptr;
@@ -1398,7 +1399,7 @@ int main(int argc, char *argv[])
uv.audio = audio_cfg_init (&uv.root_module, &opt.audio,
opt.requested_encryption,
opt.force_ip_version, opt.requested_mcast_if,
opt.bitrate, &audio_offset, &start_time,
opt.bitrate, &audio_offset, start_time,
opt.requested_mtu, opt.requested_ttl, exporter);
if(!uv.audio) {
exit_uv(EXIT_FAIL_AUDIO);
@@ -1504,7 +1505,7 @@ int main(int argc, char *argv[])
params["fec"].str = opt.requested_video_fec;
params["encryption"].str = opt.requested_encryption;
params["bitrate"].ll = opt.bitrate;
params["start_time"].cptr = (const void *) &start_time;
params["start_time"].ll = start_time;
params["video_delay"].vptr = (volatile void *) &video_offset;
// UltraGrid RTP

View File

@@ -63,6 +63,7 @@
#include "rtp/rtp_callback.h"
#include "rtp/ptime.h"
#include "rtp/pbuf.h"
#include "tv.h"
#include <algorithm>
#include <climits>
@@ -91,9 +92,9 @@ struct pbuf_node {
struct pbuf_node *nxt;
struct pbuf_node *prv;
uint32_t rtp_timestamp; /* RTP timestamp for the frame */
std::chrono::high_resolution_clock::time_point arrival_time; /* Arrival time of first packet in frame */
std::chrono::high_resolution_clock::time_point playout_time; /* Playout time for the frame */
std::chrono::high_resolution_clock::time_point deletion_time; /* Deletion time for the frame */
time_ns_t arrival_time; /* Arrival time of first packet in frame */
time_ns_t playout_time; /* Playout time for the frame */
time_ns_t deletion_time; /* Deletion time for the frame */
struct coded_data *cdata; /* */
int decoded; /* Non-zero if we've decoded this frame */
int mbit; /* determines if mbit of frame had been seen */
@@ -297,9 +298,9 @@ static struct pbuf_node *create_new_pnode(rtp_packet * pkt, long long playout_de
tmp->rtp_timestamp = pkt->ts;
tmp->mbit = pkt->m;
tmp->playout_time =
tmp->arrival_time = std::chrono::high_resolution_clock::now();
tmp->playout_time += std::chrono::microseconds(playout_delay_us);
tmp->deletion_time = tmp->playout_time + std::chrono::microseconds(playout_delay_us);
tmp->arrival_time = get_time_in_ns();
tmp->playout_time += playout_delay_us * 1000;
tmp->deletion_time = tmp->playout_time + playout_delay_us * 1000;
tmp->cdata = (struct coded_data *) malloc(sizeof(struct coded_data));
if (tmp->cdata != NULL) {
@@ -488,7 +489,7 @@ static void free_cdata(struct coded_data *head)
}
}
void pbuf_remove(struct pbuf *playout_buf, std::chrono::high_resolution_clock::time_point const & curr_time)
void pbuf_remove(struct pbuf *playout_buf, time_ns_t curr_time)
{
/* Remove previously decoded frames that have passed their playout */
/* time from the playout buffer. Incomplete frames that have passed */
@@ -552,10 +553,9 @@ int pbuf_is_empty(struct pbuf *playout_buf)
}
int
pbuf_decode(struct pbuf *playout_buf, std::chrono::high_resolution_clock::time_point const & curr_time,
pbuf_decode(struct pbuf *playout_buf, time_ns_t curr_time,
decode_frame_t decode_func, void *data)
{
using namespace std::chrono_literals;
/* Find the first complete frame that has reached it's playout */
/* time, and decode it into the framebuffer. Mark the frame as */
/* decoded, but otherwise leave it in the playout buffer. */
@@ -575,7 +575,7 @@ pbuf_decode(struct pbuf *playout_buf, std::chrono::high_resolution_clock::time_p
curr->decoded = 1;
return ret;
} else {
if (curr_time > curr->playout_time + 1s) {
if (curr_time > curr->playout_time + 1 * NS_IN_SEC) {
curr->completed = true;
}
debug_msg

View File

@@ -61,6 +61,7 @@
#include "audio/types.h"
#include "rtp/rtp.h"
#include "tv.h"
#ifdef __cplusplus
extern "C" {
@@ -109,28 +110,19 @@ struct pbuf_audio_data {
typedef int decode_frame_t(struct coded_data *cdata, void *decode_data, struct pbuf_stats *stats);
/*
* External C interface:
* External interface:
*/
struct pbuf *pbuf_init(volatile int *delay_ms);
void pbuf_destroy(struct pbuf *);
void pbuf_insert(struct pbuf *playout_buf, rtp_packet *r);
int pbuf_is_empty(struct pbuf *playout_buf);
int pbuf_decode(struct pbuf *playout_buf, time_ns_t curr_time,
decode_frame_t decode_func, void *data);
//struct video_frame *framebuffer, int i, struct state_decoder *decoder);
void pbuf_remove(struct pbuf *playout_buf, time_ns_t curr_time);
void pbuf_set_playout_delay(struct pbuf *playout_buf, double playout_delay);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
#include <chrono>
/*
* External C++ interface:
*/
int pbuf_is_empty(struct pbuf *playout_buf);
int pbuf_decode(struct pbuf *playout_buf, std::chrono::high_resolution_clock::time_point const & curr_time,
decode_frame_t decode_func, void *data);
//struct video_frame *framebuffer, int i, struct state_decoder *decoder);
void pbuf_remove(struct pbuf *playout_buf, std::chrono::high_resolution_clock::time_point const & curr_time);
void pbuf_set_playout_delay(struct pbuf *playout_buf, double playout_delay);
#endif

View File

@@ -4,6 +4,7 @@
* MODIFIED: Ladan Gharai <ladan@isi.edu>
*
* Copyright (c) 2001-2003 University of Southern California
* Copyright (c) 2005-2022 CESNET z.s.p.o.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted provided that the following conditions
@@ -44,6 +45,15 @@
*
*/
#ifndef TV_H_8332A958_38EB_4FE7_94E6_22C71BECD013
#define TV_H_8332A958_38EB_4FE7_94E6_22C71BECD013
#ifdef __cplusplus
#include <ctime>
#else
#include <time.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -57,7 +67,16 @@ int tv_gt(struct timeval a, struct timeval b);
uint32_t get_std_audio_local_mediatime(double samples, int rate);
uint32_t get_std_video_local_mediatime(void);
typedef long long time_ns_t;
#define NS_IN_SEC 1000000000LL
static inline time_ns_t get_time_in_ns() {
struct timespec ts = { 0, 0 };
timespec_get(&ts, TIME_UTC);
return ts.tv_sec * NS_IN_SEC + ts.tv_nsec;
}
#ifdef __cplusplus
}
#endif
#endif // ! defined TV_H_8332A958_38EB_4FE7_94E6_22C71BECD013

View File

@@ -287,16 +287,15 @@ vidcap_rtsp_thread(void *arg) {
struct rtsp_state *s;
s = (struct rtsp_state *) arg;
struct timeval start_time;
gettimeofday(&start_time, NULL);
time_ns_t start_time = get_time_in_ns();
struct video_frame *frame = vf_alloc_desc_data(s->vrtsp_state.desc);
while (!s->should_exit) {
auto curr_time_hr = std::chrono::high_resolution_clock::now();
struct timeval curr_time;
gettimeofday(&curr_time, NULL);
uint32_t timestamp = tv_diff(curr_time, start_time) * 90000;
time_ns_t time_ns = get_time_in_ns();
uint32_t timestamp = (time_ns - start_time) / 100'000 * 9; // at 90000 Hz
rtp_update(s->vrtsp_state.device, curr_time);
@@ -313,7 +312,7 @@ vidcap_rtsp_thread(void *arg) {
d.frame = frame;
d.offset_len = s->vrtsp_state.h264_offset_len;
d.video_pt = s->vrtsp_state.pt;
if (pbuf_decode(cp->playout_buffer, curr_time_hr,
if (pbuf_decode(cp->playout_buffer, time_ns,
decode_frame_by_pt, &d))
{
pthread_mutex_lock(&s->vrtsp_state.lock);
@@ -332,7 +331,7 @@ vidcap_rtsp_thread(void *arg) {
pthread_mutex_unlock(&s->vrtsp_state.lock);
}
}
pbuf_remove(cp->playout_buffer, curr_time_hr);
pbuf_remove(cp->playout_buffer, time_ns);
cp = pdb_iter_next(&it);
}

View File

@@ -44,6 +44,7 @@
#include "debug.h"
#include "host.h"
#include "lib_common.h"
#include "tv.h"
#include "video.h"
#include "video_capture.h"
#include "video_display.h"
@@ -111,7 +112,7 @@ static int vidcap_ug_input_init(struct vidcap_params *cap_params, void **state)
int ret = initialize_video_display(vidcap_params_get_parent(cap_params), "pipe", cfg, 0, NULL, &s->display);
assert(ret == 0 && "Unable to initialize proxy display");
auto start_time = std::chrono::steady_clock::now();
time_ns_t start_time = get_time_in_ns();
map<string, param_u> params;
// common
@@ -132,7 +133,7 @@ static int vidcap_ug_input_init(struct vidcap_params *cap_params, void **state)
params["fec"].str = "none";
params["encryption"].str = NULL;
params["bitrate"].ll = 0;
params["start_time"].cptr = (const void *) &start_time;
params["start_time"].ll = start_time;
params["video_delay"].vptr = 0;
// UltraGrid RTP
@@ -158,7 +159,7 @@ static int vidcap_ug_input_init(struct vidcap_params *cap_params, void **state)
.codec_cfg = "PCM"
};
s->audio = audio_cfg_init(vidcap_params_get_parent(cap_params), &opt, nullptr, 0, nullptr, RATE_UNLIMITED,
nullptr, &start_time, 1500, -1, nullptr);
nullptr, start_time, 1500, -1, nullptr);
if (s->audio == nullptr) {
delete s;
return VIDCAP_INIT_FAIL;

View File

@@ -55,6 +55,7 @@
#include "host.h"
#include "lib_common.h"
#include "transmit.h"
#include "tv.h"
#include "rtp/rtp.h"
#include "rtp/rtpenc_h264.h"
#include "video_rxtx.h"
@@ -90,10 +91,9 @@ void h264_rtp_video_rxtx::send_frame(shared_ptr<video_frame> tx_frame)
}
}
if ((m_rxtx_mode & MODE_RECEIVER) == 0) { // send RTCP (receiver thread would otherwise do this
uint32_t ts = (get_time_in_ns() - m_start_time) / 100'000 * 9; // at 90000 Hz
struct timeval curr_time;
uint32_t ts;
gettimeofday(&curr_time, NULL);
ts = std::chrono::duration_cast<std::chrono::duration<double>>(m_start_time - std::chrono::steady_clock::now()).count() * 90000;
rtp_update(m_network_devices[0], curr_time);
rtp_send_ctrl(m_network_devices[0], ts, 0, curr_time);

View File

@@ -209,7 +209,7 @@ struct response *rtp_video_rxtx::process_sender_message(struct msg_sender *msg,
}
rtp_video_rxtx::rtp_video_rxtx(map<string, param_u> const &params) :
video_rxtx(params), m_fec_state(NULL), m_start_time(*(const std::chrono::steady_clock::time_point *) params.at("start_time").cptr), m_video_desc{}
video_rxtx(params), m_fec_state(NULL), m_start_time(params.at("start_time").ll), m_video_desc{}
{
m_participants = pdb_init((volatile int *) params.at("video_delay").vptr);
m_requested_receiver = params.at("receiver").str;

View File

@@ -38,9 +38,9 @@
#ifndef VIDEO_RXTX_RTP_H_
#define VIDEO_RXTX_RTP_H_
#include "tv.h"
#include "video_rxtx.h"
#include <chrono>
#include <mutex>
#include <string>
@@ -80,7 +80,7 @@ protected:
const char *m_requested_mcast_if;
int m_requested_ttl;
fec *m_fec_state;
const std::chrono::steady_clock::time_point m_start_time;
time_ns_t m_start_time;
video_desc m_video_desc;
private:
struct response *process_sender_message(struct msg_sender *i, int *status);

View File

@@ -172,9 +172,8 @@ void ultragrid_rtp_video_rxtx::send_frame_async(shared_ptr<video_frame> tx_frame
if ((m_rxtx_mode & MODE_RECEIVER) == 0) { // otherwise receiver thread does the stuff...
struct timeval curr_time;
uint32_t ts;
gettimeofday(&curr_time, NULL);
ts = std::chrono::duration_cast<std::chrono::duration<double>>(m_start_time - std::chrono::steady_clock::now()).count() * 90000;
uint32_t ts = (get_time_in_ns() - m_start_time) / 100'000 * 9; // at 90000 Hz
rtp_update(m_network_devices[0], curr_time);
rtp_send_ctrl(m_network_devices[0], ts, 0, curr_time);
@@ -296,7 +295,6 @@ struct vcodec_state *ultragrid_rtp_video_rxtx::new_video_decoder(struct display
void *ultragrid_rtp_video_rxtx::receiver_loop()
{
set_thread_name(__func__);
uint32_t ts;
struct pdb_e *cp;
struct timeval curr_time;
int fr;
@@ -316,15 +314,14 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
fr = 1;
auto last_not_timeout = std::chrono::steady_clock::time_point::min();
time_ns_t last_not_timeout = 0;
while (!should_exit) {
struct timeval timeout;
/* Housekeeping and RTCP... */
gettimeofday(&curr_time, NULL);
auto curr_time_st = std::chrono::steady_clock::now();
auto curr_time_hr = std::chrono::high_resolution_clock::now();
ts = std::chrono::duration_cast<std::chrono::duration<double>>(m_start_time - curr_time_st).count() * 90000;
time_ns_t time_ns = get_time_in_ns();
uint32_t ts = (m_start_time - time_ns) / 100'000 * 9; // at 90000 Hz
rtp_update(m_network_devices[0], curr_time);
rtp_send_ctrl(m_network_devices[0], ts, 0, curr_time);
@@ -340,7 +337,7 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
timeout.tv_sec = 0;
//timeout.tv_usec = 999999 / 59.94;
// use longer timeout when we are not receivng any data
if (std::chrono::duration_cast<std::chrono::duration<double>>(last_not_timeout - curr_time_st).count() > 1.0) {
if ((last_not_timeout - time_ns) > NS_IN_SEC) {
timeout.tv_usec = 100000;
} else {
timeout.tv_usec = 1000;
@@ -353,7 +350,7 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
receiver_process_messages();
//printf("Failed to receive data\n");
} else {
last_not_timeout = curr_time_st;
last_not_timeout = time_ns;
}
/* Decode and render for each participant in the conference... */
@@ -407,7 +404,7 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
/* Decode and render video... */
if (pbuf_decode
(cp->playout_buffer, curr_time_hr, decode_video_frame, vdecoder_state)) {
(cp->playout_buffer, time_ns, decode_video_frame, vdecoder_state)) {
tiles_post++;
/* we have data from all connections we need */
if(tiles_post == m_connections_count)
@@ -456,7 +453,7 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
}
}
pbuf_remove(cp->playout_buffer, curr_time_hr);
pbuf_remove(cp->playout_buffer, time_ns);
cp = pdb_iter_next(&it);
}
pdb_iter_done(&it);