|
|
@@ -27,6 +27,9 @@ struct rtp_state {
|
|
|
/* for rtcp sending */
|
|
|
DWORD transmit_interval;
|
|
|
DWORD last_transmit_tick;
|
|
|
+
|
|
|
+ /*for rtcp tmmbr */
|
|
|
+ RtcpTmmbrInfo tmmbr_info;
|
|
|
};
|
|
|
|
|
|
#ifndef JAN_1970
|
|
|
@@ -37,6 +40,25 @@ struct rtp_state {
|
|
|
|
|
|
|
|
|
|
|
|
+#define rtcp_fb_tmmbr_fci_get_ssrc(tmmbr) ntohl((tmmbr)->ssrc)
|
|
|
+#define rtcp_fb_tmmbr_fci_get_mxtbr_exp(tmmbr) \
|
|
|
+ ((unsigned char)((ntohl((tmmbr)->value) >> 26) & 0x0000003F))
|
|
|
+#define rtcp_fb_tmmbr_fci_set_mxtbr_exp(tmmbr, mxtbr_exp) \
|
|
|
+ ((tmmbr)->value) = htonl((ntohl((tmmbr)->value) & 0x03FFFFFF) | (((mxtbr_exp) & 0x0000003F) << 26))
|
|
|
+#define rtcp_fb_tmmbr_fci_get_mxtbr_mantissa(tmmbr) \
|
|
|
+ ((unsigned int)((ntohl((tmmbr)->value) >> 9) & 0x0001FFFF))
|
|
|
+#define rtcp_fb_tmmbr_fci_set_mxtbr_mantissa(tmmbr, mxtbr_mantissa) \
|
|
|
+ ((tmmbr)->value) = htonl((ntohl((tmmbr)->value) & 0xFC0001FF) | (((mxtbr_mantissa) & 0x0001FFFF) << 9))
|
|
|
+#define rtcp_fb_tmmbr_fci_get_measured_overhead(tmmbr) \
|
|
|
+ ((unsigned short)(ntohl((tmmbr)->value) & 0x000001FF))
|
|
|
+#define rtcp_fb_tmmbr_fci_set_measured_overhead(tmmbr, measured_overhead) \
|
|
|
+ ((tmmbr)->value) = htonl((ntohl((tmmbr)->value) & 0xFFFFFE00) | ((measured_overhead) & 0x000001FF))
|
|
|
+
|
|
|
+
|
|
|
+#define MIN_RTCP_PSFB_PACKET_SIZE (sizeof(rtcp_common_t) + sizeof(rtcp_fb_header_t))
|
|
|
+#define MIN_RTCP_RTPFB_PACKET_SIZE (sizeof(rtcp_common_t) + sizeof(rtcp_fb_header_t))
|
|
|
+
|
|
|
+
|
|
|
TOOLKIT_API int rtp_state_fill_rtcp_sender_info(rtp_state *rs, rtcp_sender_info_t *info);
|
|
|
TOOLKIT_API int rtp_state_fill_rtcp_reception_report(rtp_state *rs, rtcp_rr_t *report);
|
|
|
TOOLKIT_API int rtp_state_fill_rtcp_sdes_item(rtp_state *rs, rtcp_sdes_type_t type, rtcp_sdes_item_t *item, int *fill_n);
|
|
|
@@ -85,6 +107,65 @@ static void gettimeofday(struct timeval *tv)
|
|
|
tv->tv_usec = st.wMilliseconds * 1000;
|
|
|
}
|
|
|
|
|
|
+static char *copymsg(char *msg, int len)
|
|
|
+{
|
|
|
+ char *newm;
|
|
|
+ newm=malloc(len);
|
|
|
+ memcpy(newm,msg,len);
|
|
|
+ return newm;
|
|
|
+}
|
|
|
+
|
|
|
+static void freemsg(char *msg)
|
|
|
+{
|
|
|
+ if (msg != NULL) {
|
|
|
+ free(msg);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static size_t rtcp_get_size(const char *msg){
|
|
|
+ rtcp_common_t *ch = (rtcp_common_t *)msg;
|
|
|
+ if (ch==NULL) return 0;
|
|
|
+ return (1+ntohs(ch->length))*4;
|
|
|
+}
|
|
|
+
|
|
|
+static int rtcp_is_rtpfb(const char *msg) {
|
|
|
+ rtcp_common_t *ch = (rtcp_common_t *)msg;
|
|
|
+ if ((ch != NULL) && (ch->pt == RTCP_RTPFB)) {
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+ return FALSE;
|
|
|
+}
|
|
|
+
|
|
|
+static rtcp_rtpfb_type_t rtcp_rtpfb_get_type(const char *msg) {
|
|
|
+ rtcp_common_t *ch = (rtcp_common_t *)msg;
|
|
|
+ return (rtcp_rtpfb_type_t)ch->count;
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned int rtcp_rtpfb_get_packet_sender_ssrc(const char *msg) {
|
|
|
+ rtcp_fb_header_t *fbh = (rtcp_fb_header_t *)(msg + sizeof(rtcp_common_t));
|
|
|
+ return ntohl(fbh->packet_sender_ssrc);
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned int rtcp_rtpfb_get_media_source_ssrc(const char *msg) {
|
|
|
+ rtcp_fb_header_t *fbh = (rtcp_fb_header_t *)(msg + sizeof(rtcp_common_t));
|
|
|
+ return ntohl(fbh->media_source_ssrc);
|
|
|
+}
|
|
|
+
|
|
|
+static rtcp_fb_tmmbr_fci_t * rtcp_rtpfb_tmmbr_get_fci(const char *msg) {
|
|
|
+ size_t size = sizeof(rtcp_common_t) + sizeof(rtcp_fb_header_t) + sizeof(rtcp_fb_tmmbr_fci_t);
|
|
|
+ size_t rtcp_size = rtcp_get_size(msg);
|
|
|
+ if (size > rtcp_size) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ return (rtcp_fb_tmmbr_fci_t *)(msg + size - sizeof(rtcp_fb_tmmbr_fci_t));
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned __int64 rtcp_rtpfb_tmmbr_get_max_bitrate(const char *msg) {
|
|
|
+ rtcp_fb_tmmbr_fci_t *fci = rtcp_rtpfb_tmmbr_get_fci(msg);
|
|
|
+ return rtcp_fb_tmmbr_fci_get_mxtbr_mantissa(fci) * (1 << rtcp_fb_tmmbr_fci_get_mxtbr_exp(fci));
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
TOOLKIT_API int rtp_state_fill_rtp(rtp_state *rs, void *hdr, unsigned int pt, unsigned int mark, unsigned int delta_ts)
|
|
|
{
|
|
|
rtp_hdr *header;
|
|
|
@@ -135,16 +216,26 @@ TOOLKIT_API int rtp_state_set_rtcp_sdes_string(rtp_state *rs,
|
|
|
return rs->sdes_str[type] ? 0 : -1;
|
|
|
}
|
|
|
|
|
|
+static unsigned __int64 rtp_timeval_to_ntp(const struct timeval *tv){
|
|
|
+ unsigned __int64 msw;
|
|
|
+ unsigned __int64 lsw;
|
|
|
+ msw=tv->tv_sec + 0x83AA7E80; /* 0x83AA7E80 is the number of seconds from 1900 to 1970 */
|
|
|
+ lsw=(unsigned int)((double)tv->tv_usec*(double)(((unsigned __int64)1)<<32)*1.0e-6);
|
|
|
+ return msw<<32 | lsw;
|
|
|
+}
|
|
|
+
|
|
|
TOOLKIT_API int rtp_state_fill_rtcp_sender_info(rtp_state *rs, rtcp_sender_info_t *info)
|
|
|
{
|
|
|
struct timeval tv;
|
|
|
+ unsigned __int64 ntp;
|
|
|
|
|
|
if (!rs)
|
|
|
return -1;
|
|
|
info->ssrc = rs->ssrc; /* sender's own ssrc */
|
|
|
gettimeofday(&tv);
|
|
|
- info->ntp_sec = (unsigned int)htonl(tv.tv_sec + JAN_1970);
|
|
|
- info->ntp_frac = (unsigned int)htonl((unsigned long)(tv.tv_usec*4294.967296));
|
|
|
+ ntp=rtp_timeval_to_ntp(&tv);
|
|
|
+ info->ntp_sec = htonl(ntp >>32);//(unsigned int)htonl(tv.tv_sec + JAN_1970);
|
|
|
+ info->ntp_frac = htonl(ntp & 0xFFFFFFFF);//(unsigned int)htonl((unsigned long)(tv.tv_usec*4294.967296));
|
|
|
info->rtp_ts = (unsigned int)htonl(rs->ts);
|
|
|
info->psent = (unsigned int)htonl((unsigned long)rs->s.total_tx_packets);
|
|
|
info->osent = (unsigned int)htonl((unsigned long)rs->s.total_tx_bytes);
|
|
|
@@ -170,23 +261,26 @@ TOOLKIT_API int rtp_state_fill_rtcp_reception_report(rtp_state *rs, rtcp_rr_t *r
|
|
|
if (packet_loss_since_last_sr < 0)
|
|
|
packet_loss_since_last_sr = 0;
|
|
|
rs->s.rx_seq_at_last_sr = ext_seq; /* update */
|
|
|
+ rs->s.rx_packets_since_last_sr = 0;//RESET
|
|
|
rs->s.total_packet_lost += (unsigned int)packet_loss_since_last_sr;
|
|
|
if (expected == 0)
|
|
|
expected = 1;
|
|
|
if (rs->s.lsr_tm.tv_sec != 0) {
|
|
|
struct timeval now;
|
|
|
+ double delay;
|
|
|
gettimeofday(&now);
|
|
|
- delay_since_lsr = (0x10000 * (now.tv_sec - rs->s.lsr_tm.tv_sec));
|
|
|
- delay_since_lsr += (now.tv_usec - rs->s.lsr_tm.tv_usec) * 0x10000 / 1000000;
|
|
|
+ delay= (now.tv_sec-rs->s.lsr_tm.tv_sec)+ ((now.tv_usec-rs->s.lsr_tm.tv_usec)*1e-6);
|
|
|
+ delay= (delay*65536);
|
|
|
+ delay_since_lsr=(unsigned int) delay;
|
|
|
}
|
|
|
loss_fraction = (unsigned char)(256 * packet_loss_since_last_sr / expected);
|
|
|
report->ssrc = rs->s.peer_ssrc;
|
|
|
report->fl_cnpl = htonl((loss_fraction << 24) | (rs->s.total_packet_lost&0xffffff));
|
|
|
report->last_seq = htonl(ext_seq);
|
|
|
report->jitter = htonl(rs->s.inter_jitter);
|
|
|
- report->lsr = rs->s.lsr;
|
|
|
+ report->lsr = htonl(rs->s.lsr);
|
|
|
report->dlsr = htonl(delay_since_lsr);
|
|
|
-
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
@@ -257,6 +351,7 @@ TOOLKIT_API int rtp_state_rtcp_make_sr(rtp_state *rs, char *buf, size_t buflen)
|
|
|
rtcp_common_t *common;
|
|
|
rtcp_sdes_t *sdes;
|
|
|
int n, t, m;
|
|
|
+ int reception_report_result;
|
|
|
|
|
|
if (!buf)
|
|
|
return -1;
|
|
|
@@ -267,8 +362,12 @@ TOOLKIT_API int rtp_state_rtcp_make_sr(rtp_state *rs, char *buf, size_t buflen)
|
|
|
n += sizeof(rtcp_common_t);
|
|
|
rtp_state_fill_rtcp_sender_info(rs, (rtcp_sender_info_t *)&buf[n]);
|
|
|
n += sizeof(rtcp_sender_info_t);
|
|
|
- rtp_state_fill_rtcp_reception_report(rs, (rtcp_rr_t *)&buf[n]);
|
|
|
- n += sizeof(rtcp_rr_t);
|
|
|
+ reception_report_result = rtp_state_fill_rtcp_reception_report(rs, (rtcp_rr_t *)&buf[n]);
|
|
|
+ if (reception_report_result < 0){
|
|
|
+ //reception_report fillʧ°Ü£¬²»·¢ËÍreception_report
|
|
|
+ } else {
|
|
|
+ n += sizeof(rtcp_rr_t);
|
|
|
+ }
|
|
|
common->p = 0;
|
|
|
common->version = 2;
|
|
|
common->pt = RTCP_SR;
|
|
|
@@ -300,6 +399,7 @@ TOOLKIT_API int rtp_state_rtcp_make_rr(rtp_state *rs, char *buf, size_t buflen)
|
|
|
rtcp_common_t *common;
|
|
|
rtcp_sdes_t *sdes;
|
|
|
int n, t, m;
|
|
|
+ int reception_report_result;
|
|
|
|
|
|
if (!buf)
|
|
|
return -1;
|
|
|
@@ -308,11 +408,14 @@ TOOLKIT_API int rtp_state_rtcp_make_rr(rtp_state *rs, char *buf, size_t buflen)
|
|
|
n = 0;
|
|
|
common = (rtcp_common_t*)&buf[n];
|
|
|
n += sizeof(rtcp_common_t);
|
|
|
- rtp_state_fill_rtcp_reception_report(rs, (rtcp_rr_t *)&buf[n]);
|
|
|
+ reception_report_result = rtp_state_fill_rtcp_reception_report(rs, (rtcp_rr_t *)&buf[n]);
|
|
|
+ if (reception_report_result < 0){
|
|
|
+ return reception_report_result;
|
|
|
+ }
|
|
|
n += sizeof(rtcp_rr_t);
|
|
|
common->p = 0;
|
|
|
common->version = 2;
|
|
|
- common->pt = RTCP_SR;
|
|
|
+ common->pt = RTCP_RR;
|
|
|
common->count = 1;
|
|
|
common->length = htons(n / 4 - 1);
|
|
|
|
|
|
@@ -351,7 +454,7 @@ TOOLKIT_API int rtp_state_rtcp_make_bye(rtp_state *rs, char *buf, size_t buflen)
|
|
|
n += sizeof(rtcp_bye_t);
|
|
|
bye->common.p = 0;
|
|
|
bye->common.version = 2;
|
|
|
- bye->common.pt = RTCP_SR;
|
|
|
+ bye->common.pt = RTCP_BYE;
|
|
|
bye->common.count = 1;
|
|
|
bye->ssrc[0] = rs->ssrc;
|
|
|
bye->common.length = htons(n / 4 - 1);
|
|
|
@@ -456,6 +559,156 @@ TOOLKIT_API int rtp_state_rtcp_make_h261_nack(rtp_state *rs, char *buf, size_t b
|
|
|
return m;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+TOOLKIT_API int rtp_state_rtcp_make_rtcp_fb_tmmbr(rtp_state *rs, char *buf, size_t buflen, unsigned __int64 mxtbr, unsigned short measured_overhead) {
|
|
|
+ rtcp_common_t *ch;
|
|
|
+ rtcp_fb_header_t *fbh;
|
|
|
+ rtcp_fb_tmmbr_fci_t *fci;
|
|
|
+ unsigned char mxtbr_exp = 0;
|
|
|
+ unsigned int mxtbr_mantissa = 0;
|
|
|
+ int length = 0;
|
|
|
+
|
|
|
+ /* Compute mxtbr exp and mantissa */
|
|
|
+ while (mxtbr >= (1 << 17)) {
|
|
|
+ mxtbr >>= 1;
|
|
|
+ mxtbr_exp++;
|
|
|
+ }
|
|
|
+ mxtbr_mantissa = mxtbr & 0x0001FFFF;
|
|
|
+
|
|
|
+ /* Fill TMMBR */
|
|
|
+ ch = (rtcp_common_t *)&buf[length];
|
|
|
+ length += sizeof(rtcp_common_t);
|
|
|
+ fbh = (rtcp_fb_header_t *)&buf[length];
|
|
|
+ length += sizeof(rtcp_fb_header_t);
|
|
|
+ fci = (rtcp_fb_tmmbr_fci_t *)&buf[length];
|
|
|
+ length += sizeof(rtcp_fb_tmmbr_fci_t);
|
|
|
+ fbh->packet_sender_ssrc = rs->ssrc;
|
|
|
+ fbh->media_source_ssrc = htonl(0);
|
|
|
+ fci->ssrc = rs->s.peer_ssrc;
|
|
|
+ rtcp_fb_tmmbr_fci_set_mxtbr_exp(fci, mxtbr_exp);
|
|
|
+ rtcp_fb_tmmbr_fci_set_mxtbr_mantissa(fci, mxtbr_mantissa);
|
|
|
+ rtcp_fb_tmmbr_fci_set_measured_overhead(fci, measured_overhead);
|
|
|
+
|
|
|
+ /* Fill common header */
|
|
|
+ ch->p = 0;
|
|
|
+ ch->version = 2;
|
|
|
+ ch->pt = RTCP_RTPFB;
|
|
|
+ ch->count = RTCP_RTPFB_TMMBR;
|
|
|
+ ch->length = htons(length / 4 - 1);
|
|
|
+
|
|
|
+ /* Store packet to be able to retransmit. */
|
|
|
+ if (rs->tmmbr_info.sent) freemsg(rs->tmmbr_info.sent);
|
|
|
+ rs->tmmbr_info.sent = copymsg(buf, length);
|
|
|
+
|
|
|
+ return length;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+TOOLKIT_API int rtp_state_rtcp_make_rtcp_fb_tmmbn(rtp_state *rs, char *buf, size_t buflen, unsigned int ssrc) {
|
|
|
+ rtcp_common_t *ch;
|
|
|
+ rtcp_fb_header_t *fbh;
|
|
|
+ rtcp_fb_tmmbr_fci_t *fci;
|
|
|
+ int length = 0;
|
|
|
+
|
|
|
+ if (!rs->tmmbr_info.received) return 0;
|
|
|
+
|
|
|
+ /* Fill TMMBN */
|
|
|
+ ch = (rtcp_common_t *)&buf[length];
|
|
|
+ length += sizeof(rtcp_common_t);
|
|
|
+ fbh = (rtcp_fb_header_t *)&buf[length];
|
|
|
+ length += sizeof(rtcp_fb_header_t);
|
|
|
+ fci = (rtcp_fb_tmmbr_fci_t *)&buf[length];
|
|
|
+ length += sizeof(rtcp_fb_tmmbr_fci_t);
|
|
|
+ fbh->packet_sender_ssrc = rs->ssrc;
|
|
|
+ fbh->media_source_ssrc = htonl(0);
|
|
|
+ memcpy(fci, rtcp_rtpfb_tmmbr_get_fci(rs->tmmbr_info.received), sizeof(rtcp_fb_tmmbr_fci_t));
|
|
|
+ fci->ssrc = htonl(ssrc);
|
|
|
+
|
|
|
+ /* Fill common header */
|
|
|
+ ch->p = 0;
|
|
|
+ ch->version = 2;
|
|
|
+ ch->pt = RTCP_RTPFB;
|
|
|
+ ch->count = RTCP_RTPFB_TMMBN;
|
|
|
+ ch->length = htons(length / 4 - 1);
|
|
|
+
|
|
|
+ return length;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+int rtp_state_get_tmmbr_wait_send_maxbitrate(rtp_state *rs, unsigned __int64 *mxtbr){
|
|
|
+ if (rs->tmmbr_info.sent) {
|
|
|
+ *mxtbr = rtcp_rtpfb_tmmbr_get_max_bitrate(rs->tmmbr_info.sent);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void handle_rtcp_rtpfb_packet(rtp_state *rs, const char *buf, int len) {
|
|
|
+ rtcp_common_t *ch = (rtcp_common_t *)&buf[0];
|
|
|
+
|
|
|
+ switch ((rtcp_rtpfb_type_t)ch->count) {
|
|
|
+ case RTCP_RTPFB_TMMBR:
|
|
|
+ if (rs->tmmbr_info.received) freemsg((char *)(rs->tmmbr_info.received));
|
|
|
+ rs->tmmbr_info.received = copymsg(buf, len);
|
|
|
+ rs->s.tmmbr_max_bitrate = rtcp_rtpfb_tmmbr_get_max_bitrate(buf);
|
|
|
+ break;
|
|
|
+ case RTCP_RTPFB_TMMBN:
|
|
|
+ if (rs->tmmbr_info.sent) {
|
|
|
+ rtcp_fb_tmmbr_fci_t *tmmbn_fci = rtcp_rtpfb_tmmbr_get_fci((char *)buf);
|
|
|
+ rtcp_fb_tmmbr_fci_t *tmmbr_fci = rtcp_rtpfb_tmmbr_get_fci((char *)(rs->tmmbr_info.sent));
|
|
|
+ if ((tmmbn_fci->ssrc == rs->ssrc) && (tmmbn_fci->value == tmmbr_fci->value)) {
|
|
|
+ freemsg((char *)(rs->tmmbr_info.sent));
|
|
|
+ rs->tmmbr_info.sent = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned int report_block_get_fraction_lost(const rtcp_rr_t * rr) {
|
|
|
+ return (ntohl(rr->fl_cnpl)>>24);
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned int report_block_get_cum_packet_lost(const rtcp_rr_t * rr){
|
|
|
+ unsigned int cum_loss = (unsigned int)ntohl(rr->fl_cnpl);
|
|
|
+ if (((cum_loss>>23)&1)==0)
|
|
|
+ return (unsigned int) (0x00FFFFFF & cum_loss);
|
|
|
+ else
|
|
|
+ return (unsigned int)(0xFF000000 | (cum_loss-0xFFFFFF-1));
|
|
|
+}
|
|
|
+
|
|
|
+static void compute_rtt_from_report_block(rtp_state *rs, const struct timeval *now, rtcp_rr_t *rr) {
|
|
|
+ unsigned int last_sr_time;
|
|
|
+ unsigned int sr_delay;
|
|
|
+
|
|
|
+ unsigned __int64 curntp;
|
|
|
+ unsigned int approx_ntp;
|
|
|
+
|
|
|
+ last_sr_time = ntohl(rr->lsr);
|
|
|
+ sr_delay = ntohl(rr->dlsr);
|
|
|
+ curntp=rtp_timeval_to_ntp(now);
|
|
|
+ approx_ntp=(curntp>>16) & 0xFFFFFFFF;
|
|
|
+ //printf("compute_rtt_from_report_block, last_sr_time:%u sr_delay:%u, approx_ntp:%u", last_sr_time, sr_delay, approx_ntp);
|
|
|
+
|
|
|
+ if (last_sr_time!=0 && sr_delay!=0){
|
|
|
+ /*we cast to int32_t to check for crazy RTT time (negative)*/
|
|
|
+ double rtt_frac=(unsigned int)(approx_ntp-last_sr_time-sr_delay);
|
|
|
+ //printf("compute_rtt_from_report_block, rtt_frac:%lf", rtt_frac);
|
|
|
+ if (rtt_frac>=0){
|
|
|
+ rtt_frac/=65536.0;
|
|
|
+
|
|
|
+ rs->s.rtt=(float)rtt_frac;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ rs->s.cum_loss = report_block_get_cum_packet_lost(rr);
|
|
|
+ rs->s.fraction_lost = report_block_get_fraction_lost(rr);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* called when receive a peer's rtp data packet
|
|
|
*/
|
|
|
@@ -471,17 +724,28 @@ TOOLKIT_API int rtp_state_on_recv_rtcp(rtp_state *rs, const void *buf, int len)
|
|
|
if (common->pt == RTCP_SR) {
|
|
|
rtcp_sender_info_t *si;
|
|
|
si = (rtcp_sender_info_t *)((const char*)buf + n);
|
|
|
- rs->s.lsr = (si->ntp_sec&0xffff0000) | (si->ntp_frac&0x0000ffff);
|
|
|
+ rs->s.lsr = ( ntohl( si->ntp_sec ) << 16 ) | ( ntohl( si->ntp_frac ) >> 16 );
|
|
|
gettimeofday(&rs->s.lsr_tm);
|
|
|
}
|
|
|
if ((common->pt == RTCP_SR || common->pt == RTCP_RR) && common->count) {
|
|
|
rtcp_rr_t *rr;
|
|
|
+ struct timeval now;
|
|
|
+ gettimeofday(&now);
|
|
|
+
|
|
|
if (common->pt == RTCP_SR)
|
|
|
rr = (rtcp_rr_t *)((const char*)buf + n + sizeof(rtcp_sender_info_t));
|
|
|
- else
|
|
|
+ else {
|
|
|
rr = (rtcp_rr_t *)((const char*)buf + n);
|
|
|
+ compute_rtt_from_report_block(rs, &now, rr);
|
|
|
+ rs->s.report_block_last_number_of_packets = ntohl(rr->last_seq) - rs->s.report_block_last_seq;
|
|
|
+ rs->s.report_block_last_seq = ntohl(rr->last_seq);
|
|
|
+ }
|
|
|
+
|
|
|
/* nothing todo */
|
|
|
}
|
|
|
+ if (rtcp_is_rtpfb((char *)common), rtcp_get_size((char *)common)) {
|
|
|
+ handle_rtcp_rtpfb_packet(rs, (char *)common, rtcp_get_size((char *)common));
|
|
|
+ }
|
|
|
n += ntohs(common->length) * 4;
|
|
|
}
|
|
|
return 0;
|