Commit 4c296488 by ziyue

修复rtcp rr/sr时间戳转换相关问题,计算rtt

parent bf8642d6
...@@ -263,11 +263,25 @@ string RtcpSR::getNtpStamp() const{ ...@@ -263,11 +263,25 @@ string RtcpSR::getNtpStamp() const{
return LogChannel::printTime(tv); return LogChannel::printTime(tv);
} }
uint64_t RtcpSR::getNtpUnixStampMS() const {
struct timeval tv;
tv.tv_sec = ntpmsw - 0x83AA7E80;
tv.tv_usec = (decltype(tv.tv_usec)) (ntplsw / ((double) (((uint64_t) 1) << 32) * 1.0e-6));
return 1000 * tv.tv_sec + tv.tv_usec / 1000;
}
void RtcpSR::setNtpStamp(struct timeval tv) { void RtcpSR::setNtpStamp(struct timeval tv) {
ntpmsw = htonl(tv.tv_sec + 0x83AA7E80); /* 0x83AA7E80 is the number of seconds from 1900 to 1970 */ ntpmsw = htonl(tv.tv_sec + 0x83AA7E80); /* 0x83AA7E80 is the number of seconds from 1900 to 1970 */
ntplsw = htonl((uint32_t) ((double) tv.tv_usec * (double) (((uint64_t) 1) << 32) * 1.0e-6)); ntplsw = htonl((uint32_t) ((double) tv.tv_usec * (double) (((uint64_t) 1) << 32) * 1.0e-6));
} }
void RtcpSR::setNtpStamp(uint64_t unix_stamp_ms) {
struct timeval tv;
tv.tv_sec = unix_stamp_ms / 1000;
tv.tv_usec = (unix_stamp_ms % 1000) * 1000;
setNtpStamp(tv);
}
string RtcpSR::dumpString() const{ string RtcpSR::dumpString() const{
_StrPrinter printer; _StrPrinter printer;
printer << RtcpHeader::dumpHeader(); printer << RtcpHeader::dumpHeader();
......
...@@ -347,12 +347,14 @@ public: ...@@ -347,12 +347,14 @@ public:
* @param tv 时间 * @param tv 时间
*/ */
void setNtpStamp(struct timeval tv); void setNtpStamp(struct timeval tv);
void setNtpStamp(uint64_t unix_stamp_ms);
/** /**
* 返回ntp时间的字符串 * 返回ntp时间的字符串
* 使用net2Host转换成主机字节序后才可使用此函数 * 使用net2Host转换成主机字节序后才可使用此函数
*/ */
string getNtpStamp() const; string getNtpStamp() const;
uint64_t getNtpUnixStampMS() const;
/** /**
* 获取ReportItem对象指针列表 * 获取ReportItem对象指针列表
......
...@@ -22,14 +22,14 @@ RtcpContext::RtcpContext(bool is_receiver) { ...@@ -22,14 +22,14 @@ RtcpContext::RtcpContext(bool is_receiver) {
_is_receiver = is_receiver; _is_receiver = is_receiver;
} }
void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, size_t bytes) { void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, uint32_t sample_rate, size_t bytes) {
if (_is_receiver) { if (_is_receiver) {
//接收者才做复杂的统计运算 //接收者才做复杂的统计运算
auto sys_stamp = getCurrentMillisecond(); auto sys_stamp = getCurrentMillisecond();
if (_last_rtp_sys_stamp) { if (_last_rtp_sys_stamp) {
//计算时间戳抖动值 //计算时间戳抖动值
double diff = double( double diff = double((int64_t(sys_stamp) - int64_t(_last_rtp_sys_stamp)) * (sample_rate / double(1000.0))
int64_t(sys_stamp) - int64_t(_last_rtp_sys_stamp) - int64_t(stamp) + int64_t(_last_rtp_stamp)); - (int64_t(stamp) - int64_t(_last_rtp_stamp)));
if (diff < 0) { if (diff < 0) {
diff = -diff; diff = -diff;
} }
...@@ -68,14 +68,9 @@ void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, size_t bytes) { ...@@ -68,14 +68,9 @@ void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, size_t bytes) {
} }
void RtcpContext::onRtcp(RtcpHeader *rtcp) { void RtcpContext::onRtcp(RtcpHeader *rtcp) {
if ((RtcpType) rtcp->pt != RtcpType::RTCP_SR) { switch ((RtcpType) rtcp->pt) {
return; case RtcpType::RTCP_SR: {
} auto rtcp_sr = (RtcpSR *) rtcp;
if (!_is_receiver) {
WarnL << "rtp发送者收到sr包";
return;
}
auto rtcp_sr = (RtcpSR *) (rtcp);
/** /**
last SR timestamp (LSR): 32 bits last SR timestamp (LSR): 32 bits
The middle 32 bits out of 64 in the NTP timestamp (as explained in The middle 32 bits out of 64 in the NTP timestamp (as explained in
...@@ -85,6 +80,37 @@ void RtcpContext::onRtcp(RtcpHeader *rtcp) { ...@@ -85,6 +80,37 @@ void RtcpContext::onRtcp(RtcpHeader *rtcp) {
*/ */
_last_sr_lsr = ((rtcp_sr->ntpmsw & 0xFFFF) << 16) | ((rtcp_sr->ntplsw >> 16) & 0xFFFF); _last_sr_lsr = ((rtcp_sr->ntpmsw & 0xFFFF) << 16) | ((rtcp_sr->ntplsw >> 16) & 0xFFFF);
_last_sr_ntp_sys = getCurrentMillisecond(); _last_sr_ntp_sys = getCurrentMillisecond();
break;
}
case RtcpType::RTCP_RR: {
auto rtcp_rr = (RtcpRR *) rtcp;
for (auto item : rtcp_rr->getItemList()) {
if (!item->last_sr_stamp) {
continue;
}
//rtp接收端收到sr包后,回复rr包的延时,已转换为毫秒
auto delay_ms = (uint64_t) item->delay_since_last_sr * 1000 / 65536;
//这个rr包对应sr包的ntpmsw和ntplsw
auto ntpmsw = item->last_sr_stamp >> 16;
auto ntplsw = (item->last_sr_stamp & 0xFFFF) << 16;
RtcpSR sr;
//获取当前时间戳
sr.setNtpStamp(getCurrentMillisecond(true));
//当前时间戳与上次发送的sr包直接的ntp时间差
int64_t ntpmsw_inc = (int64_t)(ntohl(sr.ntpmsw) & 0xFFFF) - (int64_t)ntpmsw;
int64_t ntplsw_inc = (int64_t)(ntohl(sr.ntplsw)) - (int64_t)ntplsw;
//转换为毫秒
auto ms_inc = ntpmsw_inc * 1000 + (ntplsw_inc / ((double) (((uint64_t) 1) << 32) * 1.0e-3));
auto rtt = (int) ((ms_inc - delay_ms) / 2);
_rtt[item->ssrc] = rtt;
//InfoL << "ssrc:" << item->ssrc << ",rtt:" << rtt;
}
break;
}
default: break;
}
} }
size_t RtcpContext::getExpectedPackets() const { size_t RtcpContext::getExpectedPackets() const {
...@@ -120,14 +146,9 @@ Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc) { ...@@ -120,14 +146,9 @@ Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc) {
throw std::runtime_error("rtp接收者尝试发送sr包"); throw std::runtime_error("rtp接收者尝试发送sr包");
} }
auto rtcp = RtcpSR::create(0); auto rtcp = RtcpSR::create(0);
rtcp->ssrc = htonl(rtcp_ssrc); rtcp->setNtpStamp(getCurrentMillisecond(true));
struct timeval tv;
gettimeofday(&tv, NULL);
rtcp->setNtpStamp(tv);
//转换成rtp时间戳
rtcp->rtpts = htonl(_last_rtp_stamp); rtcp->rtpts = htonl(_last_rtp_stamp);
rtcp->ssrc = htonl(rtcp_ssrc);
rtcp->packet_count = htonl((uint32_t) _packets); rtcp->packet_count = htonl((uint32_t) _packets);
rtcp->octet_count = htonl((uint32_t) _bytes); rtcp->octet_count = htonl((uint32_t) _bytes);
return RtcpHeader::toBuffer(std::move(rtcp)); return RtcpHeader::toBuffer(std::move(rtcp));
......
...@@ -30,9 +30,10 @@ public: ...@@ -30,9 +30,10 @@ public:
* 输出或输入rtp时调用 * 输出或输入rtp时调用
* @param seq rtp的seq * @param seq rtp的seq
* @param stamp rtp的时间戳,单位采样数(非毫秒) * @param stamp rtp的时间戳,单位采样数(非毫秒)
* @param rtp rtp时间戳采样率,视频一般为90000,音频一般为采样率
* @param bytes rtp数据长度 * @param bytes rtp数据长度
*/ */
void onRtp(uint16_t seq, uint32_t stamp, size_t bytes); void onRtp(uint16_t seq, uint32_t stamp, uint32_t sample_rate, size_t bytes);
/** /**
* 输入sr rtcp包 * 输入sr rtcp包
...@@ -112,6 +113,7 @@ private: ...@@ -112,6 +113,7 @@ private:
uint32_t _last_sr_lsr = 0; uint32_t _last_sr_lsr = 0;
//上次收到sr时的系统时间戳,单位毫秒 //上次收到sr时的系统时间戳,单位毫秒
uint64_t _last_sr_ntp_sys = 0; uint64_t _last_sr_ntp_sys = 0;
unordered_map<uint32_t/*ssrc*/, uint32_t/*rtt*/> _rtt;
}; };
}//namespace mediakit }//namespace mediakit
......
...@@ -35,7 +35,7 @@ public: ...@@ -35,7 +35,7 @@ public:
void onRecvRtp(const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len){ void onRecvRtp(const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len){
//统计rtp接受情况,用于发送rr包 //统计rtp接受情况,用于发送rr包
auto header = (RtpHeader *) buf->data(); auto header = (RtpHeader *) buf->data();
onRtp(ntohs(header->seq), ntohl(header->stamp), buf->size()); onRtp(ntohs(header->seq), ntohl(header->stamp), _sample_rate, buf->size());
sendRtcp(ntohl(header->ssrc), addr, addr_len); sendRtcp(ntohl(header->ssrc), addr, addr_len);
} }
......
...@@ -591,7 +591,7 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrC ...@@ -591,7 +591,7 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrC
void RtspPlayer::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_idx){ void RtspPlayer::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_idx){
auto &rtcp_ctx = _rtcp_context[track_idx]; auto &rtcp_ctx = _rtcp_context[track_idx];
rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->size() - RtpPacket::kRtpTcpHeaderSize); rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
auto &ticker = _rtcp_send_ticker[track_idx]; auto &ticker = _rtcp_send_ticker[track_idx];
if (ticker.elapsedTime() < 3 * 1000) { if (ticker.elapsedTime() < 3 * 1000) {
......
...@@ -360,7 +360,7 @@ void RtspPusher::updateRtcpContext(const RtpPacket::Ptr &rtp){ ...@@ -360,7 +360,7 @@ void RtspPusher::updateRtcpContext(const RtpPacket::Ptr &rtp){
int track_index = getTrackIndexByTrackType(rtp->type); int track_index = getTrackIndexByTrackType(rtp->type);
auto &ticker = _rtcp_send_ticker[track_index]; auto &ticker = _rtcp_send_ticker[track_index];
auto &rtcp_ctx = _rtcp_context[track_index]; auto &rtcp_ctx = _rtcp_context[track_index];
rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->size() - RtpPacket::kRtpTcpHeaderSize); rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
//send rtcp every 5 second //send rtcp every 5 second
if (ticker.elapsedTime() > 5 * 1000) { if (ticker.elapsedTime() > 5 * 1000) {
......
...@@ -1126,7 +1126,7 @@ void RtspSession::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_index){ ...@@ -1126,7 +1126,7 @@ void RtspSession::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_index){
void RtspSession::updateRtcpContext(const RtpPacket::Ptr &rtp){ void RtspSession::updateRtcpContext(const RtpPacket::Ptr &rtp){
int track_index = getTrackIndexByTrackType(rtp->type); int track_index = getTrackIndexByTrackType(rtp->type);
auto &rtcp_ctx = _rtcp_context[track_index]; auto &rtcp_ctx = _rtcp_context[track_index];
rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->size() - RtpPacket::kRtpTcpHeaderSize); rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
auto &ticker = _rtcp_send_tickers[track_index]; auto &ticker = _rtcp_send_tickers[track_index];
//send rtcp every 5 second //send rtcp every 5 second
......
...@@ -586,7 +586,7 @@ public: ...@@ -586,7 +586,7 @@ public:
//统计rtp接受情况,便于生成nack rtcp包 //统计rtp接受情况,便于生成nack rtcp包
_nack_ctx.received(seq); _nack_ctx.received(seq);
//统计rtp收到的情况,好做rr汇报 //统计rtp收到的情况,好做rr汇报
_rtcp_context.onRtp(seq, ntohl(rtp->stamp), len); _rtcp_context.onRtp(seq, ntohl(rtp->stamp), sample_rate, len);
} }
return RtpTrack::inputRtp(type, sample_rate, ptr, len); return RtpTrack::inputRtp(type, sample_rate, ptr, len);
} }
...@@ -825,7 +825,7 @@ void WebRtcTransportImp::onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool r ...@@ -825,7 +825,7 @@ void WebRtcTransportImp::onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool r
} }
if (!rtx) { if (!rtx) {
//统计rtp发送情况,好做sr汇报 //统计rtp发送情况,好做sr汇报
track->rtcp_context_send->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->size() - RtpPacket::kRtpTcpHeaderSize); track->rtcp_context_send->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
track->nack_list.push_back(rtp); track->nack_list.push_back(rtp);
#if 0 #if 0
//此处模拟发送丢包 //此处模拟发送丢包
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论