mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 19:00:01 +08:00
修复rtcp rr/sr时间戳转换相关问题,计算rtt
This commit is contained in:
parent
bf8642d62f
commit
4c296488f1
@ -263,11 +263,25 @@ string RtcpSR::getNtpStamp() const{
|
||||
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) {
|
||||
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));
|
||||
}
|
||||
|
||||
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{
|
||||
_StrPrinter printer;
|
||||
printer << RtcpHeader::dumpHeader();
|
||||
|
@ -347,12 +347,14 @@ public:
|
||||
* @param tv 时间
|
||||
*/
|
||||
void setNtpStamp(struct timeval tv);
|
||||
void setNtpStamp(uint64_t unix_stamp_ms);
|
||||
|
||||
/**
|
||||
* 返回ntp时间的字符串
|
||||
* 使用net2Host转换成主机字节序后才可使用此函数
|
||||
*/
|
||||
string getNtpStamp() const;
|
||||
uint64_t getNtpUnixStampMS() const;
|
||||
|
||||
/**
|
||||
* 获取ReportItem对象指针列表
|
||||
|
@ -22,14 +22,14 @@ RtcpContext::RtcpContext(bool 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) {
|
||||
//接收者才做复杂的统计运算
|
||||
auto sys_stamp = getCurrentMillisecond();
|
||||
if (_last_rtp_sys_stamp) {
|
||||
//计算时间戳抖动值
|
||||
double diff = double(
|
||||
int64_t(sys_stamp) - int64_t(_last_rtp_sys_stamp) - int64_t(stamp) + int64_t(_last_rtp_stamp));
|
||||
double diff = double((int64_t(sys_stamp) - int64_t(_last_rtp_sys_stamp)) * (sample_rate / double(1000.0))
|
||||
- (int64_t(stamp) - int64_t(_last_rtp_stamp)));
|
||||
if (diff < 0) {
|
||||
diff = -diff;
|
||||
}
|
||||
@ -68,23 +68,49 @@ void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, size_t bytes) {
|
||||
}
|
||||
|
||||
void RtcpContext::onRtcp(RtcpHeader *rtcp) {
|
||||
if ((RtcpType) rtcp->pt != RtcpType::RTCP_SR) {
|
||||
return;
|
||||
switch ((RtcpType) rtcp->pt) {
|
||||
case RtcpType::RTCP_SR: {
|
||||
auto rtcp_sr = (RtcpSR *) rtcp;
|
||||
/**
|
||||
last SR timestamp (LSR): 32 bits
|
||||
The middle 32 bits out of 64 in the NTP timestamp (as explained in
|
||||
Section 4) received as part of the most recent RTCP sender report
|
||||
(SR) packet from source SSRC_n. If no SR has been received yet,
|
||||
the field is set to zero.
|
||||
*/
|
||||
_last_sr_lsr = ((rtcp_sr->ntpmsw & 0xFFFF) << 16) | ((rtcp_sr->ntplsw >> 16) & 0xFFFF);
|
||||
_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;
|
||||
}
|
||||
if (!_is_receiver) {
|
||||
WarnL << "rtp发送者收到sr包";
|
||||
return;
|
||||
}
|
||||
auto rtcp_sr = (RtcpSR *) (rtcp);
|
||||
/**
|
||||
last SR timestamp (LSR): 32 bits
|
||||
The middle 32 bits out of 64 in the NTP timestamp (as explained in
|
||||
Section 4) received as part of the most recent RTCP sender report
|
||||
(SR) packet from source SSRC_n. If no SR has been received yet,
|
||||
the field is set to zero.
|
||||
*/
|
||||
_last_sr_lsr = ((rtcp_sr->ntpmsw & 0xFFFF) << 16) | ((rtcp_sr->ntplsw >> 16) & 0xFFFF);
|
||||
_last_sr_ntp_sys = getCurrentMillisecond();
|
||||
}
|
||||
|
||||
size_t RtcpContext::getExpectedPackets() const {
|
||||
@ -120,14 +146,9 @@ Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc) {
|
||||
throw std::runtime_error("rtp接收者尝试发送sr包");
|
||||
}
|
||||
auto rtcp = RtcpSR::create(0);
|
||||
rtcp->ssrc = htonl(rtcp_ssrc);
|
||||
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
rtcp->setNtpStamp(tv);
|
||||
|
||||
//转换成rtp时间戳
|
||||
rtcp->setNtpStamp(getCurrentMillisecond(true));
|
||||
rtcp->rtpts = htonl(_last_rtp_stamp);
|
||||
rtcp->ssrc = htonl(rtcp_ssrc);
|
||||
rtcp->packet_count = htonl((uint32_t) _packets);
|
||||
rtcp->octet_count = htonl((uint32_t) _bytes);
|
||||
return RtcpHeader::toBuffer(std::move(rtcp));
|
||||
|
@ -30,9 +30,10 @@ public:
|
||||
* 输出或输入rtp时调用
|
||||
* @param seq rtp的seq
|
||||
* @param stamp rtp的时间戳,单位采样数(非毫秒)
|
||||
* @param rtp rtp时间戳采样率,视频一般为90000,音频一般为采样率
|
||||
* @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包
|
||||
@ -112,6 +113,7 @@ private:
|
||||
uint32_t _last_sr_lsr = 0;
|
||||
//上次收到sr时的系统时间戳,单位毫秒
|
||||
uint64_t _last_sr_ntp_sys = 0;
|
||||
unordered_map<uint32_t/*ssrc*/, uint32_t/*rtt*/> _rtt;
|
||||
};
|
||||
|
||||
}//namespace mediakit
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
void onRecvRtp(const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len){
|
||||
//统计rtp接受情况,用于发送rr包
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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){
|
||||
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];
|
||||
if (ticker.elapsedTime() < 3 * 1000) {
|
||||
|
@ -360,7 +360,7 @@ void RtspPusher::updateRtcpContext(const RtpPacket::Ptr &rtp){
|
||||
int track_index = getTrackIndexByTrackType(rtp->type);
|
||||
auto &ticker = _rtcp_send_ticker[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
|
||||
if (ticker.elapsedTime() > 5 * 1000) {
|
||||
|
@ -1126,7 +1126,7 @@ void RtspSession::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_index){
|
||||
void RtspSession::updateRtcpContext(const RtpPacket::Ptr &rtp){
|
||||
int track_index = getTrackIndexByTrackType(rtp->type);
|
||||
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];
|
||||
//send rtcp every 5 second
|
||||
|
@ -586,7 +586,7 @@ public:
|
||||
//统计rtp接受情况,便于生成nack rtcp包
|
||||
_nack_ctx.received(seq);
|
||||
//统计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);
|
||||
}
|
||||
@ -825,7 +825,7 @@ void WebRtcTransportImp::onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool r
|
||||
}
|
||||
if (!rtx) {
|
||||
//统计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);
|
||||
#if 0
|
||||
//此处模拟发送丢包
|
||||
|
Loading…
Reference in New Issue
Block a user