Commit a0424bbf authored by Simon Morlat's avatar Simon Morlat

Implement new bandwidth estimator. However its computational cost may make it...

Implement new bandwidth estimator. However its computational cost may make it not so interesting to use.
parent 9f41b23d
......@@ -302,6 +302,7 @@ typedef struct _OrtpStream {
socklen_t loc_addrlen;
struct sockaddr_storage loc_addr;
struct _RtpTransport *tr;
OrtpBwEstimator recv_bw_estimator;
struct timeval send_bw_start; /* used for bandwidth estimation */
struct timeval recv_bw_start; /* used for bandwidth estimation */
unsigned int sent_bytes; /* used for bandwidth estimation */
......
......@@ -63,9 +63,7 @@ typedef struct msgb
unsigned char *b_wptr;
uint32_t reserved1;
uint32_t reserved2;
#if defined(ORTP_TIMESTAMP)
struct timeval timestamp;
#endif
ortp_recv_addr_t recv_addr; /*contains the destination address of incoming packets, used for ICE processing*/
struct sockaddr_storage net_addr; /*source address of incoming packet, or dest address of outgoing packet, used only by simulator and modifiers*/
socklen_t net_addrlen; /*source (dest) address of incoming (outgoing) packet length used by simulator and modifiers*/
......
......@@ -71,6 +71,26 @@ ORTP_PUBLIC void ortp_kalman_rls_init(OrtpKalmanRLS *obj, double m0, double b0);
ORTP_PUBLIC void ortp_kalman_rls_record(OrtpKalmanRLS *obj, double xmes, double ymes);
typedef struct _OrtpBwEstimator{
float one_minus_alpha;
float inv_step;
float exp_constant;
struct timeval last_packet_recv;
float value;
}OrtpBwEstimator;
/**
* Utility object to compute a sliding exponential mean bitrate.
* @param obj the estimator structure to initialize
* @param alpha the weight of previous estimation (between 0 and 1)
* @param step a time constant in seconds representing the sampling period
**/
ORTP_PUBLIC void ortp_bw_estimator_init(OrtpBwEstimator *obj, float alpha, float step);
ORTP_PUBLIC void ortp_bw_estimator_packet_received (OrtpBwEstimator *obj, size_t bytes, const struct timeval *recv_time);
ORTP_PUBLIC float ortp_bw_estimator_get_value(OrtpBwEstimator *obj);
#ifdef __cplusplus
}
#endif
......
......@@ -399,7 +399,6 @@ int ortp_timespec_compare(const ortpTimeSpec *s1, const ortpTimeSpec *s2){
return 1;
}
#if defined(ORTP_TIMESTAMP)
static mblk_t * rtp_session_netsim_find_next_packet_to_send(RtpSession *session){
mblk_t *om;
ortpTimeSpec min_packet_time = { 0, 0};
......@@ -420,7 +419,6 @@ static mblk_t * rtp_session_netsim_find_next_packet_to_send(RtpSession *session)
}
return next_packet;
}
#endif
static void rtp_session_schedule_outbound_network_simulator(RtpSession *session, ortpTimeSpec *sleep_until){
mblk_t *om;
......@@ -459,7 +457,6 @@ static void rtp_session_schedule_outbound_network_simulator(RtpSession *session,
}
}
}else if (session->net_sim_ctx->params.mode==OrtpNetworkSimulatorOutboundControlled){
#if defined(ORTP_TIMESTAMP)
ortpTimeSpec current={0};
ortpTimeSpec packet_time;
mblk_t *todrop=NULL;
......@@ -499,16 +496,6 @@ static void rtp_session_schedule_outbound_network_simulator(RtpSession *session,
sleep_until->tv_sec=current.tv_sec;
sleep_until->tv_nsec=current.tv_nsec+1000000LL; /*in 1 ms*/
}
#else
ortp_mutex_lock(&session->net_sim_ctx->mutex);
while((om=getq(&session->net_sim_ctx->send_q))!=NULL){
ortp_mutex_unlock(&session->net_sim_ctx->mutex);
freemsg(om);
ortp_error("Network simulator is in mode OrtpNetworkSimulatorOutboundControlled but oRTP wasn't compiled with --enable-ntp-timestamp.");
ortp_mutex_lock(&session->net_sim_ctx->mutex);
}
ortp_mutex_unlock(&session->net_sim_ctx->mutex);
#endif
}
}
......@@ -306,6 +306,9 @@ rtp_session_init (RtpSession * session, int mode)
rtp_session_set_transports(session, rtp_tr, rtcp_tr);
}
session->tev_send_pt = -1; /*check in rtp profile when needed*/
ortp_bw_estimator_init(&session->rtp.gs.recv_bw_estimator, 0.95, 0.01);
ortp_bw_estimator_init(&session->rtcp.gs.recv_bw_estimator, 0.95, 0.01);
}
void rtp_session_enable_congestion_detection(RtpSession *session, bool_t enabled){
......@@ -1846,7 +1849,8 @@ float rtp_session_compute_send_bandwidth(RtpSession *session) {
* Computation must have been done with rtp_session_compute_recv_bandwidth()
**/
float rtp_session_get_recv_bandwidth(RtpSession *session){
return session->rtp.gs.download_bw + session->rtcp.gs.download_bw;
//return session->rtp.gs.download_bw + session->rtcp.gs.download_bw;
return ortp_bw_estimator_get_value(&session->rtp.gs.recv_bw_estimator) + ortp_bw_estimator_get_value(&session->rtcp.gs.recv_bw_estimator);
}
float rtp_session_get_recv_bandwidth_smooth(RtpSession *session){
......@@ -1866,7 +1870,8 @@ float rtp_session_get_send_bandwidth_smooth(RtpSession *session){
}
float rtp_session_get_rtp_recv_bandwidth(RtpSession *session) {
return session->rtp.gs.download_bw;
//return session->rtp.gs.download_bw;
return ortp_bw_estimator_get_value(&session->rtp.gs.recv_bw_estimator);
}
float rtp_session_get_rtp_send_bandwidth(RtpSession *session) {
......@@ -1874,7 +1879,8 @@ float rtp_session_get_rtp_send_bandwidth(RtpSession *session) {
}
float rtp_session_get_rtcp_recv_bandwidth(RtpSession *session) {
return session->rtcp.gs.download_bw;
//return session->rtcp.gs.download_bw;
return ortp_bw_estimator_get_value(&session->rtcp.gs.recv_bw_estimator);
}
float rtp_session_get_rtcp_send_bandwidth(RtpSession *session) {
......
......@@ -205,7 +205,6 @@ static ortp_socket_t create_and_bind(const char *addr, int *port, int *sock_fami
}
}
#if defined(ORTP_TIMESTAMP)
optval=1;
err = setsockopt (sock, SOL_SOCKET, SO_TIMESTAMP,
(SOCKET_OPTION_VALUE)&optval, sizeof (optval));
......@@ -213,7 +212,6 @@ static ortp_socket_t create_and_bind(const char *addr, int *port, int *sock_fami
{
ortp_warning ("Fail to set rtp timestamp: %s.",getSocketError());
}
#endif
err = 0;
optval=1;
switch (res->ai_family) {
......@@ -1139,12 +1137,13 @@ void update_sent_bytes(OrtpStream *os, int nbytes) {
os->sent_bytes += nbytes + overhead;
}
static void update_recv_bytes(OrtpStream *os, int nbytes) {
static void update_recv_bytes(OrtpStream *os, size_t nbytes, const struct timeval *recv_time) {
int overhead = ortp_stream_is_ipv6(os) ? IP6_UDP_OVERHEAD : IP_UDP_OVERHEAD;
if ((os->recv_bytes == 0) && (os->recv_bw_start.tv_sec == 0) && (os->recv_bw_start.tv_usec == 0)) {
ortp_gettimeofday(&os->recv_bw_start, NULL);
}
os->recv_bytes += nbytes + overhead;
ortp_bw_estimator_packet_received(&os->recv_bw_estimator, nbytes + overhead, recv_time);
}
static void log_send_error(RtpSession *session, const char *type, mblk_t *m, struct sockaddr *destaddr, socklen_t destlen){
......@@ -1331,11 +1330,9 @@ int rtp_session_rtp_recv_abstract(ortp_socket_t socket, mblk_t *msg, int flags,
ret = bytes_received;
#endif
for (cmsghdr = CMSG_FIRSTHDR(&msghdr); cmsghdr != NULL ; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) {
#if defined(ORTP_TIMESTAMP)
if (cmsghdr->cmsg_level == SOL_SOCKET && cmsghdr->cmsg_type == SO_TIMESTAMP) {
memcpy(&msg->timestamp, (struct timeval *)CMSG_DATA(cmsghdr), sizeof(struct timeval));
}
#endif
#ifdef IP_PKTINFO
if ((cmsghdr->cmsg_level == IPPROTO_IP) && (cmsghdr->cmsg_type == IP_PKTINFO)) {
struct in_pktinfo *pi = (struct in_pktinfo *)CMSG_DATA(cmsghdr);
......@@ -1507,7 +1504,7 @@ static int process_rtcp_packet( RtpSession *session, mblk_t *block, struct socka
return -1;
}
update_recv_bytes(&session->rtcp.gs, (int)(block->b_wptr - block->b_rptr));
update_recv_bytes(&session->rtcp.gs, (int)(block->b_wptr - block->b_rptr), &block->timestamp);
/* compound rtcp packet can be composed by more than one rtcp message */
do{
......@@ -1595,7 +1592,7 @@ static void rtp_process_incoming_packet(RtpSession * session, mblk_t * mp, bool_
}
}
/* then parse the message and put on jitter buffer queue */
update_recv_bytes(&session->rtp.gs, (int)(mp->b_wptr - mp->b_rptr));
update_recv_bytes(&session->rtp.gs, (size_t)(mp->b_wptr - mp->b_rptr), &mp->timestamp);
rtp_session_rtp_parse(session, mp, user_ts, remaddr,addrlen);
/*for bandwidth measurements:*/
}else {
......
......@@ -18,7 +18,9 @@
*/
#include "ortp/port.h"
#include "ortp/logging.h"
#include "utils.h"
#include "math.h"
uint64_t ortp_timeval_to_ntp(const struct timeval *tv){
......@@ -28,3 +30,34 @@ uint64_t ortp_timeval_to_ntp(const struct timeval *tv){
lsw=(uint32_t)((double)tv->tv_usec*(double)(((uint64_t)1)<<32)*1.0e-6);
return msw<<32 | lsw;
}
void ortp_bw_estimator_init(OrtpBwEstimator *obj, float alpha, float step){
obj->one_minus_alpha = 1.0f - alpha;
obj->inv_step = 1.0/step;
obj->exp_constant = logf(alpha) * obj->inv_step;
obj->last_packet_recv.tv_sec = 0;
obj->last_packet_recv.tv_usec = 0;
obj->value = 0;
}
void ortp_bw_estimator_packet_received (OrtpBwEstimator *obj, size_t bytes, const struct timeval *recv_time){
float diff_time;
if (obj->last_packet_recv.tv_sec == 0){
diff_time = 1.0/obj->inv_step;
ortp_message("First estimation");
}else{
diff_time = (float)(recv_time->tv_sec - obj->last_packet_recv.tv_sec) + 1e-6*(recv_time->tv_usec - obj->last_packet_recv.tv_usec);
}
obj->value = ((float)bytes * obj->one_minus_alpha) + expf(diff_time * obj->exp_constant)*obj->value;
obj->last_packet_recv = *recv_time;
}
float ortp_bw_estimator_get_value(OrtpBwEstimator *obj){
struct timeval current;
bctbx_gettimeofday(&current, NULL);
ortp_bw_estimator_packet_received(obj, 0, &current);
return obj->value * 8.0 * obj->inv_step;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment