mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-04-07 20:06:01 +00:00
RTP: work also with time in NS
This commit is contained in:
@@ -662,10 +662,8 @@ 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);
|
||||
time_ns_t curr_time = get_time_in_ns();
|
||||
uint32_t ts = (curr_time - s->start_time) / 100'000 * 9; // at 90000 Hz
|
||||
rtp_update(s->audio_network_device, curr_time);
|
||||
rtp_send_ctrl(s->audio_network_device, ts, 0, curr_time);
|
||||
struct timeval timeout;
|
||||
@@ -713,14 +711,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, time_ns, s->receiver == NET_NATIVE ? decode_audio_frame : decode_audio_frame_mulaw, &dec_state->pbuf_data)) {
|
||||
while (pbuf_decode(cp->playout_buffer, curr_time, 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, time_ns);
|
||||
pbuf_remove(cp->playout_buffer, curr_time);
|
||||
cp = pdb_iter_next(&it);
|
||||
|
||||
if (decoded && !playback_supports_multiple_streams)
|
||||
@@ -1002,9 +1000,8 @@ 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;
|
||||
gettimeofday(&curr_time, NULL);
|
||||
time_ns_t curr_time = get_time_in_ns();
|
||||
uint32_t ts = (curr_time - s->start_time) / 10'0000 * 9; // at 90000 Hz
|
||||
rtp_update(s->audio_network_device, curr_time);
|
||||
rtp_send_ctrl(s->audio_network_device, ts, 0, curr_time);
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ static struct pdb_e *pdb_create_item(uint32_t ssrc, volatile int *delay_ms)
|
||||
{
|
||||
struct pdb_e *p = malloc(sizeof(struct pdb_e));
|
||||
if (p != NULL) {
|
||||
gettimeofday(&(p->creation_time), NULL);
|
||||
p->creation_time = get_time_in_ns();
|
||||
p->ssrc = ssrc;
|
||||
p->sdes_cname = NULL;
|
||||
p->sdes_name = NULL;
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tv.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -81,7 +83,7 @@ struct pdb_e {
|
||||
uint8_t pt; /* Last seen RTP payload type for this participant */
|
||||
struct pbuf *playout_buffer;
|
||||
struct tfrc *tfrc_state;
|
||||
struct timeval creation_time; /* Time this entry was created */
|
||||
time_ns_t creation_time; /* Time this entry was created */
|
||||
};
|
||||
|
||||
struct pdb; /* The participant database */
|
||||
|
||||
131
src/rtp/rtp.c
131
src/rtp/rtp.c
@@ -192,7 +192,7 @@ typedef struct _rtcp_rr_wrapper {
|
||||
uint32_t reporter_ssrc;
|
||||
rtcp_rr *rr;
|
||||
rtcp_rx *rx;
|
||||
struct timeval ts; /* Arrival time of this RR */
|
||||
time_ns_t ts; /* Arrival time of this RR */
|
||||
} rtcp_rr_wrapper;
|
||||
|
||||
/*
|
||||
@@ -215,7 +215,7 @@ typedef struct _source {
|
||||
rtcp_sr *sr;
|
||||
uint32_t last_sr_sec;
|
||||
uint32_t last_sr_frac;
|
||||
struct timeval last_active;
|
||||
time_ns_t last_active;
|
||||
int should_advertise_sdes; /* TRUE if this source is a CSRC which we need to advertise SDES for */
|
||||
int sender;
|
||||
int got_bye; /* TRUE if we've received an RTCP bye from this source */
|
||||
@@ -292,10 +292,10 @@ struct rtp {
|
||||
double avg_rtcp_size;
|
||||
int we_sent;
|
||||
double rtcp_bw; /* RTCP bandwidth fraction, in octets per second. */
|
||||
struct timeval last_update;
|
||||
struct timeval last_rtp_send_time;
|
||||
struct timeval last_rtcp_send_time;
|
||||
struct timeval next_rtcp_send_time;
|
||||
time_ns_t last_update;
|
||||
time_ns_t last_rtp_send_time;
|
||||
time_ns_t last_rtcp_send_time;
|
||||
time_ns_t next_rtcp_send_time;
|
||||
double rtcp_interval;
|
||||
int sdes_count_pri;
|
||||
int sdes_count_sec;
|
||||
@@ -407,7 +407,7 @@ static void insert_rr(struct rtp *session, uint32_t reporter_ssrc, rtcp_rr * rr,
|
||||
free(cur->rx);
|
||||
cur->rr = rr;
|
||||
cur->rx = rx;
|
||||
gettimeofday(&cur->ts, NULL);
|
||||
cur->ts = get_time_in_ns();
|
||||
return;
|
||||
}
|
||||
cur = cur->next;
|
||||
@@ -418,7 +418,7 @@ static void insert_rr(struct rtp *session, uint32_t reporter_ssrc, rtcp_rr * rr,
|
||||
cur->reporter_ssrc = reporter_ssrc;
|
||||
cur->rr = rr;
|
||||
cur->rx = rx;
|
||||
gettimeofday(&cur->ts, NULL);
|
||||
cur->ts = get_time_in_ns();
|
||||
/* Fix links */
|
||||
cur->next = start->next;
|
||||
cur->next->prev = cur;
|
||||
@@ -472,7 +472,7 @@ static void remove_rr(struct rtp *session, uint32_t ssrc)
|
||||
}
|
||||
}
|
||||
|
||||
static void timeout_rr(struct rtp *session, struct timeval *curr_ts)
|
||||
static void timeout_rr(struct rtp *session, time_ns_t curr_ts)
|
||||
{
|
||||
/* Timeout any reception reports which have been in the database for more than 3 */
|
||||
/* times the RTCP reporting interval without refresh. */
|
||||
@@ -485,8 +485,8 @@ static void timeout_rr(struct rtp *session, struct timeval *curr_ts)
|
||||
start = &session->rr[i][j];
|
||||
cur = start->next;
|
||||
while (cur != start) {
|
||||
if (tv_diff(*curr_ts, cur->ts) >
|
||||
(session->rtcp_interval * 3)) {
|
||||
if (curr_ts - cur->ts >
|
||||
session->rtcp_interval * 3 * NS_IN_SEC) {
|
||||
/* Signal the application... */
|
||||
if (!filter_event
|
||||
(session, cur->reporter_ssrc)) {
|
||||
@@ -633,7 +633,7 @@ static source *really_create_source(struct rtp *session, uint32_t ssrc,
|
||||
s->probation = 0;
|
||||
}
|
||||
|
||||
gettimeofday(&(s->last_active), NULL);
|
||||
s->last_active = get_time_in_ns();
|
||||
/* Now, add it to the database... */
|
||||
if (session->db[h] != NULL) {
|
||||
session->db[h]->prev = s;
|
||||
@@ -667,7 +667,7 @@ static inline source *create_source(struct rtp *session, uint32_t ssrc,
|
||||
}
|
||||
/* Source is already in the database... Mark it as */
|
||||
/* active and exit (this is the common case...) */
|
||||
gettimeofday(&(s->last_active), NULL);
|
||||
s->last_active = get_time_in_ns();
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -677,12 +677,10 @@ static void delete_source(struct rtp *session, uint32_t ssrc)
|
||||
source *s = get_source(session, ssrc);
|
||||
int h = ssrc_hash(ssrc);
|
||||
rtp_event event;
|
||||
struct timeval event_ts;
|
||||
time_ns_t event_ts = get_time_in_ns();
|
||||
|
||||
assert(s != NULL); /* Deleting a source which doesn't exist is an error... */
|
||||
|
||||
gettimeofday(&event_ts, NULL);
|
||||
|
||||
check_source(s);
|
||||
check_database(session);
|
||||
if (session->db[h] == s) {
|
||||
@@ -735,14 +733,14 @@ static void delete_source(struct rtp *session, uint32_t ssrc)
|
||||
/* o The value of pmembers is set equal to members. */
|
||||
session->ssrc_count--;
|
||||
if (session->ssrc_count < session->ssrc_count_prev) {
|
||||
gettimeofday(&(session->next_rtcp_send_time), NULL);
|
||||
gettimeofday(&(session->last_rtcp_send_time), NULL);
|
||||
tv_add(&(session->next_rtcp_send_time),
|
||||
session->next_rtcp_send_time =
|
||||
session->last_rtcp_send_time = get_time_in_ns();
|
||||
session->next_rtcp_send_time +=
|
||||
(session->ssrc_count / session->ssrc_count_prev)
|
||||
* tv_diff(session->next_rtcp_send_time, event_ts));
|
||||
tv_add(&(session->last_rtcp_send_time),
|
||||
-((session->ssrc_count / session->ssrc_count_prev)
|
||||
* tv_diff(event_ts, session->last_rtcp_send_time)));
|
||||
* (session->next_rtcp_send_time - event_ts) * NS_IN_SEC;
|
||||
session->last_rtcp_send_time -=
|
||||
((session->ssrc_count / session->ssrc_count_prev)
|
||||
* (event_ts - session->last_rtcp_send_time)) * NS_IN_SEC;
|
||||
session->ssrc_count_prev = session->ssrc_count;
|
||||
}
|
||||
|
||||
@@ -1170,14 +1168,14 @@ struct rtp *rtp_init_if(const char *addr, const char *iface,
|
||||
session->tfrc_on = tfrc_on;
|
||||
session->rtp_bcount = 0;
|
||||
session->rtp_bytes_sent = 0;
|
||||
gettimeofday(&(session->last_update), NULL);
|
||||
gettimeofday(&(session->last_rtcp_send_time), NULL);
|
||||
gettimeofday(&(session->next_rtcp_send_time), NULL);
|
||||
session->last_update =
|
||||
session->last_rtcp_send_time =
|
||||
session->next_rtcp_send_time = get_time_in_ns();
|
||||
session->encryption_enabled = 0;
|
||||
session->encryption_algorithm = NULL;
|
||||
|
||||
/* Calculate when we're supposed to send our first RTCP packet... */
|
||||
tv_add(&(session->next_rtcp_send_time), rtcp_interval(session));
|
||||
session->next_rtcp_send_time += rtcp_interval(session) * NS_IN_SEC;
|
||||
|
||||
/* Initialise the source database... */
|
||||
for (i = 0; i < RTP_DB_SIZE; i++) {
|
||||
@@ -1263,14 +1261,14 @@ rtp_t rtp_init_with_udp_socket(struct socket_udp_local *l, struct sockaddr *sa,
|
||||
session->tfrc_on = tfrc_on;
|
||||
session->rtp_bcount = 0;
|
||||
session->rtp_bytes_sent = 0;
|
||||
gettimeofday(&(session->last_update), NULL);
|
||||
gettimeofday(&(session->last_rtcp_send_time), NULL);
|
||||
gettimeofday(&(session->next_rtcp_send_time), NULL);
|
||||
session->last_update =
|
||||
session->last_rtcp_send_time =
|
||||
session->next_rtcp_send_time = get_time_in_ns();
|
||||
session->encryption_enabled = 0;
|
||||
session->encryption_algorithm = NULL;
|
||||
|
||||
/* Calculate when we're supposed to send our first RTCP packet... */
|
||||
tv_add(&(session->next_rtcp_send_time), rtcp_interval(session));
|
||||
session->next_rtcp_send_time += NS_IN_SEC * rtcp_interval(session);
|
||||
|
||||
/* Initialise the source database... */
|
||||
for (i = 0; i < RTP_DB_SIZE; i++) {
|
||||
@@ -2967,7 +2965,7 @@ rtp_send_data_hdr(struct rtp *session,
|
||||
session->rtp_pcount += 1;
|
||||
session->rtp_bcount += buffer_len;
|
||||
session->rtp_bytes_sent += buffer_len + data_len;
|
||||
gettimeofday(&session->last_rtp_send_time, NULL);
|
||||
session->last_rtp_send_time = get_time_in_ns();
|
||||
|
||||
check_database(session);
|
||||
return rc;
|
||||
@@ -3445,31 +3443,25 @@ static void send_rtcp(struct rtp *session, uint32_t rtp_ts,
|
||||
* frequently.
|
||||
*/
|
||||
void rtp_send_ctrl(struct rtp *session, uint32_t rtp_ts,
|
||||
rtcp_app_callback appcallback, struct timeval curr_time)
|
||||
rtcp_app_callback appcallback, time_ns_t curr_time)
|
||||
{
|
||||
/* Send an RTCP packet, if one is due... */
|
||||
|
||||
check_database(session);
|
||||
if (tv_gt(curr_time, session->next_rtcp_send_time)) {
|
||||
if (curr_time > session->next_rtcp_send_time) {
|
||||
/* The RTCP transmission timer has expired. The following */
|
||||
/* implements draft-ietf-avt-rtp-new-02.txt section 6.3.6 */
|
||||
int h;
|
||||
source *s;
|
||||
struct timeval new_send_time;
|
||||
double new_interval;
|
||||
|
||||
new_interval =
|
||||
double new_interval =
|
||||
rtcp_interval(session) / (session->csrc_count + 1);
|
||||
new_send_time = session->last_rtcp_send_time;
|
||||
tv_add(&new_send_time, new_interval);
|
||||
if (tv_gt(curr_time, new_send_time)) {
|
||||
time_ns_t new_send_time = session->last_rtcp_send_time + new_interval * NS_IN_SEC;
|
||||
if (curr_time > new_send_time) {
|
||||
send_rtcp(session, rtp_ts, appcallback);
|
||||
session->initial_rtcp = FALSE;
|
||||
session->last_rtcp_send_time = curr_time;
|
||||
session->next_rtcp_send_time = curr_time;
|
||||
tv_add(&(session->next_rtcp_send_time),
|
||||
rtcp_interval(session) / (session->csrc_count +
|
||||
1));
|
||||
session->next_rtcp_send_time = curr_time + (rtcp_interval(session) / (session->csrc_count +
|
||||
1)) * NS_IN_SEC;
|
||||
/* We're starting a new RTCP reporting interval, zero out */
|
||||
/* the per-interval statistics. */
|
||||
session->sender_count = 0;
|
||||
@@ -3497,22 +3489,21 @@ void rtp_send_ctrl(struct rtp *session, uint32_t rtp_ts,
|
||||
* through the data structures to once per second, it can be safely
|
||||
* called more frequently.
|
||||
*/
|
||||
void rtp_update(struct rtp *session, struct timeval curr_time)
|
||||
void rtp_update(struct rtp *session, time_ns_t curr_time)
|
||||
{
|
||||
/* Perform housekeeping on the source database... */
|
||||
int h;
|
||||
source *s, *n;
|
||||
double delay;
|
||||
|
||||
if (tv_diff(curr_time, session->last_update) < 1.0) {
|
||||
if (curr_time - session->last_update < 1 * NS_IN_SEC) {
|
||||
/* We only perform housekeeping once per second... */
|
||||
return;
|
||||
}
|
||||
session->last_update = curr_time;
|
||||
|
||||
/* Update we_sent (section 6.3.8 of RTP spec) */
|
||||
delay = tv_diff(curr_time, session->last_rtp_send_time);
|
||||
if (delay >= 2 * rtcp_interval(session)) {
|
||||
time_ns_t delay = curr_time - session->last_rtp_send_time;
|
||||
if (delay >= 2 * NS_IN_SEC * rtcp_interval(session)) {
|
||||
session->we_sent = FALSE;
|
||||
}
|
||||
|
||||
@@ -3526,24 +3517,24 @@ void rtp_update(struct rtp *session, struct timeval curr_time)
|
||||
/* Section 6.2.1 of the RTP specification details the timers used. */
|
||||
|
||||
/* How int since we last heard from this source? */
|
||||
delay = tv_diff(curr_time, s->last_active);
|
||||
delay = curr_time - s->last_active;
|
||||
|
||||
/* Check if we've received a BYE packet from this source. */
|
||||
/* If we have, and it was received more than 2 seconds ago */
|
||||
/* then the source is deleted. The arbitrary 2 second delay */
|
||||
/* is to ensure that all delayed packets are received before */
|
||||
/* the source is timed out. */
|
||||
if (s->got_bye && (delay > 2.0)) {
|
||||
if (s->got_bye && (delay > 2 * NS_IN_SEC)) {
|
||||
debug_msg
|
||||
("Deleting source 0x%08" PRIx32 " due to reception of BYE %f seconds ago...\n",
|
||||
s->ssrc, delay);
|
||||
s->ssrc, (double) delay / NS_IN_SEC);
|
||||
delete_source(session, s->ssrc);
|
||||
}
|
||||
|
||||
/* Sources are marked as inactive if they haven't been heard */
|
||||
/* from for more than 2 intervals (RTP section 6.3.5) */
|
||||
if ((s->ssrc != rtp_my_ssrc(session))
|
||||
&& (delay > (session->rtcp_interval * 2))) {
|
||||
&& (delay > (session->rtcp_interval * 2 * NS_IN_SEC))) {
|
||||
if (s->sender) {
|
||||
s->sender = FALSE;
|
||||
session->sender_count--;
|
||||
@@ -3553,7 +3544,7 @@ void rtp_update(struct rtp *session, struct timeval curr_time)
|
||||
/* If a source hasn't been heard from for more than 5 RTCP */
|
||||
/* reporting intervals, we delete it from our database... */
|
||||
if ((s->ssrc != rtp_my_ssrc(session))
|
||||
&& (delay > (session->rtcp_interval * 5))) {
|
||||
&& (delay > (session->rtcp_interval * 5 * NS_IN_SEC))) {
|
||||
debug_msg
|
||||
("Deleting source 0x%08" PRIx32 " due to timeout...\n",
|
||||
s->ssrc);
|
||||
@@ -3563,7 +3554,7 @@ void rtp_update(struct rtp *session, struct timeval curr_time)
|
||||
}
|
||||
|
||||
/* Timeout those reception reports which haven't been refreshed for a int time */
|
||||
timeout_rr(session, &curr_time);
|
||||
timeout_rr(session, curr_time);
|
||||
check_database(session);
|
||||
}
|
||||
|
||||
@@ -3642,7 +3633,6 @@ static void rtp_send_bye_now(struct rtp *session)
|
||||
*/
|
||||
void rtp_send_bye(struct rtp *session)
|
||||
{
|
||||
struct timeval curr_time, timeout, new_send_time;
|
||||
uint8_t buffer[RTP_MAX_PACKET_LEN];
|
||||
int buflen;
|
||||
double new_interval;
|
||||
@@ -3661,28 +3651,25 @@ void rtp_send_bye(struct rtp *session)
|
||||
if (session->ssrc_count < 50) {
|
||||
rtp_send_bye_now(session);
|
||||
} else {
|
||||
gettimeofday(&curr_time, NULL);
|
||||
time_ns_t curr_time = get_time_in_ns();
|
||||
session->sending_bye = TRUE;
|
||||
session->last_rtcp_send_time = curr_time;
|
||||
session->next_rtcp_send_time = curr_time;
|
||||
session->last_rtcp_send_time =
|
||||
session->next_rtcp_send_time = curr_time;
|
||||
session->bye_count = 1;
|
||||
session->initial_rtcp = TRUE;
|
||||
session->we_sent = FALSE;
|
||||
session->sender_count = 0;
|
||||
session->avg_rtcp_size = 70.0 + RTP_LOWER_LAYER_OVERHEAD; /* FIXME */
|
||||
tv_add(&session->next_rtcp_send_time,
|
||||
rtcp_interval(session) / (session->csrc_count + 1));
|
||||
session->next_rtcp_send_time += (rtcp_interval(session) / (session->csrc_count + 1)) * NS_IN_SEC;
|
||||
|
||||
debug_msg("Preparing to send BYE...\n");
|
||||
while (1) {
|
||||
/* Schedule us to block in udp_select() until the time we are due to send our */
|
||||
/* BYE packet. If we receive an RTCP packet from another participant before */
|
||||
/* then, we are woken up to handle it... */
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
tv_add(&timeout,
|
||||
tv_diff(session->next_rtcp_send_time,
|
||||
curr_time));
|
||||
long long ms = (session->next_rtcp_send_time - curr_time) / NS_IN_MS;
|
||||
lldiv_t d = lldiv(ms, MS_IN_SEC);
|
||||
struct timeval timeout = { .tv_sec = d.quot, .tv_usec = d.rem };
|
||||
udp_fd_zero();
|
||||
udp_fd_set(session->rtcp_socket);
|
||||
if ((udp_select(&timeout) > 0)
|
||||
@@ -3695,12 +3682,11 @@ void rtp_send_bye(struct rtp *session)
|
||||
rtp_process_ctrl(session, buffer, buflen);
|
||||
}
|
||||
/* Is it time to send our BYE? */
|
||||
gettimeofday(&curr_time, NULL);
|
||||
time_ns_t curr_time = get_time_in_ns();
|
||||
new_interval =
|
||||
rtcp_interval(session) / (session->csrc_count + 1);
|
||||
new_send_time = session->last_rtcp_send_time;
|
||||
tv_add(&new_send_time, new_interval);
|
||||
if (tv_gt(curr_time, new_send_time)) {
|
||||
time_ns_t new_send_time = session->last_rtcp_send_time + new_interval * NS_IN_SEC;
|
||||
if (curr_time > new_send_time) {
|
||||
debug_msg("Sent BYE...\n");
|
||||
rtp_send_bye_now(session);
|
||||
break;
|
||||
@@ -3708,8 +3694,7 @@ void rtp_send_bye(struct rtp *session)
|
||||
/* No, we reconsider... */
|
||||
session->next_rtcp_send_time = new_send_time;
|
||||
debug_msg("Reconsidered sending BYE... delay = %f\n",
|
||||
tv_diff(session->next_rtcp_send_time,
|
||||
curr_time));
|
||||
(session->next_rtcp_send_time - curr_time) / (double) NS_IN_SEC);
|
||||
/* ...and perform housekeeping in the usual manner */
|
||||
rtp_update(session, curr_time);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "tv.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -268,8 +270,8 @@ int rtp_send_data_hdr(struct rtp *session,
|
||||
char *data, int data_len,
|
||||
char *extn, uint16_t extn_len, uint16_t extn_type);
|
||||
void rtp_send_ctrl(struct rtp *session, uint32_t rtp_ts,
|
||||
rtcp_app_callback appcallback, struct timeval curr_time);
|
||||
void rtp_update(struct rtp *session, struct timeval curr_time);
|
||||
rtcp_app_callback appcallback, time_ns_t curr_time);
|
||||
void rtp_update(struct rtp *session, time_ns_t curr_time);
|
||||
|
||||
uint32_t rtp_my_ssrc(struct rtp *session);
|
||||
bool rtp_add_csrc(struct rtp *session, uint32_t csrc);
|
||||
|
||||
@@ -204,12 +204,10 @@ void rtp_recv_callback(struct rtp *session, rtp_event * e)
|
||||
rtp_packet *pckt_rtp = (rtp_packet *) e->data;
|
||||
struct pdb *participants = (struct pdb *)rtp_get_userdata(session);
|
||||
struct pdb_e *state = pdb_get(participants, e->ssrc);
|
||||
struct timeval curr_time;
|
||||
|
||||
switch (e->type) {
|
||||
case RX_RTP:
|
||||
gettimeofday(&curr_time, NULL);
|
||||
tfrc_recv_data(state->tfrc_state, curr_time, pckt_rtp->seq,
|
||||
tfrc_recv_data(state->tfrc_state, get_time_in_ns(), pckt_rtp->seq,
|
||||
pckt_rtp->data_len + 40);
|
||||
if (pckt_rtp->data_len > 0) { /* Only process packets that contain data... */
|
||||
pbuf_insert(state->playout_buffer, pckt_rtp);
|
||||
@@ -237,8 +235,7 @@ void rtp_recv_callback(struct rtp *session, rtp_event * e)
|
||||
if (strncmp(pckt_app->name, "RTT_", 4) == 0) {
|
||||
assert(pckt_app->length == 3);
|
||||
assert(pckt_app->subtype == 0);
|
||||
gettimeofday(&curr_time, NULL);
|
||||
// tfrc_recv_rtt(state->tfrc_state, curr_time, ntohl(*((int *) pckt_app->data)));
|
||||
// tfrc_recv_rtt(state->tfrc_state, get_time_in_ns(), ntohl(*((int *) pckt_app->data)));
|
||||
}
|
||||
break;
|
||||
case RX_BYE:
|
||||
|
||||
37
src/tfrc.c
37
src/tfrc.c
@@ -71,10 +71,10 @@ struct tfrc {
|
||||
int ooo;
|
||||
int cycles; /* number of times seq number cycles 65535 */
|
||||
uint32_t RTT; /* received from sender in app packet */
|
||||
struct timeval feedback_timer; /* indicates points in time when p should be computed */
|
||||
time_ns_t feedback_timer; /* indicates points in time when p should be computed */
|
||||
double p, p_prev;
|
||||
int s;
|
||||
struct timeval start_time;
|
||||
time_ns_t start_time;
|
||||
int loss_count;
|
||||
int interval_count;
|
||||
int gap[20];
|
||||
@@ -130,10 +130,10 @@ static double transfer_rate(double p)
|
||||
static void compute_transfer_rate(void)
|
||||
{
|
||||
double t1;
|
||||
struct timeval now;
|
||||
time_ns_t now;
|
||||
|
||||
t1 = transfer_rate(p);
|
||||
gettimeofday(&now, NULL);
|
||||
now = get_time_in_ns()
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -245,7 +245,7 @@ record_loss(struct tfrc *state, uint32_t s1, uint32_t s2, uint32_t ts1,
|
||||
}
|
||||
|
||||
static void
|
||||
save_arrival(struct tfrc *state, struct timeval curr_time, uint16_t seq)
|
||||
save_arrival(struct tfrc *state, time_ns_t curr_time, uint16_t seq)
|
||||
{
|
||||
int kk, inc, last_jj;
|
||||
uint16_t udelta;
|
||||
@@ -255,8 +255,8 @@ save_arrival(struct tfrc *state, struct timeval curr_time, uint16_t seq)
|
||||
static uint32_t ext_last_ack;
|
||||
static int last_ack_jj = 0;
|
||||
|
||||
gettimeofday(&curr_time, NULL);
|
||||
now = tv_diff_usec(curr_time, state->start_time);
|
||||
curr_time = get_time_in_ns();
|
||||
now = (curr_time - state->start_time) / 1000;
|
||||
|
||||
if (state->jj == -1) {
|
||||
/* first packet arrival */
|
||||
@@ -330,7 +330,6 @@ static double compute_loss_event(struct tfrc *state)
|
||||
int i;
|
||||
uint32_t t __attribute__((unused));
|
||||
uint32_t temp, I_tot0 = 0, I_tot1 = 0, I_tot = 0;
|
||||
struct timeval now;
|
||||
double I_mean, p;
|
||||
|
||||
if (state->ii < N) {
|
||||
@@ -352,8 +351,7 @@ static double compute_loss_event(struct tfrc *state)
|
||||
I_mean = I_tot / state->W_tot;
|
||||
p = 1 / I_mean;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
t = tv_diff_usec(now, state->start_time);
|
||||
t = (get_time_in_ns() - state->start_time) / 1000;
|
||||
|
||||
return p;
|
||||
|
||||
@@ -364,7 +362,7 @@ static double compute_loss_event(struct tfrc *state)
|
||||
*
|
||||
*/
|
||||
|
||||
struct tfrc *tfrc_init(struct timeval curr_time)
|
||||
struct tfrc *tfrc_init(time_ns_t curr_time)
|
||||
{
|
||||
struct tfrc *state;
|
||||
int i;
|
||||
@@ -435,7 +433,7 @@ void tfrc_done(struct tfrc *state)
|
||||
}
|
||||
|
||||
void
|
||||
tfrc_recv_data(struct tfrc *state, struct timeval curr_time, uint16_t seqnum,
|
||||
tfrc_recv_data(struct tfrc *state, time_ns_t curr_time, uint16_t seqnum,
|
||||
unsigned length)
|
||||
{
|
||||
/* This is called each time an RTP packet is received. Accordingly, */
|
||||
@@ -459,7 +457,7 @@ tfrc_recv_data(struct tfrc *state, struct timeval curr_time, uint16_t seqnum,
|
||||
state->s = length; /* packet size is needed transfer_rate */
|
||||
}
|
||||
|
||||
void tfrc_recv_rtt(struct tfrc *state, struct timeval curr_time, uint32_t rtt)
|
||||
void tfrc_recv_rtt(struct tfrc *state, time_ns_t curr_time, uint32_t rtt)
|
||||
{
|
||||
/* Called whenever the receiver gets an RTCP APP packet telling */
|
||||
/* it the RTT to the sender. Not performance critical. */
|
||||
@@ -468,25 +466,24 @@ void tfrc_recv_rtt(struct tfrc *state, struct timeval curr_time, uint32_t rtt)
|
||||
validate_tfrc_state(state);
|
||||
|
||||
if (state->RTT == 0) {
|
||||
state->feedback_timer = curr_time;
|
||||
tv_add(&(state->feedback_timer), rtt);
|
||||
state->feedback_timer = curr_time + rtt * NS_IN_SEC;
|
||||
}
|
||||
state->RTT = rtt;
|
||||
}
|
||||
|
||||
int tfrc_feedback_is_due(struct tfrc *state, struct timeval curr_time)
|
||||
int tfrc_feedback_is_due(struct tfrc *state, time_ns_t curr_time)
|
||||
{
|
||||
/* Determine if it is time to send feedback to the sender */
|
||||
validate_tfrc_state(state);
|
||||
|
||||
if ((state->RTT == 0) || tv_gt(state->feedback_timer, curr_time)) {
|
||||
if ((state->RTT == 0) || state->feedback_timer > curr_time) {
|
||||
/* Not yet time to send feedback to the sender... */
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
double tfrc_feedback_txrate(struct tfrc *state, struct timeval curr_time)
|
||||
double tfrc_feedback_txrate(struct tfrc *state, time_ns_t curr_time)
|
||||
{
|
||||
/* Calculate the appropriate transmission rate, to be included */
|
||||
/* in a feedback message to the sender. */
|
||||
@@ -495,9 +492,7 @@ double tfrc_feedback_txrate(struct tfrc *state, struct timeval curr_time)
|
||||
|
||||
assert(tfrc_feedback_is_due(state, curr_time));
|
||||
|
||||
state->feedback_timer.tv_sec = curr_time.tv_sec;
|
||||
state->feedback_timer.tv_usec = curr_time.tv_usec;
|
||||
tv_add(&(state->feedback_timer), state->RTT);
|
||||
state->feedback_timer = curr_time + state->RTT * NS_IN_SEC;
|
||||
state->p = compute_loss_event(state);
|
||||
//compute_transfer_rate ();
|
||||
if (state->ii >= N) {
|
||||
|
||||
12
src/tfrc.h
12
src/tfrc.h
@@ -47,15 +47,17 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "tv.h"
|
||||
|
||||
struct tfrc;
|
||||
|
||||
struct tfrc *tfrc_init(struct timeval curr_time);
|
||||
struct tfrc *tfrc_init(time_ns_t curr_time);
|
||||
void tfrc_done(struct tfrc *state);
|
||||
|
||||
void tfrc_recv_data (struct tfrc *state, struct timeval curr_time, uint16_t seqnum, unsigned length);
|
||||
void tfrc_recv_rtt (struct tfrc *state, struct timeval curr_time, uint32_t rtt);
|
||||
double tfrc_feedback_txrate(struct tfrc *state, struct timeval curr_time);
|
||||
int tfrc_feedback_is_due(struct tfrc *state, struct timeval curr_time);
|
||||
void tfrc_recv_data (struct tfrc *state, time_ns_t curr_time, uint16_t seqnum, unsigned length);
|
||||
void tfrc_recv_rtt (struct tfrc *state, time_ns_t curr_time, uint32_t rtt);
|
||||
double tfrc_feedback_txrate(struct tfrc *state, time_ns_t curr_time);
|
||||
int tfrc_feedback_is_due(struct tfrc *state, time_ns_t curr_time);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -894,7 +894,6 @@ void audio_tx_send_standard(struct tx* tx, struct rtp *rtp_session,
|
||||
int pt;
|
||||
uint32_t ts;
|
||||
static uint32_t ts_prev = 0;
|
||||
struct timeval curr_time;
|
||||
|
||||
// Configure the right Payload type,
|
||||
// 8000 Hz, 1 channel and 2 bps is the ITU-T G.711 standard (should be 1 bps...)
|
||||
@@ -952,8 +951,7 @@ void audio_tx_send_standard(struct tx* tx, struct rtp *rtp_session,
|
||||
} else {
|
||||
ts = get_std_audio_local_mediatime((double) pkt_len / (double) buffer->get_channel_count() / (double) buffer->get_sample_rate(), buffer->get_sample_rate());
|
||||
}
|
||||
gettimeofday(&curr_time, NULL);
|
||||
rtp_send_ctrl(rtp_session, ts_prev, 0, curr_time); //send RTCP SR
|
||||
rtp_send_ctrl(rtp_session, ts_prev, 0, get_time_in_ns()); //send RTCP SR
|
||||
ts_prev = ts;
|
||||
// Send the packet
|
||||
rtp_send_data(rtp_session, ts, pt, 0, 0, /* contributing sources */
|
||||
|
||||
2
src/tv.c
2
src/tv.c
@@ -51,8 +51,6 @@
|
||||
#include "crypto/random.h"
|
||||
#include "tv.h"
|
||||
|
||||
#define MS_IN_SEC 1000000LL
|
||||
|
||||
uint32_t get_local_mediatime(void)
|
||||
{
|
||||
static struct timeval start_time;
|
||||
|
||||
2
src/tv.h
2
src/tv.h
@@ -68,7 +68,9 @@ 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 MS_IN_SEC 1000000LL
|
||||
#define NS_IN_SEC 1000000000LL
|
||||
#define NS_IN_MS (NS_IN_SEC/MS_IN_SEC)
|
||||
static inline time_ns_t get_time_in_ns() {
|
||||
struct timespec ts = { 0, 0 };
|
||||
timespec_get(&ts, TIME_UTC);
|
||||
|
||||
@@ -292,10 +292,8 @@ vidcap_rtsp_thread(void *arg) {
|
||||
struct video_frame *frame = vf_alloc_desc_data(s->vrtsp_state.desc);
|
||||
|
||||
while (!s->should_exit) {
|
||||
struct timeval curr_time;
|
||||
gettimeofday(&curr_time, NULL);
|
||||
time_ns_t time_ns = get_time_in_ns();
|
||||
uint32_t timestamp = (time_ns - start_time) / 100'000 * 9; // at 90000 Hz
|
||||
time_ns_t curr_time = get_time_in_ns();
|
||||
uint32_t timestamp = (curr_time - start_time) / 100'000 * 9; // at 90000 Hz
|
||||
|
||||
rtp_update(s->vrtsp_state.device, curr_time);
|
||||
|
||||
@@ -312,7 +310,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, time_ns,
|
||||
if (pbuf_decode(cp->playout_buffer, curr_time,
|
||||
decode_frame_by_pt, &d))
|
||||
{
|
||||
pthread_mutex_lock(&s->vrtsp_state.lock);
|
||||
@@ -331,7 +329,7 @@ vidcap_rtsp_thread(void *arg) {
|
||||
pthread_mutex_unlock(&s->vrtsp_state.lock);
|
||||
}
|
||||
}
|
||||
pbuf_remove(cp->playout_buffer, time_ns);
|
||||
pbuf_remove(cp->playout_buffer, curr_time);
|
||||
cp = pdb_iter_next(&it);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,9 +91,8 @@ 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;
|
||||
gettimeofday(&curr_time, NULL);
|
||||
time_ns_t curr_time = get_time_in_ns();
|
||||
uint32_t ts = (curr_time - 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);
|
||||
|
||||
|
||||
@@ -218,9 +218,8 @@ void h264_sdp_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
|
||||
struct timeval curr_time;
|
||||
uint32_t ts = get_std_video_local_mediatime();
|
||||
gettimeofday(&curr_time, NULL);
|
||||
time_ns_t curr_time = get_time_in_ns();
|
||||
rtp_update(m_network_devices[0], curr_time);
|
||||
rtp_send_ctrl(m_network_devices[0], ts, 0, curr_time);
|
||||
|
||||
|
||||
@@ -171,9 +171,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;
|
||||
gettimeofday(&curr_time, NULL);
|
||||
uint32_t ts = (get_time_in_ns() - m_start_time) / 100'000 * 9; // at 90000 Hz
|
||||
time_ns_t curr_time = get_time_in_ns();
|
||||
uint32_t ts = (curr_time - 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,11 +295,10 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
|
||||
{
|
||||
set_thread_name(__func__);
|
||||
struct pdb_e *cp;
|
||||
struct timeval curr_time;
|
||||
int fr;
|
||||
int ret;
|
||||
int tiles_post = 0;
|
||||
struct timeval last_tile_received = {0, 0};
|
||||
time_ns_t last_tile_received = 0;
|
||||
int last_buf_size = INITIAL_VIDEO_RECV_BUFFER_SIZE;
|
||||
|
||||
#ifdef SHARED_DECODER
|
||||
@@ -319,9 +317,8 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
|
||||
while (!should_exit) {
|
||||
struct timeval timeout;
|
||||
/* Housekeeping and RTCP... */
|
||||
gettimeofday(&curr_time, NULL);
|
||||
time_ns_t time_ns = get_time_in_ns();
|
||||
uint32_t ts = (m_start_time - time_ns) / 100'000 * 9; // at 90000 Hz
|
||||
time_ns_t curr_time = get_time_in_ns();
|
||||
uint32_t ts = (m_start_time - curr_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);
|
||||
@@ -329,7 +326,7 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
|
||||
/* Receive packets from the network... The timeout is adjusted */
|
||||
/* to match the video capture rate, so the transmitter works. */
|
||||
if (fr) {
|
||||
gettimeofday(&curr_time, NULL);
|
||||
curr_time = get_time_in_ns();
|
||||
receiver_process_messages();
|
||||
fr = 0;
|
||||
}
|
||||
@@ -337,7 +334,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 ((last_not_timeout - time_ns) > NS_IN_SEC) {
|
||||
if ((last_not_timeout - curr_time) > NS_IN_SEC) {
|
||||
timeout.tv_usec = 100000;
|
||||
} else {
|
||||
timeout.tv_usec = 1000;
|
||||
@@ -350,7 +347,7 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
|
||||
receiver_process_messages();
|
||||
//printf("Failed to receive data\n");
|
||||
} else {
|
||||
last_not_timeout = time_ns;
|
||||
last_not_timeout = curr_time;
|
||||
}
|
||||
|
||||
/* Decode and render for each participant in the conference... */
|
||||
@@ -404,13 +401,13 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
|
||||
|
||||
/* Decode and render video... */
|
||||
if (pbuf_decode
|
||||
(cp->playout_buffer, time_ns, decode_video_frame, vdecoder_state)) {
|
||||
(cp->playout_buffer, curr_time, decode_video_frame, vdecoder_state)) {
|
||||
tiles_post++;
|
||||
/* we have data from all connections we need */
|
||||
if(tiles_post == m_connections_count)
|
||||
{
|
||||
tiles_post = 0;
|
||||
gettimeofday(&curr_time, NULL);
|
||||
curr_time = get_time_in_ns();
|
||||
fr = 1;
|
||||
#if 0
|
||||
display_put_frame(uv->display_device,
|
||||
@@ -423,10 +420,10 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
|
||||
}
|
||||
|
||||
/* dual-link TIMEOUT - we won't wait for next tiles */
|
||||
if(tiles_post > 1 && tv_diff(curr_time, last_tile_received) >
|
||||
if(tiles_post > 1 && (last_tile_received - curr_time) / (double) NS_IN_SEC >
|
||||
999999 / 59.94 / m_connections_count) {
|
||||
tiles_post = 0;
|
||||
gettimeofday(&curr_time, NULL);
|
||||
curr_time = get_time_in_ns();
|
||||
fr = 1;
|
||||
#if 0
|
||||
display_put_frame(uv->display_device,
|
||||
@@ -453,7 +450,7 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
|
||||
}
|
||||
}
|
||||
|
||||
pbuf_remove(cp->playout_buffer, time_ns);
|
||||
pbuf_remove(cp->playout_buffer, curr_time);
|
||||
cp = pdb_iter_next(&it);
|
||||
}
|
||||
pdb_iter_done(&it);
|
||||
|
||||
Reference in New Issue
Block a user